mirror of
https://github.com/SukkaW/Surge.git
synced 2025-12-12 17:20:35 +08:00
Refactor: use foxts more
This commit is contained in:
parent
017ff38b5e
commit
bdc1f5ec82
@ -1,11 +1,11 @@
|
|||||||
import { parseFelixDnsmasqFromResp } from './lib/parse-dnsmasq';
|
import { parseFelixDnsmasqFromResp } from './lib/parse-dnsmasq';
|
||||||
import { task } from './trace';
|
import { task } from './trace';
|
||||||
import { SHARED_DESCRIPTION } from './constants/description';
|
import { SHARED_DESCRIPTION } from './constants/description';
|
||||||
import { createMemoizedPromise } from './lib/memo-promise';
|
import { once } from 'foxts/once';
|
||||||
import { DomainsetOutput } from './lib/rules/domainset';
|
import { DomainsetOutput } from './lib/rules/domainset';
|
||||||
import { $$fetch } from './lib/fetch-retry';
|
import { $$fetch } from './lib/fetch-retry';
|
||||||
|
|
||||||
export const getAppleCdnDomainsPromise = createMemoizedPromise(() => $$fetch('https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/apple.china.conf').then(parseFelixDnsmasqFromResp));
|
export const getAppleCdnDomainsPromise = once(() => $$fetch('https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/apple.china.conf').then(parseFelixDnsmasqFromResp));
|
||||||
|
|
||||||
export const buildAppleCdn = task(require.main === module, __filename)(async (span) => {
|
export const buildAppleCdn = task(require.main === module, __filename)(async (span) => {
|
||||||
const res: string[] = await span.traceChildPromise('get apple cdn domains', getAppleCdnDomainsPromise());
|
const res: string[] = await span.traceChildPromise('get apple cdn domains', getAppleCdnDomainsPromise());
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import { fetchRemoteTextByLine } from './lib/fetch-text-by-line';
|
import { fetchRemoteTextByLine } from './lib/fetch-text-by-line';
|
||||||
import { task } from './trace';
|
import { task } from './trace';
|
||||||
|
|
||||||
import { createMemoizedPromise } from './lib/memo-promise';
|
import { once } from 'foxts/once';
|
||||||
import { IPListOutput } from './lib/rules/ip';
|
import { IPListOutput } from './lib/rules/ip';
|
||||||
import { createFileDescription } from './constants/description';
|
import { createFileDescription } from './constants/description';
|
||||||
|
|
||||||
export const getChnCidrPromise = createMemoizedPromise(async function getChnCidr() {
|
export const getChnCidrPromise = once(async function getChnCidr() {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
fetchRemoteTextByLine('https://chnroutes2.cdn.skk.moe/chnroutes.txt', true).then(Array.fromAsync<string>),
|
fetchRemoteTextByLine('https://chnroutes2.cdn.skk.moe/chnroutes.txt', true).then(Array.fromAsync<string>),
|
||||||
fetchRemoteTextByLine('https://gaoyifan.github.io/china-operator-ip/china6.txt', true).then(Array.fromAsync<string>)
|
fetchRemoteTextByLine('https://gaoyifan.github.io/china-operator-ip/china6.txt', true).then(Array.fromAsync<string>)
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { readFileIntoProcessedArray } from './lib/fetch-text-by-line';
|
|||||||
import { compareAndWriteFile } from './lib/create-file';
|
import { compareAndWriteFile } from './lib/create-file';
|
||||||
import { task } from './trace';
|
import { task } from './trace';
|
||||||
import { SHARED_DESCRIPTION } from './constants/description';
|
import { SHARED_DESCRIPTION } from './constants/description';
|
||||||
import { createMemoizedPromise } from './lib/memo-promise';
|
import { once } from 'foxts/once';
|
||||||
import * as yaml from 'yaml';
|
import * as yaml from 'yaml';
|
||||||
import { appendArrayInPlace } from 'foxts/append-array-in-place';
|
import { appendArrayInPlace } from 'foxts/append-array-in-place';
|
||||||
import { OUTPUT_INTERNAL_DIR, OUTPUT_MODULES_DIR, OUTPUT_MODULES_RULES_DIR, SOURCE_DIR } from './constants/dir';
|
import { OUTPUT_INTERNAL_DIR, OUTPUT_MODULES_DIR, OUTPUT_MODULES_RULES_DIR, SOURCE_DIR } from './constants/dir';
|
||||||
@ -52,7 +52,7 @@ export function createGetDnsMappingRule(allowWildcard: boolean) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDomesticAndDirectDomainsRulesetPromise = createMemoizedPromise(async () => {
|
export const getDomesticAndDirectDomainsRulesetPromise = once(async () => {
|
||||||
const domestics = await readFileIntoProcessedArray(path.join(SOURCE_DIR, 'non_ip/domestic.conf'));
|
const domestics = await readFileIntoProcessedArray(path.join(SOURCE_DIR, 'non_ip/domestic.conf'));
|
||||||
const directs = await readFileIntoProcessedArray(path.resolve(SOURCE_DIR, 'non_ip/direct.conf'));
|
const directs = await readFileIntoProcessedArray(path.resolve(SOURCE_DIR, 'non_ip/direct.conf'));
|
||||||
const lans: string[] = [];
|
const lans: string[] = [];
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { task } from './trace';
|
import { task } from './trace';
|
||||||
import { SHARED_DESCRIPTION } from './constants/description';
|
import { SHARED_DESCRIPTION } from './constants/description';
|
||||||
import { createMemoizedPromise } from './lib/memo-promise';
|
import { once } from 'foxts/once';
|
||||||
import { RulesetOutput } from './lib/rules/ruleset';
|
import { RulesetOutput } from './lib/rules/ruleset';
|
||||||
import Worktank from 'worktank';
|
import Worktank from 'worktank';
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ const pool = new Worktank({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getMicrosoftCdnRulesetPromise = createMemoizedPromise<[domains: string[], domainSuffixes: string[]]>(async () => {
|
export const getMicrosoftCdnRulesetPromise = once<Promise<[domains: string[], domainSuffixes: string[]]>>(async () => {
|
||||||
const res = await pool.exec(
|
const res = await pool.exec(
|
||||||
'getMicrosoftCdnRuleset',
|
'getMicrosoftCdnRuleset',
|
||||||
[import.meta.url]
|
[import.meta.url]
|
||||||
|
|||||||
@ -2,12 +2,12 @@
|
|||||||
import { createReadlineInterfaceFromResponse } from './lib/fetch-text-by-line';
|
import { createReadlineInterfaceFromResponse } from './lib/fetch-text-by-line';
|
||||||
import { task } from './trace';
|
import { task } from './trace';
|
||||||
import { SHARED_DESCRIPTION } from './constants/description';
|
import { SHARED_DESCRIPTION } from './constants/description';
|
||||||
import { createMemoizedPromise } from './lib/memo-promise';
|
import { once } from 'foxts/once';
|
||||||
import { RulesetOutput } from './lib/rules/ruleset';
|
import { RulesetOutput } from './lib/rules/ruleset';
|
||||||
import { $$fetch } from './lib/fetch-retry';
|
import { $$fetch } from './lib/fetch-retry';
|
||||||
import { fastIpVersion } from './lib/misc';
|
import { fastIpVersion } from './lib/misc';
|
||||||
|
|
||||||
export const getTelegramCIDRPromise = createMemoizedPromise(async () => {
|
export const getTelegramCIDRPromise = once(async () => {
|
||||||
const resp = await $$fetch('https://core.telegram.org/resources/cidr.txt');
|
const resp = await $$fetch('https://core.telegram.org/resources/cidr.txt');
|
||||||
const lastModified = resp.headers.get('last-modified');
|
const lastModified = resp.headers.get('last-modified');
|
||||||
const date = lastModified ? new Date(lastModified) : new Date();
|
const date = lastModified ? new Date(lastModified) : new Date();
|
||||||
|
|||||||
@ -80,7 +80,11 @@ const domesticDohServers: Array<[string, DNS2.DnsResolver]> = ([
|
|||||||
|
|
||||||
const domainAliveMutex = createKeyedAsyncMutex('isDomainAlive');
|
const domainAliveMutex = createKeyedAsyncMutex('isDomainAlive');
|
||||||
|
|
||||||
export async function isDomainAlive(domain: string, isIncludeAllSubdomain: boolean = domain[0] === '.'): Promise<boolean> {
|
export async function isDomainAlive(
|
||||||
|
domain: string,
|
||||||
|
// we dont need to check domain[0] here, this is only from runAgainstSourceFile
|
||||||
|
isIncludeAllSubdomain: boolean
|
||||||
|
): Promise<boolean> {
|
||||||
if (domainAliveMap.has(domain)) {
|
if (domainAliveMap.has(domain)) {
|
||||||
return domainAliveMap.get(domain)!;
|
return domainAliveMap.get(domain)!;
|
||||||
}
|
}
|
||||||
@ -102,8 +106,6 @@ export async function isDomainAlive(domain: string, isIncludeAllSubdomain: boole
|
|||||||
return domainAliveMutex.acquire(domain, async () => {
|
return domainAliveMutex.acquire(domain, async () => {
|
||||||
domain = domain[0] === '.' ? domain.slice(1) : domain;
|
domain = domain[0] === '.' ? domain.slice(1) : domain;
|
||||||
|
|
||||||
const $domain = isIncludeAllSubdomain ? '.' + domain : domain;
|
|
||||||
|
|
||||||
const aDns: string[] = [];
|
const aDns: string[] = [];
|
||||||
const aaaaDns: string[] = [];
|
const aaaaDns: string[] = [];
|
||||||
|
|
||||||
@ -113,7 +115,7 @@ export async function isDomainAlive(domain: string, isIncludeAllSubdomain: boole
|
|||||||
// eslint-disable-next-line no-await-in-loop -- sequential
|
// eslint-disable-next-line no-await-in-loop -- sequential
|
||||||
const aRecords = (await $resolve(domain, 'A', servers[i]));
|
const aRecords = (await $resolve(domain, 'A', servers[i]));
|
||||||
if (aRecords.answers.length > 0) {
|
if (aRecords.answers.length > 0) {
|
||||||
domainAliveMap.set($domain, true);
|
domainAliveMap.set(domain, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +125,7 @@ export async function isDomainAlive(domain: string, isIncludeAllSubdomain: boole
|
|||||||
// eslint-disable-next-line no-await-in-loop -- sequential
|
// eslint-disable-next-line no-await-in-loop -- sequential
|
||||||
const aaaaRecords = (await $resolve(domain, 'AAAA', servers[i]));
|
const aaaaRecords = (await $resolve(domain, 'AAAA', servers[i]));
|
||||||
if (aaaaRecords.answers.length > 0) {
|
if (aaaaRecords.answers.length > 0) {
|
||||||
domainAliveMap.set($domain, true);
|
domainAliveMap.set(domain, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +137,7 @@ export async function isDomainAlive(domain: string, isIncludeAllSubdomain: boole
|
|||||||
// eslint-disable-next-line no-await-in-loop -- sequential
|
// eslint-disable-next-line no-await-in-loop -- sequential
|
||||||
const aRecords = (await $resolve(domain, 'A', pickOne(domesticDohServers)));
|
const aRecords = (await $resolve(domain, 'A', pickOne(domesticDohServers)));
|
||||||
if (aRecords.answers.length > 0) {
|
if (aRecords.answers.length > 0) {
|
||||||
domainAliveMap.set($domain, true);
|
domainAliveMap.set(domain, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
aDns.push(aRecords.dns);
|
aDns.push(aRecords.dns);
|
||||||
@ -144,7 +146,7 @@ export async function isDomainAlive(domain: string, isIncludeAllSubdomain: boole
|
|||||||
// eslint-disable-next-line no-await-in-loop -- sequential
|
// eslint-disable-next-line no-await-in-loop -- sequential
|
||||||
const aaaaRecords = (await $resolve(domain, 'AAAA', pickOne(domesticDohServers)));
|
const aaaaRecords = (await $resolve(domain, 'AAAA', pickOne(domesticDohServers)));
|
||||||
if (aaaaRecords.answers.length > 0) {
|
if (aaaaRecords.answers.length > 0) {
|
||||||
domainAliveMap.set($domain, true);
|
domainAliveMap.set(domain, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
aaaaDns.push(aaaaRecords.dns);
|
aaaaDns.push(aaaaRecords.dns);
|
||||||
@ -152,7 +154,7 @@ export async function isDomainAlive(domain: string, isIncludeAllSubdomain: boole
|
|||||||
|
|
||||||
console.log(picocolors.red('[domain dead]'), 'no A/AAAA records', { domain, a: aDns, aaaa: aaaaDns });
|
console.log(picocolors.red('[domain dead]'), 'no A/AAAA records', { domain, a: aDns, aaaa: aaaaDns });
|
||||||
|
|
||||||
domainAliveMap.set($domain, false);
|
domainAliveMap.set(domain, false);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,26 +0,0 @@
|
|||||||
const notError = Symbol('notError');
|
|
||||||
|
|
||||||
export function createMemoizedPromise<T>(
|
|
||||||
fn: () => Promise<T>,
|
|
||||||
/** whether to create promise immediately or only create after first access */
|
|
||||||
preload = true
|
|
||||||
): () => Promise<T> {
|
|
||||||
let error: Error | typeof notError = notError;
|
|
||||||
|
|
||||||
let promise: Promise<T> | null = preload
|
|
||||||
? fn().catch(e => {
|
|
||||||
// Here we record the error so that we can throw it later when the function is called
|
|
||||||
error = e;
|
|
||||||
// Here we make sure the Promise still returns the never type
|
|
||||||
throw e;
|
|
||||||
})
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
if (error !== notError) {
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
promise ??= fn();
|
|
||||||
return promise;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -31,7 +31,7 @@
|
|||||||
"fast-cidr-tools": "^0.3.2",
|
"fast-cidr-tools": "^0.3.2",
|
||||||
"fast-fifo": "^1.3.2",
|
"fast-fifo": "^1.3.2",
|
||||||
"fdir": "^6.4.5",
|
"fdir": "^6.4.5",
|
||||||
"foxts": "^3.3.3",
|
"foxts": "^3.4.0",
|
||||||
"hash-wasm": "^4.12.0",
|
"hash-wasm": "^4.12.0",
|
||||||
"json-stringify-pretty-compact": "3.0.0",
|
"json-stringify-pretty-compact": "3.0.0",
|
||||||
"null-prototype-object": "^1.2.0",
|
"null-prototype-object": "^1.2.0",
|
||||||
|
|||||||
24
pnpm-lock.yaml
generated
24
pnpm-lock.yaml
generated
@ -50,8 +50,8 @@ importers:
|
|||||||
specifier: ^6.4.5
|
specifier: ^6.4.5
|
||||||
version: 6.4.5(picomatch@4.0.2)
|
version: 6.4.5(picomatch@4.0.2)
|
||||||
foxts:
|
foxts:
|
||||||
specifier: ^3.3.3
|
specifier: ^3.4.0
|
||||||
version: 3.3.3
|
version: 3.4.0
|
||||||
hash-wasm:
|
hash-wasm:
|
||||||
specifier: ^4.12.0
|
specifier: ^4.12.0
|
||||||
version: 4.12.0
|
version: 4.12.0
|
||||||
@ -1200,8 +1200,8 @@ packages:
|
|||||||
fast-deep-equal@3.1.3:
|
fast-deep-equal@3.1.3:
|
||||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||||
|
|
||||||
fast-escape-html@1.0.0:
|
fast-escape-html@1.1.0:
|
||||||
resolution: {integrity: sha512-f5flzdfLAWKlW2hJAHFh2iyMhTlX6tEMaBuRXwvSKtyYEqv9OR0y7mJz6tHs3CDB2opBU5hTWpm9AROhfWTK7A==}
|
resolution: {integrity: sha512-nRvjfywv8gzIBs0fM/ht6S5scNUamm+o+91p/69cYYNWODb7b/UiQfjFx+6n8NMtdHs6K80kh+hW1dPNS/opIA==}
|
||||||
|
|
||||||
fast-fifo@1.3.2:
|
fast-fifo@1.3.2:
|
||||||
resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==}
|
resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==}
|
||||||
@ -1257,8 +1257,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
|
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
foxts@3.3.3:
|
foxts@3.4.0:
|
||||||
resolution: {integrity: sha512-9TkeFw6bXXphI9Pu7SOI/+gO8g5bNjs3/s2kPDRwRHnJ46weDxoB6V+gG7mzr+9xsVedjSVxv+4xErNGpgDOtQ==}
|
resolution: {integrity: sha512-zpI41ZJ/ZjG745XMVJy338CU1WLwkp1AobgGNKvFDEvSz8y7Lv+DTUpAj/BUyXg7TocGDpSwRH6o9XyAvkMO5A==}
|
||||||
|
|
||||||
fs-constants@1.0.0:
|
fs-constants@1.0.0:
|
||||||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
||||||
@ -2764,7 +2764,7 @@ snapshots:
|
|||||||
eslint-plugin-regexp: 2.7.0(eslint@9.27.0)
|
eslint-plugin-regexp: 2.7.0(eslint@9.27.0)
|
||||||
eslint-plugin-sukka: 6.20.0(eslint@9.27.0)(typescript@5.8.3)
|
eslint-plugin-sukka: 6.20.0(eslint@9.27.0)(typescript@5.8.3)
|
||||||
eslint-plugin-unused-imports: 4.1.4(@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.27.0)(typescript@5.8.3))(eslint@9.27.0)(typescript@5.8.3))(eslint@9.27.0)
|
eslint-plugin-unused-imports: 4.1.4(@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.27.0)(typescript@5.8.3))(eslint@9.27.0)(typescript@5.8.3))(eslint@9.27.0)
|
||||||
foxts: 3.3.3
|
foxts: 3.4.0
|
||||||
jsonc-eslint-parser: 2.4.0
|
jsonc-eslint-parser: 2.4.0
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
typescript-eslint: 8.32.1(eslint@9.27.0)(typescript@5.8.3)
|
typescript-eslint: 8.32.1(eslint@9.27.0)(typescript@5.8.3)
|
||||||
@ -2898,7 +2898,7 @@ snapshots:
|
|||||||
'@eslint-sukka/shared': 6.20.0(eslint@9.27.0)(typescript@5.8.3)
|
'@eslint-sukka/shared': 6.20.0(eslint@9.27.0)(typescript@5.8.3)
|
||||||
'@typescript-eslint/type-utils': 8.32.1(eslint@9.27.0)(typescript@5.8.3)
|
'@typescript-eslint/type-utils': 8.32.1(eslint@9.27.0)(typescript@5.8.3)
|
||||||
'@typescript-eslint/utils': 8.32.1(eslint@9.27.0)(typescript@5.8.3)
|
'@typescript-eslint/utils': 8.32.1(eslint@9.27.0)(typescript@5.8.3)
|
||||||
foxts: 3.3.3
|
foxts: 3.4.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.8.3
|
typescript: 5.8.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@ -3002,7 +3002,7 @@ snapshots:
|
|||||||
|
|
||||||
fast-deep-equal@3.1.3: {}
|
fast-deep-equal@3.1.3: {}
|
||||||
|
|
||||||
fast-escape-html@1.0.0: {}
|
fast-escape-html@1.1.0: {}
|
||||||
|
|
||||||
fast-fifo@1.3.2: {}
|
fast-fifo@1.3.2: {}
|
||||||
|
|
||||||
@ -3055,9 +3055,9 @@ snapshots:
|
|||||||
cross-spawn: 7.0.6
|
cross-spawn: 7.0.6
|
||||||
signal-exit: 4.1.0
|
signal-exit: 4.1.0
|
||||||
|
|
||||||
foxts@3.3.3:
|
foxts@3.4.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
fast-escape-html: 1.0.0
|
fast-escape-html: 1.1.0
|
||||||
|
|
||||||
fs-constants@1.0.0: {}
|
fs-constants@1.0.0: {}
|
||||||
|
|
||||||
@ -3656,7 +3656,7 @@ snapshots:
|
|||||||
undici-cache-store-better-sqlite3@1.0.0(undici@7.10.0):
|
undici-cache-store-better-sqlite3@1.0.0(undici@7.10.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
better-sqlite3: 11.10.0
|
better-sqlite3: 11.10.0
|
||||||
foxts: 3.3.3
|
foxts: 3.4.0
|
||||||
undici: 7.10.0
|
undici: 7.10.0
|
||||||
|
|
||||||
undici-types@6.21.0: {}
|
undici-types@6.21.0: {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user