mirror of
https://github.com/SukkaW/Surge.git
synced 2025-12-13 17:50:34 +08:00
Minor changes here and there
This commit is contained in:
parent
b7cae1061c
commit
7b2334ee3b
@ -2,7 +2,6 @@ import { fetchRemoteTextByLine } from './lib/fetch-text-by-line';
|
|||||||
import { resolve as pathResolve } from 'path';
|
import { resolve as pathResolve } from 'path';
|
||||||
import { compareAndWriteFile, withBannerArray } from './lib/create-file';
|
import { compareAndWriteFile, withBannerArray } from './lib/create-file';
|
||||||
import { processLineFromReadline } from './lib/process-line';
|
import { processLineFromReadline } from './lib/process-line';
|
||||||
import { traceSync } from './lib/trace-runner';
|
|
||||||
import { task } from './trace';
|
import { task } from './trace';
|
||||||
|
|
||||||
import { exclude } from 'fast-cidr-tools';
|
import { exclude } from 'fast-cidr-tools';
|
||||||
@ -21,11 +20,7 @@ const INCLUDE_CIDRS = [
|
|||||||
|
|
||||||
export const getChnCidrPromise = createMemoizedPromise(async () => {
|
export const getChnCidrPromise = createMemoizedPromise(async () => {
|
||||||
const cidr = await processLineFromReadline(await fetchRemoteTextByLine('https://raw.githubusercontent.com/misakaio/chnroutes2/master/chnroutes.txt'));
|
const cidr = await processLineFromReadline(await fetchRemoteTextByLine('https://raw.githubusercontent.com/misakaio/chnroutes2/master/chnroutes.txt'));
|
||||||
return traceSync(
|
return exclude([...cidr, ...INCLUDE_CIDRS], EXCLUDE_CIDRS, true);
|
||||||
picocolors.gray('processing chnroutes2'),
|
|
||||||
() => exclude([...cidr, ...INCLUDE_CIDRS], EXCLUDE_CIDRS, true),
|
|
||||||
picocolors.gray
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const buildChnCidr = task(import.meta.path, async (span) => {
|
export const buildChnCidr = task(import.meta.path, async (span) => {
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { traceAsync } from './lib/trace-runner';
|
|
||||||
import { task } from './trace';
|
import { task } from './trace';
|
||||||
import { createRuleset } from './lib/create-file';
|
import { createRuleset } from './lib/create-file';
|
||||||
import { fetchRemoteTextByLine } from './lib/fetch-text-by-line';
|
import { fetchRemoteTextByLine } from './lib/fetch-text-by-line';
|
||||||
|
|||||||
@ -1,18 +1,14 @@
|
|||||||
import { TTL, fsFetchCache } from './lib/cache-filesystem';
|
import { TTL, fsFetchCache } from './lib/cache-filesystem';
|
||||||
import { defaultRequestInit, fetchWithRetry } from './lib/fetch-retry';
|
import { defaultRequestInit, fetchWithRetry } from './lib/fetch-retry';
|
||||||
import { createMemoizedPromise } from './lib/memo-promise';
|
import { createMemoizedPromise } from './lib/memo-promise';
|
||||||
import { traceAsync } from './lib/trace-runner';
|
|
||||||
|
|
||||||
export const getPublicSuffixListTextPromise = createMemoizedPromise(() => traceAsync(
|
export const getPublicSuffixListTextPromise = createMemoizedPromise(() => fsFetchCache.apply(
|
||||||
'obtain public_suffix_list',
|
'https://publicsuffix.org/list/public_suffix_list.dat',
|
||||||
() => fsFetchCache.apply(
|
() => fetchWithRetry('https://publicsuffix.org/list/public_suffix_list.dat', defaultRequestInit).then(r => r.text()),
|
||||||
'https://publicsuffix.org/list/public_suffix_list.dat',
|
{
|
||||||
() => fetchWithRetry('https://publicsuffix.org/list/public_suffix_list.dat', defaultRequestInit).then(r => r.text()),
|
// https://github.com/publicsuffix/list/blob/master/.github/workflows/tld-update.yml
|
||||||
{
|
// Though the action runs every 24 hours, the IANA list is updated every 7 days.
|
||||||
// https://github.com/publicsuffix/list/blob/master/.github/workflows/tld-update.yml
|
// So a 3 day TTL should be enough.
|
||||||
// Though the action runs every 24 hours, the IANA list is updated every 7 days.
|
ttl: TTL.THREE_DAYS()
|
||||||
// So a 3 day TTL should be enough.
|
}
|
||||||
ttl: TTL.THREE_DAYS()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
));
|
));
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import os from 'os';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { mkdirSync } from 'fs';
|
import { mkdirSync } from 'fs';
|
||||||
import picocolors from 'picocolors';
|
import picocolors from 'picocolors';
|
||||||
import { traceSync } from './trace-runner';
|
|
||||||
|
|
||||||
const identity = (x: any) => x;
|
const identity = (x: any) => x;
|
||||||
|
|
||||||
@ -72,7 +71,13 @@ export class Cache<S = string> {
|
|||||||
type: S extends string ? 'string' : 'buffer';
|
type: S extends string ? 'string' : 'buffer';
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
cachePath = path.join(os.tmpdir() || '/tmp', 'hdc'), tbd, tableName = 'cache', type }: CacheOptions<S> = {}) {
|
cachePath = path.join(os.tmpdir() || '/tmp', 'hdc'),
|
||||||
|
tbd,
|
||||||
|
tableName = 'cache',
|
||||||
|
type
|
||||||
|
}: CacheOptions<S> = {}) {
|
||||||
|
const start = Bun.nanoseconds();
|
||||||
|
|
||||||
this.cachePath = cachePath;
|
this.cachePath = cachePath;
|
||||||
mkdirSync(this.cachePath, { recursive: true });
|
mkdirSync(this.cachePath, { recursive: true });
|
||||||
if (tbd != null) this.tbd = tbd;
|
if (tbd != null) this.tbd = tbd;
|
||||||
@ -111,6 +116,9 @@ export class Cache<S = string> {
|
|||||||
this.set('__LAST_VACUUM', dateString, 10 * 365 * 60 * 60 * 24 * 1000);
|
this.set('__LAST_VACUUM', dateString, 10 * 365 * 60 * 60 * 24 * 1000);
|
||||||
this.db.exec('VACUUM;');
|
this.db.exec('VACUUM;');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const end = Bun.nanoseconds();
|
||||||
|
console.log(`${picocolors.gray(`[${((end - start) / 1e6).toFixed(3)}ms]`)} cache initialized from ${this.cachePath}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(key: string, value: string, ttl = 60 * 1000): void {
|
set(key: string, value: string, ttl = 60 * 1000): void {
|
||||||
@ -195,7 +203,7 @@ export class Cache<S = string> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fsFetchCache = traceSync('initializing filesystem cache for fetch', () => new Cache({ cachePath: path.resolve(import.meta.dir, '../../.cache') }));
|
export const fsFetchCache = new Cache({ cachePath: path.resolve(import.meta.dir, '../../.cache') });
|
||||||
// process.on('exit', () => {
|
// process.on('exit', () => {
|
||||||
// fsFetchCache.destroy();
|
// fsFetchCache.destroy();
|
||||||
// });
|
// });
|
||||||
|
|||||||
@ -1,11 +1,9 @@
|
|||||||
import { createCache } from './cache-apply';
|
import { createCache } from './cache-apply';
|
||||||
import type { PublicSuffixList } from '@gorhill/publicsuffixlist';
|
import type { PublicSuffixList } from '@gorhill/publicsuffixlist';
|
||||||
|
|
||||||
let gothillGetDomainCache: ReturnType<typeof createCache> | null = null;
|
let gorhillGetDomainCache: ReturnType<typeof createCache> | null = null;
|
||||||
export const createCachedGorhillGetDomain = (gorhill: PublicSuffixList) => {
|
export const createCachedGorhillGetDomain = (gorhill: PublicSuffixList) => {
|
||||||
gothillGetDomainCache ??= createCache('cached-gorhill-get-domain', true);
|
gorhillGetDomainCache ??= createCache('cached-gorhill-get-domain', true);
|
||||||
return (domain: string) => {
|
return (domain: string) => gorhillGetDomainCache! // we do know gothillGetDomainCache exists here
|
||||||
// we do know gothillGetDomainCache exists here
|
.sync(domain, () => gorhill.getDomain(domain[0] === '.' ? domain.slice(1) : domain));
|
||||||
return gothillGetDomainCache!.sync(domain, () => gorhill.getDomain(domain[0] === '.' ? domain.slice(1) : domain));
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -24,15 +24,9 @@ const REQUIRE_REWRITE = {
|
|||||||
export const surgeRulesetToClashClassicalTextRuleset = (rules: string[] | Set<string>) => {
|
export const surgeRulesetToClashClassicalTextRuleset = (rules: string[] | Set<string>) => {
|
||||||
const trie = Trie.from(rules);
|
const trie = Trie.from(rules);
|
||||||
|
|
||||||
return CLASH_SUPPORTED_RULE_TYPE.flatMap(
|
return CLASH_SUPPORTED_RULE_TYPE.flatMap(type => trie.find(`${type},`)).concat(
|
||||||
type => trie.find(`${type},`)
|
Object.keys(REQUIRE_REWRITE).flatMap((type) => trie.find(`${type},`)
|
||||||
).concat(
|
.map(line => `${REQUIRE_REWRITE[type as keyof typeof REQUIRE_REWRITE]}${line.slice(type.length)}`))
|
||||||
Object.keys(REQUIRE_REWRITE).flatMap(
|
|
||||||
(type) => {
|
|
||||||
const found = trie.find(`${type},`);
|
|
||||||
return found.map(line => `${REQUIRE_REWRITE[type as keyof typeof REQUIRE_REWRITE]}${line.slice(type.length)}`);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -12,20 +12,10 @@ const sleepWithAbort = (ms: number, signal: AbortSignal) => new Promise<void>((r
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
signal.addEventListener('abort', stop);
|
function stop(this: AbortSignal) { reject(this.reason); }
|
||||||
Bun.sleep(ms).then(done).catch(doReject);
|
|
||||||
|
|
||||||
function done() {
|
signal.addEventListener('abort', stop, { once: true });
|
||||||
signal.removeEventListener('abort', stop);
|
Bun.sleep(ms).then(resolve).catch(reject).finally(() => signal.removeEventListener('abort', stop));
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
function stop(this: AbortSignal) {
|
|
||||||
reject(this.reason);
|
|
||||||
}
|
|
||||||
function doReject(reason: unknown) {
|
|
||||||
signal.removeEventListener('abort', stop);
|
|
||||||
reject(reason);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export async function fetchAssets(url: string, fallbackUrls: string[] | readonly string[]) {
|
export async function fetchAssets(url: string, fallbackUrls: string[] | readonly string[]) {
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
import { toASCII } from 'punycode';
|
import { toASCII } from 'punycode';
|
||||||
import { traceAsync } from './trace-runner';
|
|
||||||
import { createMemoizedPromise } from './memo-promise';
|
import { createMemoizedPromise } from './memo-promise';
|
||||||
import { getPublicSuffixListTextPromise } from '../download-publicsuffixlist';
|
import { getPublicSuffixListTextPromise } from '../download-publicsuffixlist';
|
||||||
|
|
||||||
const customFetch = (url: string | URL): Promise<Blob> => Promise.resolve(Bun.file(url));
|
const customFetch = (url: string | URL): Promise<Blob> => Promise.resolve(Bun.file(url));
|
||||||
|
|
||||||
export const getGorhillPublicSuffixPromise = createMemoizedPromise(() => traceAsync('create gorhill public suffix instance', async () => {
|
export const getGorhillPublicSuffixPromise = createMemoizedPromise(async () => {
|
||||||
const [publicSuffixListDat, { default: gorhill }] = await Promise.all([
|
const [publicSuffixListDat, { default: gorhill }] = await Promise.all([
|
||||||
getPublicSuffixListTextPromise(),
|
getPublicSuffixListTextPromise(),
|
||||||
import('@gorhill/publicsuffixlist')
|
import('@gorhill/publicsuffixlist')
|
||||||
@ -15,4 +14,4 @@ export const getGorhillPublicSuffixPromise = createMemoizedPromise(() => traceAs
|
|||||||
await gorhill.enableWASM({ customFetch });
|
await gorhill.enableWASM({ customFetch });
|
||||||
|
|
||||||
return gorhill;
|
return gorhill;
|
||||||
}));
|
});
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
export const createMemoizedPromise = <T>(fn: () => Promise<T>, preload = true): () => Promise<T> => {
|
export const createMemoizedPromise = <T>(fn: () => Promise<T>, preload = true): () => Promise<T> => {
|
||||||
let promise: Promise<T> | null = null;
|
let promise: Promise<T> | null = preload ? fn() : null;
|
||||||
|
|
||||||
if (preload) {
|
|
||||||
promise = fn();
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
promise ??= fn();
|
promise ??= fn();
|
||||||
|
|||||||
@ -1,20 +0,0 @@
|
|||||||
import picocolors from 'picocolors';
|
|
||||||
|
|
||||||
type Formatter = (result: string) => string;
|
|
||||||
|
|
||||||
export function traceSync<T>(prefix: string, fn: () => T, timeFormatter: Formatter = picocolors.blue): T {
|
|
||||||
const start = Bun.nanoseconds();
|
|
||||||
const result = fn();
|
|
||||||
const end = Bun.nanoseconds();
|
|
||||||
console.log(`${timeFormatter(`[${((end - start) / 1e6).toFixed(3)}ms]`)} ${prefix}`);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
// traceSync.skip = <T>(_prefix: string, fn: () => T): T => fn();
|
|
||||||
|
|
||||||
export const traceAsync = async <T>(prefix: string, fn: () => Promise<T>, timeFormatter: Formatter = picocolors.blue): Promise<T> => {
|
|
||||||
const start = Bun.nanoseconds();
|
|
||||||
const result = await fn();
|
|
||||||
const end = Bun.nanoseconds();
|
|
||||||
console.log(`${timeFormatter(`[${((end - start) / 1e6).toFixed(3)}ms]`)} ${prefix}`);
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
@ -211,11 +211,11 @@ export const createTrie = (from?: string[] | Set<string> | null) => {
|
|||||||
for (let i = suffix.length - 1; i >= 0; i--) {
|
for (let i = suffix.length - 1; i >= 0; i--) {
|
||||||
const token = suffix[i];
|
const token = suffix[i];
|
||||||
|
|
||||||
if (node.has(token)) {
|
if (!node.has(token)) {
|
||||||
node = node.get(token)!;
|
|
||||||
} else {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node = node.get(token)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
return node[SENTINEL];
|
return node[SENTINEL];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user