From 071b8120a6a2bbb32b17b289ebf6bc52dae6d392 Mon Sep 17 00:00:00 2001 From: SukkaW Date: Wed, 15 Nov 2023 15:20:37 +0800 Subject: [PATCH] Chore: more refactor to the bun --- Build/build-anti-bogus-domain.js | 6 +- Build/build-apple-cdn.js | 2 +- .../{build-cdn-conf.js => build-cdn-conf.ts} | 45 +++++++------ Build/build-chn-cidr.js | 2 +- Build/build-common.js | 2 +- Build/build-domestic-ruleset.js | 2 +- Build/build-internal-cdn-rules.js | 2 +- Build/build-internal-chn-domains.js | 2 +- Build/build-internal-reverse-chn-cidr.js | 8 +-- Build/build-phishing-domainset.js | 2 +- Build/build-public.js | 5 +- Build/build-redirect-module.js | 2 +- Build/build-reject-domainset.js | 2 +- Build/build-speedtest-domainset.js | 3 +- Build/build-stream-service.js | 2 +- Build/build-telegram-cidr.js | 3 +- Build/download-previous-build.js | 25 +++---- Build/lib/create-file.js | 6 +- Build/lib/domain-deduper.js | 32 --------- Build/lib/domain-deduper.ts | 25 +++++++ ...y-line.js => fetch-remote-text-by-line.ts} | 35 ++++------ Build/lib/fetch-retry.js | 10 +-- Build/lib/get-gorhill-publicsuffix.js | 12 ++-- .../{parse-dnsmasq.js => parse-dnsmasq.ts} | 16 ++--- Build/lib/parse-filter.js | 10 +++ Build/lib/process-line.js | 48 -------------- Build/lib/process-line.ts | 35 ++++++++++ ...t-data-source.js => reject-data-source.ts} | 20 ++---- Build/lib/{trie.js => trie.ts} | 62 ++++++++---------- Build/validate-domainset.js | 2 +- Source/domainset/cdn.conf | 2 +- Source/non_ip/cdn.conf | 2 + bun.lockb | Bin 101978 -> 101698 bytes eslint.config.js | 6 +- package.json | 6 +- tsconfig.json | 6 +- 36 files changed, 200 insertions(+), 250 deletions(-) rename Build/{build-cdn-conf.js => build-cdn-conf.ts} (58%) delete mode 100644 Build/lib/domain-deduper.js create mode 100644 Build/lib/domain-deduper.ts rename Build/lib/{fetch-remote-text-by-line.js => fetch-remote-text-by-line.ts} (62%) rename Build/lib/{parse-dnsmasq.js => parse-dnsmasq.ts} (57%) delete mode 100644 Build/lib/process-line.js create mode 100644 Build/lib/process-line.ts rename Build/lib/{reject-data-source.js => reject-data-source.ts} (93%) rename Build/lib/{trie.js => trie.ts} (89%) diff --git a/Build/build-anti-bogus-domain.js b/Build/build-anti-bogus-domain.js index 0d98e26d..89be4388 100644 --- a/Build/build-anti-bogus-domain.js +++ b/Build/build-anti-bogus-domain.js @@ -23,13 +23,11 @@ const getBogusNxDomainIPs = async () => { }; const buildAntiBogusDomain = task(__filename, async () => { - const filePath = path.resolve(__dirname, '../Source/ip/reject.conf'); - const bogusIpPromise = getBogusNxDomainIPs(); /** @type {string[]} */ const result = []; - for await (const line of readFileByLine(filePath)) { + for await (const line of readFileByLine(path.resolve(__dirname, '../Source/ip/reject.conf'))) { if (line === '# --- [Anti Bogus Domain Replace Me] ---') { (await bogusIpPromise).forEach(rule => result.push(rule)); continue; @@ -65,6 +63,6 @@ const buildAntiBogusDomain = task(__filename, async () => { module.exports.buildAntiBogusDomain = buildAntiBogusDomain; -if (require.main === module) { +if (import.meta.main) { buildAntiBogusDomain(); } diff --git a/Build/build-apple-cdn.js b/Build/build-apple-cdn.js index f6449462..5ca897e8 100644 --- a/Build/build-apple-cdn.js +++ b/Build/build-apple-cdn.js @@ -44,6 +44,6 @@ const buildAppleCdn = task(__filename, async () => { module.exports.buildAppleCdn = buildAppleCdn; -if (require.main === module) { +if (import.meta.main) { buildAppleCdn(); } diff --git a/Build/build-cdn-conf.js b/Build/build-cdn-conf.ts similarity index 58% rename from Build/build-cdn-conf.js rename to Build/build-cdn-conf.ts index 3c174445..8d9e531b 100644 --- a/Build/build-cdn-conf.js +++ b/Build/build-cdn-conf.ts @@ -1,18 +1,18 @@ -// @ts-check -const path = require('path'); -const { createRuleset } = require('./lib/create-file'); -const { fetchRemoteTextAndCreateReadlineInterface, readFileByLine } = require('./lib/fetch-remote-text-by-line'); -const createTrie = require('./lib/trie'); -const { task } = require('./lib/trace-runner'); -const fs = require('fs'); -const { processLine } = require('./lib/process-line'); +import path from 'path'; +import { createRuleset } from './lib/create-file'; +import { fetchRemoteTextAndCreateReadlineInterface, readFileByLine } from './lib/fetch-remote-text-by-line'; +import { createTrie } from './lib/trie'; +import { task } from './lib/trace-runner'; +import { processLine } from './lib/process-line'; -const publicSuffixPath = path.resolve(__dirname, '../node_modules/.cache/public_suffix_list_dat.txt'); +const publicSuffixPath: string = path.resolve(__dirname, '../node_modules/.cache/public_suffix_list_dat.txt'); -const getS3OSSDomains = async () => { +const getS3OSSDomains = async (): Promise> => { const trie = createTrie(); - if (fs.existsSync(publicSuffixPath)) { + const publicSuffixFile = Bun.file(publicSuffixPath); + + if (await publicSuffixFile.exists()) { for await (const line of readFileByLine(publicSuffixPath)) { trie.add(line); } @@ -25,11 +25,10 @@ const getS3OSSDomains = async () => { /** * Extract OSS domain from publicsuffix list - * @type {Set} */ - const S3OSSDomains = new Set(); + const S3OSSDomains = new Set(); - trie.find('.amazonaws.com').forEach(line => { + trie.find('.amazonaws.com').forEach((line: string) => { if ( (line.startsWith('s3-') || line.startsWith('s3.')) && !line.includes('cn-') @@ -37,7 +36,7 @@ const getS3OSSDomains = async () => { S3OSSDomains.add(line); } }); - trie.find('.scw.cloud').forEach(line => { + trie.find('.scw.cloud').forEach((line: string) => { if ( (line.startsWith('s3-') || line.startsWith('s3.')) && !line.includes('cn-') @@ -45,7 +44,7 @@ const getS3OSSDomains = async () => { S3OSSDomains.add(line); } }); - trie.find('sakurastorage.jp').forEach(line => { + trie.find('sakurastorage.jp').forEach((line: string) => { if ( (line.startsWith('s3-') || line.startsWith('s3.')) ) { @@ -56,15 +55,15 @@ const getS3OSSDomains = async () => { return S3OSSDomains; }; -const buildCdnConf = task(__filename, async () => { +const buildCdnConf = task(__filename, async () => { /** @type {string[]} */ - const cdnDomainsList = []; + const cdnDomainsList: string[] = []; - const getS3OSSDomainsPromise = getS3OSSDomains(); + const getS3OSSDomainsPromise: Promise> = getS3OSSDomains(); for await (const l of readFileByLine(path.resolve(__dirname, '../Source/non_ip/cdn.conf'))) { if (l === '# --- [AWS S3 Replace Me] ---') { - (await getS3OSSDomainsPromise).forEach(domain => { cdnDomainsList.push(`DOMAIN-SUFFIX,${domain}`); }); + (await getS3OSSDomainsPromise).forEach((domain: string) => { cdnDomainsList.push(`DOMAIN-SUFFIX,${domain}`); }); continue; } const line = processLine(l); @@ -73,7 +72,7 @@ const buildCdnConf = task(__filename, async () => { } } - const description = [ + const description: string[] = [ 'License: AGPL 3.0', 'Homepage: https://ruleset.skk.moe', 'GitHub: https://github.com/SukkaW/Surge', @@ -92,8 +91,8 @@ const buildCdnConf = task(__filename, async () => { )); }); -module.exports.buildCdnConf = buildCdnConf; +export { buildCdnConf }; -if (require.main === module) { +if (import.meta.main) { buildCdnConf(); } diff --git a/Build/build-chn-cidr.js b/Build/build-chn-cidr.js index 6a3be632..9cc1023f 100644 --- a/Build/build-chn-cidr.js +++ b/Build/build-chn-cidr.js @@ -52,6 +52,6 @@ const buildChnCidr = task(__filename, async () => { module.exports.buildChnCidr = buildChnCidr; -if (require.main === module) { +if (import.meta.main) { buildChnCidr(); } diff --git a/Build/build-common.js b/Build/build-common.js index 22c19d42..a757789b 100644 --- a/Build/build-common.js +++ b/Build/build-common.js @@ -47,7 +47,7 @@ const buildCommon = task(__filename, async () => { module.exports.buildCommon = buildCommon; -if (require.main === module) { +if (import.meta.main) { buildCommon(); } diff --git a/Build/build-domestic-ruleset.js b/Build/build-domestic-ruleset.js index ed446a05..d839a39b 100644 --- a/Build/build-domestic-ruleset.js +++ b/Build/build-domestic-ruleset.js @@ -60,6 +60,6 @@ const buildDomesticRuleset = task(__filename, async () => { module.exports.buildDomesticRuleset = buildDomesticRuleset; -if (require.main === module) { +if (import.meta.main) { buildDomesticRuleset(); } diff --git a/Build/build-internal-cdn-rules.js b/Build/build-internal-cdn-rules.js index 02627b51..02d5473e 100644 --- a/Build/build-internal-cdn-rules.js +++ b/Build/build-internal-cdn-rules.js @@ -95,6 +95,6 @@ const buildInternalCDNDomains = task(__filename, async () => { module.exports.buildInternalCDNDomains = buildInternalCDNDomains; -if (require.main === module) { +if (import.meta.main) { buildInternalCDNDomains(); } diff --git a/Build/build-internal-chn-domains.js b/Build/build-internal-chn-domains.js index a134bb17..710a88a0 100644 --- a/Build/build-internal-chn-domains.js +++ b/Build/build-internal-chn-domains.js @@ -19,6 +19,6 @@ const buildInternalChnDomains = task(__filename, async () => { module.exports.buildInternalChnDomains = buildInternalChnDomains; -if (require.main === module) { +if (import.meta.main) { buildInternalChnDomains(); } diff --git a/Build/build-internal-reverse-chn-cidr.js b/Build/build-internal-reverse-chn-cidr.js index 4f8b2d42..57f25de1 100644 --- a/Build/build-internal-reverse-chn-cidr.js +++ b/Build/build-internal-reverse-chn-cidr.js @@ -2,7 +2,6 @@ const { fetchRemoteTextAndCreateReadlineInterface } = require('./lib/fetch-remote-text-by-line'); const { processLineFromReadline } = require('./lib/process-line'); const path = require('path'); -const fs = require('fs'); const fsp = require('fs/promises'); const { task } = require('./lib/trace-runner'); @@ -42,14 +41,11 @@ const buildInternalReverseChnCIDR = task(__filename, async () => { true ); - return fs.promises.writeFile( - path.resolve(__dirname, '../List/internal/reversed-chn-cidr.txt'), - `${reversedCidr.join('\n')}\n` - ); + return Bun.write(path.resolve(__dirname, '../List/internal/reversed-chn-cidr.txt'), `${reversedCidr.join('\n')}\n`); }); module.exports.buildInternalReverseChnCIDR = buildInternalReverseChnCIDR; -if (require.main === module) { +if (import.meta.main) { buildInternalReverseChnCIDR(); } diff --git a/Build/build-phishing-domainset.js b/Build/build-phishing-domainset.js index 757ba6b6..0f7e8e18 100644 --- a/Build/build-phishing-domainset.js +++ b/Build/build-phishing-domainset.js @@ -185,6 +185,6 @@ const buildPhishingDomainSet = task(__filename, async () => { module.exports.buildPhishingDomainSet = buildPhishingDomainSet; -if (require.main === module) { +if (import.meta.main) { buildPhishingDomainSet(); } diff --git a/Build/build-public.js b/Build/build-public.js index 56739533..ff38a5b7 100644 --- a/Build/build-public.js +++ b/Build/build-public.js @@ -1,6 +1,5 @@ const listDir = require('@sukka/listdir'); const path = require('path'); -const fs = require('fs'); const fsp = require('fs/promises'); const { task } = require('./lib/trace-runner'); @@ -31,12 +30,12 @@ const buildPublicHtml = task(__filename, async () => { const html = template(list); - return fs.promises.writeFile(path.join(publicPath, 'index.html'), html, 'utf-8'); + return Bun.write(path.join(publicPath, 'index.html'), html); }); module.exports.buildPublicHtml = buildPublicHtml; -if (require.main === module) { +if (import.meta.main) { buildPublicHtml(); } diff --git a/Build/build-redirect-module.js b/Build/build-redirect-module.js index 22c86cf0..19eef59d 100644 --- a/Build/build-redirect-module.js +++ b/Build/build-redirect-module.js @@ -96,6 +96,6 @@ const buildRedirectModule = task(__filename, async () => { module.exports.buildRedirectModule = buildRedirectModule; -if (require.main === module) { +if (import.meta.main) { buildRedirectModule(); } diff --git a/Build/build-reject-domainset.js b/Build/build-reject-domainset.js index f7f65a54..a1ce3a51 100644 --- a/Build/build-reject-domainset.js +++ b/Build/build-reject-domainset.js @@ -233,6 +233,6 @@ const buildRejectDomainSet = task(__filename, async () => { module.exports.buildRejectDomainSet = buildRejectDomainSet; -if (require.main === module) { +if (import.meta.main) { buildRejectDomainSet(); } diff --git a/Build/build-speedtest-domainset.js b/Build/build-speedtest-domainset.js index 138ad4f2..ae8fb282 100644 --- a/Build/build-speedtest-domainset.js +++ b/Build/build-speedtest-domainset.js @@ -1,4 +1,3 @@ -const { fetch } = require('undici'); const { domainDeduper } = require('./lib/domain-deduper'); const path = require('path'); const { createRuleset } = require('./lib/create-file'); @@ -143,6 +142,6 @@ const buildSpeedtestDomainSet = task(__filename, async () => { module.exports.buildSpeedtestDomainSet = buildSpeedtestDomainSet; -if (require.main === module) { +if (import.meta.main) { buildSpeedtestDomainSet(); } diff --git a/Build/build-stream-service.js b/Build/build-stream-service.js index 6250e603..51377342 100644 --- a/Build/build-stream-service.js +++ b/Build/build-stream-service.js @@ -74,6 +74,6 @@ const buildStreamService = task(__filename, async () => { module.exports.buildStreamService = buildStreamService; -if (require.main === module) { +if (import.meta.main) { buildStreamService(); } diff --git a/Build/build-telegram-cidr.js b/Build/build-telegram-cidr.js index a7688a0c..769f1077 100644 --- a/Build/build-telegram-cidr.js +++ b/Build/build-telegram-cidr.js @@ -1,3 +1,4 @@ +// @ts-check const { fetchWithRetry } = require('./lib/fetch-retry'); const { createReadlineInterfaceFromResponse } = require('./lib/fetch-remote-text-by-line'); const path = require('path'); @@ -53,6 +54,6 @@ const buildTelegramCIDR = task(__filename, async () => { module.exports.buildTelegramCIDR = buildTelegramCIDR; -if (require.main === module) { +if (import.meta.main) { buildTelegramCIDR(); } diff --git a/Build/download-previous-build.js b/Build/download-previous-build.js index 0e359b43..87615bbf 100644 --- a/Build/download-previous-build.js +++ b/Build/download-previous-build.js @@ -1,6 +1,5 @@ -const { fetch } = require('undici'); +// @ts-check const tar = require('tar'); -const fs = require('fs'); const fsp = require('fs/promises'); const path = require('path'); const { tmpdir } = require('os'); @@ -10,12 +9,6 @@ const { readFileByLine } = require('./lib/fetch-remote-text-by-line'); const { isCI } = require('ci-info'); const { task, traceAsync } = require('./lib/trace-runner'); -const fileExists = (path) => { - return fs.promises.access(path, fs.constants.F_OK) - .then(() => true) - .catch(() => false); -}; - const downloadPreviousBuild = task(__filename, async () => { const filesList = ['Clash', 'List']; @@ -31,7 +24,7 @@ const downloadPreviousBuild = task(__filename, async () => { filesList.push(line); if (!isCI) { - allFileExists = fs.existsSync(path.join(__dirname, '..', line)); + allFileExists = await Bun.file(path.join(__dirname, '..', line)).exists(); if (!allFileExists) { break; } @@ -59,6 +52,9 @@ const downloadPreviousBuild = task(__filename, async () => { Readable.fromWeb(resp.body), tar.x({ cwd: extractedPath, + /** + * @param {string} p + */ filter(p) { return p.includes('/List/') || p.includes('/Modules/') || p.includes('/Clash/'); } @@ -70,7 +66,7 @@ const downloadPreviousBuild = task(__filename, async () => { await Promise.all(filesList.map(async p => { const src = path.join(extractedPath, 'ruleset.skk.moe-master', p); - if (await fileExists(src)) { + if (await Bun.file(src).exists()) { return fsp.cp( src, path.join(__dirname, '..', p), @@ -79,7 +75,7 @@ const downloadPreviousBuild = task(__filename, async () => { } })); - // return fs.promises.unlink(extractedPath).catch(() => { }); + // return fsp.unlink(extractedPath).catch(() => { }); }); const downloadPublicSuffixList = task(__filename, async () => { @@ -91,16 +87,13 @@ const downloadPublicSuffixList = task(__filename, async () => { fsp.mkdir(publicSuffixDir, { recursive: true }) ]); - return pipeline( - Readable.fromWeb(resp.body), - fs.createWriteStream(publicSuffixPath) - ); + return Bun.write(publicSuffixPath, resp); }, 'download-publicsuffixlist'); module.exports.downloadPreviousBuild = downloadPreviousBuild; module.exports.downloadPublicSuffixList = downloadPublicSuffixList; -if (require.main === module) { +if (import.meta.main) { Promise.all([ downloadPreviousBuild(), downloadPublicSuffixList() diff --git a/Build/lib/create-file.js b/Build/lib/create-file.js index 7f6a4314..7126309d 100644 --- a/Build/lib/create-file.js +++ b/Build/lib/create-file.js @@ -1,5 +1,4 @@ // @ts-check -const fs = require('fs'); const { readFileByLine } = require('./fetch-remote-text-by-line'); const { surgeDomainsetToClashDomainset, surgeRulesetToClashClassicalTextRuleset } = require('./clash'); @@ -9,7 +8,9 @@ const { surgeDomainsetToClashDomainset, surgeRulesetToClashClassicalTextRuleset */ async function compareAndWriteFile(linesA, filePath) { let isEqual = true; - if (!fs.existsSync(filePath)) { + const file = Bun.file(filePath); + + if (!(await file.exists())) { console.log(`${filePath} does not exists, writing...`); isEqual = false; } else if (linesA.length === 0) { @@ -44,7 +45,6 @@ async function compareAndWriteFile(linesA, filePath) { } if (!isEqual) { - const file = Bun.file(filePath); const writer = file.writer(); for (let i = 0, len = linesA.length; i < len; i++) { diff --git a/Build/lib/domain-deduper.js b/Build/lib/domain-deduper.js deleted file mode 100644 index 95bb6101..00000000 --- a/Build/lib/domain-deduper.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -const createTrie = require('./trie'); - -/** - * @param {string[]} inputDomains - */ -const domainDeduper = (inputDomains) => { - const trie = createTrie(inputDomains); - const sets = new Set(inputDomains); - - for (let j = 0, len = inputDomains.length; j < len; j++) { - const d = inputDomains[j]; - if (d[0] !== '.') { - continue; - } - - // delete all included subdomains (ends with `.example.com`) - // eslint-disable-next-line sukka/unicorn/no-array-method-this-argument -- it is not an array - trie.find(d, false).forEach(f => sets.delete(f)); - - // if `.example.com` exists, then `example.com` should also be removed - const a = d.slice(1); - - if (sets.has(a)) { - sets.delete(a); - } - } - - return Array.from(sets); -}; - -module.exports.domainDeduper = domainDeduper; diff --git a/Build/lib/domain-deduper.ts b/Build/lib/domain-deduper.ts new file mode 100644 index 00000000..75545035 --- /dev/null +++ b/Build/lib/domain-deduper.ts @@ -0,0 +1,25 @@ +import createTrie from './trie'; + +const domainDeduper = (inputDomains: string[]): string[] => { + const trie = createTrie(inputDomains); + const sets = new Set(inputDomains); + + for (let j = 0, len = inputDomains.length; j < len; j++) { + const d = inputDomains[j]; + if (d[0] !== '.') { + continue; + } + + trie.find(d, false).forEach(f => sets.delete(f)); + + const a: string = d.slice(1); + + if (sets.has(a)) { + sets.delete(a); + } + } + + return Array.from(sets); +}; + +export default domainDeduper; diff --git a/Build/lib/fetch-remote-text-by-line.js b/Build/lib/fetch-remote-text-by-line.ts similarity index 62% rename from Build/lib/fetch-remote-text-by-line.js rename to Build/lib/fetch-remote-text-by-line.ts index 64a93f44..3e93dd16 100644 --- a/Build/lib/fetch-remote-text-by-line.js +++ b/Build/lib/fetch-remote-text-by-line.ts @@ -1,14 +1,16 @@ -// @ts-check -const { fetchWithRetry } = require('./fetch-retry'); +import type { BunFile } from 'bun'; +import { fetchWithRetry } from './fetch-retry'; const decoder = new TextDecoder('utf-8'); -/** - * @param {string} path - */ -module.exports.readFileByLine = async function *(path) { + +export async function* readFileByLine(file: string | BunFile): AsyncGenerator { + if (typeof file === 'string') { + file = Bun.file(file); + } + let buf = ''; - for await (const chunk of Bun.file(path).stream()) { + for await (const chunk of file.stream()) { const chunkStr = decoder.decode(chunk).replaceAll('\r\n', '\n'); for (let i = 0, len = chunkStr.length; i < len; i++) { const char = chunkStr[i]; @@ -24,12 +26,9 @@ module.exports.readFileByLine = async function *(path) { if (buf) { yield buf; } -}; +} -/** - * @param {import('undici').Response} resp - */ -const createReadlineInterfaceFromResponse = async function *(resp) { +export async function* createReadlineInterfaceFromResponse(resp: Response): AsyncGenerator { if (!resp.body) { throw new Error('Failed to fetch remote text'); } @@ -55,15 +54,9 @@ const createReadlineInterfaceFromResponse = async function *(resp) { if (buf) { yield buf; } -}; +} -module.exports.createReadlineInterfaceFromResponse = createReadlineInterfaceFromResponse; - -/** - * @param {import('undici').RequestInfo} url - * @param {import('undici').RequestInit} [opt] - */ -module.exports.fetchRemoteTextAndCreateReadlineInterface = async (url, opt) => { +export async function fetchRemoteTextAndCreateReadlineInterface(url: string | URL, opt?: RequestInit): Promise> { const resp = await fetchWithRetry(url, opt); return createReadlineInterfaceFromResponse(resp); -}; +} diff --git a/Build/lib/fetch-retry.js b/Build/lib/fetch-retry.js index a309f4ff..4ee7b99b 100644 --- a/Build/lib/fetch-retry.js +++ b/Build/lib/fetch-retry.js @@ -1,11 +1,3 @@ // @ts-check -const undici = require('undici'); - -// Enable HTTP/2 supports -// undici.setGlobalDispatcher(new undici.Agent({ -// allowH2: true, -// pipelining: 10 -// })); - -const fetchWithRetry = /** @type {import('undici').fetch} */(require('@vercel/fetch-retry')(undici.fetch)); +const fetchWithRetry = require('@vercel/fetch-retry')(fetch); module.exports.fetchWithRetry = fetchWithRetry; diff --git a/Build/lib/get-gorhill-publicsuffix.js b/Build/lib/get-gorhill-publicsuffix.js index 71e2abc0..517bc7f5 100644 --- a/Build/lib/get-gorhill-publicsuffix.js +++ b/Build/lib/get-gorhill-publicsuffix.js @@ -1,5 +1,4 @@ const { toASCII } = require('punycode/'); -const fs = require('fs'); const path = require('path'); const { traceAsync } = require('./trace-runner'); @@ -7,15 +6,14 @@ const publicSuffixPath = path.resolve(__dirname, '../../node_modules/.cache/publ const getGorhillPublicSuffix = () => traceAsync('create gorhill public suffix instance', async () => { const customFetch = async (url) => { - const buf = await fs.promises.readFile(url); - return { - arrayBuffer() { return Promise.resolve(buf.buffer); } - }; + return Bun.file(url); }; + const publicSuffixFile = Bun.file(publicSuffixPath); + const [publicSuffixListDat, { default: gorhill }] = await Promise.all([ - fs.existsSync(publicSuffixPath) - ? fs.promises.readFile(publicSuffixPath, 'utf-8') + await publicSuffixFile.exists() + ? publicSuffixFile.text() : fetch('https://publicsuffix.org/list/public_suffix_list.dat').then(r => { console.log('public_suffix_list.dat not found, fetch directly from remote.'); return r.text(); diff --git a/Build/lib/parse-dnsmasq.js b/Build/lib/parse-dnsmasq.ts similarity index 57% rename from Build/lib/parse-dnsmasq.js rename to Build/lib/parse-dnsmasq.ts index 0051802b..d8c3a8d0 100644 --- a/Build/lib/parse-dnsmasq.js +++ b/Build/lib/parse-dnsmasq.ts @@ -1,17 +1,13 @@ -const { fetchRemoteTextAndCreateReadlineInterface } = require('./fetch-remote-text-by-line'); -const tldts = require('tldts'); +import { fetchRemoteTextAndCreateReadlineInterface } from './fetch-remote-text-by-line'; +import tldts from 'tldts'; -const isDomainLoose = (domain) => { +const isDomainLoose = (domain: string): boolean => { const { isIcann, isPrivate, isIp } = tldts.parse(domain); return !!(!isIp && (isIcann || isPrivate)); }; -/** - * @param {string | URL} url - */ -const parseFelixDnsmasq = async (url) => { - /** @type {string[]} */ - const res = []; +const parseFelixDnsmasq = async (url: string | URL): Promise => { + const res: string[] = []; for await (const line of await fetchRemoteTextAndCreateReadlineInterface(url)) { if (line.startsWith('server=/') && line.endsWith('/114.114.114.114')) { const domain = line.replace('server=/', '').replace('/114.114.114.114', ''); @@ -24,4 +20,4 @@ const parseFelixDnsmasq = async (url) => { return res; }; -module.exports.parseFelixDnsmasq = parseFelixDnsmasq; +export { parseFelixDnsmasq }; diff --git a/Build/lib/parse-filter.js b/Build/lib/parse-filter.js index 855ae2ed..aa77c11c 100644 --- a/Build/lib/parse-filter.js +++ b/Build/lib/parse-filter.js @@ -11,6 +11,13 @@ const DEBUG_DOMAIN_TO_FIND = null; // example.com | null let foundDebugDomain = false; const warnOnceUrl = new Set(); +/** + * + * @param {string} url + * @param {boolean} isWhite + * @param {...any} message + * @returns + */ const warnOnce = (url, isWhite, ...message) => { const key = `${url}${isWhite ? 'white' : 'black'}`; if (warnOnceUrl.has(key)) { @@ -153,6 +160,9 @@ async function processFilterRules(filterRulesUrl, fallbackUrls) { let downloadTime = 0; const gorhill = await getGorhillPublicSuffixPromise(); + /** + * @param {string} line + */ const lineCb = (line) => { const result = parse(line, gorhill); if (result) { diff --git a/Build/lib/process-line.js b/Build/lib/process-line.js deleted file mode 100644 index 8578343f..00000000 --- a/Build/lib/process-line.js +++ /dev/null @@ -1,48 +0,0 @@ -/* eslint-disable camelcase -- cache index access */ - -/** - * If line is commented out or empty, return null. - * Otherwise, return trimmed line. - * - * @param {string} line - */ -const processLine = (line) => { - if (!line) { - return null; - } - - const line_0 = line[0]; - - if ( - line_0 === '#' - || line_0 === ' ' - || line_0 === '\r' - || line_0 === '\n' - || line_0 === '!' - ) { - return null; - } - - const trimmed = line.trim(); - if (trimmed === '') { - return null; - } - - return trimmed; -}; -module.exports.processLine = processLine; - -/** - * @param {import('readline').ReadLine} rl - */ -module.exports.processLineFromReadline = async (rl) => { - /** @type {string[]} */ - const res = []; - for await (const line of rl) { - const l = processLine(line); - if (l) { - res.push(l); - } - } - return res; -}; diff --git a/Build/lib/process-line.ts b/Build/lib/process-line.ts new file mode 100644 index 00000000..512711ac --- /dev/null +++ b/Build/lib/process-line.ts @@ -0,0 +1,35 @@ +export const processLine = (line: string): string | null => { + if (!line) { + return null; + } + + const line_0: string = line[0]; + + if ( + line_0 === '#' + || line_0 === ' ' + || line_0 === '\r' + || line_0 === '\n' + || line_0 === '!' + ) { + return null; + } + + const trimmed: string = line.trim(); + if (trimmed === '') { + return null; + } + + return trimmed; +}; + +export const processLineFromReadline = async (rl: AsyncGenerator): Promise => { + const res: string[] = []; + for await (const line of rl) { + const l: string | null = processLine(line); + if (l) { + res.push(l); + } + } + return res; +}; diff --git a/Build/lib/reject-data-source.js b/Build/lib/reject-data-source.ts similarity index 93% rename from Build/lib/reject-data-source.js rename to Build/lib/reject-data-source.ts index f8133c3a..eff74ef2 100644 --- a/Build/lib/reject-data-source.js +++ b/Build/lib/reject-data-source.ts @@ -1,6 +1,4 @@ -// @ts-check -/** @type {[string, boolean][]} */ -const HOSTS = [ +export const HOSTS: [string, boolean][] = [ // ['https://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext', false], ['https://raw.githubusercontent.com/hoshsadiq/adblock-nocoin-list/master/hosts.txt', false], ['https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt', false], @@ -9,7 +7,7 @@ const HOSTS = [ ['https://raw.githubusercontent.com/durablenapkin/block/master/luminati.txt', false] ]; -const ADGUARD_FILTERS = /** @type {const} */([ +export const ADGUARD_FILTERS = [ // EasyList [ 'https://easylist.to/easylist/easylist.txt', @@ -146,9 +144,9 @@ const ADGUARD_FILTERS = /** @type {const} */([ 'https://paulgb.github.io/BarbBlock/blacklists/ublock-origin.txt', // Brave First Party & First Party CNAME 'https://raw.githubusercontent.com/brave/adblock-lists/master/brave-lists/brave-firstparty.txt' -]); +] as const; -const PREDEFINED_WHITELIST = [ +export const PREDEFINED_WHITELIST = [ 'localhost', 'broadcasthost', 'ip6-loopback', @@ -194,11 +192,11 @@ const PREDEFINED_WHITELIST = [ 'vlscppe.microsoft.com' ]; -const PREDEFINED_ENFORCED_BACKLIST = [ +export const PREDEFINED_ENFORCED_BACKLIST = [ 'telemetry.mozilla.org' ]; -const PREDEFINED_ENFORCED_WHITELIST = [ +export const PREDEFINED_ENFORCED_WHITELIST = [ 'godaddysites.com', 'web.app', 'firebaseapp.com', @@ -219,9 +217,3 @@ const PREDEFINED_ENFORCED_WHITELIST = [ 'blogspot.com', 'appspot.com' ]; - -module.exports.HOSTS = HOSTS; -module.exports.ADGUARD_FILTERS = ADGUARD_FILTERS; -module.exports.PREDEFINED_WHITELIST = PREDEFINED_WHITELIST; -module.exports.PREDEFINED_ENFORCED_BACKLIST = PREDEFINED_ENFORCED_BACKLIST; -module.exports.PREDEFINED_ENFORCED_WHITELIST = PREDEFINED_ENFORCED_WHITELIST; diff --git a/Build/lib/trie.js b/Build/lib/trie.ts similarity index 89% rename from Build/lib/trie.js rename to Build/lib/trie.ts index 47a12aef..0abcbee5 100644 --- a/Build/lib/trie.js +++ b/Build/lib/trie.ts @@ -2,23 +2,23 @@ * Suffix Trie based on Mnemonist Trie */ -const SENTINEL = String.fromCodePoint(0); +export const SENTINEL: string = String.fromCodePoint(0); /** * @param {string[] | Set} [from] */ -const createTrie = (from) => { - let size = 0; - const root = {}; +export const createTrie = (from?: string[] | Set) => { + let size: number = 0; + const root: any = {}; /** * Method used to add the given prefix to the trie. * * @param {string} suffix - Prefix to follow. */ - const add = (suffix) => { - let node = root; - let token; + const add = (suffix: string): void => { + let node: any = root; + let token: string; for (let i = suffix.length - 1; i >= 0; i--) { token = suffix[i]; node[token] ||= {}; @@ -35,9 +35,9 @@ const createTrie = (from) => { /** * @param {string} suffix */ - const contains = (suffix) => { - let node = root; - let token; + const contains = (suffix: string): boolean => { + let node: any = root; + let token: string; for (let i = suffix.length - 1; i >= 0; i--) { token = suffix[i]; @@ -56,10 +56,10 @@ const createTrie = (from) => { * @param {boolean} [includeEqualWithSuffix] * @return {string[]} */ - const find = (suffix, includeEqualWithSuffix = true) => { - let node = root; - const matches = []; - let token; + const find = (suffix: string, includeEqualWithSuffix: boolean = true): string[] => { + let node: any = root; + const matches: string[] = []; + let token: string; for (let i = suffix.length - 1; i >= 0; i--) { token = suffix[i]; @@ -70,15 +70,15 @@ const createTrie = (from) => { } // Performing DFS from prefix - const nodeStack = [node]; + const nodeStack: any[] = [node]; - const suffixStack = [suffix]; - let k; + const suffixStack: string[] = [suffix]; + let k: string; - let $suffix = suffix; + let $suffix: string = suffix; while (nodeStack.length) { - $suffix = suffixStack.pop(); + $suffix = suffixStack.pop()!; node = nodeStack.pop(); // eslint-disable-next-line guard-for-in -- plain object @@ -105,12 +105,12 @@ const createTrie = (from) => { * @param {string} suffix - Prefix to delete. * @return {boolean} */ - const remove = (suffix) => { - let node = root; - let toPrune = null; - let tokenToPrune = null; - let parent; - let token; + const remove = (suffix: string): boolean => { + let node: any = root; + let toPrune: any = null; + let tokenToPrune: string | null = null; + let parent: any; + let token: string; for (let i = suffix.length - 1; i >= 0; i--) { token = suffix[i]; @@ -138,7 +138,7 @@ const createTrie = (from) => { size--; - if (toPrune) { + if (tokenToPrune) { delete toPrune[tokenToPrune]; } else { delete node[SENTINEL]; @@ -153,8 +153,8 @@ const createTrie = (from) => { * @param {string} suffix - Prefix to check. * @return {boolean} */ - const has = (suffix) => { - let node = root; + const has = (suffix: string): boolean => { + let node: any = root; for (let i = suffix.length - 1; i >= 0; i--) { node = node[suffix[i]]; @@ -445,8 +445,4 @@ const createTrie = (from) => { // }; // } -/** - * Exporting. - */ -module.exports.SENTINEL = SENTINEL; -module.exports = createTrie; +export default createTrie; diff --git a/Build/validate-domainset.js b/Build/validate-domainset.js index dd2dc3cf..70613501 100644 --- a/Build/validate-domainset.js +++ b/Build/validate-domainset.js @@ -71,6 +71,6 @@ const validate = task(__filename, async () => { }); module.exports.validate = validate; -if (require.main === module) { +if (import.meta.main) { validate(); } diff --git a/Source/domainset/cdn.conf b/Source/domainset/cdn.conf index cd0ade30..dfa2b8da 100644 --- a/Source/domainset/cdn.conf +++ b/Source/domainset/cdn.conf @@ -298,7 +298,7 @@ mir-s3-cdn-cf.behance.net # >> Amazon CDN .ssl-images-amazon.com .media-amazon.com -.cloudfront.net +# .cloudfront.net public suffix # AWS .awsstatic.com cdn.assets.as2.amazonaws.com diff --git a/Source/non_ip/cdn.conf b/Source/non_ip/cdn.conf index 24f2a9af..f3e2e0c6 100644 --- a/Source/non_ip/cdn.conf +++ b/Source/non_ip/cdn.conf @@ -1,5 +1,7 @@ # $ custom_build_script +# >> Amazon CloudFront +DOMAIN-SUFFIX,cloudfront.net # >> GitHub Pages DOMAIN-SUFFIX,github.io # >> GitHub diff --git a/bun.lockb b/bun.lockb index 604998da0b23c825a2098b8b257844cfc539b205..810feff19a4d81f20c2d163eed92d43e10eca989 100755 GIT binary patch delta 17476 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 diff --git a/eslint.config.js b/eslint.config.js index 1de43423..fe1c67b3 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -9,10 +9,12 @@ module.exports = require('eslint-config-sukka').sukka({ } } }, - node: true + node: true, + ts: true }, { rules: { 'sukka/unicorn/prefer-math-trunc': 'off', - 'sukka/unicorn/prefer-number-properties': ['warn', { checkInfinity: false }] + 'sukka/unicorn/prefer-number-properties': ['warn', { checkInfinity: false }], + 'n/no-missing-require': 'off' } }); diff --git a/package.json b/package.json index 178d8bc6..44ac7c0b 100644 --- a/package.json +++ b/package.json @@ -29,8 +29,7 @@ "punycode": "^2.3.1", "table": "^6.8.1", "tar": "^6.2.0", - "tldts": "^6.0.19", - "undici": "5.27.0" + "tldts": "^6.0.19" }, "devDependencies": { "@eslint-sukka/node": "^4.1.7", @@ -39,7 +38,8 @@ "chai": "4.3.10", "eslint-config-sukka": "4.1.7", "eslint-formatter-sukka": "4.1.7", - "mocha": "^10.2.0" + "mocha": "^10.2.0", + "typescript": "^5.2.2" }, "resolutions": { "has": "npm:@nolyfill/has@latest" diff --git a/tsconfig.json b/tsconfig.json index 96ea9459..0d90f2b7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,5 +14,9 @@ "forceConsistentCasingInFileNames": true, "strict": true, "skipLibCheck": true - } + }, + "include": [ + "./Build/**/*.js", + "./Build/**/*.ts" + ] }