Implement suffix (reversed) trie

This commit is contained in:
SukkaW 2023-07-07 14:18:27 +08:00
parent 762fed66fe
commit 9dd9e4aa05
4 changed files with 760 additions and 10 deletions

300
Build/lib/trie.js Normal file
View File

@ -0,0 +1,300 @@
/**
* Suffix Trie based on Mnemonist Trie
*/
const SENTINEL = String.fromCharCode(0);
class Trie {
size = 0;
root = {};
/**
* Method used to add the given prefix to the trie.
*
* @param {string} suffix - Prefix to follow.
* @return {Trie}
*/
add(suffix) {
let node = this.root;
let token;
for (let i = suffix.length - 1; i >= 0; i--) {
token = suffix[i];
node = node[token] || (node[token] = {});
}
// Do we need to increase size?
if (!(SENTINEL in node)) this.size++;
node[SENTINEL] = true;
return this;
}
/**
* Method used to retrieve every item in the trie with the given prefix.
*
* @param {string} suffix - Prefix to query.
* @param {boolean} [includeEqualWithSuffix]
* @return {string[]}
*/
find(suffix, includeEqualWithSuffix = true) {
let node = this.root;
const matches = [];
let token;
let i;
let l;
for (let i = suffix.length - 1; i >= 0; i--) {
token = suffix[i];
node = node[token];
if (node == null) return matches;
}
// Performing DFS from prefix
const nodeStack = [node];
const suffixStack = [suffix];
let k;
let $suffix = suffix;
while (nodeStack.length) {
$suffix = suffixStack.pop();
node = nodeStack.pop();
for (k in node) {
if (k === SENTINEL) {
if (includeEqualWithSuffix) {
matches.push($suffix);
} else if ($suffix !== suffix) {
matches.push($suffix);
}
continue;
}
nodeStack.push(node[k]);
suffixStack.push(k + $suffix);
}
}
return matches;
}
toJSON() {
return this.root;
}
/**
* Method used to clear the trie.
*
* @return {void}
*/
// clear() {
// // Properties
// this.root = {};
// this.size = 0;
// }
/**
* Method used to update the value of the given prefix in the trie.
*
* @param {string|array} prefix - Prefix to follow.
* @param {(oldValue: any | undefined) => any} updateFunction - Update value visitor callback.
* @return {Trie}
*/
// update(prefix, updateFunction) {
// let node = this.root;
// let token;
// for (let i = 0, l = prefix.length; i < l; i++) {
// token = prefix[i];
// node = node[token] || (node[token] = {});
// }
// // Do we need to increase size?
// if (!(SENTINEL in node))
// this.size++;
// node[SENTINEL] = updateFunction(node[SENTINEL]);
// return this;
// }
/**
* Method used to delete a prefix from the trie.
*
* @param {string|array} suffix - Prefix to delete.
* @return {boolean}
*/
delete(suffix) {
let node = this.root;
let toPrune = null;
let tokenToPrune = null;
let parent;
let token;
for (let i = suffix.length - 1; i >= 0; i--) {
token = suffix[i];
parent = node;
node = node[token];
// Prefix does not exist
if (typeof node === 'undefined')
return false;
// Keeping track of a potential branch to prune
if (toPrune !== null) {
if (Object.keys(node).length > 1) {
toPrune = null;
tokenToPrune = null;
}
}
else {
if (Object.keys(node).length < 2) {
toPrune = parent;
tokenToPrune = token;
}
}
}
if (!(SENTINEL in node)) return false;
this.size--;
if (toPrune) {
delete toPrune[tokenToPrune];
} else {
delete node[SENTINEL];
}
return true;
}
/**
* Method used to assert whether the given prefix exists in the Trie.
*
* @param {string} suffix - Prefix to check.
* @return {boolean}
*/
has(suffix) {
let node = this.root;
let token;
for (let i = suffix.length - 1; i >= 0; i--) {
token = suffix[i];
node = node[token];
if (typeof node === 'undefined')
return false;
}
return SENTINEL in node;
}
/**
* Method returning an iterator over the trie's prefixes.
*
* @param {string|array} [prefix] - Optional starting prefix.
* @return {Iterator}
*/
// prefixes(prefix) {
// let node = this.root;
// const nodeStack = [];
// const prefixStack = [];
// let token;
// let i;
// let l;
// const isString = this.mode === 'string';
// // Resolving initial prefix
// if (prefix) {
// for (i = 0, l = prefix.length; i < l; i++) {
// token = prefix[i];
// node = node[token];
// // If the prefix does not exist, we return an empty iterator
// if (typeof node === 'undefined')
// return Iterator.empty();
// }
// }
// else {
// prefix = isString ? '' : [];
// }
// nodeStack.push(node);
// prefixStack.push(prefix);
// return new Iterator(() => {
// let currentNode;
// let currentPrefix;
// let hasValue = false;
// let k;
// while (nodeStack.length) {
// currentNode = nodeStack.pop();
// currentPrefix = prefixStack.pop();
// for (k in currentNode) {
// if (k === SENTINEL) {
// hasValue = true;
// continue;
// }
// nodeStack.push(currentNode[k]);
// prefixStack.push(isString ? currentPrefix + k : currentPrefix.concat(k));
// }
// if (hasValue)
// return { done: false, value: currentPrefix };
// }
// return { done: true };
// });
// }
/**
* Convenience known methods.
*/
// inspect() {
// const proxy = new Set();
// const iterator = this.prefixes();
// let step;
// while ((step = iterator.next(), !step.done))
// proxy.add(step.value);
// // Trick so that node displays the name of the constructor
// Object.defineProperty(proxy, 'constructor', {
// value: Trie,
// enumerable: false
// });
// return proxy;
// }
/**
* Static .from function taking an arbitrary iterable & converting it into
* a trie.
*
* @param {string[]} iterable - Target iterable.
* @return {Trie}
*/
static from = iterable => {
const trie = new Trie();
iterable.forEach(i => trie.add(i));
return trie;
};
}
/**
* Exporting.
*/
module.exports.SENTINEL = SENTINEL;
module.exports = Trie;

