mirror of
https://github.com/SukkaW/Surge.git
synced 2026-01-29 01:51:52 +08:00
Refactor: continues to rewrite to TS
This commit is contained in:
@@ -1,19 +1,15 @@
|
||||
/**
|
||||
* @typedef {Object} Node
|
||||
* @prop {number} [depth = 0]
|
||||
* @prop {string} key
|
||||
* @prop {boolean} [word = false]
|
||||
* @prop {Record<string, Node>} [children={}]
|
||||
* @prop {Node} [fail]
|
||||
* @prop {number} [count=0]
|
||||
*/
|
||||
interface Node {
|
||||
/** @default 0 */
|
||||
depth?: number;
|
||||
key: string;
|
||||
/** @default false */
|
||||
word?: boolean;
|
||||
children: Record<string, Node>;
|
||||
fail?: Node;
|
||||
count: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
* @param {number} depth
|
||||
* @returns {Node}
|
||||
*/
|
||||
const createNode = (key, depth = 0) => ({
|
||||
const createNode = (key: string, depth = 0): Node => ({
|
||||
depth,
|
||||
key,
|
||||
word: false,
|
||||
@@ -22,15 +18,11 @@ const createNode = (key, depth = 0) => ({
|
||||
count: 0
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string[] | Set<string>} keys
|
||||
*/
|
||||
const createKeywordFilter = (keys) => {
|
||||
const createKeywordFilter = (keys: string[] | Set<string>) => {
|
||||
const root = createNode('root');
|
||||
|
||||
const build = () => {
|
||||
/** @type {Node[]} */
|
||||
const queue = [];
|
||||
const queue: Node[] = [];
|
||||
queue.push(root);
|
||||
|
||||
let idx = 0;
|
||||
@@ -57,11 +49,7 @@ const createKeywordFilter = (keys) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} key
|
||||
* @param {number} len
|
||||
*/
|
||||
const put = (key, len) => {
|
||||
const put = (key: string, len: number) => {
|
||||
let node = root;
|
||||
const lastIdx = len - 1;
|
||||
node.count++;
|
||||
@@ -91,12 +79,8 @@ const createKeywordFilter = (keys) => {
|
||||
|
||||
build();
|
||||
|
||||
/**
|
||||
* @param {string} text
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const search = (text) => {
|
||||
let node = root;
|
||||
const search = (text: string) => {
|
||||
let node: Node | undefined = root;
|
||||
|
||||
for (let i = 0, textLen = text.length; i < textLen; i++) {
|
||||
// const key = text.charAt(i);
|
||||
@@ -120,4 +104,4 @@ const createKeywordFilter = (keys) => {
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = createKeywordFilter;
|
||||
export default createKeywordFilter;
|
||||
@@ -1,7 +1,4 @@
|
||||
/**
|
||||
* @param {string} [namespace]
|
||||
*/
|
||||
const createCache = (namespace, printStats = false) => {
|
||||
export const createCache = (namespace?: string, printStats = false) => {
|
||||
const cache = new Map();
|
||||
|
||||
let hit = 0;
|
||||
@@ -12,13 +9,7 @@ const createCache = (namespace, printStats = false) => {
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* @template T
|
||||
* @param {string} key
|
||||
* @param {() => T} fn
|
||||
* @returns {T}
|
||||
*/
|
||||
sync(key, fn) {
|
||||
sync<T>(key: string, fn: () => T): T {
|
||||
if (cache.has(key)) {
|
||||
hit++;
|
||||
return cache.get(key);
|
||||
@@ -27,13 +18,7 @@ const createCache = (namespace, printStats = false) => {
|
||||
cache.set(key, value);
|
||||
return value;
|
||||
},
|
||||
/**
|
||||
* @template T
|
||||
* @param {string} key
|
||||
* @param {() => Promise<T>} fn
|
||||
* @returns {Promise<T>}
|
||||
*/
|
||||
async async(key, fn) {
|
||||
async async<T>(key: string, fn: () => Promise<T>): Promise<T> {
|
||||
if (cache.has(key)) {
|
||||
hit++;
|
||||
return cache.get(key);
|
||||
@@ -44,4 +29,3 @@ const createCache = (namespace, printStats = false) => {
|
||||
}
|
||||
};
|
||||
};
|
||||
module.exports.createCache = createCache;
|
||||
@@ -1,24 +0,0 @@
|
||||
const tldts = require('tldts');
|
||||
const { createCache } = require('./cache-apply');
|
||||
|
||||
const cache = createCache('cached-tld-parse', true);
|
||||
|
||||
const sharedConfig = { allowPrivateDomains: true };
|
||||
|
||||
/**
|
||||
* @param {string} domain
|
||||
* @returns {ReturnType<import('tldts').parse>}
|
||||
*/
|
||||
module.exports.parse = (domain) => cache.sync(domain, () => tldts.parse(domain, sharedConfig));
|
||||
|
||||
let gothillGetDomainCache = null;
|
||||
/**
|
||||
* @param {import('gorhill-publicsuffixlist').default | null} gorhill
|
||||
*/
|
||||
module.exports.createCachedGorhillGetDomain = (gorhill) => {
|
||||
gothillGetDomainCache ||= createCache('cached-gorhill-get-domain', true);
|
||||
/**
|
||||
* @param {string} domain
|
||||
*/
|
||||
return (domain) => (/** @type {ReturnType<typeof createCache>} */ (gothillGetDomainCache)).sync(domain, () => gorhill.getDomain(domain[0] === '.' ? domain.slice(1) : domain));
|
||||
};
|
||||
17
Build/lib/cached-tld-parse.ts
Normal file
17
Build/lib/cached-tld-parse.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import tldts from 'tldts';
|
||||
import { createCache } from './cache-apply';
|
||||
import { PublicSuffixList } from 'gorhill-publicsuffixlist';
|
||||
|
||||
const cache = createCache('cached-tld-parse', true);
|
||||
|
||||
const sharedConfig = { allowPrivateDomains: true };
|
||||
|
||||
export const parse = (domain: string) => cache.sync(domain, () => tldts.parse(domain, sharedConfig));
|
||||
|
||||
let gothillGetDomainCache: ReturnType<typeof createCache> | null = null;
|
||||
export const createCachedGorhillGetDomain = (gorhill: PublicSuffixList) => {
|
||||
return (domain: string) => {
|
||||
gothillGetDomainCache ??= createCache('cached-gorhill-get-domain', true);
|
||||
return gothillGetDomainCache.sync(domain, () => gorhill.getDomain(domain[0] === '.' ? domain.slice(1) : domain))
|
||||
};
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
// @ts-check
|
||||
const _Trie = require('mnemonist/trie');
|
||||
const Trie = _Trie.default || _Trie;
|
||||
import Trie from 'mnemonist/trie';
|
||||
|
||||
// https://dreamacro.github.io/clash/configuration/rules.html
|
||||
const CLASH_SUPPORTED_RULE_TYPE = [
|
||||
@@ -17,21 +16,13 @@ const CLASH_SUPPORTED_RULE_TYPE = [
|
||||
'PROCESS-PATH'
|
||||
];
|
||||
|
||||
/**
|
||||
* @param {string[] | Set<string>} rules
|
||||
*/
|
||||
const surgeRulesetToClashClassicalTextRuleset = (rules) => {
|
||||
export const surgeRulesetToClashClassicalTextRuleset = (rules: string[] | Set<string>) => {
|
||||
const trie = Trie.from(rules);
|
||||
return CLASH_SUPPORTED_RULE_TYPE.flatMap(
|
||||
type => trie.find(`${type},`)
|
||||
);
|
||||
};
|
||||
module.exports.surgeRulesetToClashClassicalTextRuleset = surgeRulesetToClashClassicalTextRuleset;
|
||||
|
||||
/**
|
||||
* @param {string[]} domainset
|
||||
*/
|
||||
const surgeDomainsetToClashDomainset = (domainset) => {
|
||||
export const surgeDomainsetToClashDomainset = (domainset: string[]) => {
|
||||
return domainset.map(i => (i[0] === '.' ? `+${i}` : i));
|
||||
};
|
||||
module.exports.surgeDomainsetToClashDomainset = surgeDomainsetToClashDomainset;
|
||||
@@ -1,12 +1,8 @@
|
||||
// @ts-check
|
||||
const { readFileByLine } = require('./fetch-remote-text-by-line');
|
||||
const { surgeDomainsetToClashDomainset, surgeRulesetToClashClassicalTextRuleset } = require('./clash');
|
||||
import { readFileByLine } from './fetch-remote-text-by-line';
|
||||
import { surgeDomainsetToClashDomainset, surgeRulesetToClashClassicalTextRuleset } from './clash';
|
||||
|
||||
/**
|
||||
* @param {string[]} linesA
|
||||
* @param {string} filePath
|
||||
*/
|
||||
async function compareAndWriteFile(linesA, filePath) {
|
||||
export async function compareAndWriteFile(linesA: string[], filePath: string) {
|
||||
let isEqual = true;
|
||||
const file = Bun.file(filePath);
|
||||
|
||||
@@ -57,16 +53,8 @@ async function compareAndWriteFile(linesA, filePath) {
|
||||
|
||||
console.log(`Same Content, bail out writing: ${filePath}`);
|
||||
}
|
||||
module.exports.compareAndWriteFile = compareAndWriteFile;
|
||||
|
||||
/**
|
||||
* @param {string} title
|
||||
* @param {string[]} description
|
||||
* @param {Date} date
|
||||
* @param {string[]} content
|
||||
* @returns {string[]}
|
||||
*/
|
||||
const withBannerArray = (title, description, date, content) => {
|
||||
export const withBannerArray = (title: string, description: string[], date: Date, content: string[]) => {
|
||||
return [
|
||||
'########################################',
|
||||
`# ${title}`,
|
||||
@@ -78,20 +66,10 @@ const withBannerArray = (title, description, date, content) => {
|
||||
'################# END ###################'
|
||||
];
|
||||
};
|
||||
module.exports.withBannerArray = withBannerArray;
|
||||
|
||||
/**
|
||||
* @param {string} title
|
||||
* @param {string[]} description
|
||||
* @param {Date} date
|
||||
* @param {string[]} content
|
||||
* @param {'ruleset' | 'domainset'} type
|
||||
* @param {string} surgePath
|
||||
* @param {string} clashPath
|
||||
*/
|
||||
const createRuleset = (
|
||||
title, description, date, content,
|
||||
type, surgePath, clashPath
|
||||
export const createRuleset = (
|
||||
title: string, description: string[], date: Date, content: string[],
|
||||
type: 'ruleset' | 'domainset', surgePath: string, clashPath: string
|
||||
) => {
|
||||
const surgeContent = withBannerArray(title, description, date, content);
|
||||
|
||||
@@ -114,4 +92,3 @@ const createRuleset = (
|
||||
compareAndWriteFile(clashContent, clashPath)
|
||||
];
|
||||
};
|
||||
module.exports.createRuleset = createRuleset;
|
||||
@@ -1,6 +1,6 @@
|
||||
import createTrie from './trie';
|
||||
|
||||
const domainDeduper = (inputDomains: string[]): string[] => {
|
||||
export const domainDeduper = (inputDomains: string[]): string[] => {
|
||||
const trie = createTrie(inputDomains);
|
||||
const sets = new Set(inputDomains);
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
// @ts-check
|
||||
const fetchWithRetry = require('@vercel/fetch-retry')(fetch);
|
||||
module.exports.fetchWithRetry = fetchWithRetry;
|
||||
4
Build/lib/fetch-retry.ts
Normal file
4
Build/lib/fetch-retry.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
// @ts-expect-error -- missing types
|
||||
import createFetchRetry from '@vercel/fetch-retry';
|
||||
|
||||
export const fetchWithRetry: typeof fetch = createFetchRetry(fetch);
|
||||
@@ -1,13 +1,12 @@
|
||||
const { toASCII } = require('punycode/');
|
||||
const path = require('path');
|
||||
const { traceAsync } = require('./trace-runner');
|
||||
import { toASCII } from 'punycode';
|
||||
import path from 'path';
|
||||
import { traceAsync } from './trace-runner';
|
||||
import type { PublicSuffixList } from 'gorhill-publicsuffixlist';
|
||||
|
||||
const publicSuffixPath = path.resolve(__dirname, '../../node_modules/.cache/public_suffix_list_dat.txt');
|
||||
|
||||
const getGorhillPublicSuffix = () => traceAsync('create gorhill public suffix instance', async () => {
|
||||
const customFetch = async (url) => {
|
||||
return Bun.file(url);
|
||||
};
|
||||
const customFetch = async (url: string | URL) => Bun.file(url);
|
||||
|
||||
const publicSuffixFile = Bun.file(publicSuffixPath);
|
||||
|
||||
@@ -27,9 +26,8 @@ const getGorhillPublicSuffix = () => traceAsync('create gorhill public suffix in
|
||||
return gorhill;
|
||||
});
|
||||
|
||||
/** @type {Promise<import('gorhill-publicsuffixlist').default> | null} */
|
||||
let gorhillPublicSuffixPromise = null;
|
||||
module.exports.getGorhillPublicSuffixPromise = () => {
|
||||
let gorhillPublicSuffixPromise: Promise<PublicSuffixList> | null = null;
|
||||
export const getGorhillPublicSuffixPromise = () => {
|
||||
gorhillPublicSuffixPromise ||= getGorhillPublicSuffix();
|
||||
return gorhillPublicSuffixPromise;
|
||||
};
|
||||
@@ -6,7 +6,7 @@ const isDomainLoose = (domain: string): boolean => {
|
||||
return !!(!isIp && (isIcann || isPrivate));
|
||||
};
|
||||
|
||||
const parseFelixDnsmasq = async (url: string | URL): Promise<string[]> => {
|
||||
export const parseFelixDnsmasq = async (url: string | URL): Promise<string[]> => {
|
||||
const res: string[] = [];
|
||||
for await (const line of await fetchRemoteTextAndCreateReadlineInterface(url)) {
|
||||
if (line.startsWith('server=/') && line.endsWith('/114.114.114.114')) {
|
||||
@@ -19,5 +19,3 @@ const parseFelixDnsmasq = async (url: string | URL): Promise<string[]> => {
|
||||
|
||||
return res;
|
||||
};
|
||||
|
||||
export { parseFelixDnsmasq };
|
||||
|
||||
@@ -1,24 +1,18 @@
|
||||
// @ts-check
|
||||
const { fetchWithRetry } = require('./fetch-retry');
|
||||
const tldts = require('./cached-tld-parse');
|
||||
const { fetchRemoteTextAndCreateReadlineInterface } = require('./fetch-remote-text-by-line');
|
||||
const { NetworkFilter } = require('@cliqz/adblocker');
|
||||
const { processLine } = require('./process-line');
|
||||
const { performance } = require('perf_hooks');
|
||||
const { getGorhillPublicSuffixPromise } = require('./get-gorhill-publicsuffix');
|
||||
import { fetchWithRetry } from './fetch-retry';
|
||||
import * as tldts from './cached-tld-parse';
|
||||
import { fetchRemoteTextAndCreateReadlineInterface } from './fetch-remote-text-by-line';
|
||||
import { NetworkFilter } from '@cliqz/adblocker';
|
||||
import { processLine } from './process-line';
|
||||
import { performance } from 'perf_hooks';
|
||||
import { getGorhillPublicSuffixPromise } from './get-gorhill-publicsuffix';
|
||||
import type { PublicSuffixList } from 'gorhill-publicsuffixlist';
|
||||
|
||||
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 warnOnceUrl = new Set<string>();
|
||||
const warnOnce = (url: string, isWhite: boolean, ...message: any[]) => {
|
||||
const key = `${url}${isWhite ? 'white' : 'black'}`;
|
||||
if (warnOnceUrl.has(key)) {
|
||||
return;
|
||||
@@ -27,10 +21,7 @@ const warnOnce = (url, isWhite, ...message) => {
|
||||
console.warn(url, isWhite ? '(white)' : '(black)', ...message);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} domain
|
||||
*/
|
||||
const normalizeDomain = (domain) => {
|
||||
const normalizeDomain = (domain: string) => {
|
||||
if (!domain) return null;
|
||||
|
||||
const parsed = tldts.parse(domain);
|
||||
@@ -47,10 +38,7 @@ const normalizeDomain = (domain) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string | URL} domainListsUrl
|
||||
*/
|
||||
async function processDomainLists(domainListsUrl) {
|
||||
export async function processDomainLists(domainListsUrl: string | URL) {
|
||||
if (typeof domainListsUrl === 'string') {
|
||||
domainListsUrl = new URL(domainListsUrl);
|
||||
}
|
||||
@@ -79,18 +67,14 @@ async function processDomainLists(domainListsUrl) {
|
||||
return domainSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | URL} hostsUrl
|
||||
*/
|
||||
async function processHosts(hostsUrl, includeAllSubDomain = false) {
|
||||
export async function processHosts(hostsUrl: string | URL, includeAllSubDomain = false) {
|
||||
console.time(` - processHosts: ${hostsUrl}`);
|
||||
|
||||
if (typeof hostsUrl === 'string') {
|
||||
hostsUrl = new URL(hostsUrl);
|
||||
}
|
||||
|
||||
/** @type Set<string> */
|
||||
const domainSets = new Set();
|
||||
const domainSets = new Set<string>();
|
||||
|
||||
for await (const l of await fetchRemoteTextAndCreateReadlineInterface(hostsUrl)) {
|
||||
const line = processLine(l);
|
||||
@@ -121,24 +105,20 @@ async function processHosts(hostsUrl, includeAllSubDomain = false) {
|
||||
return domainSets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | URL} filterRulesUrl
|
||||
* @param {readonly (string | URL)[] | undefined} [fallbackUrls]
|
||||
* @returns {Promise<{ white: Set<string>, black: Set<string>, foundDebugDomain: boolean }>}
|
||||
*/
|
||||
async function processFilterRules(filterRulesUrl, fallbackUrls) {
|
||||
export async function processFilterRules(
|
||||
filterRulesUrl: string | URL,
|
||||
fallbackUrls?: readonly (string | URL)[] | undefined
|
||||
): Promise<{ white: Set<string>, black: Set<string>, foundDebugDomain: boolean }> {
|
||||
const runStart = performance.now();
|
||||
|
||||
/** @type Set<string> */
|
||||
const whitelistDomainSets = new Set();
|
||||
/** @type Set<string> */
|
||||
const blacklistDomainSets = new Set();
|
||||
const whitelistDomainSets = new Set<string>();
|
||||
const blacklistDomainSets = new Set<string>();
|
||||
|
||||
/**
|
||||
* @param {string} domainToBeAddedToBlack
|
||||
* @param {boolean} isSubDomain
|
||||
*/
|
||||
const addToBlackList = (domainToBeAddedToBlack, isSubDomain) => {
|
||||
const addToBlackList = (domainToBeAddedToBlack: string, isSubDomain: boolean) => {
|
||||
if (isSubDomain && domainToBeAddedToBlack[0] !== '.') {
|
||||
blacklistDomainSets.add(`.${domainToBeAddedToBlack}`);
|
||||
} else {
|
||||
@@ -149,7 +129,7 @@ async function processFilterRules(filterRulesUrl, fallbackUrls) {
|
||||
* @param {string} domainToBeAddedToWhite
|
||||
* @param {boolean} [isSubDomain]
|
||||
*/
|
||||
const addToWhiteList = (domainToBeAddedToWhite, isSubDomain = true) => {
|
||||
const addToWhiteList = (domainToBeAddedToWhite: string, isSubDomain = true) => {
|
||||
if (isSubDomain && domainToBeAddedToWhite[0] !== '.') {
|
||||
whitelistDomainSets.add(`.${domainToBeAddedToWhite}`);
|
||||
} else {
|
||||
@@ -163,7 +143,7 @@ async function processFilterRules(filterRulesUrl, fallbackUrls) {
|
||||
/**
|
||||
* @param {string} line
|
||||
*/
|
||||
const lineCb = (line) => {
|
||||
const lineCb = (line: string) => {
|
||||
const result = parse(line, gorhill);
|
||||
if (result) {
|
||||
const flag = result[1];
|
||||
@@ -250,12 +230,7 @@ async function processFilterRules(filterRulesUrl, fallbackUrls) {
|
||||
const R_KNOWN_NOT_NETWORK_FILTER_PATTERN = /[#%&=~]/;
|
||||
const R_KNOWN_NOT_NETWORK_FILTER_PATTERN_2 = /(\$popup|\$removeparam|\$popunder)/;
|
||||
|
||||
/**
|
||||
* @param {string} $line
|
||||
* @param {import('gorhill-publicsuffixlist').default} gorhill
|
||||
* @returns {null | [hostname: string, flag: 0 | 1 | 2 | -1]} - 0 white include subdomain, 1 black abosulte, 2 black include subdomain, -1 white
|
||||
*/
|
||||
function parse($line, gorhill) {
|
||||
function parse($line: string, gorhill: PublicSuffixList): null | [hostname: string, flag: 0 | 1 | 2 | -1] {
|
||||
if (
|
||||
// doesn't include
|
||||
!$line.includes('.') // rule with out dot can not be a domain
|
||||
@@ -615,7 +590,3 @@ function parse($line, gorhill) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
module.exports.processDomainLists = processDomainLists;
|
||||
module.exports.processHosts = processHosts;
|
||||
module.exports.processFilterRules = processFilterRules;
|
||||
@@ -1,10 +1,7 @@
|
||||
// @ts-check
|
||||
/**
|
||||
* @param {string | null} a
|
||||
* @param {string | null} b
|
||||
* @returns {0 | 1 | -1}
|
||||
*/
|
||||
const compare = (a, b) => {
|
||||
import type { PublicSuffixList } from 'gorhill-publicsuffixlist';
|
||||
import { createCachedGorhillGetDomain } from './cached-tld-parse';
|
||||
|
||||
const compare = (a: string | null, b: string | null) => {
|
||||
if (a === b) return 0;
|
||||
if (b == null) {
|
||||
return 1;
|
||||
@@ -38,22 +35,11 @@ const compare = (a, b) => {
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {import('gorhill-publicsuffixlist').default | null} [gorhill]
|
||||
*/
|
||||
const createDomainSorter = (gorhill = null) => {
|
||||
const createDomainSorter = (gorhill: PublicSuffixList | null = null) => {
|
||||
if (gorhill) {
|
||||
/**
|
||||
* @param {string} input
|
||||
*/
|
||||
const getDomain = require('./cached-tld-parse').createCachedGorhillGetDomain(gorhill);
|
||||
const getDomain = createCachedGorhillGetDomain(gorhill);
|
||||
|
||||
/**
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
* @returns {0 | 1 | -1}
|
||||
*/
|
||||
return (a, b) => {
|
||||
return (a: string, b: string) => {
|
||||
if (a === b) return 0;
|
||||
|
||||
const aDomain = getDomain(a);
|
||||
@@ -65,12 +51,8 @@ const createDomainSorter = (gorhill = null) => {
|
||||
}
|
||||
|
||||
const tldts = require('./cached-tld-parse');
|
||||
/**
|
||||
* @param {string} a
|
||||
* @param {string} b
|
||||
* @returns {0 | 1 | -1}
|
||||
*/
|
||||
return (a, b) => {
|
||||
|
||||
return (a: string, b: string) => {
|
||||
if (a === b) return 0;
|
||||
|
||||
const aDomain = tldts.parse(a).domain;
|
||||
@@ -81,5 +63,5 @@ const createDomainSorter = (gorhill = null) => {
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = createDomainSorter();
|
||||
module.exports.createDomainSorter = createDomainSorter;
|
||||
export default createDomainSorter();
|
||||
export { createDomainSorter };
|
||||
@@ -1,44 +1,24 @@
|
||||
// @ts-check
|
||||
const path = require('path');
|
||||
const { performance } = require('perf_hooks');
|
||||
import path from 'path';
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {string} prefix
|
||||
* @param {() => T} fn
|
||||
* @returns {T}
|
||||
*/
|
||||
const traceSync = (prefix, fn) => {
|
||||
const traceSync = <T>(prefix: string, fn: () => T): T => {
|
||||
const start = performance.now();
|
||||
const result = fn();
|
||||
const end = performance.now();
|
||||
console.log(`${prefix}: ${(end - start).toFixed(3)}ms`);
|
||||
return result;
|
||||
};
|
||||
module.exports.traceSync = traceSync;
|
||||
export { traceSync };
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {string} prefix
|
||||
* @param {() => Promise<T>} fn
|
||||
* @returns {Promise<T>}
|
||||
*/
|
||||
const traceAsync = async (prefix, fn) => {
|
||||
const traceAsync = async <T>(prefix: string, fn: () => Promise<T>): Promise<T> => {
|
||||
const start = performance.now();
|
||||
const result = await fn();
|
||||
const end = performance.now();
|
||||
console.log(`${prefix}: ${(end - start).toFixed(3)}ms`);
|
||||
return result;
|
||||
};
|
||||
module.exports.traceAsync = traceAsync;
|
||||
export { traceAsync };
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {string} __filename
|
||||
* @param {() => Promise<T>} fn
|
||||
* @param {string | null} [customname]
|
||||
*/
|
||||
module.exports.task = (__filename, fn, customname = null) => {
|
||||
const task = <T>(__filename: string, fn: () => Promise<T>, customname: string | null = null) => {
|
||||
const taskName = customname ?? path.basename(__filename, path.extname(__filename));
|
||||
return async () => {
|
||||
console.log(`🏃 [${taskName}] Start executing`);
|
||||
@@ -47,6 +27,7 @@ module.exports.task = (__filename, fn, customname = null) => {
|
||||
const end = performance.now();
|
||||
console.log(`✅ [${taskName}] Executed successfully: ${(end - start).toFixed(3)}ms`);
|
||||
|
||||
return { start, end, taskName };
|
||||
return { start, end, taskName } as const;
|
||||
};
|
||||
};
|
||||
export { task };
|
||||
Reference in New Issue
Block a user