diff --git a/.swcrc b/.swcrc index 97a75ad4..65a083f9 100644 --- a/.swcrc +++ b/.swcrc @@ -6,5 +6,9 @@ "syntax": "typescript", "dynamicImport": true } + }, + "module": { + "type": "commonjs", + "ignoreDynamic": true } } diff --git a/Build/build-apple-cdn.ts b/Build/build-apple-cdn.ts index 047ad568..6c084097 100644 --- a/Build/build-apple-cdn.ts +++ b/Build/build-apple-cdn.ts @@ -17,7 +17,7 @@ export const getAppleCdnDomainsPromise = createMemoizedPromise(() => fsFetchCach } )); -export const buildAppleCdn = task(import.meta.main, import.meta.path)(async (span) => { +export const buildAppleCdn = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const res: string[] = await span.traceChildPromise('get apple cdn domains', getAppleCdnDomainsPromise()); const description = [ @@ -40,8 +40,8 @@ export const buildAppleCdn = task(import.meta.main, import.meta.path)(async (spa new Date(), ruleset, 'ruleset', - path.resolve(import.meta.dir, '../List/non_ip/apple_cdn.conf'), - path.resolve(import.meta.dir, '../Clash/non_ip/apple_cdn.txt') + path.resolve(__dirname, '../List/non_ip/apple_cdn.conf'), + path.resolve(__dirname, '../Clash/non_ip/apple_cdn.txt') ), createRuleset( span, @@ -50,8 +50,8 @@ export const buildAppleCdn = task(import.meta.main, import.meta.path)(async (spa new Date(), domainset, 'domainset', - path.resolve(import.meta.dir, '../List/domainset/apple_cdn.conf'), - path.resolve(import.meta.dir, '../Clash/domainset/apple_cdn.txt') + path.resolve(__dirname, '../List/domainset/apple_cdn.conf'), + path.resolve(__dirname, '../Clash/domainset/apple_cdn.txt') ) ]); }); diff --git a/Build/build-cdn-download-conf.ts b/Build/build-cdn-download-conf.ts index 6771dcc9..4ed561bd 100644 --- a/Build/build-cdn-download-conf.ts +++ b/Build/build-cdn-download-conf.ts @@ -48,7 +48,7 @@ const getS3OSSDomainsPromise = (async (): Promise => { return Array.from(S3OSSDomains); })(); -export const buildCdnDownloadConf = task(import.meta.main, import.meta.path)(async (span) => { +export const buildCdnDownloadConf = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const [ S3OSSDomains, @@ -57,9 +57,9 @@ export const buildCdnDownloadConf = task(import.meta.main, import.meta.path)(asy steamDomainSet ] = await Promise.all([ getS3OSSDomainsPromise, - readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/domainset/cdn.conf')), - readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/domainset/download.conf')), - readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/domainset/steam.conf')) + readFileIntoProcessedArray(path.resolve(__dirname, '../Source/domainset/cdn.conf')), + readFileIntoProcessedArray(path.resolve(__dirname, '../Source/domainset/download.conf')), + readFileIntoProcessedArray(path.resolve(__dirname, '../Source/domainset/steam.conf')) ]); appendArrayInPlace(downloadDomainSet, S3OSSDomains.map(domain => `.${domain}`)); @@ -77,8 +77,8 @@ export const buildCdnDownloadConf = task(import.meta.main, import.meta.path)(asy new Date(), sortDomains(domainDeduper(cdnDomainsList)), 'domainset', - path.resolve(import.meta.dir, '../List/domainset/cdn.conf'), - path.resolve(import.meta.dir, '../Clash/domainset/cdn.txt') + path.resolve(__dirname, '../List/domainset/cdn.conf'), + path.resolve(__dirname, '../Clash/domainset/cdn.txt') ), createRuleset( span, @@ -91,8 +91,8 @@ export const buildCdnDownloadConf = task(import.meta.main, import.meta.path)(asy new Date(), sortDomains(domainDeduper(downloadDomainSet)), 'domainset', - path.resolve(import.meta.dir, '../List/domainset/download.conf'), - path.resolve(import.meta.dir, '../Clash/domainset/download.txt') + path.resolve(__dirname, '../List/domainset/download.conf'), + path.resolve(__dirname, '../Clash/domainset/download.txt') ) ]); }); diff --git a/Build/build-chn-cidr.ts b/Build/build-chn-cidr.ts index 834abe13..7484281e 100644 --- a/Build/build-chn-cidr.ts +++ b/Build/build-chn-cidr.ts @@ -16,7 +16,7 @@ export const getChnCidrPromise = createMemoizedPromise(async () => { return exclude(cidr, NON_CN_CIDR_INCLUDED_IN_CHNROUTE, true); }); -export const buildChnCidr = task(import.meta.main, import.meta.path)(async (span) => { +export const buildChnCidr = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const filteredCidr = await span.traceChildAsync('download chnroutes2', getChnCidrPromise); // Can not use SHARED_DESCRIPTION here as different license @@ -38,7 +38,7 @@ export const buildChnCidr = task(import.meta.main, import.meta.path)(async (span new Date(), filteredCidr.map(i => `IP-CIDR,${i}`) ), - pathResolve(import.meta.dir, '../List/ip/china_ip.conf') + pathResolve(__dirname, '../List/ip/china_ip.conf') ), compareAndWriteFile( span, @@ -48,7 +48,7 @@ export const buildChnCidr = task(import.meta.main, import.meta.path)(async (span new Date(), filteredCidr ), - pathResolve(import.meta.dir, '../Clash/ip/china_ip.txt') + pathResolve(__dirname, '../Clash/ip/china_ip.txt') ) ]); }); diff --git a/Build/build-cloudmounter-rules.ts b/Build/build-cloudmounter-rules.ts index 0d953f77..4c22d6a0 100644 --- a/Build/build-cloudmounter-rules.ts +++ b/Build/build-cloudmounter-rules.ts @@ -4,10 +4,10 @@ import { SHARED_DESCRIPTION } from './lib/constants'; import { createRuleset } from './lib/create-file'; import { task } from './trace'; -const outputSurgeDir = path.resolve(import.meta.dir, '../List'); -const outputClashDir = path.resolve(import.meta.dir, '../Clash'); +const outputSurgeDir = path.resolve(__dirname, '../List'); +const outputClashDir = path.resolve(__dirname, '../Clash'); -export const buildCloudMounterRules = task(import.meta.main, import.meta.path)(async (span) => { +export const buildCloudMounterRules = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { // AND,((SRC-IP,192.168.1.110), (DOMAIN, example.com)) const results = DOMAINS.flatMap(domain => { diff --git a/Build/build-common.ts b/Build/build-common.ts index bfacafea..c62446d5 100644 --- a/Build/build-common.ts +++ b/Build/build-common.ts @@ -15,13 +15,13 @@ const MAGIC_COMMAND_SKIP = '# $ custom_build_script'; const MAGIC_COMMAND_TITLE = '# $ meta_title '; const MAGIC_COMMAND_DESCRIPTION = '# $ meta_description '; -const sourceDir = path.resolve(import.meta.dir, '../Source'); -const outputSurgeDir = path.resolve(import.meta.dir, '../List'); -const outputClashDir = path.resolve(import.meta.dir, '../Clash'); +const sourceDir = path.resolve(__dirname, '../Source'); +const outputSurgeDir = path.resolve(__dirname, '../List'); +const outputClashDir = path.resolve(__dirname, '../Clash'); const domainsetSrcFolder = 'domainset' + path.sep; -export const buildCommon = task(import.meta.main, import.meta.path)(async (span) => { +export const buildCommon = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const promises: Array> = []; const paths = await new Fdir() diff --git a/Build/build-deprecate-files.ts b/Build/build-deprecate-files.ts index 2882c861..ec40ce2f 100644 --- a/Build/build-deprecate-files.ts +++ b/Build/build-deprecate-files.ts @@ -8,10 +8,10 @@ const DEPRECATED_FILES = [ ['domainset/reject_phishing', 'This file has been merged with domainset/reject'] ]; -const outputSurgeDir = path.resolve(import.meta.dir, '../List'); -const outputClashDir = path.resolve(import.meta.dir, '../Clash'); +const outputSurgeDir = path.resolve(__dirname, '../List'); +const outputClashDir = path.resolve(__dirname, '../Clash'); -export const buildDeprecateFiles = task(import.meta.main, import.meta.path)((span) => span.traceChildAsync('create deprecated files', async (childSpan) => { +export const buildDeprecateFiles = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)((span) => span.traceChildAsync('create deprecated files', async (childSpan) => { const promises: Array> = []; for (const [filePath, description] of DEPRECATED_FILES) { diff --git a/Build/build-domestic-direct-lan-ruleset-dns-mapping-module.ts b/Build/build-domestic-direct-lan-ruleset-dns-mapping-module.ts index 96e82918..76da3298 100644 --- a/Build/build-domestic-direct-lan-ruleset-dns-mapping-module.ts +++ b/Build/build-domestic-direct-lan-ruleset-dns-mapping-module.ts @@ -12,8 +12,8 @@ import * as yaml from 'yaml'; import { appendArrayInPlace } from './lib/append-array-in-place'; export const getDomesticAndDirectDomainsRulesetPromise = createMemoizedPromise(async () => { - const domestics = await readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/non_ip/domestic.conf')); - const directs = await readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/non_ip/direct.conf')); + const domestics = await readFileIntoProcessedArray(path.resolve(__dirname, '../Source/non_ip/domestic.conf')); + const directs = await readFileIntoProcessedArray(path.resolve(__dirname, '../Source/non_ip/direct.conf')); const lans: string[] = []; Object.entries(DOMESTICS).forEach(([, { domains }]) => { @@ -29,7 +29,7 @@ export const getDomesticAndDirectDomainsRulesetPromise = createMemoizedPromise(a return [domestics, directs, lans] as const; }); -export const buildDomesticRuleset = task(import.meta.main, import.meta.path)(async (span) => { +export const buildDomesticRuleset = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const res = await getDomesticAndDirectDomainsRulesetPromise(); const dataset = Object.entries(DOMESTICS); @@ -48,8 +48,8 @@ export const buildDomesticRuleset = task(import.meta.main, import.meta.path)(asy new Date(), res[0], 'ruleset', - path.resolve(import.meta.dir, '../List/non_ip/domestic.conf'), - path.resolve(import.meta.dir, '../Clash/non_ip/domestic.txt') + path.resolve(__dirname, '../List/non_ip/domestic.conf'), + path.resolve(__dirname, '../Clash/non_ip/domestic.txt') ), createRuleset( span, @@ -62,8 +62,8 @@ export const buildDomesticRuleset = task(import.meta.main, import.meta.path)(asy new Date(), res[1], 'ruleset', - path.resolve(import.meta.dir, '../List/non_ip/direct.conf'), - path.resolve(import.meta.dir, '../Clash/non_ip/direct.txt') + path.resolve(__dirname, '../List/non_ip/direct.conf'), + path.resolve(__dirname, '../Clash/non_ip/direct.txt') ), createRuleset( span, @@ -76,8 +76,8 @@ export const buildDomesticRuleset = task(import.meta.main, import.meta.path)(asy new Date(), res[2], 'ruleset', - path.resolve(import.meta.dir, '../List/non_ip/lan.conf'), - path.resolve(import.meta.dir, '../Clash/non_ip/lan.txt') + path.resolve(__dirname, '../List/non_ip/lan.conf'), + path.resolve(__dirname, '../Clash/non_ip/lan.txt') ), compareAndWriteFile( span, @@ -94,10 +94,10 @@ export const buildDomesticRuleset = task(import.meta.main, import.meta.path)(asy ]) ]) ], - path.resolve(import.meta.dir, '../Modules/sukka_local_dns_mapping.sgmodule') + path.resolve(__dirname, '../Modules/sukka_local_dns_mapping.sgmodule') ), fsp.writeFile( - path.resolve(import.meta.dir, '../Internal/clash_nameserver_policy.yaml'), + path.resolve(__dirname, '../Internal/clash_nameserver_policy.yaml'), yaml.stringify( { dns: { diff --git a/Build/build-internal-reverse-chn-cidr.ts b/Build/build-internal-reverse-chn-cidr.ts index 190c4c68..46d2f96e 100644 --- a/Build/build-internal-reverse-chn-cidr.ts +++ b/Build/build-internal-reverse-chn-cidr.ts @@ -7,7 +7,7 @@ import { NON_CN_CIDR_INCLUDED_IN_CHNROUTE, RESERVED_IPV4_CIDR } from './constant import fsp from 'fs/promises'; -export const buildInternalReverseChnCIDR = task(import.meta.main, import.meta.path)(async () => { +export const buildInternalReverseChnCIDR = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async () => { const cidr = await getChnCidrPromise(); const reversedCidr = merge( @@ -22,7 +22,7 @@ export const buildInternalReverseChnCIDR = task(import.meta.main, import.meta.pa ); return fsp.writeFile( - path.resolve(import.meta.dir, '../Internal/reversed-chn-cidr.txt'), + path.resolve(__dirname, '../Internal/reversed-chn-cidr.txt'), reversedCidr.join('\n') + '\n', { encoding: 'utf-8' } ); diff --git a/Build/build-microsoft-cdn.ts b/Build/build-microsoft-cdn.ts index 50a291b1..48188258 100644 --- a/Build/build-microsoft-cdn.ts +++ b/Build/build-microsoft-cdn.ts @@ -44,7 +44,7 @@ export const getMicrosoftCdnRulesetPromise = createMemoizedPromise(async () => { .concat(WHITELIST); }); -export const buildMicrosoftCdn = task(import.meta.main, import.meta.path)(async (span) => { +export const buildMicrosoftCdn = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const description = [ ...SHARED_DESCRIPTION, '', @@ -63,7 +63,7 @@ export const buildMicrosoftCdn = task(import.meta.main, import.meta.path)(async new Date(), res, 'ruleset', - path.resolve(import.meta.dir, '../List/non_ip/microsoft_cdn.conf'), - path.resolve(import.meta.dir, '../Clash/non_ip/microsoft_cdn.txt') + path.resolve(__dirname, '../List/non_ip/microsoft_cdn.conf'), + path.resolve(__dirname, '../Clash/non_ip/microsoft_cdn.txt') ); }); diff --git a/Build/build-public.ts b/Build/build-public.ts index 10d44f84..23dceec5 100644 --- a/Build/build-public.ts +++ b/Build/build-public.ts @@ -8,8 +8,8 @@ import { sort } from './lib/timsort'; import Trie from 'mnemonist/trie'; -const rootPath = path.resolve(import.meta.dir, '../'); -const publicPath = path.resolve(import.meta.dir, '../public'); +const rootPath = path.resolve(__dirname, '../'); +const publicPath = path.resolve(__dirname, '../public'); const folderAndFilesToBeDeployed = [ `Mock${path.sep}`, @@ -21,7 +21,7 @@ const folderAndFilesToBeDeployed = [ 'LICENSE' ]; -export const buildPublic = task(import.meta.main, import.meta.path)(async (span) => { +export const buildPublic = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { await span .traceChild('copy public files') .traceAsyncFn(async () => { diff --git a/Build/build-reject-domainset.ts b/Build/build-reject-domainset.ts index c230d87b..4b234416 100644 --- a/Build/build-reject-domainset.ts +++ b/Build/build-reject-domainset.ts @@ -20,9 +20,9 @@ import { getPhishingDomains } from './lib/get-phishing-domains'; import { setAddFromArray, setAddFromArrayCurried } from './lib/set-add-from-array'; import { sort } from './lib/timsort'; -const getRejectSukkaConfPromise = readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/domainset/reject_sukka.conf')); +const getRejectSukkaConfPromise = readFileIntoProcessedArray(path.resolve(__dirname, '../Source/domainset/reject_sukka.conf')); -export const buildRejectDomainSet = task(import.meta.main, import.meta.path)(async (span) => { +export const buildRejectDomainSet = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { /** Whitelists */ const filterRuleWhitelistDomainSets = new Set(PREDEFINED_WHITELIST); @@ -98,7 +98,7 @@ export const buildRejectDomainSet = task(import.meta.main, import.meta.path)(asy /** Collect DOMAIN-KEYWORD from non_ip/reject.conf for deduplication */ const domainKeywordsSet = new Set(); - for await (const line of readFileByLine(path.resolve(import.meta.dir, '../Source/non_ip/reject.conf'))) { + for await (const line of readFileByLine(path.resolve(__dirname, '../Source/non_ip/reject.conf'))) { const [type, value] = line.split(','); if (type === 'DOMAIN-KEYWORD') { @@ -191,8 +191,8 @@ export const buildRejectDomainSet = task(import.meta.main, import.meta.path)(asy new Date(), span.traceChildSync('sort reject domainset (base)', () => sortDomains(dudupedDominArray, domainArrayMainDomainMap, domainArraySubdomainMap)), 'domainset', - path.resolve(import.meta.dir, '../List/domainset/reject.conf'), - path.resolve(import.meta.dir, '../Clash/domainset/reject.txt') + path.resolve(__dirname, '../List/domainset/reject.conf'), + path.resolve(__dirname, '../Clash/domainset/reject.txt') ), createRuleset( span, @@ -211,13 +211,13 @@ export const buildRejectDomainSet = task(import.meta.main, import.meta.path)(asy new Date(), span.traceChildSync('sort reject domainset (extra)', () => sortDomains(dudupedDominArrayExtra, domainArrayMainDomainMap, domainArraySubdomainMap)), 'domainset', - path.resolve(import.meta.dir, '../List/domainset/reject_extra.conf'), - path.resolve(import.meta.dir, '../Clash/domainset/reject_extra.txt') + path.resolve(__dirname, '../List/domainset/reject_extra.conf'), + path.resolve(__dirname, '../Clash/domainset/reject_extra.txt') ), compareAndWriteFile( span, rejectDomainsStats.map(([domain, count]) => `${domain}${' '.repeat(100 - domain.length)}${count}`), - path.resolve(import.meta.dir, '../Internal/reject-stats.txt') + path.resolve(__dirname, '../Internal/reject-stats.txt') ) ]); }); diff --git a/Build/build-reject-ip-list.ts b/Build/build-reject-ip-list.ts index 972c2678..1a4ceac6 100644 --- a/Build/build-reject-ip-list.ts +++ b/Build/build-reject-ip-list.ts @@ -65,9 +65,9 @@ const getBotNetFilterIPsPromise = fsFetchCache.apply( } ); -const localRejectIPSourcesPromise = readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/ip/reject.conf')); +const localRejectIPSourcesPromise = readFileIntoProcessedArray(path.resolve(__dirname, '../Source/ip/reject.conf')); -export const buildRejectIPList = task(import.meta.main, import.meta.path)(async (span) => { +export const buildRejectIPList = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const result = await localRejectIPSourcesPromise; const bogusNxDomainIPs = await span.traceChildPromise('get bogus nxdomain ips', getBogusNxDomainIPsPromise); @@ -93,7 +93,7 @@ export const buildRejectIPList = task(import.meta.main, import.meta.path)(async new Date(), result, 'ruleset', - path.resolve(import.meta.dir, '../List/ip/reject.conf'), - path.resolve(import.meta.dir, '../Clash/ip/reject.txt') + path.resolve(__dirname, '../List/ip/reject.conf'), + path.resolve(__dirname, '../Clash/ip/reject.txt') ); }); diff --git a/Build/build-sgmodule-always-realip.ts b/Build/build-sgmodule-always-realip.ts index 333e7ef3..f12e64ea 100644 --- a/Build/build-sgmodule-always-realip.ts +++ b/Build/build-sgmodule-always-realip.ts @@ -43,7 +43,7 @@ const HOSTNAMES = [ '*.battlenet.com' ]; -export const buildAlwaysRealIPModule = task(import.meta.main, import.meta.path)(async (span) => { +export const buildAlwaysRealIPModule = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { // Intranet, Router Setup, and mant more const dataset = [Object.entries(DIRECTS), Object.entries(LANS)]; const surge = dataset.flatMap(data => data.flatMap(([, { domains }]) => domains.flatMap((domain) => [`*.${domain}`, domain]))); @@ -59,10 +59,10 @@ export const buildAlwaysRealIPModule = task(import.meta.main, import.meta.path)( '[General]', `always-real-ip = %APPEND% ${HOSTNAMES.concat(surge).join(', ')}` ], - path.resolve(import.meta.dir, '../Modules/sukka_common_always_realip.sgmodule') + path.resolve(__dirname, '../Modules/sukka_common_always_realip.sgmodule') ), fsp.writeFile( - path.resolve(import.meta.dir, '../Internal/clash_fake_ip_filter.yaml'), + path.resolve(__dirname, '../Internal/clash_fake_ip_filter.yaml'), yaml.stringify( { dns: { diff --git a/Build/build-sgmodule-redirect.ts b/Build/build-sgmodule-redirect.ts index cd98c651..592bf4c8 100644 --- a/Build/build-sgmodule-redirect.ts +++ b/Build/build-sgmodule-redirect.ts @@ -120,7 +120,7 @@ const REDIRECT_FAKEWEBSITES = [ ['zbrushcn.com', 'https://www.maxon.net/en/zbrush'] ] as const; -export const buildRedirectModule = task(import.meta.main, import.meta.path)(async (span) => { +export const buildRedirectModule = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const domains = Array.from(new Set([ ...REDIRECT_MIRROR.map(([from]) => getHostname(from, { detectIp: false })), ...REDIRECT_FAKEWEBSITES.flatMap(([from]) => [from, `www.${from}`]) @@ -139,6 +139,6 @@ export const buildRedirectModule = task(import.meta.main, import.meta.path)(asyn ...REDIRECT_MIRROR.map(([from, to]) => `^https?://${escapeRegExp(from)}(.*) ${to}$1`), ...REDIRECT_FAKEWEBSITES.map(([from, to]) => `^https?://(www.)?${escapeRegExp(from)} ${to}`) ], - path.resolve(import.meta.dir, '../Modules/sukka_url_redirect.sgmodule') + path.resolve(__dirname, '../Modules/sukka_url_redirect.sgmodule') ); }); diff --git a/Build/build-speedtest-domainset.ts b/Build/build-speedtest-domainset.ts index 5079f8f1..ae6828fb 100644 --- a/Build/build-speedtest-domainset.ts +++ b/Build/build-speedtest-domainset.ts @@ -82,7 +82,7 @@ const querySpeedtestApi = async (keyword: string): Promise> } }; -export const buildSpeedtestDomainSet = task(import.meta.main, import.meta.path)(async (span) => { +export const buildSpeedtestDomainSet = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const domainTrie = createTrie( [ // speedtest.net @@ -183,7 +183,7 @@ export const buildSpeedtestDomainSet = task(import.meta.main, import.meta.path)( async () => { try { ( - await readFileIntoProcessedArray(path.resolve(import.meta.dir, '../List/domainset/speedtest.conf')) + await readFileIntoProcessedArray(path.resolve(__dirname, '../List/domainset/speedtest.conf')) ) .forEach(line => { const hn = getHostname(line, { detectIp: false, validateHostname: true }); if (hn) { @@ -267,7 +267,7 @@ export const buildSpeedtestDomainSet = task(import.meta.main, import.meta.path)( new Date(), deduped, 'domainset', - path.resolve(import.meta.dir, '../List/domainset/speedtest.conf'), - path.resolve(import.meta.dir, '../Clash/domainset/speedtest.txt') + path.resolve(__dirname, '../List/domainset/speedtest.conf'), + path.resolve(__dirname, '../Clash/domainset/speedtest.txt') ); }); diff --git a/Build/build-sspanel-appprofile.ts b/Build/build-sspanel-appprofile.ts index 97ce6626..2cfda001 100644 --- a/Build/build-sspanel-appprofile.ts +++ b/Build/build-sspanel-appprofile.ts @@ -28,7 +28,7 @@ const removeNoResolved = (line: string) => line.replace(',no-resolve', ''); /** * This only generates a simplified version, for under-used users only. */ -export const buildSSPanelUIMAppProfile = task(import.meta.main, import.meta.path)(async (span) => { +export const buildSSPanelUIMAppProfile = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const [ [domesticDomains, directDomains, lanDomains], appleCdnDomains, @@ -55,18 +55,18 @@ export const buildSSPanelUIMAppProfile = task(import.meta.main, import.meta.path ), getAppleCdnDomainsPromise().then(domains => domains.map(domain => `DOMAIN-SUFFIX,${domain}`)), getMicrosoftCdnRulesetPromise().then(surgeRulesetToClashClassicalTextRuleset), - readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/non_ip/apple_cn.conf')), - readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/non_ip/neteasemusic.conf')).then(surgeRulesetToClashClassicalTextRuleset), + readFileIntoProcessedArray(path.resolve(__dirname, '../Source/non_ip/apple_cn.conf')), + readFileIntoProcessedArray(path.resolve(__dirname, '../Source/non_ip/neteasemusic.conf')).then(surgeRulesetToClashClassicalTextRuleset), // microsoft & apple - domains - readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/non_ip/microsoft.conf')), - readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/non_ip/apple_services.conf')).then(surgeRulesetToClashClassicalTextRuleset), + readFileIntoProcessedArray(path.resolve(__dirname, '../Source/non_ip/microsoft.conf')), + readFileIntoProcessedArray(path.resolve(__dirname, '../Source/non_ip/apple_services.conf')).then(surgeRulesetToClashClassicalTextRuleset), // stream - domains surgeRulesetToClashClassicalTextRuleset(AllStreamServices.flatMap((i) => i.rules)), // steam - domains - readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/domainset/steam.conf')).then(surgeDomainsetToClashRuleset), + readFileIntoProcessedArray(path.resolve(__dirname, '../Source/domainset/steam.conf')).then(surgeDomainsetToClashRuleset), // global - domains - readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/non_ip/global.conf')).then(surgeRulesetToClashClassicalTextRuleset), - readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/non_ip/telegram.conf')).then(surgeRulesetToClashClassicalTextRuleset), + readFileIntoProcessedArray(path.resolve(__dirname, '../Source/non_ip/global.conf')).then(surgeRulesetToClashClassicalTextRuleset), + readFileIntoProcessedArray(path.resolve(__dirname, '../Source/non_ip/telegram.conf')).then(surgeRulesetToClashClassicalTextRuleset), // domestic - ip cidr getChnCidrPromise().then(cidrs => cidrs.map(cidr => `IP-CIDR,${cidr}`)), AllStreamServices.flatMap((i) => ( @@ -80,7 +80,7 @@ export const buildSSPanelUIMAppProfile = task(import.meta.main, import.meta.path // global - ip cidr getTelegramCIDRPromise(), // lan - ip cidr - readFileIntoProcessedArray(path.resolve(import.meta.dir, '../Source/ip/lan.conf')) + readFileIntoProcessedArray(path.resolve(__dirname, '../Source/ip/lan.conf')) ] as const); const telegramCidrs = rawTelegramCidrs.map(removeNoResolved); @@ -118,7 +118,7 @@ export const buildSSPanelUIMAppProfile = task(import.meta.main, import.meta.path await compareAndWriteFile( span, output, - path.resolve(import.meta.dir, '../Internal/appprofile.php') + path.resolve(__dirname, '../Internal/appprofile.php') ); }); diff --git a/Build/build-stream-service.ts b/Build/build-stream-service.ts index b4eff845..f0682458 100644 --- a/Build/build-stream-service.ts +++ b/Build/build-stream-service.ts @@ -22,8 +22,8 @@ export const createRulesetForStreamService = (span: Span, fileId: string, title: new Date(), streamServices.flatMap((i) => i.rules), 'ruleset', - path.resolve(import.meta.dir, `../List/non_ip/${fileId}.conf`), - path.resolve(import.meta.dir, `../Clash/non_ip/${fileId}.txt`) + path.resolve(__dirname, `../List/non_ip/${fileId}.conf`), + path.resolve(__dirname, `../Clash/non_ip/${fileId}.txt`) ), // IP createRuleset( @@ -44,13 +44,13 @@ export const createRulesetForStreamService = (span: Span, fileId: string, title: : [] )), 'ruleset', - path.resolve(import.meta.dir, `../List/ip/${fileId}.conf`), - path.resolve(import.meta.dir, `../Clash/ip/${fileId}.txt`) + path.resolve(__dirname, `../List/ip/${fileId}.conf`), + path.resolve(__dirname, `../Clash/ip/${fileId}.txt`) ) ])); }; -export const buildStreamService = task(import.meta.main, import.meta.path)(async (span) => { +export const buildStreamService = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { return Promise.all([ createRulesetForStreamService(span, 'stream', 'All', ALL), createRulesetForStreamService(span, 'stream_us', 'North America', NORTH_AMERICA), diff --git a/Build/build-telegram-cidr.ts b/Build/build-telegram-cidr.ts index 1ac9a5ec..3eaa2576 100644 --- a/Build/build-telegram-cidr.ts +++ b/Build/build-telegram-cidr.ts @@ -32,7 +32,7 @@ export const getTelegramCIDRPromise = createMemoizedPromise(async () => { return { date, results }; }); -export const buildTelegramCIDR = task(import.meta.main, import.meta.path)(async (span) => { +export const buildTelegramCIDR = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const { date, results } = await span.traceChildAsync('get telegram cidr', getTelegramCIDRPromise); if (results.length === 0) { @@ -52,7 +52,7 @@ export const buildTelegramCIDR = task(import.meta.main, import.meta.path)(async date, results, 'ruleset', - path.resolve(import.meta.dir, '../List/ip/telegram.conf'), - path.resolve(import.meta.dir, '../Clash/ip/telegram.txt') + path.resolve(__dirname, '../List/ip/telegram.conf'), + path.resolve(__dirname, '../Clash/ip/telegram.txt') ); }); diff --git a/Build/download-mock-assets.ts b/Build/download-mock-assets.ts index 6a729d1f..06bc79f4 100644 --- a/Build/download-mock-assets.ts +++ b/Build/download-mock-assets.ts @@ -13,9 +13,9 @@ const ASSETS_LIST = { 'amazon-adsystem-com_amazon-apstag.js': 'https://raw.githubusercontent.com/AdguardTeam/Scriptlets/master/dist/redirect-files/amazon-apstag.js' } as const; -const mockDir = path.resolve(import.meta.dir, '../Mock'); +const mockDir = path.resolve(__dirname, '../Mock'); -export const downloadMockAssets = task(import.meta.main, import.meta.path)((span) => Promise.all(Object.entries(ASSETS_LIST).map( +export const downloadMockAssets = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)((span) => Promise.all(Object.entries(ASSETS_LIST).map( ([filename, url]) => span .traceChild(url) .traceAsyncFn(() => fetchWithRetry(url).then(res => { diff --git a/Build/download-previous-build.ts b/Build/download-previous-build.ts index dd946fb7..31467e38 100644 --- a/Build/download-previous-build.ts +++ b/Build/download-previous-build.ts @@ -13,7 +13,7 @@ import { Readable } from 'stream'; const IS_READING_BUILD_OUTPUT = 1 << 2; const ALL_FILES_EXISTS = 1 << 3; -export const downloadPreviousBuild = task(import.meta.main, import.meta.path)(async (span) => { +export const downloadPreviousBuild = task(typeof Bun !== 'undefined' ? Bun.main === __filename : require.main === module, __filename)(async (span) => { const buildOutputList: string[] = []; let flag = 1 | ALL_FILES_EXISTS; @@ -21,7 +21,7 @@ export const downloadPreviousBuild = task(import.meta.main, import.meta.path)(as await span .traceChild('read .gitignore') .traceAsyncFn(async () => { - for await (const line of readFileByLine(path.resolve(import.meta.dir, '../.gitignore'))) { + for await (const line of readFileByLine(path.resolve(__dirname, '../.gitignore'))) { if (line === '# $ build output') { flag = flag | IS_READING_BUILD_OUTPUT; continue; @@ -33,7 +33,7 @@ export const downloadPreviousBuild = task(import.meta.main, import.meta.path)(as buildOutputList.push(line); if (!isCI) { - if (!existsSync(path.join(import.meta.dir, '..', line))) { + if (!existsSync(path.join(__dirname, '..', line))) { flag = flag & ~ALL_FILES_EXISTS; } } @@ -83,7 +83,7 @@ export const downloadPreviousBuild = task(import.meta.main, import.meta.path)(as } const relativeEntryPath = entry.header.name.replace(pathPrefix, ''); - const targetPath = path.join(import.meta.dir, '..', relativeEntryPath); + const targetPath = path.join(__dirname, '..', relativeEntryPath); await mkdir(path.dirname(targetPath), { recursive: true }); await pipeline(entry, createWriteStream(targetPath)); diff --git a/Build/lib/cache-filesystem.ts b/Build/lib/cache-filesystem.ts index 40b6ccb9..db74cc9a 100644 --- a/Build/lib/cache-filesystem.ts +++ b/Build/lib/cache-filesystem.ts @@ -1,11 +1,11 @@ -// eslint-disable-next-line import-x/no-unresolved -- bun built-in module -import { Database } from 'bun:sqlite'; +import createDb from 'better-sqlite3'; +import type { Database } from 'better-sqlite3'; import os from 'os'; import path from 'path'; import { mkdirSync } from 'fs'; import picocolors from 'picocolors'; import { fastStringArrayJoin } from './misc'; -import { peek } from 'bun'; +import { peek } from './bun'; import { performance } from 'perf_hooks'; const identity = (x: any) => x; @@ -92,12 +92,12 @@ export class Cache { this.type = 'string'; } - const db = new Database(path.join(this.cachePath, 'cache.db')); + const db = createDb(path.join(this.cachePath, 'cache.db')); - db.exec('PRAGMA journal_mode = WAL;'); - db.exec('PRAGMA synchronous = normal;'); - db.exec('PRAGMA temp_store = memory;'); - db.exec('PRAGMA optimize;'); + db.pragma('journal_mode = WAL'); + db.pragma('synchronous = normal'); + db.pragma('temp_store = memory'); + db.pragma('optimize'); db.prepare(`CREATE TABLE IF NOT EXISTS ${this.tableName} (key TEXT PRIMARY KEY, value ${this.type === 'string' ? 'TEXT' : 'BLOB'}, ttl REAL NOT NULL);`).run(); db.prepare(`CREATE INDEX IF NOT EXISTS cache_ttl ON ${this.tableName} (ttl);`).run(); @@ -130,15 +130,20 @@ export class Cache { `INSERT INTO ${this.tableName} (key, value, ttl) VALUES ($key, $value, $valid) ON CONFLICT(key) DO UPDATE SET value = $value, ttl = $valid` ); + const valid = Date.now() + ttl; + insert.run({ $key: key, + key, $value: value, - $valid: Date.now() + ttl + value, + $valid: valid, + valid }); } get(key: string, defaultValue?: S): S | undefined { - const rv = this.db.prepare<{ value: S }, string>( + const rv = this.db.prepare( `SELECT value FROM ${this.tableName} WHERE key = ? LIMIT 1` ).get(key); @@ -148,7 +153,7 @@ export class Cache { has(key: string): CacheStatus { const now = Date.now(); - const rv = this.db.prepare<{ ttl: number }, string>(`SELECT ttl FROM ${this.tableName} WHERE key = ?`).get(key); + const rv = this.db.prepare(`SELECT ttl FROM ${this.tableName} WHERE key = ?`).get(key); return !rv ? CacheStatus.Miss : (rv.ttl > now ? CacheStatus.Hit : CacheStatus.Stale); } @@ -206,18 +211,14 @@ export class Cache { } } -export const fsFetchCache = new Cache({ cachePath: path.resolve(import.meta.dir, '../../.cache') }); +export const fsFetchCache = new Cache({ cachePath: path.resolve(__dirname, '../../.cache') }); // process.on('exit', () => { // fsFetchCache.destroy(); // }); -// export const fsCache = traceSync('initializing filesystem cache', () => new Cache({ cachePath: path.resolve(import.meta.dir, '../../.cache'), type: 'buffer' })); +// export const fsCache = traceSync('initializing filesystem cache', () => new Cache({ cachePath: path.resolve(__dirname, '../../.cache'), type: 'buffer' })); const separator = '\u0000'; -// const textEncoder = new TextEncoder(); -// const textDecoder = new TextDecoder(); -// export const serializeString = (str: string) => textEncoder.encode(str); -// export const deserializeString = (str: string) => textDecoder.decode(new Uint8Array(str.split(separator).map(Number))); export const serializeSet = (set: Set) => fastStringArrayJoin(Array.from(set), separator); export const deserializeSet = (str: string) => new Set(str.split(separator)); export const serializeArray = (arr: string[]) => fastStringArrayJoin(arr, separator); diff --git a/Build/lib/create-file.ts b/Build/lib/create-file.ts index d9a76b07..662e8910 100644 --- a/Build/lib/create-file.ts +++ b/Build/lib/create-file.ts @@ -11,8 +11,6 @@ import { readFileByLine } from './fetch-text-by-line'; export async function compareAndWriteFile(span: Span, linesA: string[], filePath: string) { let isEqual = true; - const fd = await fsp.open(filePath); - const linesALen = linesA.length; if (!fs.existsSync(filePath)) { @@ -22,12 +20,10 @@ export async function compareAndWriteFile(span: Span, linesA: string[], filePath console.log(`Nothing to write to ${filePath}...`); isEqual = false; } else { - /* The `isEqual` variable is used to determine whether the content of a file is equal to the - provided lines or not. It is initially set to `true`, and then it is updated based on different - conditions: */ + const fd = await fsp.open(filePath); + isEqual = await span.traceChildAsync(`comparing ${filePath}`, async () => { let index = 0; - for await (const lineB of readFileByLine(fd)) { const lineA = linesA[index] as string | undefined; index++; @@ -63,6 +59,8 @@ export async function compareAndWriteFile(span: Span, linesA: string[], filePath return true; }); + + await fd.close(); } if (isEqual) { @@ -83,8 +81,6 @@ export async function compareAndWriteFile(span: Span, linesA: string[], filePath // return writer.end(); }); - - await fd.close(); } export const withBannerArray = (title: string, description: string[] | readonly string[], date: Date, content: string[]) => { diff --git a/Build/lib/fetch-text-by-line.bench.ts b/Build/lib/fetch-text-by-line.bench.ts index 6093d7e3..8159a4a9 100644 --- a/Build/lib/fetch-text-by-line.bench.ts +++ b/Build/lib/fetch-text-by-line.bench.ts @@ -4,7 +4,7 @@ import { readFileByLine } from './fetch-text-by-line'; import path from 'path'; import fsp from 'fs/promises'; -const file = path.resolve(import.meta.dir, '../../Source/domainset/cdn.conf'); +const file = path.resolve(__dirname, '../../Source/domainset/cdn.conf'); group('read file by line', () => { bench('readline', () => processLineFromReadline(readFileByLine(file))); diff --git a/Build/lib/fetch-text-by-line.ts b/Build/lib/fetch-text-by-line.ts index 3e89f448..c69b6064 100644 --- a/Build/lib/fetch-text-by-line.ts +++ b/Build/lib/fetch-text-by-line.ts @@ -1,9 +1,12 @@ +import fs from 'fs'; +import { Readable } from 'stream'; import type { BunFile } from 'bun'; import { fetchWithRetry, defaultRequestInit } from './fetch-retry'; import type { FileHandle } from 'fs/promises'; import { TextLineStream } from './text-line-transform-stream'; import { PolyfillTextDecoderStream } from './text-decoder-stream'; +import { TextDecoderStream as NodeTextDecoderStream } from 'stream/web'; import { processLine } from './process-line'; const enableTextLineStream = !!process.env.ENABLE_TEXT_LINE_STREAM; @@ -36,19 +39,32 @@ async function *createTextLineAsyncIterableFromStreamSource(stream: ReadableStre } } -const getReadableStream = (file: string | BunFile | FileHandle): ReadableStream => { - if (typeof file === 'string') { - return Bun.file(file).stream(); +const getReadableStream = typeof Bun !== 'undefined' + ? (file: string | BunFile | FileHandle): ReadableStream => { + if (typeof file === 'string') { + return Bun.file(file).stream(); + } + if ('writer' in file) { + return file.stream(); + } + return file.readableWebStream(); } - if ('writer' in file) { - return file.stream(); - } - return file.readableWebStream(); -}; + : (file: string | BunFile | FileHandle): ReadableStream => { + if (typeof file === 'string') { + return Readable.toWeb(fs.createReadStream(file /* { encoding: 'utf-8' } */)); + } + if ('writer' in file) { + return file.stream(); + } + return file.readableWebStream(); + }; + +// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- On Bun, NodeTextDecoderStream is undefined +const TextDecoderStream = NodeTextDecoderStream ?? PolyfillTextDecoderStream; // TODO: use FileHandle.readLine() export const readFileByLine: ((file: string | BunFile | FileHandle) => AsyncIterable) = enableTextLineStream - ? (file: string | BunFile | FileHandle) => getReadableStream(file).pipeThrough(new PolyfillTextDecoderStream()).pipeThrough(new TextLineStream()) + ? (file: string | BunFile | FileHandle) => getReadableStream(file).pipeThrough(new TextDecoderStream()).pipeThrough(new TextLineStream()) : (file: string | BunFile | FileHandle) => createTextLineAsyncIterableFromStreamSource(getReadableStream(file)); const ensureResponseBody = (resp: Response) => { @@ -62,7 +78,7 @@ const ensureResponseBody = (resp: Response) => { }; export const createReadlineInterfaceFromResponse: ((resp: Response) => AsyncIterable) = enableTextLineStream - ? (resp) => ensureResponseBody(resp).pipeThrough(new PolyfillTextDecoderStream()).pipeThrough(new TextLineStream()) + ? (resp) => ensureResponseBody(resp).pipeThrough(new TextDecoderStream()).pipeThrough(new TextLineStream()) : (resp) => createTextLineAsyncIterableFromStreamSource(ensureResponseBody(resp)); export function fetchRemoteTextByLine(url: string | URL) { diff --git a/Build/lib/get-gorhill-publicsuffix.ts b/Build/lib/get-gorhill-publicsuffix.ts index 78766707..503f30af 100644 --- a/Build/lib/get-gorhill-publicsuffix.ts +++ b/Build/lib/get-gorhill-publicsuffix.ts @@ -1,10 +1,16 @@ -import { toASCII } from 'punycode'; +import fsp from 'fs/promises'; +import { toASCII } from 'punycode/punycode'; import { createMemoizedPromise } from './memo-promise'; import { getPublicSuffixListTextPromise } from './download-publicsuffixlist'; +import { fileURLToPath } from 'url'; const customFetch = typeof Bun !== 'undefined' ? (url: string | URL) => Promise.resolve(Bun.file(url)) - : (url: string | URL) => fetch(url).then(resp => resp.blob() as Promise); + : async (url: string | URL) => { + const filePath = fileURLToPath(url); + const file = await fsp.readFile(filePath); + return new Blob([file]) as any; + }; export const getGorhillPublicSuffixPromise = createMemoizedPromise(async () => { const [publicSuffixListDat, { default: gorhill }] = await Promise.all([ diff --git a/Build/trace/index.ts b/Build/trace/index.ts index dac69c49..bc223993 100644 --- a/Build/trace/index.ts +++ b/Build/trace/index.ts @@ -1,4 +1,4 @@ -import path from 'path'; +import { basename, extname } from 'path'; import picocolors from 'picocolors'; const SPAN_STATUS_START = 0; @@ -95,7 +95,7 @@ export const createSpan = (name: string, parentTraceResult?: TraceResult): Span }; export const task = (importMetaMain: boolean, importMetaPath: string) => (fn: (span: Span) => Promise, customName?: string) => { - const taskName = customName ?? path.basename(importMetaPath, path.extname(importMetaPath)); + const taskName = customName ?? basename(importMetaPath, extname(importMetaPath)); const dummySpan = createSpan(taskName); diff --git a/Build/trim-source.ts b/Build/trim-source.ts index 58d48a93..30840c2a 100644 --- a/Build/trim-source.ts +++ b/Build/trim-source.ts @@ -3,7 +3,7 @@ import fsp from 'fs/promises'; import { fdir as Fdir } from 'fdir'; import { readFileByLine } from './lib/fetch-text-by-line'; -const sourceDir = path.resolve(import.meta.dir, '../Source'); +const sourceDir = path.resolve(__dirname, '../Source'); (async () => { const promises: Array> = []; diff --git a/Build/validate-domestic.ts b/Build/validate-domestic.ts index 7ce7bbc4..52992496 100644 --- a/Build/validate-domestic.ts +++ b/Build/validate-domestic.ts @@ -62,7 +62,7 @@ export const parseDomesticList = async () => { }; // await Promise.all([ - await runAgainstRuleset(path.resolve(import.meta.dir, '../List/non_ip/domestic.conf')); + await runAgainstRuleset(path.resolve(__dirname, '../List/non_ip/domestic.conf')); // ]); console.log(notIncludedDomestic.size, notIncludedDomestic); diff --git a/Build/validate-gfwlist.ts b/Build/validate-gfwlist.ts index aa84fba5..7ee4e8d3 100644 --- a/Build/validate-gfwlist.ts +++ b/Build/validate-gfwlist.ts @@ -105,9 +105,9 @@ export const parseGfwList = async () => { }; await Promise.all([ - runAgainstRuleset(path.resolve(import.meta.dir, '../Source/non_ip/global.conf')), - runAgainstRuleset(path.resolve(import.meta.dir, '../Source/non_ip/telegram.conf')), - runAgainstRuleset(path.resolve(import.meta.dir, '../List/non_ip/stream.conf')) + runAgainstRuleset(path.resolve(__dirname, '../Source/non_ip/global.conf')), + runAgainstRuleset(path.resolve(__dirname, '../Source/non_ip/telegram.conf')), + runAgainstRuleset(path.resolve(__dirname, '../List/non_ip/stream.conf')) ]); console.log(notIncludedTop500Gfwed); diff --git a/bun.lockb b/bun.lockb index c6173197..633bba7d 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 8cdc8a2f..e8bd9661 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ }, "scripts": { "build": "bun ./Build/index.ts", - "build-node": "ENABLE_TEXT_LINE_STREAM=true node -r @swc-node/register ./Build/index.ts", + "build-node": "SWCRC=true ENABLE_TEXT_LINE_STREAM=true node -r @swc-node/register ./Build/index.ts", "build-stream": "ENABLE_TEXT_LINE_STREAM=true bun ./Build/index.ts", "lint": "eslint --format=sukka ." }, @@ -20,6 +20,7 @@ "@gorhill/publicsuffixlist": "3.0.1", "async-retry": "^1.3.3", "async-sema": "^3.1.1", + "better-sqlite3": "^11.1.2", "ci-info": "^4.0.0", "csv-parse": "^5.5.6", "fast-cidr-tools": "^0.2.5", @@ -38,8 +39,11 @@ "devDependencies": { "@eslint-sukka/node": "^6.1.6", "@swc-node/register": "^1.10.9", + "@swc/core": "^1.7.0", "@types/async-retry": "^1.4.8", + "@types/better-sqlite3": "^7.6.11", "@types/bun": "^1.1.6", + "@types/punycode": "^2.1.4", "@types/tar-stream": "^3.1.3", "bun-types": "^1.1.20", "eslint": "^9.7.0",