185
Build/lib/trie.test.js Normal file
View File

@ -0,0 +1,185 @@
require('chai').should();
const Trie = require('./trie');
const assert = require('assert');
var SENTINEL = Trie.SENTINEL;
describe('Trie', () => {
it('should be possible to add items to a Trie.', () => {
const trie = new Trie();
trie.add('sukka');
trie.add('ukka');
trie.add('akku');
trie.size.should.eq(3);
trie.has('sukka').should.eq(true);
trie.has('ukka').should.eq(true);
trie.has('akku').should.eq(true);
trie.has('noc').should.eq(false);
trie.has('suk').should.eq(false);
trie.has('sukkaw').should.eq(false);
});
it('adding the same item several times should not increase size.', () => {
const trie = new Trie();
trie.add('rat');
trie.add('erat');
trie.add('rat');
assert.strictEqual(trie.size, 2);
assert.strictEqual(trie.has('rat'), true);
});
it('should be possible to set the null sequence.', () => {
let trie = new Trie();
trie.add('');
trie.size.should.eq(1);
trie.has('').should.eq(true);
trie = new Trie(Array);
trie.add([]);
trie.size.should.eq(1);
trie.has([]).should.eq(true);
});
it('should be possible to delete items.', () => {
const trie = new Trie();
trie.add('rat');
trie.add('rate');
trie.add('tar');
assert.strictEqual(trie.delete(''), false);
trie.delete('').should.eq(false);
trie.delete('hello').should.eq(false);
trie.delete('rat').should.eq(true);
trie.has('rat').should.eq(false);
trie.has('rate').should.eq(true);
trie.size.should.eq(2);
assert.strictEqual(trie.delete('rate'), true);
assert.strictEqual(trie.size, 1);
assert.strictEqual(trie.delete('tar'), true);
assert.strictEqual(trie.size, 0);
});
it('should be possible to check the existence of a sequence in the Trie.', () => {
const trie = new Trie();
trie.add('romanesque');
assert.strictEqual(trie.has('romanesque'), true);
assert.strictEqual(trie.has('roman'), false);
assert.strictEqual(trie.has(''), false);
});
it('should be possible to retrieve items matching the given prefix.', () => {
const trie = new Trie();
trie.add('roman');
trie.add('esqueroman');
trie.add('sesqueroman');
trie.add('greek');
assert.deepStrictEqual(trie.find('roman'), ['roman', 'esqueroman', 'sesqueroman']);
assert.deepStrictEqual(trie.find('man'), ['roman', 'esqueroman', 'sesqueroman']);
assert.deepStrictEqual(trie.find('esqueroman'), ['esqueroman', 'sesqueroman']);
assert.deepStrictEqual(trie.find('eek'), ['greek']);
assert.deepStrictEqual(trie.find('hello'), []);
assert.deepStrictEqual(trie.find(''), ['greek', 'roman', 'esqueroman', 'sesqueroman']);
});
// it('should work with custom tokens.', () => {
// const trie = new Trie(Array);
// trie.add(['the', 'cat', 'eats', 'the', 'mouse']);
// trie.add(['the', 'mouse', 'eats', 'cheese']);
// trie.add(['hello', 'world']);
// assert.strictEqual(trie.size, 3);
// assert.strictEqual(trie.has(['the', 'mouse', 'eats', 'cheese']), true);
// assert.strictEqual(trie.has(['the', 'mouse', 'eats']), false);
// assert.strictEqual(trie.delete(['hello']), false);
// assert.strictEqual(trie.delete(['hello', 'world']), true);
// assert.strictEqual(trie.size, 2);
// });
// it('should be possible to iterate over the trie\'s prefixes.', () => {
// const trie = new Trie();
// trie.add('rat');
// trie.add('rate');
// let prefixes = take(trie.prefixes());
// assert.deepStrictEqual(prefixes, ['rat', 'rate']);
// trie.add('rater');
// trie.add('rates');
// prefixes = take(trie.keys('rate'));
// assert.deepStrictEqual(prefixes, ['rate', 'rates', 'rater']);
// });
// it('should be possible to iterate over the trie\'s prefixes using for...of.', () => {
// const trie = new Trie();
// trie.add('rat');
// trie.add('rate');
// const tests = [
// 'rat',
// 'rate'
// ];
// let i = 0;
// for (const prefix of trie)
// assert.deepStrictEqual(prefix, tests[i++]);
// });
it('should be possible to create a trie from an arbitrary iterable.', () => {
const words = ['roman', 'esqueroman'];
const trie = Trie.from(words);
assert.strictEqual(trie.size, 2);
assert.deepStrictEqual(trie.has('roman'), true);
});
});
describe('surge domainset dedupe', () => {
it('should not remove same entry', () => {
const trie = Trie.from(['.skk.moe', 'noc.one']);
trie.find('.skk.moe').should.eql(['.skk.moe']);
trie.find('noc.one').should.eql(['noc.one']);
});
it('should remove subdomain', () => {
const trie = Trie.from(['www.noc.one', 'www.sukkaw.com', 'blog.skk.moe', 'image.cdn.skk.moe', 'cdn.sukkaw.net']);
// trie.find('noc.one').should.eql(['www.noc.one']);
trie.find('.skk.moe').should.eql(['image.cdn.skk.moe', 'blog.skk.moe']);
// trie.find('sukkaw.net').should.eql(['cdn.sukkaw.net']);
trie.find('.sukkaw.com').should.eql(['www.sukkaw.com']);
});
it('should not remove non-subdomain', () => {
const trie = Trie.from(['skk.moe', 'sukkaskk.moe']);
trie.find('.skk.moe').should.eql([]);
});
})

View File

@ -125,7 +125,10 @@
"undici": "5.22.1"
},
"devDependencies": {
"@types/mocha": "^10.0.1",
"chai": "^4.3.7",
"eslint-plugin-import": "npm:eslint-plugin-i@2.27.5-4",
"mocha": "^10.2.0",
"wireit": "^0.9.5"
},
"engines": {

282
pnpm-lock.yaml generated
View File

@ -43,9 +43,18 @@ dependencies:
version: 5.22.1
devDependencies:
'@types/mocha':
specifier: ^10.0.1
version: 10.0.1
chai:
specifier: ^4.3.7
version: 4.3.7
eslint-plugin-import:
specifier: npm:eslint-plugin-i@2.27.5-4
version: /eslint-plugin-i@2.27.5-4(eslint@8.44.0)
mocha:
specifier: ^10.2.0
version: 10.2.0
wireit:
specifier: ^0.9.5
version: 0.9.5
@ -104,7 +113,7 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
ajv: 6.12.6
debug: 4.3.4
debug: 4.3.4(supports-color@8.1.1)
espree: 9.6.0
globals: 13.20.0
ignore: 5.2.4
@ -126,7 +135,7 @@ packages:
engines: {node: '>=10.10.0'}
dependencies:
'@humanwhocodes/object-schema': 1.2.1
debug: 4.3.4
debug: 4.3.4(supports-color@8.1.1)
minimatch: 3.1.2
transitivePeerDependencies:
- supports-color
@ -220,13 +229,17 @@ packages:
resolution: {integrity: sha512-o0J30wqycjF5miWDKYKKzzOU1ZTLuA42HZ4HE7/zqTOc/jTLdQ5NhYWvsRQo45Nfi1KHoRdNhteSI4BAxTF1Pg==}
dev: false
/@types/mocha@10.0.1:
resolution: {integrity: sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==}
dev: true
/@vercel/fetch-retry@5.1.3(node-fetch@2.6.11):
resolution: {integrity: sha512-UIbFc4VsEZHOr6dWuE+kxY4NxnOLXFMCWm0fSKRRHUEtrIzaJLzHpWk2QskCXTSzFgFvhkLAvSrBK2XZg7NSzg==}
peerDependencies:
node-fetch: ^2.6.7
dependencies:
async-retry: 1.3.3
debug: 4.3.4
debug: 4.3.4(supports-color@8.1.1)
node-fetch: 2.6.11
transitivePeerDependencies:
- supports-color
@ -264,6 +277,11 @@ packages:
uri-js: 4.4.1
dev: false
/ansi-colors@4.1.1:
resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==}
engines: {node: '>=6'}
dev: true
/ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
@ -286,6 +304,10 @@ packages:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
dev: true
/assertion-error@1.1.0:
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
dev: true
/astral-regex@2.0.0:
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
engines: {node: '>=8'}
@ -317,6 +339,12 @@ packages:
concat-map: 0.0.1
dev: true
/brace-expansion@2.0.1:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
dependencies:
balanced-match: 1.0.2
dev: true
/braces@3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'}
@ -324,6 +352,10 @@ packages:
fill-range: 7.0.1
dev: true
/browser-stdout@1.3.1:
resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==}
dev: true
/busboy@1.6.0:
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
engines: {node: '>=10.16.0'}
@ -336,6 +368,24 @@ packages:
engines: {node: '>=6'}
dev: true
/camelcase@6.3.0:
resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
engines: {node: '>=10'}
dev: true
/chai@4.3.7:
resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==}
engines: {node: '>=4'}
dependencies:
assertion-error: 1.1.0
check-error: 1.0.2
deep-eql: 4.1.3
get-func-name: 2.0.0
loupe: 2.3.6
pathval: 1.1.1
type-detect: 4.0.8
dev: true
/chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
@ -344,6 +394,10 @@ packages:
supports-color: 7.2.0
dev: true
/check-error@1.0.2:
resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==}
dev: true
/chokidar@3.5.3:
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
engines: {node: '>= 8.10.0'}
@ -386,6 +440,14 @@ packages:
string-natural-compare: 3.0.1
dev: false
/cliui@7.0.4:
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
dependencies:
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi: 7.0.0
dev: true
/color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
@ -416,10 +478,10 @@ packages:
supports-color:
optional: true
dependencies:
ms: 2.1.2
ms: 2.1.3
dev: true
/debug@4.3.4:
/debug@4.3.4(supports-color@8.1.1):
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
peerDependencies:
@ -429,11 +491,29 @@ packages:
optional: true
dependencies:
ms: 2.1.2
supports-color: 8.1.1
/decamelize@4.0.0:
resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==}
engines: {node: '>=10'}
dev: true
/deep-eql@4.1.3:
resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
engines: {node: '>=6'}
dependencies:
type-detect: 4.0.8
dev: true
/deep-is@0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
dev: true
/diff@5.0.0:
resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==}
engines: {node: '>=0.3.1'}
dev: true
/doctrine@2.1.0:
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
engines: {node: '>=0.10.0'}
@ -450,7 +530,11 @@ packages:
/emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
dev: false
/escalade@3.1.1:
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
engines: {node: '>=6'}
dev: true
/escape-string-regexp@4.0.0:
resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
@ -546,7 +630,7 @@ packages:
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.3
debug: 4.3.4
debug: 4.3.4(supports-color@8.1.1)
doctrine: 3.0.0
escape-string-regexp: 4.0.0
eslint-scope: 7.2.0
@ -674,6 +758,11 @@ packages:
rimraf: 3.0.2
dev: true
/flat@5.0.2:
resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==}
hasBin: true
dev: true
/flatted@3.2.7:
resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==}
dev: true
@ -710,6 +799,15 @@ packages:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
dev: true
/get-caller-file@2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
dev: true
/get-func-name@2.0.0:
resolution: {integrity: sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==}
dev: true
/get-tsconfig@4.6.2:
resolution: {integrity: sha512-E5XrT4CbbXcXWy+1jChlZmrmCwd5KGx502kDCXJJ7y898TtWW9FwoG5HfOLVRKmlmDGkWN2HM9Ho+/Y8F0sJDg==}
dependencies:
@ -730,6 +828,17 @@ packages:
is-glob: 4.0.3
dev: true
/glob@7.2.0:
resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==}
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 3.1.2
once: 1.4.0
path-is-absolute: 1.0.1
dev: true
/glob@7.2.3:
resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
dependencies:
@ -758,7 +867,6 @@ packages:
/has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
dev: true
/has@1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
@ -779,6 +887,11 @@ packages:
resolution: {integrity: sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==}
dev: false
/he@1.2.0:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
hasBin: true
dev: true
/ignore@5.2.4:
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
engines: {node: '>= 4'}
@ -839,7 +952,6 @@ packages:
/is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
dev: false
/is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
@ -858,6 +970,16 @@ packages:
engines: {node: '>=8'}
dev: true
/is-plain-obj@2.1.0:
resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==}
engines: {node: '>=8'}
dev: true
/is-unicode-supported@0.1.0:
resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==}
engines: {node: '>=10'}
dev: true
/isexe@2.0.0:
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
dev: true
@ -916,6 +1038,20 @@ packages:
resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==}
dev: false
/log-symbols@4.1.0:
resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==}
engines: {node: '>=10'}
dependencies:
chalk: 4.1.2
is-unicode-supported: 0.1.0
dev: true
/loupe@2.3.6:
resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==}
dependencies:
get-func-name: 2.0.0
dev: true
/lru-cache@6.0.0:
resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
engines: {node: '>=10'}
@ -942,6 +1078,13 @@ packages:
brace-expansion: 1.1.11
dev: true
/minimatch@5.0.1:
resolution: {integrity: sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==}
engines: {node: '>=10'}
dependencies:
brace-expansion: 2.0.1
dev: true
/minipass@3.3.6:
resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
engines: {node: '>=8'}
@ -968,9 +1111,47 @@ packages:
hasBin: true
dev: false
/mocha@10.2.0:
resolution: {integrity: sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==}
engines: {node: '>= 14.0.0'}
hasBin: true
dependencies:
ansi-colors: 4.1.1
browser-stdout: 1.3.1
chokidar: 3.5.3
debug: 4.3.4(supports-color@8.1.1)
diff: 5.0.0
escape-string-regexp: 4.0.0
find-up: 5.0.0
glob: 7.2.0
he: 1.2.0
js-yaml: 4.1.0
log-symbols: 4.1.0
minimatch: 5.0.1
ms: 2.1.3
nanoid: 3.3.3
serialize-javascript: 6.0.0
strip-json-comments: 3.1.1
supports-color: 8.1.1
workerpool: 6.2.1
yargs: 16.2.0
yargs-parser: 20.2.4
yargs-unparser: 2.0.0
dev: true
/ms@2.1.2:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
/ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
dev: true
/nanoid@3.3.3:
resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
dev: true
/natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
dev: true
@ -1075,6 +1256,10 @@ packages:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true
/pathval@1.1.1:
resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==}
dev: true
/picocolors@1.0.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
dev: false
@ -1115,6 +1300,12 @@ packages:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
dev: true
/randombytes@2.1.0:
resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==}
dependencies:
safe-buffer: 5.2.1
dev: true
/readdirp@3.6.0:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
@ -1122,6 +1313,11 @@ packages:
picomatch: 2.3.1
dev: true
/require-directory@2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
dev: true
/require-from-string@2.0.2:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
@ -1173,6 +1369,10 @@ packages:
queue-microtask: 1.2.3
dev: true
/safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
dev: true
/semver@7.5.3:
resolution: {integrity: sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==}
engines: {node: '>=10'}
@ -1181,6 +1381,12 @@ packages:
lru-cache: 6.0.0
dev: true
/serialize-javascript@6.0.0:
resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==}
dependencies:
randombytes: 2.1.0
dev: true
/shebang-command@2.0.0:
resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
engines: {node: '>=8'}
@ -1222,7 +1428,6 @@ packages:
emoji-regex: 8.0.0
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
dev: false
/strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
@ -1242,6 +1447,12 @@ packages:
has-flag: 4.0.0
dev: true
/supports-color@8.1.1:
resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
engines: {node: '>=10'}
dependencies:
has-flag: 4.0.0
/supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
@ -1313,6 +1524,11 @@ packages:
prelude-ls: 1.2.1
dev: true
/type-detect@4.0.8:
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
engines: {node: '>=4'}
dev: true
/type-fest@0.20.2:
resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
engines: {node: '>=10'}
@ -1366,13 +1582,59 @@ packages:
proper-lockfile: 4.1.2
dev: true
/workerpool@6.2.1:
resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==}
dev: true
/wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
dev: true
/wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
dev: true
/y18n@5.0.8:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
dev: true
/yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
/yargs-parser@20.2.4:
resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==}
engines: {node: '>=10'}
dev: true
/yargs-unparser@2.0.0:
resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==}
engines: {node: '>=10'}
dependencies:
camelcase: 6.3.0
decamelize: 4.0.0
flat: 5.0.2
is-plain-obj: 2.1.0
dev: true
/yargs@16.2.0:
resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
engines: {node: '>=10'}
dependencies:
cliui: 7.0.4
escalade: 3.1.1
get-caller-file: 2.0.5
require-directory: 2.1.1
string-width: 4.2.3
y18n: 5.0.8
yargs-parser: 20.2.4
dev: true
/yocto-queue@0.1.0:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}