diff --git a/.eslintrc.json b/.eslintrc.json index 5286a891..7b8d2605 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,17 +1,28 @@ { "env": { - "browser": true, - "es6": true + "browser": true, + "es6": true }, + "parser": "@typescript-eslint/parser", + "plugins": [ + "@typescript-eslint" + ], "extends": [ - "standard" + "eslint:recommended", + "standard", + "plugin:@typescript-eslint/eslint-recommended" ], "globals": { - "Atomics": "readonly", - "SharedArrayBuffer": "readonly" + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" }, "rules": { "quotes": ["error", "single", { "avoidEscape": true }], - "no-prototype-builtins": 0 + "no-prototype-builtins": 0, + "no-use-before-define": 0, + "@typescript-eslint/no-use-before-define": [ + "error", + { "functions": false, "classes": false, "variables": false } + ] } } diff --git a/.gitignore b/.gitignore index 5c3cf647..2082689e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,5 +5,6 @@ /dist /examples/dist /examples/node_modules +/benchmarks/dist /coverage yarn-error.log diff --git a/babel.config.js b/babel.config.js deleted file mode 100644 index 13141f1d..00000000 --- a/babel.config.js +++ /dev/null @@ -1,55 +0,0 @@ -const CONFIG = { - default: { - plugins: [ - '@babel/plugin-proposal-object-rest-spread' - ], - }, - commonjs: { - presets: [ - ['@babel/preset-env', { - loose: true, - targets: { - node: '10' - } - }] - ], - }, - es5m: { - presets: [ - ['@babel/preset-env', { - modules: false, - loose: true, - targets: { - browsers: ['last 3 versions'] - } - }] - ], - }, - test: { - presets: [ - ['@babel/preset-env', { - loose: true, - targets: { - node: '10' - } - }] - ], - } -}; - -module.exports = (api) => { - let format; - api.caller(caller => format = caller.output || process.env.BABEL_OUTPUT || process.env.NODE_ENV); - api.cache.using(() => format); - - if (format === 'default' || !CONFIG[format]) { - return CONFIG.default; - } - - const { presets = [], plugins = [] } = CONFIG[format]; - - return { - presets: presets.concat(CONFIG.default.presets || []), - plugins: plugins.concat(CONFIG.default.plugins || []), - }; -}; diff --git a/benchmarks/autoSuggestion.js b/benchmarks/autoSuggestion.js index 2984c241..912b597c 100644 --- a/benchmarks/autoSuggestion.js +++ b/benchmarks/autoSuggestion.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +const Benchmark = require('benchmark') import { miniSearch as ms } from './divinaCommedia.js' const suite = new Benchmark.Suite('Auto suggestion') diff --git a/benchmarks/combinedSearch.js b/benchmarks/combinedSearch.js index 674d8dd7..04416c1d 100644 --- a/benchmarks/combinedSearch.js +++ b/benchmarks/combinedSearch.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +const Benchmark = require('benchmark') import { miniSearch as ms } from './divinaCommedia.js' const suite = new Benchmark.Suite('Combined search') diff --git a/benchmarks/exactSearch.js b/benchmarks/exactSearch.js index 9d8572b5..e1acd8be 100644 --- a/benchmarks/exactSearch.js +++ b/benchmarks/exactSearch.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +const Benchmark = require('benchmark') import { index } from './divinaCommedia.js' const suite = new Benchmark.Suite('Exact search') diff --git a/benchmarks/fuzzySearch.js b/benchmarks/fuzzySearch.js index f0f1dc10..f73b7a10 100644 --- a/benchmarks/fuzzySearch.js +++ b/benchmarks/fuzzySearch.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +const Benchmark = require('benchmark') import { index } from './divinaCommedia.js' const suite = new Benchmark.Suite('Fuzzy search') diff --git a/benchmarks/indexing.js b/benchmarks/indexing.js index 47e59469..4a4b71a3 100644 --- a/benchmarks/indexing.js +++ b/benchmarks/indexing.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +const Benchmark = require('benchmark') import MiniSearch from '../src/MiniSearch.js' import { lines } from './divinaCommedia.js' diff --git a/benchmarks/loadIndex.js b/benchmarks/loadIndex.js index 8d0c6c86..d5ec732a 100644 --- a/benchmarks/loadIndex.js +++ b/benchmarks/loadIndex.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +const Benchmark = require('benchmark') import MiniSearch from '../src/MiniSearch.js' import { miniSearch as ms } from './divinaCommedia.js' diff --git a/benchmarks/prefixSearch.js b/benchmarks/prefixSearch.js index e6f2fc6f..25b62e9d 100644 --- a/benchmarks/prefixSearch.js +++ b/benchmarks/prefixSearch.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +const Benchmark = require('benchmark') import { index } from './divinaCommedia.js' const suite = new Benchmark.Suite('Prefix search') diff --git a/benchmarks/searchFiltering.js b/benchmarks/searchFiltering.js index 9e9b0cb1..0f003051 100644 --- a/benchmarks/searchFiltering.js +++ b/benchmarks/searchFiltering.js @@ -1,4 +1,4 @@ -import Benchmark from 'benchmark' +const Benchmark = require('benchmark') import { miniSearch } from './divinaCommedia.js' const suite = new Benchmark.Suite('Search filtering') diff --git a/examples/package.json b/examples/package.json index 7d466cae..28cd5f9c 100644 --- a/examples/package.json +++ b/examples/package.json @@ -28,6 +28,7 @@ "webpack-dev-server": "^3.1.9" }, "dependencies": { - "core-js": "3" + "core-js": "3", + "minisearch": "file:../" } } diff --git a/examples/src/app.js b/examples/src/app.js index b0881d37..08658278 100644 --- a/examples/src/app.js +++ b/examples/src/app.js @@ -1,6 +1,6 @@ import React from 'react' import fetch from 'unfetch' -import MiniSearch from '../../src/MiniSearch.js' +import MiniSearch from 'minisearch' class App extends React.PureComponent { constructor (props) { diff --git a/examples/yarn.lock b/examples/yarn.lock index a89160a4..77d547bf 100644 --- a/examples/yarn.lock +++ b/examples/yarn.lock @@ -3347,6 +3347,9 @@ minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +"minisearch@file:..": + version "2.6.2" + mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" diff --git a/package.json b/package.json index 795f847c..203e743b 100644 --- a/package.json +++ b/package.json @@ -24,13 +24,9 @@ "license": "MIT", "dependencies": {}, "devDependencies": { - "@babel/cli": "^7.0.0", - "@babel/core": "^7.0.1", - "@babel/node": "^7.5.5", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/preset-env": "^7.0.0", - "babel-core": "^7.0.0-0", - "babel-jest": "^26.3.0", + "@rollup/plugin-typescript": "^6.0.0", + "@typescript-eslint/eslint-plugin": "^4.1.1", + "@typescript-eslint/parser": "^4.1.1", "benchmark": "^2.1.4", "core-js": "^3.1.4", "coveralls": "^3.0.2", @@ -46,9 +42,10 @@ "jsdoc": "^3.6.4", "regenerator-runtime": "^0.13.1", "rollup": "^2.2.0", - "rollup-plugin-babel": "^4.4.0", "rollup-plugin-terser": "^7.0.0", "snazzy": "^8.0.0", + "ts-jest": "^26.3.0", + "tslib": "^2.0.1", "typescript": "^4.0.2" }, "files": [ @@ -59,6 +56,14 @@ ], "jest": { "testURL": "http://localhost:3000/", + "transform": { + "\\.(js|ts)$": "ts-jest" + }, + "moduleFileExtensions": [ + "ts", + "js" + ], + "testRegex": "\\.test\\.(ts|js)$", "setupFilesAfterEnv": [ "/src/testSetup/jest.js" ] @@ -67,14 +72,15 @@ "test": "jest", "test-watch": "jest --watch", "coverage": "jest --coverage", - "benchmark": "NODE_ENV=production BABEL_OUTPUT=commonjs babel-node --expose-gc benchmarks/index.js", - "build": "NODE_ENV=production rollup -c", + "benchmark": "BENCHMARKS=true yarn build && NODE_ENV=production node --expose-gc benchmarks/dist/index.js", + "build": "yarn build-typedef && NODE_ENV=production rollup -c", "build-minified": "MINIFY=true yarn build", "build-docs": "jsdoc --configure jsdoc.json", - "lint": "eslint 'src/**/*.js'", - "lintfix": "eslint --fix 'src/**/*.js'", + "build-typedef": "tsc --outDir dist --declaration --emitDeclarationOnly", + "lint": "eslint 'src/**/*.{js,ts}'", + "lintfix": "eslint --fix 'src/**/*.{js,ts}'", "prepublishOnly": "yarn test && yarn build" }, "sideEffects": false, - "types": "./src/index.d.ts" + "types": "./dist/index.d.ts" } diff --git a/rollup.config.js b/rollup.config.js index 13acff67..fa9a251d 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,8 +1,8 @@ -import babel from 'rollup-plugin-babel' +import typescript from '@rollup/plugin-typescript' import { terser } from 'rollup-plugin-terser' const config = ({ format, output, name, dir }) => ({ - input: 'src/index.js', + input: 'src/index.ts', output: { sourcemap: true, dir: `dist/${dir || format}`, @@ -19,18 +19,23 @@ const config = ({ format, output, name, dir }) => ({ })] : [] }, - plugins: [ - babel({ - rootMode: 'upward', - caller: { - output - } - }) - ] + plugins: [typescript()] }) -export default [ +const benchmarks = { + input: 'benchmarks/index.js', + output: { + sourcemap: false, + dir: 'benchmarks/dist', + format: 'commonjs', + entryFileNames: '[name].js', + plugins: [] + }, + plugins: [typescript()] +} + +export default process.env.BENCHMARKS === 'true' ? [benchmarks] : [ config({ format: 'es', output: 'es6' }), config({ format: 'es', output: 'es5m', dir: 'es5m' }), - config({ format: 'umd', output: 'es5m', name: 'MiniSearch' }) + config({ format: 'umd', output: 'es5m', name: 'MiniSearch' }), ] diff --git a/src/MiniSearch.js b/src/MiniSearch.js deleted file mode 100644 index 22e567c5..00000000 --- a/src/MiniSearch.js +++ /dev/null @@ -1,841 +0,0 @@ -import SearchableMap from './SearchableMap/SearchableMap.js' - -const OR = 'or' -const AND = 'and' - -/** -* MiniSearch is the main entrypoint class, and represents a full-text search -* engine. -* -* @example -* const documents = [ -* { -* id: 1, -* title: 'Moby Dick', -* text: 'Call me Ishmael. Some years ago...', -* category: 'fiction' -* }, -* { -* id: 2, -* title: 'Zen and the Art of Motorcycle Maintenance', -* text: 'I can see by my watch...', -* category: 'fiction' -* }, -* { -* id: 3, -* title: 'Neuromancer', -* text: 'The sky above the port was...', -* category: 'fiction' -* }, -* { -* id: 4, -* title: 'Zen and the Art of Archery', -* text: 'At first sight it must seem...', -* category: 'non-fiction' -* }, -* // ...and more -* ] -* -* // Create a search engine that indexes the 'title' and 'text' fields for -* // full-text search. Search results will include 'title' and 'category' (plus the -* // id field, that is always stored and returned) -* const miniSearch = MiniSearch.new({ -* fields: ['title', 'text'], -* storeFields: ['title', 'category'] -* }) -* -* // Add documents to the index -* miniSearch.addAll(documents) -* -* // Search for documents: -* let results = miniSearch.search('zen art motorcycle') -* // => [ -* { id: 2, title: 'Zen and the Art of Motorcycle Maintenance', category: 'fiction', score: 2.77258 }, -* { id: 4, title: 'Zen and the Art of Archery', category: 'non-fiction', score: 1.38629 } -* ] -* */ -class MiniSearch { - /** - * @callback MiniSearch~extractField - * @param {Object} document - A document object - * @param {string} fieldName - Name of the field to extract - * @return string - Value of the field - */ - - /** - * @callback MiniSearch~tokenize - * @param {string} text - Text to tokenize - * @param {?string} fieldName - Name of the field to tokenize - * @return string[] - Tokenized terms - */ - - /** - * @callback MiniSearch~processTerm - * @param {string} text - The text to tokenize - * @param {?string} fieldName - The name of the field to tokenize - * @return string|null|undefined|false - Processed term, or a falsy value to discard the term - */ - - /** - * @param {Object} options - Configuration options - * @param {Array} options.fields - Fields to be indexed. Required. - * @param {string} [options.idField='id'] - ID field, uniquely identifying a document - * @param {Array} [options.storeFields] - Fields to store, so that search results would include them. By default none, so resuts would only contain the id field. - * @param {MiniSearch~extractField} [options.extractField] - Function used to get the value of a field in a document - * @param {MiniSearch~tokenize} [options.tokenize] - Function used to split a field into individual terms - * @param {MiniSearch~processTerm} [options.processTerm] - Function used to process a term before indexing it or searching - * @param {Object} [options.searchOptions] - Default search options (see the `search` method for details) - * - * @example - * // Create a search engine that indexes the 'title' and 'text' fields of your - * // documents: - * const miniSearch = MiniSearch.new({ fields: ['title', 'text'] }) - * - * @example - * // Your documents are assumed to include a unique 'id' field, but if you want - * // to use a different field for document identification, you can set the - * // 'idField' option: - * const miniSearch = MiniSearch.new({ idField: 'key', fields: ['title', 'text'] }) - * - * @example - * // The full set of options (here with their default value) is: - * const miniSearch = MiniSearch.new({ - * // idField: field that uniquely identifies a document - * idField: 'id', - * - * // extractField: function used to get the value of a field in a document. - * // By default, it assumes the document is a flat object with field names as - * // property keys and field values as string property values, but custom logic - * // can be implemented by setting this option to a custom extractor function. - * extractField: (document, fieldName) => document[fieldName], - * - * // tokenize: function used to split fields into individual terms. By - * // default, it is also used to tokenize search queries, unless a specific - * // `tokenize` search option is supplied. When tokenizing an indexed field, - * // the field name is passed as the second argument. - * tokenize: (string, _fieldName) => string.split(SPACE_OR_PUNCTUATION), - * - * // processTerm: function used to process each tokenized term before - * // indexing. It can be used for stemming and normalization. Return a falsy - * // value in order to discard a term. By default, it is also used to process - * // search queries, unless a specific `processTerm` option is supplied as a - * // search option. When processing a term from a indexed field, the field - * // name is passed as the second argument. - * processTerm: (term, _fieldName) => term.toLowerCase(), - * - * // searchOptions: default search options, see the `search` method for - * // details - * searchOptions: undefined, - * - * // fields: document fields to be indexed. Mandatory, but not set by default - * fields: undefined - * - * // storeFields: document fields to be stored and returned as part of the - * // search results. - * storeFields: [] - * }) - */ - constructor (options = {}) { - /** @private */ - this._options = { ...defaultOptions, ...options } - - this._options.searchOptions = { ...defaultSearchOptions, ...(this._options.searchOptions || {}) } - const { fields } = this._options - - if (fields == null) { - throw new Error('MiniSearch: option "fields" must be provided') - } - - /** @private */ - this._index = new SearchableMap() - - /** @private */ - this._documentCount = 0 - - /** @private */ - this._documentIds = {} - - /** @private */ - this._fieldIds = {} - - /** @private */ - this._fieldLength = {} - - /** @private */ - this._averageFieldLength = {} - - /** @private */ - this._nextId = 0 - - /** @private */ - this._storedFields = {} - - addFields(this, fields) - } - - /** - * Adds a document to the index - * - * @param {Object} document - the document to be indexed - */ - add (document) { - const { extractField, tokenize, processTerm, fields, idField } = this._options - const id = extractField(document, idField) - if (id == null) { - throw new Error(`MiniSearch: document does not have ID field "${idField}"`) - } - const shortDocumentId = addDocumentId(this, id) - saveStoredFields(this, shortDocumentId, document) - - fields.forEach(field => { - const fieldValue = extractField(document, field) - if (fieldValue == null) { return } - - const tokens = tokenize(fieldValue.toString(), field) - - addFieldLength(this, shortDocumentId, this._fieldIds[field], this.documentCount - 1, tokens.length) - - tokens.forEach(term => { - const processedTerm = processTerm(term, field) - if (isTruthy(processedTerm)) { - addTerm(this, this._fieldIds[field], shortDocumentId, processedTerm) - } - }) - }) - } - - /** - * Adds all the given documents to the index - * - * @param {Object[]} documents - an array of documents to be indexed - */ - addAll (documents) { - documents.forEach(document => this.add(document)) - } - - /** - * Adds all the given documents to the index asynchronously. - * - * Returns a promise that resolves to undefined when the indexing is done. This - * method is useful when index many documents, to avoid blocking the main - * thread. The indexing is performed asynchronously and in chunks. - * - * @param {Object[]} documents - an array of documents to be indexed - * @param {Object} [options] - Configuration options - * @param {number} [options.chunkSize] - Size of the document chunks indexed, 10 by default - * @return {Promise} A promise resolving to `null` when the indexing is done - */ - addAllAsync (documents, options = {}) { - const { chunkSize = 10 } = options - const acc = { chunk: [], promise: Promise.resolve(null) } - - const { chunk, promise } = documents.reduce(({ chunk, promise }, document, i) => { - chunk.push(document) - if ((i + 1) % chunkSize === 0) { - return { chunk: [], promise: promise.then(() => this.addAll(chunk)) } - } else { - return { chunk, promise } - } - }, acc) - - return promise.then(() => this.addAll(chunk)) - } - - /** - * Removes the given document from the index. - * - * The document to delete must NOT have changed between indexing and deletion, - * otherwise the index will be corrupted. Therefore, when reindexing a document - * after a change, the correct order of operations is: - * - * 1. remove old version - * 2. apply changes - * 3. index new version - * - * @param {Object} document - the document to be removed - */ - remove (document) { - const { tokenize, processTerm, extractField, fields, idField } = this._options - const id = extractField(document, idField) - - if (id == null) { - throw new Error(`MiniSearch: document does not have ID field "${idField}"`) - } - - const [shortDocumentId] = Object.entries(this._documentIds) - .find(([_, longId]) => id === longId) || [] - - if (shortDocumentId == null) { - throw new Error(`MiniSearch: cannot remove document with ID ${id}: it is not in the index`) - } - - fields.forEach(field => { - const fieldValue = extractField(document, field) - if (fieldValue == null) { return } - - const tokens = tokenize(fieldValue.toString(), field) - - tokens.forEach(term => { - const processedTerm = processTerm(term, field) - if (isTruthy(processedTerm)) { - removeTerm(this, this._fieldIds[field], shortDocumentId, processedTerm) - } - }) - }) - - delete this._storedFields[shortDocumentId] - delete this._documentIds[shortDocumentId] - this._documentCount -= 1 - } - - /** - * Removes all the given documents from the index. If called with no arguments, - * it removes _all_ documents from the index. - * - * @param {Array} [documents] - the documents to be removed - */ - removeAll (documents) { - if (arguments.length === 0) { - this._index = new SearchableMap() - this._documentCount = 0 - this._documentIds = {} - this._fieldLength = {} - this._averageFieldLength = {} - this._storedFields = {} - this._nextId = 0 - } else { - documents.forEach(document => this.remove(document)) - } - } - - /** - * @callback MiniSearch~prefixFn - * @param {string} term - Search term - * @param {number} i - Index of the term in the query terms array - * @param {string[]} terms - Array of all query terms - * @return boolean - `true` to perform prefix search, `false` to not perform it - */ - - /** - * @callback MiniSearch~fuzzyFn - * @param {string} term - Search term - * @param {number} i - Index of the search term in the tokenized search query - * @param {string[]} terms - Array of all query terms - * @return number|false - Maximum edit distance, or `false` to not perform fuzzy search - */ - - /** - * @callback MiniSearch~filter - * @param {Object} result - A search result - * @return boolean - `true` to keep the result, `false` to filter it out - */ - - /** - * Search for documents matching the given search query. - * - * The result is a list of scored document IDs matching the query, sorted by - * descending score, and each including data about which terms were matched and - * in which fields. - * - * @param {string} queryString - Query string to search for - * @param {Object} [options] - Search options. Each option, if not given, defaults to the corresponding value of `searchOptions` given to the constructor, or to the library default. - * @param {Array} [options.fields] - Fields to search in. If omitted, all fields are searched - * @param {Object} [options.boost] - Key-value object of boosting values for fields - * @param {boolean|MiniSearch~prefixFn} [options.prefix=false] - Whether to perform prefix search. Value can be a boolean, or a function computing the boolean from each tokenized and processed query term. If a function is given, it is called with the following arguments: `term: string` - the query term; `i: number` - the term index in the query terms; `terms: Array` - the array of query terms. - * @param {number|false|MiniSearch~fuzzyFn} [options.fuzzy=false] - If set to a number greater than or equal 1, it performs fuzzy search within a maximum edit distance equal to that value. If set to a number less than 1, it performs fuzzy search with a maximum edit distance equal to the term length times the value, rouded at the nearest integer. If set to a function, it calls the function for each tokenized and processed query term and expects a numeric value indicating the maximum edit distance, or a falsy falue if fuzzy search should not be performed. If a function is given, it is called with the following arguments: `term: string` - the query term; `i: number` - the term index in the query terms; `terms: Array` - the array of query terms. - * @param {string} [options.combineWith='OR'] - How to combine term queries (it can be 'OR' or 'AND') - * @param {MiniSearch~tokenize} [options.tokenize] - Function used to tokenize the search query. It defaults to the same tokenizer used for indexing. - * @param {MiniSearch~processTerm} [options.processTerm] - Function used to process each search term. Return a falsy value to discard a term. Defaults to the same function used to process terms upon indexing. - * @param {MiniSearch~filter} [options.filter] - Function used to filter search results, for example on the basis of stored fields - * @return {Array<{ id: any, score: number, match: Object }>} A sorted array of scored document IDs matching the search - * - * @example - * // Search for "zen art motorcycle" with default options: terms have to match - * // exactly, and individual terms are joined with OR - * miniSearch.search('zen art motorcycle') - * // => [ { id: 2, score: 2.77258, match: { ... } }, { id: 4, score: 1.38629, match: { ... } } ] - * - * @example - * // Search only in the 'title' field - * miniSearch.search('zen', { fields: ['title'] }) - * - * @example - * // Boost a field - * miniSearch.search('zen', { boost: { title: 2 } }) - * - * @example - * // Search for "moto" with prefix search (it will match documents - * // containing terms that start with "moto" or "neuro") - * miniSearch.search('moto neuro', { prefix: true }) - * - * @example - * // Search for "ismael" with fuzzy search (it will match documents containing - * // terms similar to "ismael", with a maximum edit distance of 0.2 term.length - * // (rounded to nearest integer) - * miniSearch.search('ismael', { fuzzy: 0.2 }) - * - * @example - * // Mix of exact match, prefix search, and fuzzy search - * miniSearch.search('ismael mob', { - * prefix: true, - * fuzzy: 0.2 - * }) - * - * @example - * // Perform fuzzy and prefix search depending on the search term. Here - * // performing prefix and fuzzy search only on terms longer than 3 characters - * miniSearch.search('ismael mob', { - * prefix: term => term.length > 3 - * fuzzy: term => term.length > 3 ? 0.2 : null - * }) - * - * @example - * // Combine search terms with AND (to match only documents that contain both - * // "motorcycle" and "art") - * miniSearch.search('motorcycle art', { combineWith: 'AND' }) - * - * @example - * // Filter only results in the 'fiction' category (assuming that 'category' - * // is a stored field) - * miniSearch.search('motorcycle art', { - * filter: (result) => result.category === 'fiction' - * }) - */ - search (queryString, options = {}) { - const { tokenize, processTerm, searchOptions } = this._options - options = { tokenize, processTerm, ...searchOptions, ...options } - const { tokenize: searchTokenize, processTerm: searchProcessTerm } = options - const queries = searchTokenize(queryString) - .map((term) => searchProcessTerm(term)) - .filter(isTruthy) - .map(termToQuery(options)) - const results = queries.map(query => this.executeQuery(query, options)) - const combinedResults = this.combineResults(results, options.combineWith) - - return Object.entries(combinedResults) - .reduce((results, [docId, { score, match, terms }]) => { - const result = { - id: this._documentIds[docId], - terms: uniq(terms), - score, - match - } - Object.assign(result, this._storedFields[docId]) - if (options.filter == null || options.filter(result)) { - results.push(result) - } - return results - }, []) - .sort(({ score: a }, { score: b }) => a < b ? 1 : -1) - } - - /** - * Provide suggestions for the given search query - * - * The result is a list of suggested modified search queries, derived from the - * given search query, each with a relevance score, sorted by descending score. - * - * @param {string} queryString - Query string to be expanded into suggestions - * @param {Object} [options] - Search options. The supported options and default values are the same as for the `search` method, except that by default prefix search is performed on the last term in the query. - * @return {Array<{ suggestion: string, score: number }>} A sorted array of suggestions sorted by relevance score. - * - * @example - * // Get suggestions for 'neuro': - * miniSearch.autoSuggest('neuro') - * // => [ { suggestion: 'neuromancer', terms: [ 'neuromancer' ], score: 0.46240 } ] - * - * @example - * // Get suggestions for 'zen ar': - * miniSearch.autoSuggest('zen ar') - * // => [ - * // { suggestion: 'zen archery art', terms: [ 'zen', 'archery', 'art' ], score: 1.73332 }, - * // { suggestion: 'zen art', terms: [ 'zen', 'art' ], score: 1.21313 } - * // ] - * - * @example - * // Correct spelling mistakes using fuzzy search: - * miniSearch.autoSuggest('neromancer', { fuzzy: 0.2 }) - * // => [ { suggestion: 'neuromancer', terms: [ 'neuromancer' ], score: 1.03998 } ] - * - * @example - * // Get suggestions for 'zen ar', but only within the 'fiction' category - * // (assuming that 'category' is a stored field): - * miniSearch.autoSuggest('zen ar', { - * filter: (result) => result.category === 'fiction' - * }) - * // => [ - * // { suggestion: 'zen archery art', terms: [ 'zen', 'archery', 'art' ], score: 1.73332 }, - * // { suggestion: 'zen art', terms: [ 'zen', 'art' ], score: 1.21313 } - * // ] - */ - autoSuggest (queryString, options = {}) { - options = { ...defaultAutoSuggestOptions, ...options } - const suggestions = this.search(queryString, options).reduce((suggestions, { score, terms }) => { - const phrase = terms.join(' ') - if (suggestions[phrase] == null) { - suggestions[phrase] = { score, terms, count: 1 } - } else { - suggestions[phrase].score += score - suggestions[phrase].count += 1 - } - return suggestions - }, {}) - return Object.entries(suggestions) - .map(([suggestion, { score, terms, count }]) => ({ suggestion, terms, score: score / count })) - .sort(({ score: a }, { score: b }) => a < b ? 1 : -1) - } - - /** - * Number of documents in the index - * - * @type {number} - */ - get documentCount () { - return this._documentCount - } - - /** - * Deserializes a JSON index (serialized with `miniSearch.toJSON()`) and - * instantiates a MiniSearch instance. It should be given the same options - * originally used when serializing the index. - * - * @example - * // If the index was serialized with: - * let miniSearch = new MiniSearch({ fields: ['title', 'text'] }) - * miniSearch.addAll(documents) - * - * const json = JSON.stringify(miniSearch) - * // It can later be deserialized like this: - * miniSearch = MiniSearch.loadJSON(json, { fields: ['title', 'text'] }) - * - * @param {string} json - JSON-serialized index - * @param {Object} options - configuration options, same as the constructor - * @return {MiniSearch} an instance of MiniSearch - */ - static loadJSON (json, options) { - if (options == null) { - throw new Error('MiniSearch: loadJSON should be given the same options used when serializing the index') - } - return MiniSearch.loadJS(JSON.parse(json), options) - } - - /** - * Get the default value of an option. It will throw an error if no option with - * the given name exists. - * - * @param {string} optionName - name of the option - * @return {any} the default value of the given option - * - * @example - * // Get default tokenizer - * MiniSearch.getDefault('tokenize') - * - * @example - * // Get default term processor - * MiniSearch.getDefault('processTerm') - * - * @example - * // Unknown options will throw an error - * MiniSearch.getDefault('notExisting') - * // => throws 'MiniSearch: unknown option "notExisting"' - */ - static getDefault (optionName) { - if (defaultOptions.hasOwnProperty(optionName)) { - return defaultOptions[optionName] - } else { - throw new Error(`MiniSearch: unknown option "${optionName}"`) - } - } - - /** - * @private - */ - static loadJS (js, options = {}) { - const { - index, - documentCount, - nextId, - documentIds, - fieldIds, - fieldLength, - averageFieldLength, - storedFields - } = js - const miniSearch = new MiniSearch(options) - miniSearch._index = new SearchableMap(index._tree, index._prefix) - miniSearch._documentCount = documentCount - miniSearch._nextId = nextId - miniSearch._documentIds = documentIds - miniSearch._fieldIds = fieldIds - miniSearch._fieldLength = fieldLength - miniSearch._averageFieldLength = averageFieldLength - miniSearch._fieldIds = fieldIds - miniSearch._storedFields = storedFields || {} - return miniSearch - } - - /** - * @private - * @ignore - */ - executeQuery (query, options = {}) { - options = { ...this._options.searchOptions, ...options } - - const boosts = (options.fields || this._options.fields).reduce((boosts, field) => - ({ ...boosts, [field]: getOwnProperty(boosts, field) || 1 }), options.boost || {}) - - const { - boostDocument, - weights: { fuzzy: fuzzyWeight = 0.9, prefix: prefixWeight = 0.75 } - } = options - - const exactMatch = termResults(this, query.term, boosts, boostDocument, this._index.get(query.term)) - - if (!query.fuzzy && !query.prefix) { return exactMatch } - - const results = [exactMatch] - - if (query.prefix) { - this._index.atPrefix(query.term).forEach((term, data) => { - const weightedDistance = (0.3 * (term.length - query.term.length)) / term.length - results.push(termResults(this, term, boosts, boostDocument, data, prefixWeight, weightedDistance)) - }) - } - - if (query.fuzzy) { - const maxDistance = query.fuzzy < 1 ? Math.round(query.term.length * query.fuzzy) : query.fuzzy - Object.entries(this._index.fuzzyGet(query.term, maxDistance)).forEach(([term, [data, distance]]) => { - const weightedDistance = distance / term.length - results.push(termResults(this, term, boosts, boostDocument, data, fuzzyWeight, weightedDistance)) - }) - } - - return results.reduce(combinators[OR], {}) - } - - /** - * @private - * @ignore - */ - combineResults (results, combineWith = OR) { - if (results.length === 0) { return {} } - const operator = combineWith.toLowerCase() - return results.reduce(combinators[operator], null) - } - - /** - * Allows serialization of the index to JSON, to possibly store it and later - * deserialize it with `MiniSearch.loadJSON`. - * - * Normally one does not directly call this method, but rather call the - * standard JavaScript `JSON.stringify()` passing the `MiniSearch` instance, - * and JavaScript will internally call this method. Upon deserialization, one - * must pass to `loadJSON` the same options used to create the original - * instance that was serialized. - * - * @example - * // Serialize the index: - * let miniSearch = new MiniSearch({ fields: ['title', 'text'] }) - * miniSearch.addAll(documents) - * const json = JSON.stringify(miniSearch) - * - * // Later, to deserialize it: - * miniSearch = MiniSearch.loadJSON(json, { fields: ['title', 'text'] }) - * - * @return {Object} the serializeable representation of the search index - */ - toJSON () { - return { - index: this._index, - documentCount: this._documentCount, - nextId: this._nextId, - documentIds: this._documentIds, - fieldIds: this._fieldIds, - fieldLength: this._fieldLength, - averageFieldLength: this._averageFieldLength, - storedFields: this._storedFields - } - } -} - -MiniSearch.SearchableMap = SearchableMap - -const addTerm = function (self, fieldId, documentId, term) { - self._index.update(term, indexData => { - indexData = indexData || {} - const fieldIndex = indexData[fieldId] || { df: 0, ds: {} } - if (fieldIndex.ds[documentId] == null) { fieldIndex.df += 1 } - fieldIndex.ds[documentId] = (fieldIndex.ds[documentId] || 0) + 1 - return { ...indexData, [fieldId]: fieldIndex } - }) -} - -const removeTerm = function (self, fieldId, documentId, term) { - if (!self._index.has(term)) { - warnDocumentChanged(self, documentId, fieldId, term) - return - } - self._index.update(term, indexData => { - const fieldIndex = indexData[fieldId] - if (fieldIndex == null || fieldIndex.ds[documentId] == null) { - warnDocumentChanged(self, documentId, fieldId, term) - return indexData - } - if (fieldIndex.ds[documentId] <= 1) { - if (fieldIndex.df <= 1) { - delete indexData[fieldId] - return indexData - } - fieldIndex.df -= 1 - } - if (fieldIndex.ds[documentId] <= 1) { - delete fieldIndex.ds[documentId] - return indexData - } - fieldIndex.ds[documentId] -= 1 - return { ...indexData, [fieldId]: fieldIndex } - }) - if (Object.keys(self._index.get(term)).length === 0) { - self._index.delete(term) - } -} - -const warnDocumentChanged = function (self, shortDocumentId, fieldId, term) { - if (console == null || console.warn == null) { return } - const fieldName = Object.entries(self._fieldIds).find(([name, id]) => id === fieldId)[0] - console.warn(`MiniSearch: document with ID ${self._documentIds[shortDocumentId]} has changed before removal: term "${term}" was not present in field "${fieldName}". Removing a document after it has changed can corrupt the index!`) -} - -const addDocumentId = function (self, documentId) { - const shortDocumentId = self._nextId.toString(36) - self._documentIds[shortDocumentId] = documentId - self._documentCount += 1 - self._nextId += 1 - return shortDocumentId -} - -const addFields = function (self, fields) { - fields.forEach((field, i) => { self._fieldIds[field] = i }) -} - -const termResults = function (self, term, boosts, boostDocument, indexData, weight = 1, editDistance = 0) { - if (indexData == null) { return {} } - return Object.entries(boosts).reduce((results, [field, boost]) => { - const fieldId = self._fieldIds[field] - const { df, ds } = indexData[fieldId] || { ds: {} } - Object.entries(ds).forEach(([documentId, tf]) => { - const docBoost = boostDocument ? boostDocument(self._documentIds[documentId], term) : 1 - if (!docBoost) { return } - const normalizedLength = self._fieldLength[documentId][fieldId] / self._averageFieldLength[fieldId] - results[documentId] = results[documentId] || { score: 0, match: {}, terms: [] } - results[documentId].terms.push(term) - results[documentId].match[term] = getOwnProperty(results[documentId].match, term) || [] - results[documentId].score += docBoost * score(tf, df, self._documentCount, normalizedLength, boost, editDistance) - results[documentId].match[term].push(field) - }) - return results - }, {}) -} - -const getOwnProperty = function (object, property) { - return Object.prototype.hasOwnProperty.call(object, property) ? object[property] : undefined -} - -const addFieldLength = function (self, documentId, fieldId, count, length) { - self._averageFieldLength[fieldId] = self._averageFieldLength[fieldId] || 0 - const totalLength = (self._averageFieldLength[fieldId] * count) + length - self._fieldLength[documentId] = self._fieldLength[documentId] || {} - self._fieldLength[documentId][fieldId] = length - self._averageFieldLength[fieldId] = totalLength / (count + 1) -} - -const saveStoredFields = function (self, documentId, doc) { - const { storeFields, extractField } = self._options - if (storeFields == null || storeFields.length === 0) { return } - self._storedFields[documentId] = self._storedFields[documentId] || {} - - storeFields.forEach((fieldName) => { - const fieldValue = extractField(doc, fieldName) - if (fieldValue === undefined) { return } - self._storedFields[documentId][fieldName] = fieldValue - }) -} - -const combinators = { - [OR]: function (a, b) { - return Object.entries(b).reduce((combined, [documentId, { score, match, terms }]) => { - if (combined[documentId] == null) { - combined[documentId] = { score, match, terms } - } else { - combined[documentId].score += score - combined[documentId].score *= 1.5 - combined[documentId].terms = [...combined[documentId].terms, ...terms] - Object.assign(combined[documentId].match, match) - } - return combined - }, a || {}) - }, - [AND]: function (a, b) { - if (a == null) { return b } - return Object.entries(b).reduce((combined, [documentId, { score, match, terms }]) => { - if (a[documentId] === undefined) { return combined } - combined[documentId] = combined[documentId] || {} - combined[documentId].score = a[documentId].score + score - combined[documentId].match = { ...a[documentId].match, ...match } - combined[documentId].terms = [...a[documentId].terms, ...terms] - return combined - }, {}) - } -} - -const tfIdf = function (tf, df, n) { - return tf * Math.log(n / df) -} - -const score = function (termFrequency, documentFrequency, documentCount, normalizedLength, boost, editDistance) { - const weight = boost / (1 + (0.333 * boost * editDistance)) - return weight * tfIdf(termFrequency, documentFrequency, documentCount) / normalizedLength -} - -const termToQuery = (options) => (term, i, terms) => { - const fuzzy = (typeof options.fuzzy === 'function') - ? options.fuzzy(term, i, terms) - : options.fuzzy - const prefix = (typeof options.prefix === 'function') - ? options.prefix(term, i, terms) - : options.prefix - return { term, fuzzy, prefix } -} - -const uniq = function (array) { - return array.filter((element, i, array) => array.indexOf(element) === i) -} - -const isTruthy = (x) => !!x - -const defaultOptions = { - idField: 'id', - extractField: (document, fieldName) => document[fieldName], - tokenize: (string, _fieldName) => string.split(SPACE_OR_PUNCTUATION), - processTerm: (term, _fieldName) => term.toLowerCase(), - fields: undefined, - searchOptions: undefined, - storeFields: [] -} - -const defaultSearchOptions = { - combineWith: OR, - prefix: false, - fuzzy: false, - weights: {} -} - -const defaultAutoSuggestOptions = { - prefix: (term, i, terms) => i === terms.length - 1 -} - -// This regular expression matches any Unicode space or punctuation character -// Adapted from https://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7BZ%7D%5Cp%7BP%7D&abb=on&c=on&esc=on -const SPACE_OR_PUNCTUATION = /[\n\r -#%-*,-/:;?@[-\]_{}\u00A0\u00A1\u00A7\u00AB\u00B6\u00B7\u00BB\u00BF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u1680\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2000-\u200A\u2010-\u2029\u202F-\u2043\u2045-\u2051\u2053-\u205F\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u3000-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]+/u - -export default MiniSearch diff --git a/src/MiniSearch.test.js b/src/MiniSearch.test.js index 9f70a460..039f32b6 100644 --- a/src/MiniSearch.test.js +++ b/src/MiniSearch.test.js @@ -1,6 +1,6 @@ /* eslint-env jest */ -import MiniSearch from './MiniSearch.js' +import MiniSearch from './MiniSearch' describe('MiniSearch', () => { describe('constructor', () => { diff --git a/src/MiniSearch.ts b/src/MiniSearch.ts new file mode 100644 index 00000000..b4ff136d --- /dev/null +++ b/src/MiniSearch.ts @@ -0,0 +1,1020 @@ +import SearchableMap from './SearchableMap/SearchableMap' + +const OR = 'or' +const AND = 'and' + +export type SearchOptions = { + fields?: string[], + + filter?: (result: SearchResult) => boolean, + + boost?: { [fieldName: string]: number }, + + weights?: { fuzzy: number, prefix: number }, + + boostDocument?: (documentId: any, term: string) => number, + + prefix?: boolean | ((term: string, index: number, terms: string[]) => boolean), + + fuzzy?: boolean | number | ((term: string, index: number, terms: string[]) => boolean | number), + + combineWith?: string, + + extractField?: (document: T, fieldName: string) => string, + + tokenize?: (text: string) => string[], + + processTerm?: (term: string) => string | null | undefined | false +} + +export type SearchOptionsWithDefaults = SearchOptions & { + boost: { [fieldName: string]: number }, + + weights: { fuzzy: number, prefix: number }, + + prefix: boolean | ((term: string, index: number, terms: string[]) => boolean), + + fuzzy: boolean | number | ((term: string, index: number, terms: string[]) => boolean | number), + + combineWith: string +} + +export type Options = { + fields: string[], + + storeFields?: string[], + + idField?: string, + + extractField?: (document: T, fieldName: string) => string, + + tokenize?: (text: string, fieldName?: string) => string[], + + processTerm?: (term: string, fieldName?: string) => string | null | undefined | false, + + searchOptions?: SearchOptions +} + +type OptionsWithDefaults = Options & { + storeFields: string[], + + idField: string, + + extractField: (document: T, fieldName: string) => string, + + tokenize: (text: string, fieldName: string) => string[], + + processTerm: (term: string, fieldName: string) => string | null | undefined | false, + + searchOptions: SearchOptionsWithDefaults +} + +export type Suggestion = { + suggestion: string, + terms: string[], + score: number +} + +export type MatchInfo = { + [term: string]: string[] +} + +export type SearchResult = { + id: any, + terms: string[], + score: number, + match: MatchInfo, + [key: string]: any +} + +export type AsPlainObject = { + index: { _tree: {}, _prefix: string }, + documentCount: number, + nextId: number, + documentIds: { [shortId: string]: any } + fieldIds: { [fieldName: string]: number } + fieldLength: { [shortId: string]: { [fieldId: string]: number } }, + averageFieldLength: { [fieldId: string]: number }, + storedFields: { [shortId: string]: any } +} + +type Query = { + prefix: boolean, + fuzzy: number | boolean, + term: string +} + +type IndexData = { + [fieldId: string]: { df: number, ds: { [shortId: string]: number } } +} + +type RawResult = { + [shortId: string]: { score: number, match: MatchInfo, terms: string[] } +} + +/** + * MiniSearch is the main entrypoint class, and represents a full-text search + * engine. + * + * @example + * const documents = [ + * { + * id: 1, + * title: 'Moby Dick', + * text: 'Call me Ishmael. Some years ago...', + * category: 'fiction' + * }, + * { + * id: 2, + * title: 'Zen and the Art of Motorcycle Maintenance', + * text: 'I can see by my watch...', + * category: 'fiction' + * }, + * { + * id: 3, + * title: 'Neuromancer', + * text: 'The sky above the port was...', + * category: 'fiction' + * }, + * { + * id: 4, + * title: 'Zen and the Art of Archery', + * text: 'At first sight it must seem...', + * category: 'non-fiction' + * }, + * // ...and more + * ] + * + * // Create a search engine that indexes the 'title' and 'text' fields for + * // full-text search. Search results will include 'title' and 'category' (plus the + * // id field, that is always stored and returned) + * const miniSearch = MiniSearch.new({ + * fields: ['title', 'text'], + * storeFields: ['title', 'category'] + * }) + * + * // Add documents to the index + * miniSearch.addAll(documents) + * + * // Search for documents: + * let results = miniSearch.search('zen art motorcycle') + * // => [ + * { id: 2, title: 'Zen and the Art of Motorcycle Maintenance', category: 'fiction', score: 2.77258 }, + * { id: 4, title: 'Zen and the Art of Archery', category: 'non-fiction', score: 1.38629 } + * ] + */ +class MiniSearch { + /** + * @callback MiniSearch~extractField + * @param {Object} document - A document object + * @param {string} fieldName - Name of the field to extract + * @return string - Value of the field + */ + + /** + * @callback MiniSearch~tokenize + * @param {string} text - Text to tokenize + * @param {?string} fieldName - Name of the field to tokenize + * @return string[] - Tokenized terms + */ + + /** + * @callback MiniSearch~processTerm + * @param {string} text - The text to tokenize + * @param {?string} fieldName - The name of the field to tokenize + * @return string|null|undefined|false - Processed term, or a falsy value to discard the term + */ + + /** + * @param {Object} options - Configuration options + * @param {Array} options.fields - Fields to be indexed. Required. + * @param {string} [options.idField='id'] - ID field, uniquely identifying a document + * @param {Array} [options.storeFields] - Fields to store, so that search results would include them. By default none, so resuts would only contain the id field. + * @param {MiniSearch~extractField} [options.extractField] - Function used to get the value of a field in a document + * @param {MiniSearch~tokenize} [options.tokenize] - Function used to split a field into individual terms + * @param {MiniSearch~processTerm} [options.processTerm] - Function used to process a term before indexing it or searching + * @param {Object} [options.searchOptions] - Default search options (see the `search` method for details) + * + * @example + * // Create a search engine that indexes the 'title' and 'text' fields of your + * // documents: + * const miniSearch = MiniSearch.new({ fields: ['title', 'text'] }) + * + * @example + * // Your documents are assumed to include a unique 'id' field, but if you want + * // to use a different field for document identification, you can set the + * // 'idField' option: + * const miniSearch = MiniSearch.new({ idField: 'key', fields: ['title', 'text'] }) + * + * @example + * // The full set of options (here with their default value) is: + * const miniSearch = MiniSearch.new({ + * // idField: field that uniquely identifies a document + * idField: 'id', + * + * // extractField: function used to get the value of a field in a document. + * // By default, it assumes the document is a flat object with field names as + * // property keys and field values as string property values, but custom logic + * // can be implemented by setting this option to a custom extractor function. + * extractField: (document, fieldName) => document[fieldName], + * + * // tokenize: function used to split fields into individual terms. By + * // default, it is also used to tokenize search queries, unless a specific + * // `tokenize` search option is supplied. When tokenizing an indexed field, + * // the field name is passed as the second argument. + * tokenize: (string, _fieldName) => string.split(SPACE_OR_PUNCTUATION), + * + * // processTerm: function used to process each tokenized term before + * // indexing. It can be used for stemming and normalization. Return a falsy + * // value in order to discard a term. By default, it is also used to process + * // search queries, unless a specific `processTerm` option is supplied as a + * // search option. When processing a term from a indexed field, the field + * // name is passed as the second argument. + * processTerm: (term, _fieldName) => term.toLowerCase(), + * + * // searchOptions: default search options, see the `search` method for + * // details + * searchOptions: undefined, + * + * // fields: document fields to be indexed. Mandatory, but not set by default + * fields: undefined + * + * // storeFields: document fields to be stored and returned as part of the + * // search results. + * storeFields: [] + * }) + */ + + protected _options: OptionsWithDefaults + protected _index: SearchableMap + protected _documentCount: number + protected _documentIds: { [shortId: string]: any } + protected _fieldIds: { [fieldName: string]: number } + protected _fieldLength: { [shortId: string]: { [fieldId: string]: number } } + protected _averageFieldLength: { [fieldId: string]: number } + protected _nextId: number + protected _storedFields: { [shortId: string]: any } + + constructor (options: Options) { + if (options?.fields == null) { + throw new Error('MiniSearch: option "fields" must be provided') + } + + /** @private */ + this._options = { + ...defaultOptions, + ...options, + searchOptions: { ...defaultSearchOptions, ...(options.searchOptions || {}) } + } + + /** @private */ + this._index = new SearchableMap() + + /** @private */ + this._documentCount = 0 + + /** @private */ + this._documentIds = {} + + /** @private */ + this._fieldIds = {} + + /** @private */ + this._fieldLength = {} + + /** @private */ + this._averageFieldLength = {} + + /** @private */ + this._nextId = 0 + + /** @private */ + this._storedFields = {} + + this.addFields(this._options.fields) + } + + /** + * Adds a document to the index + * + * @param {Object} document - the document to be indexed + */ + add (document: T): void { + const { extractField, tokenize, processTerm, fields, idField } = this._options + const id = extractField(document, idField) + if (id == null) { + throw new Error(`MiniSearch: document does not have ID field "${idField}"`) + } + const shortDocumentId = this.addDocumentId(id) + this.saveStoredFields(shortDocumentId, document) + + fields.forEach(field => { + const fieldValue = extractField(document, field) + if (fieldValue == null) { return } + + const tokens = tokenize(fieldValue.toString(), field) + + this.addFieldLength(shortDocumentId, this._fieldIds[field], this.documentCount - 1, tokens.length) + + tokens.forEach(term => { + const processedTerm = processTerm(term, field) + if (processedTerm) { + this.addTerm(this._fieldIds[field], shortDocumentId, processedTerm) + } + }) + }) + } + + /** + * Adds all the given documents to the index + * + * @param {Object[]} documents - an array of documents to be indexed + */ + addAll (documents: T[]): void { + documents.forEach(document => this.add(document)) + } + + /** + * Adds all the given documents to the index asynchronously. + * + * Returns a promise that resolves to undefined when the indexing is done. This + * method is useful when index many documents, to avoid blocking the main + * thread. The indexing is performed asynchronously and in chunks. + * + * @param {Object[]} documents - an array of documents to be indexed + * @param {Object} [options] - Configuration options + * @param {number} [options.chunkSize] - Size of the document chunks indexed, 10 by default + * @return {Promise} A promise resolving to `null` when the indexing is done + */ + addAllAsync (documents: T[], options: { chunkSize?: number } = {}): Promise { + const { chunkSize = 10 } = options + const acc: { chunk: T[], promise: Promise } = { chunk: [], promise: Promise.resolve() } + + const { chunk, promise } = documents.reduce(({ chunk, promise }, document: T, i: number) => { + chunk.push(document) + if ((i + 1) % chunkSize === 0) { + return { chunk: [], promise: promise.then(() => this.addAll(chunk)) } + } else { + return { chunk, promise } + } + }, acc) + + return promise.then(() => this.addAll(chunk)) + } + + /** + * Removes the given document from the index. + * + * The document to delete must NOT have changed between indexing and deletion, + * otherwise the index will be corrupted. Therefore, when reindexing a document + * after a change, the correct order of operations is: + * + * 1. remove old version + * 2. apply changes + * 3. index new version + * + * @param {Object} document - the document to be removed + */ + remove (document: T): void { + const { tokenize, processTerm, extractField, fields, idField } = this._options + const id = extractField(document, idField) + + if (id == null) { + throw new Error(`MiniSearch: document does not have ID field "${idField}"`) + } + + const [shortDocumentId] = Object.entries(this._documentIds) + .find(([_, longId]) => id === longId) || [] + + if (shortDocumentId == null) { + throw new Error(`MiniSearch: cannot remove document with ID ${id}: it is not in the index`) + } + + fields.forEach(field => { + const fieldValue = extractField(document, field) + if (fieldValue == null) { return } + + const tokens = tokenize(fieldValue.toString(), field) + + tokens.forEach(term => { + const processedTerm = processTerm(term, field) + if (processedTerm) { + this.removeTerm(this._fieldIds[field], shortDocumentId, processedTerm) + } + }) + }) + + delete this._storedFields[shortDocumentId] + delete this._documentIds[shortDocumentId] + this._documentCount -= 1 + } + + /** + * Removes all the given documents from the index. If called with no arguments, + * it removes _all_ documents from the index. + * + * @param {Array} [documents] - the documents to be removed + */ + removeAll (documents: T[]): void { + if (arguments.length === 0) { + this._index = new SearchableMap() + this._documentCount = 0 + this._documentIds = {} + this._fieldLength = {} + this._averageFieldLength = {} + this._storedFields = {} + this._nextId = 0 + } else { + documents.forEach(document => this.remove(document)) + } + } + + /** + * @callback MiniSearch~prefixFn + * @param {string} term - Search term + * @param {number} i - Index of the term in the query terms array + * @param {string[]} terms - Array of all query terms + * @return boolean - `true` to perform prefix search, `false` to not perform it + */ + + /** + * @callback MiniSearch~fuzzyFn + * @param {string} term - Search term + * @param {number} i - Index of the search term in the tokenized search query + * @param {string[]} terms - Array of all query terms + * @return number|false - Maximum edit distance, or `false` to not perform fuzzy search + */ + + /** + * @callback MiniSearch~filter + * @param {Object} result - A search result + * @return boolean - `true` to keep the result, `false` to filter it out + */ + + /** + * Search for documents matching the given search query. + * + * The result is a list of scored document IDs matching the query, sorted by + * descending score, and each including data about which terms were matched and + * in which fields. + * + * @param {string} queryString - Query string to search for + * @param {Object} [options] - Search options. Each option, if not given, defaults to the corresponding value of `searchOptions` given to the constructor, or to the library default. + * @param {Array} [options.fields] - Fields to search in. If omitted, all fields are searched + * @param {Object} [options.boost] - Key-value object of boosting values for fields + * @param {boolean|MiniSearch~prefixFn} [options.prefix=false] - Whether to perform prefix search. Value can be a boolean, or a function computing the boolean from each tokenized and processed query term. If a function is given, it is called with the following arguments: `term: string` - the query term; `i: number` - the term index in the query terms; `terms: Array` - the array of query terms. + * @param {number|false|MiniSearch~fuzzyFn} [options.fuzzy=false] - If set to a number greater than or equal 1, it performs fuzzy search within a maximum edit distance equal to that value. If set to a number less than 1, it performs fuzzy search with a maximum edit distance equal to the term length times the value, rouded at the nearest integer. If set to a function, it calls the function for each tokenized and processed query term and expects a numeric value indicating the maximum edit distance, or a falsy falue if fuzzy search should not be performed. If a function is given, it is called with the following arguments: `term: string` - the query term; `i: number` - the term index in the query terms; `terms: Array` - the array of query terms. + * @param {string} [options.combineWith='OR'] - How to combine term queries (it can be 'OR' or 'AND') + * @param {MiniSearch~tokenize} [options.tokenize] - Function used to tokenize the search query. It defaults to the same tokenizer used for indexing. + * @param {MiniSearch~processTerm} [options.processTerm] - Function used to process each search term. Return a falsy value to discard a term. Defaults to the same function used to process terms upon indexing. + * @param {MiniSearch~filter} [options.filter] - Function used to filter search results, for example on the basis of stored fields + * @return {Array<{ id: any, score: number, match: Object }>} A sorted array of scored document IDs matching the search + * + * @example + * // Search for "zen art motorcycle" with default options: terms have to match + * // exactly, and individual terms are joined with OR + * miniSearch.search('zen art motorcycle') + * // => [ { id: 2, score: 2.77258, match: { ... } }, { id: 4, score: 1.38629, match: { ... } } ] + * + * @example + * // Search only in the 'title' field + * miniSearch.search('zen', { fields: ['title'] }) + * + * @example + * // Boost a field + * miniSearch.search('zen', { boost: { title: 2 } }) + * + * @example + * // Search for "moto" with prefix search (it will match documents + * // containing terms that start with "moto" or "neuro") + * miniSearch.search('moto neuro', { prefix: true }) + * + * @example + * // Search for "ismael" with fuzzy search (it will match documents containing + * // terms similar to "ismael", with a maximum edit distance of 0.2 term.length + * // (rounded to nearest integer) + * miniSearch.search('ismael', { fuzzy: 0.2 }) + * + * @example + * // Mix of exact match, prefix search, and fuzzy search + * miniSearch.search('ismael mob', { + * prefix: true, + * fuzzy: 0.2 + * }) + * + * @example + * // Perform fuzzy and prefix search depending on the search term. Here + * // performing prefix and fuzzy search only on terms longer than 3 characters + * miniSearch.search('ismael mob', { + * prefix: term => term.length > 3 + * fuzzy: term => term.length > 3 ? 0.2 : null + * }) + * + * @example + * // Combine search terms with AND (to match only documents that contain both + * // "motorcycle" and "art") + * miniSearch.search('motorcycle art', { combineWith: 'AND' }) + * + * @example + * // Filter only results in the 'fiction' category (assuming that 'category' + * // is a stored field) + * miniSearch.search('motorcycle art', { + * filter: (result) => result.category === 'fiction' + * }) + */ + search (queryString: string, searchOptions: SearchOptions = {}): SearchResult[] { + const { tokenize, processTerm, searchOptions: globalSearchOptions } = this._options + const options = { tokenize, processTerm, ...globalSearchOptions, ...searchOptions } + const { tokenize: searchTokenize, processTerm: searchProcessTerm } = options + const terms = searchTokenize(queryString) + .map((term: string) => searchProcessTerm(term)) + .filter((term) => !!term) as string[] + const queries: Query[] = terms.map(termToQuery(options)) + const results = queries.map(query => this.executeQuery(query, options)) + const combinedResults: RawResult = this.combineResults(results, options.combineWith) + + return Object.entries(combinedResults) + .reduce((results: { id: any, terms: string[], score: number, match: MatchInfo }[], [docId, { score, match, terms }]) => { + const result = { + id: this._documentIds[docId], + terms: uniq(terms), + score, + match + } + Object.assign(result, this._storedFields[docId]) + if (options.filter == null || options.filter(result)) { + results.push(result) + } + return results + }, []) + .sort(({ score: a }, { score: b }) => a < b ? 1 : -1) + } + + /** + * Provide suggestions for the given search query + * + * The result is a list of suggested modified search queries, derived from the + * given search query, each with a relevance score, sorted by descending score. + * + * @param {string} queryString - Query string to be expanded into suggestions + * @param {Object} [options] - Search options. The supported options and default values are the same as for the `search` method, except that by default prefix search is performed on the last term in the query. + * @return {Array<{ suggestion: string, score: number }>} A sorted array of suggestions sorted by relevance score. + * + * @example + * // Get suggestions for 'neuro': + * miniSearch.autoSuggest('neuro') + * // => [ { suggestion: 'neuromancer', terms: [ 'neuromancer' ], score: 0.46240 } ] + * + * @example + * // Get suggestions for 'zen ar': + * miniSearch.autoSuggest('zen ar') + * // => [ + * // { suggestion: 'zen archery art', terms: [ 'zen', 'archery', 'art' ], score: 1.73332 }, + * // { suggestion: 'zen art', terms: [ 'zen', 'art' ], score: 1.21313 } + * // ] + * + * @example + * // Correct spelling mistakes using fuzzy search: + * miniSearch.autoSuggest('neromancer', { fuzzy: 0.2 }) + * // => [ { suggestion: 'neuromancer', terms: [ 'neuromancer' ], score: 1.03998 } ] + * + * @example + * // Get suggestions for 'zen ar', but only within the 'fiction' category + * // (assuming that 'category' is a stored field): + * miniSearch.autoSuggest('zen ar', { + * filter: (result) => result.category === 'fiction' + * }) + * // => [ + * // { suggestion: 'zen archery art', terms: [ 'zen', 'archery', 'art' ], score: 1.73332 }, + * // { suggestion: 'zen art', terms: [ 'zen', 'art' ], score: 1.21313 } + * // ] + */ + autoSuggest (queryString: string, options: SearchOptions = {}): Suggestion[] { + options = { ...defaultAutoSuggestOptions, ...options } + const suggestions = this.search(queryString, options).reduce(( + suggestions: { [phrase: string]: Omit & { count: number } }, + { score, terms } + ) => { + const phrase = terms.join(' ') + if (suggestions[phrase] == null) { + suggestions[phrase] = { score, terms, count: 1 } + } else { + suggestions[phrase].score += score + suggestions[phrase].count += 1 + } + return suggestions + }, {}) + return Object.entries(suggestions) + .map(([suggestion, { score, terms, count }]) => ({ suggestion, terms, score: score / count })) + .sort(({ score: a }, { score: b }) => a < b ? 1 : -1) + } + + /** + * Number of documents in the index + * + * @type {number} + */ + get documentCount (): number { + return this._documentCount + } + + /** + * Deserializes a JSON index (serialized with `miniSearch.toJSON()`) and + * instantiates a MiniSearch instance. It should be given the same options + * originally used when serializing the index. + * + * @example + * // If the index was serialized with: + * let miniSearch = new MiniSearch({ fields: ['title', 'text'] }) + * miniSearch.addAll(documents) + * + * const json = JSON.stringify(miniSearch) + * // It can later be deserialized like this: + * miniSearch = MiniSearch.loadJSON(json, { fields: ['title', 'text'] }) + * + * @param {string} json - JSON-serialized index + * @param {Object} options - configuration options, same as the constructor + * @return {MiniSearch} an instance of MiniSearch + */ + static loadJSON (json: string, options: Options): MiniSearch { + if (options == null) { + throw new Error('MiniSearch: loadJSON should be given the same options used when serializing the index') + } + return MiniSearch.loadJS(JSON.parse(json), options) + } + + /** + * Get the default value of an option. It will throw an error if no option with + * the given name exists. + * + * @param {string} optionName - name of the option + * @return {any} the default value of the given option + * + * @example + * // Get default tokenizer + * MiniSearch.getDefault('tokenize') + * + * @example + * // Get default term processor + * MiniSearch.getDefault('processTerm') + * + * @example + * // Unknown options will throw an error + * MiniSearch.getDefault('notExisting') + * // => throws 'MiniSearch: unknown option "notExisting"' + */ + static getDefault (optionName: string): any { + if (defaultOptions.hasOwnProperty(optionName)) { + return getOwnProperty(defaultOptions, optionName) + } else { + throw new Error(`MiniSearch: unknown option "${optionName}"`) + } + } + + /** + * @private + */ + static loadJS (js: AsPlainObject, options: Options): MiniSearch { + const { + index, + documentCount, + nextId, + documentIds, + fieldIds, + fieldLength, + averageFieldLength, + storedFields + } = js + const miniSearch = new MiniSearch(options) + + miniSearch._index = new SearchableMap(index._tree, index._prefix) + miniSearch._documentCount = documentCount + miniSearch._nextId = nextId + miniSearch._documentIds = documentIds + miniSearch._fieldIds = fieldIds + miniSearch._fieldLength = fieldLength + miniSearch._averageFieldLength = averageFieldLength + miniSearch._fieldIds = fieldIds + miniSearch._storedFields = storedFields || {} + + return miniSearch + } + + /** + * @private + * @ignore + */ + private executeQuery (query: Query, searchOptions: SearchOptions): RawResult { + const options: SearchOptionsWithDefaults = { ...this._options.searchOptions, ...searchOptions } + + const boosts = (options.fields || this._options.fields).reduce((boosts, field) => + ({ ...boosts, [field]: getOwnProperty(boosts, field) || 1 }), options.boost || {}) + + const { + boostDocument, + weights + } = options + + const { fuzzy: fuzzyWeight, prefix: prefixWeight } = { ...defaultSearchOptions.weights, ...weights } + + const exactMatch = this.termResults(query.term, boosts, boostDocument, this._index.get(query.term)) + + if (!query.fuzzy && !query.prefix) { return exactMatch } + + const results: RawResult[] = [exactMatch] + + if (query.prefix) { + this._index.atPrefix(query.term).forEach((term: string, data: {}) => { + const weightedDistance = (0.3 * (term.length - query.term.length)) / term.length + results.push(this.termResults(term, boosts, boostDocument, data, prefixWeight, weightedDistance)) + }) + } + + if (query.fuzzy) { + const fuzzy = (query.fuzzy === true) ? 0.2 : query.fuzzy + const maxDistance = fuzzy < 1 ? Math.round(query.term.length * fuzzy) : fuzzy + + Object.entries(this._index.fuzzyGet(query.term, maxDistance)).forEach(([term, [data, distance]]) => { + const weightedDistance = distance / term.length + results.push(this.termResults(term, boosts, boostDocument, data, fuzzyWeight, weightedDistance)) + }) + } + + return results.reduce(combinators[OR], {}) + } + + /** + * @private + * @ignore + */ + combineResults (results: RawResult[], combineWith = OR): RawResult { + if (results.length === 0) { return {} } + const operator = combineWith.toLowerCase() + return results.reduce(combinators[operator], null) || {} + } + + /** + * Allows serialization of the index to JSON, to possibly store it and later + * deserialize it with `MiniSearch.loadJSON`. + * + * Normally one does not directly call this method, but rather call the + * standard JavaScript `JSON.stringify()` passing the `MiniSearch` instance, + * and JavaScript will internally call this method. Upon deserialization, one + * must pass to `loadJSON` the same options used to create the original + * instance that was serialized. + * + * @example + * // Serialize the index: + * let miniSearch = new MiniSearch({ fields: ['title', 'text'] }) + * miniSearch.addAll(documents) + * const json = JSON.stringify(miniSearch) + * + * // Later, to deserialize it: + * miniSearch = MiniSearch.loadJSON(json, { fields: ['title', 'text'] }) + * + * @return {Object} the serializeable representation of the search index + */ + toJSON (): AsPlainObject { + return { + index: this._index, + documentCount: this._documentCount, + nextId: this._nextId, + documentIds: this._documentIds, + fieldIds: this._fieldIds, + fieldLength: this._fieldLength, + averageFieldLength: this._averageFieldLength, + storedFields: this._storedFields + } + } + + /** + * @private + * @ignore + */ + private termResults ( + term: string, + boosts: { [field: string]: number }, + boostDocument: ((id: any, term: string) => number) | undefined, + indexData: IndexData, + weight: number = 1, + editDistance: number = 0 + ): RawResult { + if (indexData == null) { return {} } + + return Object.entries(boosts).reduce(( + results: { [shortId: string]: { score: number, match: MatchInfo, terms: string[] } }, + [field, boost] + ) => { + const fieldId = this._fieldIds[field] + const { df, ds } = indexData[fieldId] || { ds: {} } + + Object.entries(ds).forEach(([documentId, tf]) => { + const docBoost = boostDocument ? boostDocument(this._documentIds[documentId], term) : 1 + if (!docBoost) { return } + const normalizedLength = this._fieldLength[documentId][fieldId] / this._averageFieldLength[fieldId] + results[documentId] = results[documentId] || { score: 0, match: {}, terms: [] } + results[documentId].terms.push(term) + results[documentId].match[term] = getOwnProperty(results[documentId].match, term) || [] + results[documentId].score += docBoost * score(tf, df, this._documentCount, normalizedLength, boost, editDistance) + results[documentId].match[term].push(field) + }) + return results + }, {}) + } + + /** + * @private + * @ignore + */ + private addTerm (fieldId: number, documentId: string, term: string): void { + this._index.update(term, (indexData: IndexData) => { + indexData = indexData || {} + const fieldIndex = indexData[fieldId] || { df: 0, ds: {} } + if (fieldIndex.ds[documentId] == null) { fieldIndex.df += 1 } + fieldIndex.ds[documentId] = (fieldIndex.ds[documentId] || 0) + 1 + return { ...indexData, [fieldId]: fieldIndex } + }) + } + + /** + * @private + * @ignore + */ + private removeTerm (fieldId: number, documentId: string, term: string): void { + if (!this._index.has(term)) { + this.warnDocumentChanged(documentId, fieldId, term) + return + } + this._index.update(term, (indexData: IndexData) => { + const fieldIndex = indexData[fieldId] + if (fieldIndex == null || fieldIndex.ds[documentId] == null) { + this.warnDocumentChanged(documentId, fieldId, term) + return indexData + } + if (fieldIndex.ds[documentId] <= 1) { + if (fieldIndex.df <= 1) { + delete indexData[fieldId] + return indexData + } + fieldIndex.df -= 1 + } + if (fieldIndex.ds[documentId] <= 1) { + delete fieldIndex.ds[documentId] + return indexData + } + fieldIndex.ds[documentId] -= 1 + return { ...indexData, [fieldId]: fieldIndex } + }) + if (Object.keys(this._index.get(term)).length === 0) { + this._index.delete(term) + } + } + + /** + * @private + * @ignore + */ + private warnDocumentChanged (shortDocumentId: string, fieldId: number, term: string): void { + if (console == null || console.warn == null) { return } + const fieldName = Object.entries(this._fieldIds).find(([name, id]) => id === fieldId)![0] + console.warn(`MiniSearch: document with ID ${this._documentIds[shortDocumentId]} has changed before removal: term "${term}" was not present in field "${fieldName}". Removing a document after it has changed can corrupt the index!`) + } + + /** + * @private + * @ignore + */ + private addDocumentId (documentId: any): string { + const shortDocumentId = this._nextId.toString(36) + this._documentIds[shortDocumentId] = documentId + this._documentCount += 1 + this._nextId += 1 + return shortDocumentId + } + + /** + * @private + * @ignore + */ + private addFields (fields: string[]): void { + fields.forEach((field, i) => { this._fieldIds[field] = i }) + } + + /** + * @private + * @ignore + */ + private addFieldLength (documentId: string, fieldId: number, count: number, length: number): void { + this._averageFieldLength[fieldId] = this._averageFieldLength[fieldId] || 0 + const totalLength = (this._averageFieldLength[fieldId] * count) + length + this._fieldLength[documentId] = this._fieldLength[documentId] || {} + this._fieldLength[documentId][fieldId] = length + this._averageFieldLength[fieldId] = totalLength / (count + 1) + } + + /** + * @private + * @ignore + */ + private saveStoredFields (documentId: string, doc: T): void { + const { storeFields, extractField } = this._options + if (storeFields == null || storeFields.length === 0) { return } + this._storedFields[documentId] = this._storedFields[documentId] || {} + + storeFields.forEach((fieldName) => { + const fieldValue = extractField(doc, fieldName) + if (fieldValue === undefined) { return } + this._storedFields[documentId][fieldName] = fieldValue + }) + } + + static SearchableMap = SearchableMap +} + +const getOwnProperty = (object: any, property: string) => + Object.prototype.hasOwnProperty.call(object, property) ? object[property] : undefined + +type CombinatorFunction = (a: RawResult | null, b: RawResult) => RawResult + +const combinators: { [kind: string]: CombinatorFunction } = { + [OR]: (a: RawResult | null, b: RawResult) => { + return Object.entries(b).reduce((combined, [documentId, { score, match, terms }]) => { + if (combined[documentId] == null) { + combined[documentId] = { score, match, terms } + } else { + combined[documentId].score += score + combined[documentId].score *= 1.5 + combined[documentId].terms = [...combined[documentId].terms, ...terms] + Object.assign(combined[documentId].match, match) + } + return combined + }, a || {}) + }, + [AND]: (a: RawResult | null, b: RawResult) => { + if (a == null) { return b } + return Object.entries(b).reduce((combined: RawResult, [documentId, { score, match, terms }]) => { + if (a[documentId] === undefined) { return combined } + combined[documentId] = combined[documentId] || {} + combined[documentId].score = a[documentId].score + score + combined[documentId].match = { ...a[documentId].match, ...match } + combined[documentId].terms = [...a[documentId].terms, ...terms] + return combined + }, {}) + } +} + +const tfIdf = (tf: number, df: number, n: number): number => tf * Math.log(n / df) + +const score = ( + termFrequency: number, + documentFrequency: number, + documentCount: number, + normalizedLength: number, + boost: number, + editDistance: number +): number => { + const weight = boost / (1 + (0.333 * boost * editDistance)) + return weight * tfIdf(termFrequency, documentFrequency, documentCount) / normalizedLength +} + +const termToQuery = (options: SearchOptions) => (term: string, i: number, terms: string[]): Query => { + const fuzzy = (typeof options.fuzzy === 'function') + ? options.fuzzy(term, i, terms) + : (options.fuzzy || false) + const prefix = (typeof options.prefix === 'function') + ? options.prefix(term, i, terms) + : (options.prefix === true) + return { term, fuzzy, prefix } +} + +const uniq = (array: T[]): T[] => + array.filter((element: T, i: number, array: T[]) => array.indexOf(element) === i) + +const defaultOptions = { + idField: 'id', + extractField: (document: { [key: string]: any }, fieldName: string) => document[fieldName], + tokenize: (text: string, fieldName?: string) => text.split(SPACE_OR_PUNCTUATION), + processTerm: (term: string, fieldName?: string) => term.toLowerCase(), + fields: undefined, + searchOptions: undefined, + storeFields: [] +} + +const defaultSearchOptions = { + combineWith: OR, + prefix: false, + fuzzy: false, + boost: {}, + weights: { fuzzy: 0.9, prefix: 0.75 } +} + +const defaultAutoSuggestOptions = { + prefix: (term: string, i: number, terms: string[]): boolean => + i === terms.length - 1 +} + +// This regular expression matches any Unicode space or punctuation character +// Adapted from https://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7BZ%7D%5Cp%7BP%7D&abb=on&c=on&esc=on +const SPACE_OR_PUNCTUATION = /[\n\r -#%-*,-/:;?@[-\]_{}\u00A0\u00A1\u00A7\u00AB\u00B6\u00B7\u00BB\u00BF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u1680\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2000-\u200A\u2010-\u2029\u202F-\u2043\u2045-\u2051\u2053-\u205F\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u3000-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]+/u + +export default MiniSearch diff --git a/src/SearchableMap/SearchableMap.js b/src/SearchableMap/SearchableMap.js deleted file mode 100644 index 09e1fe38..00000000 --- a/src/SearchableMap/SearchableMap.js +++ /dev/null @@ -1,323 +0,0 @@ -import { TreeIterator, ENTRIES, KEYS, VALUES, LEAF } from './TreeIterator.js' -import fuzzySearch from './fuzzySearch.js' - -/** -* A class implementing the same interface as a standard JavaScript `Map` with -* string keys, but adding support for efficiently searching entries with prefix -* or fuzzy search. This is the class internally used by `MiniSearch` as the -* inverted index data structure. The implementation is a radix tree (compressed -* prefix tree). -* -* @implements {Map} -*/ -class SearchableMap { - constructor (tree = {}, prefix = '') { - /** @private */ - this._tree = tree - /** @private */ - this._prefix = prefix - } - - /** - * Creates and returns a mutable view of this `SearchableMap`, containing only - * entries that share the given prefix. - * - * @example - * let map = new SearchableMap() - * map.set("unicorn", 1) - * map.set("universe", 2) - * map.set("university", 3) - * map.set("unique", 4) - * map.set("hello", 5) - * - * let uni = map.atPrefix("uni") - * uni.get("unique") // => 4 - * uni.get("unicorn") // => 1 - * uni.get("hello") // => undefined - * - * let univer = map.atPrefix("univer") - * univer.get("unique") // => undefined - * univer.get("universe") // => 2 - * univer.get("university") // => 3 - * - * @param {string} prefix - The prefix - * @return {SearchableMap} A `SearchableMap` representing a mutable view of the original Map at the given prefix - */ - atPrefix (prefix) { - if (!prefix.startsWith(this._prefix)) { throw new Error('Mismatched prefix') } - const [node, path] = trackDown(this._tree, prefix.slice(this._prefix.length)) - if (node === undefined) { - const [parentNode, key] = last(path) - const nodeKey = Object.keys(parentNode).find(k => k !== LEAF && k.startsWith(key)) - if (nodeKey !== undefined) { - return new SearchableMap({ [nodeKey.slice(key.length)]: parentNode[nodeKey] }, prefix) - } - } - return new SearchableMap(node || {}, prefix) - } - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear - * @return {undefined} - */ - clear () { - delete this._size - this._tree = {} - } - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete - * @param {string} key - * @return {undefined} - */ - delete (key) { - delete this._size - return remove(this._tree, key) - } - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries - * @return {Iterator} - */ - entries () { - return new TreeIterator(this, ENTRIES) - } - - /** - * @callback SearchableMap~forEachFn - * @param {string} key - Key - * @param {any} value - Value associated to key - * @return any - */ - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach - * @param {SearchableMap~forEachFn} fn - * @return {undefined} - */ - forEach (fn) { - for (const [key, value] of this) { - fn(key, value, this) - } - } - - /** - * Returns a key-value object of all the entries that have a key within the - * given edit distance from the search key. The keys of the returned object are - * the matching keys, while the values are two-elements arrays where the first - * element is the value associated to the key, and the second is the edit - * distance of the key to the search key. - * - * @example - * let map = new SearchableMap() - * map.set('hello', 'world') - * map.set('hell', 'yeah') - * map.set('ciao', 'mondo') - * - * // Get all entries that match the key 'hallo' with a maximum edit distance of 2 - * map.fuzzyGet('hallo', 2) - * // => { "hello": ["world", 1], "hell": ["yeah", 2] } - * - * // In the example, the "hello" key has value "world" and edit distance of 1 - * // (change "e" to "a"), the key "hell" has value "yeah" and edit distance of 2 - * // (change "e" to "a", delete "o") - * - * @param {string} key - The search key - * @param {number} maxEditDistance - The maximum edit distance - * @return {Object} A key-value object of the matching keys to their value and edit distance - */ - fuzzyGet (key, maxEditDistance) { - return fuzzySearch(this._tree, key, maxEditDistance) - } - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get - * @param {string} key - * @return {any} - */ - get (key) { - const node = lookup(this._tree, key) - return node !== undefined ? node[LEAF] : undefined - } - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has - * @param {string} key - * @return {boolean} - */ - has (key) { - const node = lookup(this._tree, key) - return node !== undefined && node.hasOwnProperty(LEAF) - } - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys - * @return {Iterator} - */ - keys () { - return new TreeIterator(this, KEYS) - } - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set - * @param {string} key - * @param {any} value - * @return {SearchableMap} The `SearchableMap` itself, to allow chaining - */ - set (key, value) { - if (typeof key !== 'string') { throw new Error('key must be a string') } - delete this._size - const node = createPath(this._tree, key) - node[LEAF] = value - return this - } - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size - * @type {number} - */ - get size () { - if (this._size) { return this._size } - /** @ignore */ - this._size = 0 - this.forEach(() => { this._size += 1 }) - return this._size - } - - /** - * @callback SearchableMap~updateFn - * @param {any} currentValue - The current value - * @return any - the updated value - */ - - /** - * Updates the value at the given key using the provided function. The function - * is called with the current value at the key, and its return value is used as - * the new value to be set. - * - * @example - * // Increment the current value by one - * searchableMap.update('somekey', (currentValue) => currentValue == null ? 0 : currentValue + 1) - * - * @param {string} key - The key - * @param {SearchableMap~updateFn} fn - The function used to compute the new value from the current one - * @return {SearchableMap} The `SearchableMap` itself, to allow chaining - */ - update (key, fn) { - if (typeof key !== 'string') { throw new Error('key must be a string') } - delete this._size - const node = createPath(this._tree, key) - node[LEAF] = fn(node[LEAF]) - return this - } - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values - * @return {Iterator} - */ - values () { - return new TreeIterator(this, VALUES) - } - - /** - * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@iterator - * @return {Iterator} - */ - [Symbol.iterator] () { - return this.entries() - } -} - -/** -* Creates a `SearchableMap` from an `Iterable` of entries -* -* @param {Iterable|Array} entries - Entries to be inserted in the `SearchableMap` -* @return {SearchableMap} A new `SearchableMap` with the given entries -**/ -SearchableMap.from = function (entries) { - const tree = new SearchableMap() - for (const [key, value] of entries) { - tree.set(key, value) - } - return tree -} - -/** -* Creates a `SearchableMap` from the iterable properties of a JavaScript object -* -* @param {Object} object - Object of entries for the `SearchableMap` -* @return {SearchableMap} A new `SearchableMap` with the given entries -**/ -SearchableMap.fromObject = function (object) { - return SearchableMap.from(Object.entries(object)) -} - -const trackDown = function (tree, key, path = []) { - if (key.length === 0) { return [tree, path] } - const nodeKey = Object.keys(tree).find(k => k !== LEAF && key.startsWith(k)) - if (nodeKey === undefined) { return trackDown(undefined, '', [...path, [tree, key]]) } - return trackDown(tree[nodeKey], key.slice(nodeKey.length), [...path, [tree, nodeKey]]) -} - -const lookup = function (tree, key) { - if (key.length === 0) { return tree } - const nodeKey = Object.keys(tree).find(k => k !== LEAF && key.startsWith(k)) - if (nodeKey === undefined) { return undefined } - return lookup(tree[nodeKey], key.slice(nodeKey.length)) -} - -const createPath = function (tree, key) { - if (key.length === 0) { return tree } - const nodeKey = Object.keys(tree).find(k => k !== LEAF && key.startsWith(k)) - if (nodeKey === undefined) { - const toSplit = Object.keys(tree).find(k => k !== LEAF && k.startsWith(key[0])) - if (toSplit === undefined) { - tree[key] = {} - } else { - const prefix = commonPrefix(key, toSplit) - tree[prefix] = { [toSplit.slice(prefix.length)]: tree[toSplit] } - delete tree[toSplit] - return createPath(tree[prefix], key.slice(prefix.length)) - } - return tree[key] - } - return createPath(tree[nodeKey], key.slice(nodeKey.length)) -} - -const commonPrefix = function (a, b, i = 0, length = Math.min(a.length, b.length), prefix = '') { - if (i >= length) { return prefix } - if (a[i] !== b[i]) { return prefix } - return commonPrefix(a, b, i + 1, length, prefix + a[i]) -} - -const remove = function (tree, key) { - const [node, path] = trackDown(tree, key) - if (node === undefined) { return } - delete node[LEAF] - const keys = Object.keys(node) - if (keys.length === 0) { cleanup(path) } - if (keys.length === 1) { merge(path, keys[0], node[keys[0]]) } -} - -const cleanup = function (path) { - if (path.length === 0) { return } - const [node, key] = last(path) - delete node[key] - if (Object.keys(node).length === 0) { - cleanup(path.slice(0, -1)) - } -} - -const merge = function (path, key, value) { - if (path.length === 0) { return } - const [node, nodeKey] = last(path) - node[nodeKey + key] = value - delete node[nodeKey] -} - -const last = function (array) { - return array[array.length - 1] -} - -export default SearchableMap -export { SearchableMap } diff --git a/src/SearchableMap/SearchableMap.test.js b/src/SearchableMap/SearchableMap.test.js index 504f7e01..840caaeb 100644 --- a/src/SearchableMap/SearchableMap.test.js +++ b/src/SearchableMap/SearchableMap.test.js @@ -1,6 +1,6 @@ /* eslint-env jest */ -import SearchableMap from './SearchableMap.js' +import SearchableMap from './SearchableMap' import * as fc from 'fast-check' describe('SearchableMap', () => { diff --git a/src/SearchableMap/SearchableMap.ts b/src/SearchableMap/SearchableMap.ts new file mode 100644 index 00000000..1d57d851 --- /dev/null +++ b/src/SearchableMap/SearchableMap.ts @@ -0,0 +1,340 @@ +import { TreeIterator, ENTRIES, KEYS, VALUES, LEAF, IterableSet } from './TreeIterator' +import fuzzySearch, { FuzzyResults } from './fuzzySearch' +import { RadixTree, Entry, Path } from './types' + +/** + * A class implementing the same interface as a standard JavaScript `Map` with + * string keys, but adding support for efficiently searching entries with prefix + * or fuzzy search. This is the class internally used by `MiniSearch` as the + * inverted index data structure. The implementation is a radix tree (compressed + * prefix tree). + * + * @implements {Map} + */ +class SearchableMap implements IterableSet { + _tree: RadixTree + _prefix: string + private _size?: number + + constructor (tree = {}, prefix = '') { + /** @private */ + this._tree = tree + /** @private */ + this._prefix = prefix + } + + /** + * Creates and returns a mutable view of this `SearchableMap`, containing only + * entries that share the given prefix. + * + * @example + * let map = new SearchableMap() + * map.set("unicorn", 1) + * map.set("universe", 2) + * map.set("university", 3) + * map.set("unique", 4) + * map.set("hello", 5) + * + * let uni = map.atPrefix("uni") + * uni.get("unique") // => 4 + * uni.get("unicorn") // => 1 + * uni.get("hello") // => undefined + * + * let univer = map.atPrefix("univer") + * univer.get("unique") // => undefined + * univer.get("universe") // => 2 + * univer.get("university") // => 3 + * + * @param {string} prefix - The prefix + * @return {SearchableMap} A `SearchableMap` representing a mutable view of the original Map at the given prefix + */ + atPrefix (prefix: string): SearchableMap { + if (!prefix.startsWith(this._prefix)) { throw new Error('Mismatched prefix') } + + const [node, path] = trackDown(this._tree, prefix.slice(this._prefix.length)) + + if (node === undefined) { + const [parentNode, key] = last(path) + const nodeKey = Object.keys(parentNode!).find(k => k !== LEAF && k.startsWith(key)) + + if (nodeKey !== undefined) { + return new SearchableMap({ [nodeKey.slice(key.length)]: parentNode![nodeKey] }, prefix) + } + } + + return new SearchableMap(node || {}, prefix) + } + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear + * @return {undefined} + */ + clear () { + delete this._size + this._tree = {} + } + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete + * @param {string} key + * @return {undefined} + */ + delete (key: string) { + delete this._size + return remove(this._tree, key) + } + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries + * @return {Iterator} + */ + entries () { + return new TreeIterator>(this, ENTRIES) + } + + /** + * @callback SearchableMap~forEachFn + * @param {string} key - Key + * @param {any} value - Value associated to key + * @return any + */ + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach + * @param {SearchableMap~forEachFn} fn + * @return {undefined} + */ + forEach (fn: (key: string, value: T, map: SearchableMap) => void) { + for (const [key, value] of this) { + fn(key, value, this) + } + } + + /** + * Returns a key-value object of all the entries that have a key within the + * given edit distance from the search key. The keys of the returned object are + * the matching keys, while the values are two-elements arrays where the first + * element is the value associated to the key, and the second is the edit + * distance of the key to the search key. + * + * @example + * let map = new SearchableMap() + * map.set('hello', 'world') + * map.set('hell', 'yeah') + * map.set('ciao', 'mondo') + * + * // Get all entries that match the key 'hallo' with a maximum edit distance of 2 + * map.fuzzyGet('hallo', 2) + * // => { "hello": ["world", 1], "hell": ["yeah", 2] } + * + * // In the example, the "hello" key has value "world" and edit distance of 1 + * // (change "e" to "a"), the key "hell" has value "yeah" and edit distance of 2 + * // (change "e" to "a", delete "o") + * + * @param {string} key - The search key + * @param {number} maxEditDistance - The maximum edit distance + * @return {Object} A key-value object of the matching keys to their value and edit distance + */ + fuzzyGet (key: string, maxEditDistance: number): FuzzyResults { + return fuzzySearch(this._tree, key, maxEditDistance) + } + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get + * @param {string} key + * @return {any} + */ + get (key: string): T | undefined { + const node = lookup(this._tree, key) + return node !== undefined ? (node[LEAF] as T) : undefined + } + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has + * @param {string} key + * @return {boolean} + */ + has (key: string): boolean { + const node = lookup(this._tree, key) + return node !== undefined && node.hasOwnProperty(LEAF) + } + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys + * @return {Iterator} + */ + keys () { + return new TreeIterator(this, KEYS) + } + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set + * @param {string} key + * @param {any} value + * @return {SearchableMap} The `SearchableMap` itself, to allow chaining + */ + set (key: string, value: T): SearchableMap { + if (typeof key !== 'string') { throw new Error('key must be a string') } + delete this._size + const node = createPath(this._tree, key) + node[LEAF] = value + return this + } + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size + * @type {number} + */ + get size (): number { + if (this._size) { return this._size } + /** @ignore */ + this._size = 0 + this.forEach(() => { this._size! += 1 }) + return this._size + } + + /** + * @callback SearchableMap~updateFn + * @param {any} currentValue - The current value + * @return any - the updated value + */ + + /** + * Updates the value at the given key using the provided function. The function + * is called with the current value at the key, and its return value is used as + * the new value to be set. + * + * @example + * // Increment the current value by one + * searchableMap.update('somekey', (currentValue) => currentValue == null ? 0 : currentValue + 1) + * + * @param {string} key - The key + * @param {SearchableMap~updateFn} fn - The function used to compute the new value from the current one + * @return {SearchableMap} The `SearchableMap` itself, to allow chaining + */ + update (key: string, fn: (value: T) => T): SearchableMap { + if (typeof key !== 'string') { throw new Error('key must be a string') } + delete this._size + const node = createPath(this._tree, key) + node[LEAF] = fn(node[LEAF] as T) + return this + } + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values + * @return {Iterator} + */ + values () { + return new TreeIterator(this, VALUES) + } + + /** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@iterator + * @return {Iterator} + */ + [Symbol.iterator] () { + return this.entries() + } + + /** + * Creates a `SearchableMap` from an `Iterable` of entries + * + * @param {Iterable|Array} entries - Entries to be inserted in the `SearchableMap` + * @return {SearchableMap} A new `SearchableMap` with the given entries + */ + static from (entries: Iterable> | Entry[]) { + const tree = new SearchableMap() + for (const [key, value] of entries) { + tree.set(key, value) + } + return tree + } + + /** + * Creates a `SearchableMap` from the iterable properties of a JavaScript object + * + * @param {Object} object - Object of entries for the `SearchableMap` + * @return {SearchableMap} A new `SearchableMap` with the given entries + */ + static fromObject (object: { [key: string]: T }) { + return SearchableMap.from(Object.entries(object)) + } +} + +const trackDown = (tree: RadixTree | undefined, key: string, path: Path = []): [RadixTree | undefined, Path] => { + if (key.length === 0 || tree == null) { return [tree, path] } + const nodeKey = Object.keys(tree || {}).find(k => k !== LEAF && key.startsWith(k)) + if (nodeKey === undefined) { return trackDown(undefined, '', [...path, [tree, key]]) } + return trackDown(tree[nodeKey] as RadixTree, key.slice(nodeKey.length), [...path, [tree, nodeKey]]) +} + +const lookup = (tree: RadixTree, key: string): RadixTree | undefined => { + if (key.length === 0 || tree == null) { return tree } + const nodeKey = Object.keys(tree).find(k => k !== LEAF && key.startsWith(k)) + if (nodeKey === undefined) { return undefined } + return lookup(tree[nodeKey] as RadixTree, key.slice(nodeKey.length)) +} + +const createPath = (tree: RadixTree, key: string): RadixTree => { + if (key.length === 0 || tree == null) { return tree } + + const nodeKey = Object.keys(tree).find(k => k !== LEAF && key.startsWith(k)) + + if (nodeKey === undefined) { + const toSplit = Object.keys(tree).find(k => k !== LEAF && k.startsWith(key[0])) + + if (toSplit === undefined) { + tree[key] = {} + } else { + const prefix = commonPrefix(key, toSplit) + tree[prefix] = { [toSplit.slice(prefix.length)]: tree[toSplit] } + delete tree[toSplit] + return createPath(tree[prefix] as RadixTree, key.slice(prefix.length)) + } + + return tree[key] as RadixTree + } + + return createPath(tree[nodeKey] as RadixTree, key.slice(nodeKey.length)) +} + +const commonPrefix = (a: string, b: string, i: number = 0, length: number = Math.min(a.length, b.length), prefix: string = ''): string => { + if (i >= length) { return prefix } + if (a[i] !== b[i]) { return prefix } + return commonPrefix(a, b, i + 1, length, prefix + a[i]) +} + +const remove = (tree: RadixTree, key: string): void => { + const [node, path] = trackDown(tree, key) + if (node === undefined) { return } + delete node[LEAF] + const keys = Object.keys(node) + if (keys.length === 0) { cleanup(path) } + if (keys.length === 1) { merge(path, keys[0], node[keys[0]]) } +} + +const cleanup = (path: Path): void => { + if (path.length === 0) { return } + + const [node, key] = last(path) + delete node![key] + + if (Object.keys(node!).length === 0) { + cleanup(path.slice(0, -1)) + } +} + +const merge = (path: Path, key: string, value: T): void => { + if (path.length === 0) { return } + + const [node, nodeKey] = last(path) + node![nodeKey + key] = value + delete node![nodeKey] +} + +const last = (array: T[]): T => { + return array[array.length - 1] +} + +export default SearchableMap +export { SearchableMap } diff --git a/src/SearchableMap/TreeIterator.js b/src/SearchableMap/TreeIterator.js deleted file mode 100644 index 340dda5e..00000000 --- a/src/SearchableMap/TreeIterator.js +++ /dev/null @@ -1,73 +0,0 @@ -/** -* @private -*/ -class TreeIterator { - constructor (set, type) { - const node = set._tree - const keys = Object.keys(node) - this.set = set - this.type = type - this.path = keys.length > 0 ? [{ node, keys }] : [] - } - - next () { - const value = this.dive() - this.backtrack() - return value - } - - dive () { - if (this.path.length === 0) { return { done: true } } - const { node, keys } = last(this.path) - if (last(keys) === LEAF) { return { done: false, value: this.result() } } - this.path.push({ node: node[last(keys)], keys: Object.keys(node[last(keys)]) }) - return this.dive() - } - - backtrack () { - if (this.path.length === 0) { return } - last(this.path).keys.pop() - if (last(this.path).keys.length > 0) { return } - this.path.pop() - this.backtrack() - } - - key () { - return this.set._prefix + this.path - .map(({ keys }) => last(keys)) - .filter(key => key !== LEAF) - .join('') - } - - value () { - return last(this.path).node[LEAF] - } - - result () { - if (this.type === VALUES) { return this.value() } - if (this.type === KEYS) { return this.key() } - return [this.key(), this.value()] - } - - [Symbol.iterator] () { - return this - } -} - -/** @ignore */ -const ENTRIES = 'ENTRIES' - -/** @ignore */ -const KEYS = 'KEYS' - -/** @ignore */ -const VALUES = 'VALUES' - -/** @ignore */ -const LEAF = '' - -const last = function (array) { - return array[array.length - 1] -} - -export { TreeIterator, ENTRIES, KEYS, VALUES, LEAF } diff --git a/src/SearchableMap/TreeIterator.ts b/src/SearchableMap/TreeIterator.ts new file mode 100644 index 00000000..0da870f5 --- /dev/null +++ b/src/SearchableMap/TreeIterator.ts @@ -0,0 +1,91 @@ +import { RadixTree, Entry } from './types' + +/** @ignore */ +const ENTRIES = 'ENTRIES' + +/** @ignore */ +const KEYS = 'KEYS' + +/** @ignore */ +const VALUES = 'VALUES' + +/** @ignore */ +const LEAF = '' + +type IteratorType = 'ENTRIES' | 'KEYS' | 'VALUES' + +type IteratorPath = { + node: RadixTree, + keys: string[] +}[] + +export type IterableSet = { + _tree: RadixTree, + _prefix: string +} + +/** + * @private + */ +class TreeIterator implements Iterator { + set: IterableSet + _type: IteratorType + _path: IteratorPath + + constructor (set: IterableSet, type: IteratorType) { + const node = set._tree + const keys = Object.keys(node) + this.set = set + this._type = type + this._path = keys.length > 0 ? [{ node, keys }] : [] + } + + next (): IteratorResult { + const value = this.dive() + this.backtrack() + return value + } + + dive (): IteratorResult { + if (this._path.length === 0) { return { done: true, value: undefined } } + const { node, keys } = last(this._path)! + if (last(keys) === LEAF) { return { done: false, value: this.result() as V } } + this._path.push({ node: node[last(keys)!] as RadixTree, keys: Object.keys(node[last(keys)!]) }) + return this.dive() + } + + backtrack (): void { + if (this._path.length === 0) { return } + last(this._path)!.keys.pop() + if (last(this._path)!.keys.length > 0) { return } + this._path.pop() + this.backtrack() + } + + key (): string { + return this.set._prefix + this._path + .map(({ keys }) => last(keys)) + .filter(key => key !== LEAF) + .join('') + } + + value (): T { + return last(this._path)!.node[LEAF] as T + } + + result (): unknown { + if (this._type === VALUES) { return this.value() } + if (this._type === KEYS) { return this.key() } + return [this.key(), this.value()] as Entry + } + + [Symbol.iterator] () { + return this + } +} + +const last = (array: T[]): T | undefined => { + return array[array.length - 1] +} + +export { TreeIterator, ENTRIES, KEYS, VALUES, LEAF } diff --git a/src/SearchableMap/fuzzySearch.js b/src/SearchableMap/fuzzySearch.ts similarity index 52% rename from src/SearchableMap/fuzzySearch.js rename to src/SearchableMap/fuzzySearch.ts index 2042c279..757106e2 100644 --- a/src/SearchableMap/fuzzySearch.js +++ b/src/SearchableMap/fuzzySearch.ts @@ -1,25 +1,53 @@ -import { LEAF } from './TreeIterator.js' +import { LEAF } from './TreeIterator' +import { RadixTree } from './types' + +const NONE = 0 +const CHANGE = 1 +const ADD = 2 +const DELETE = 3 + +type Edit = 0 | 1 | 2 | 3 | undefined + +type StackElement = { + distance: number, + i: number, + key: string, + node: RadixTree, + edit?: Edit +} + +type InnerStackElement = { + distance: number, + ia: number, + ib: number, + edit: Edit +} + +export type FuzzyResult = [T, number] + +export type FuzzyResults = { [key: string]: FuzzyResult } /** -* @ignore -*/ -export const fuzzySearch = function (node, query, maxDistance) { - const stack = [{ distance: 0, i: 0, key: '', node }] - const results = {} - const innerStack = [] + * @ignore + */ +export const fuzzySearch = (node: RadixTree, query: string, maxDistance: number): FuzzyResults => { + const stack: StackElement[] = [{ distance: 0, i: 0, key: '', node }] + const results: FuzzyResults = {} + const innerStack: InnerStackElement[] = [] while (stack.length > 0) { - const { node, distance, key, i, edit } = stack.pop() + const { node, distance, key, i, edit } = stack.pop()! + Object.keys(node).forEach((k) => { if (k === LEAF) { const totDistance = distance + (query.length - i) const [, d] = results[key] || [null, Infinity] if (totDistance <= maxDistance && totDistance < d) { - results[key] = [node[k], totDistance] + results[key] = [node[k] as T, totDistance] } } else { withinDistance(query, k, maxDistance - distance, i, edit, innerStack).forEach(({ distance: d, i, edit }) => { - stack.push({ node: node[k], distance: distance + d, key: key + k, i, edit }) + stack.push({ node: node[k] as RadixTree, distance: distance + d, key: key + k, i, edit }) }) } }) @@ -28,14 +56,14 @@ export const fuzzySearch = function (node, query, maxDistance) { } /** -* @ignore -*/ -export const withinDistance = function (a, b, maxDistance, i, edit, stack) { + * @ignore + */ +export const withinDistance = (a: string, b: string, maxDistance: number, i: number, edit: Edit, stack: InnerStackElement[]) => { stack.push({ distance: 0, ia: i, ib: 0, edit }) - const results = [] + const results: { distance: number, i: number, edit: Edit }[] = [] while (stack.length > 0) { - const { distance, ia, ib, edit } = stack.pop() + const { distance, ia, ib, edit } = stack.pop()! if (ib === b.length) { results.push({ distance, i: ia, edit }) @@ -66,9 +94,4 @@ export const withinDistance = function (a, b, maxDistance, i, edit, stack) { return results } -const NONE = 0 -const CHANGE = 1 -const ADD = 2 -const DELETE = 3 - export default fuzzySearch diff --git a/src/SearchableMap/types.ts b/src/SearchableMap/types.ts new file mode 100644 index 00000000..1fec9203 --- /dev/null +++ b/src/SearchableMap/types.ts @@ -0,0 +1,7 @@ +export type RadixTree = { + [key: string]: RadixTree | T +} + +export type Entry = [string, T] + +export type Path = [RadixTree | undefined, string][] diff --git a/src/index.d.ts b/src/index.d.ts deleted file mode 100644 index e14717de..00000000 --- a/src/index.d.ts +++ /dev/null @@ -1,87 +0,0 @@ -// Type definitions for MiniSearch - -declare class MiniSearch { - constructor(options: Options); - - documentCount: number; - - add(document: T): void; - - addAll(documents: T[]): void; - - addAllAsync(documents: T[], options?: { chunkSize?: number }): Promise; - - autoSuggest(query: string, options?: SearchOptions): Suggestion[]; - - remove(document: T): void; - - removeAll(documents?: T[]): void; - - search(query: string, options?: SearchOptions): SearchResult[]; - - toJSON(): object; - - static getDefault(optionName: string): any; - - static loadJSON(json: string, options: Options): MiniSearch; -} - -export declare interface SearchOptions { - fields?: string[], - - filter?: (result: SearchResult) => boolean, - - boost?: { [fieldName: string]: number }, - - prefix?: boolean - | ((term: string, index: number, terms: string[]) => boolean), - - fuzzy?: boolean | number - | ((term: string, index: number, terms: string[]) => boolean | number), - - combineWith?: string, - - extractField?: (document: T, fieldName: string) => string, - - tokenize?: (text: string) => string[], - - processTerm?: (term: string) => string | null | undefined | false -} - -export declare interface Options { - fields: string[], - - storeFields?: string[], - - idField?: string, - - extractField?: (document: T, fieldName: string) => string, - - tokenize?: (text: string, fieldName: string) => string[], - - processTerm?: (term: string, fieldName: string) => string | null | undefined | false, - - searchOptions?: SearchOptions -} - -export declare interface Suggestion { - suggestion: string, - - score: number -} - -export declare interface MatchInfo { - [term: string]: string[] -} - -export declare interface SearchResult { - id: any, - - score: number, - - match: MatchInfo, - - [key: string]: any -} - -export default MiniSearch diff --git a/src/index.js b/src/index.js deleted file mode 100644 index e100163d..00000000 --- a/src/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import MiniSearch from './MiniSearch.js' - -export default MiniSearch diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..3f667e0b --- /dev/null +++ b/src/index.ts @@ -0,0 +1,3 @@ +import MiniSearch from './MiniSearch' + +export default MiniSearch diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..ebc6074b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,71 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ + "allowJs": true, /* Allow javascript files to be compiled. */ + "checkJs": false, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + // "outDir": "./dist", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */ + }, + "include": ["./src/**/*.ts", "./src/**/*.js"], + "exclude": ["node_modules", "./src/**/*.test.ts", "./src/**/*.test.js", "./src/testSetup/**/*"] +} diff --git a/yarn.lock b/yarn.lock index b73e13cd..cdaed807 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,22 +2,6 @@ # yarn lockfile v1 -"@babel/cli@^7.0.0": - version "7.11.6" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.11.6.tgz#1fcbe61c2a6900c3539c06ee58901141f3558482" - integrity sha512-+w7BZCvkewSmaRM6H4L2QM3RL90teqEIHDIFXAmrW33+0jhlymnDAEdqVeCZATvxhQuio1ifoGVlJJbIiH9Ffg== - dependencies: - commander "^4.0.1" - convert-source-map "^1.1.0" - fs-readdir-recursive "^1.1.0" - glob "^7.0.0" - lodash "^4.17.19" - make-dir "^2.1.0" - slash "^2.0.0" - source-map "^0.5.0" - optionalDependencies: - chokidar "^2.1.8" - "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" @@ -25,16 +9,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/compat-data@^7.10.4", "@babel/compat-data@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.11.0.tgz#e9f73efe09af1355b723a7f39b11bad637d7c99c" - integrity sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ== - dependencies: - browserslist "^4.12.0" - invariant "^2.2.4" - semver "^5.5.0" - -"@babel/core@^7.0.1", "@babel/core@^7.1.0", "@babel/core@^7.7.5": +"@babel/core@^7.1.0", "@babel/core@^7.7.5": version "7.11.6" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651" integrity sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg== @@ -65,69 +40,6 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz#5bf0d495a3f757ac3bda48b5bf3b3ba309c72ba3" - integrity sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" - integrity sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg== - dependencies: - "@babel/helper-explode-assignable-expression" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-compilation-targets@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz#804ae8e3f04376607cc791b9d47d540276332bd2" - integrity sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ== - dependencies: - "@babel/compat-data" "^7.10.4" - browserslist "^4.12.0" - invariant "^2.2.4" - levenary "^1.1.1" - semver "^5.5.0" - -"@babel/helper-create-class-features-plugin@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz#9f61446ba80e8240b0a5c85c6fdac8459d6f259d" - integrity sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-member-expression-to-functions" "^7.10.5" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" - -"@babel/helper-create-regexp-features-plugin@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz#fdd60d88524659a0b6959c0579925e425714f3b8" - integrity sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-regex" "^7.10.4" - regexpu-core "^4.7.0" - -"@babel/helper-define-map@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" - integrity sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/types" "^7.10.5" - lodash "^4.17.19" - -"@babel/helper-explode-assignable-expression@^7.10.4": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz#2d8e3470252cc17aba917ede7803d4a7a276a41b" - integrity sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ== - dependencies: - "@babel/types" "^7.10.4" - "@babel/helper-function-name@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" @@ -144,28 +56,21 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-hoist-variables@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz#d49b001d1d5a68ca5e6604dda01a6297f7c9381e" - integrity sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-member-expression-to-functions@^7.10.4", "@babel/helper-member-expression-to-functions@^7.10.5": +"@babel/helper-member-expression-to-functions@^7.10.4": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz#ae69c83d84ee82f4b42f96e2a09410935a8f26df" integrity sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q== dependencies: "@babel/types" "^7.11.0" -"@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.10.4": +"@babel/helper-module-imports@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz#4c5c54be04bd31670a7382797d75b9fa2e5b5620" integrity sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw== dependencies: "@babel/types" "^7.10.4" -"@babel/helper-module-transforms@^7.10.4", "@babel/helper-module-transforms@^7.10.5", "@babel/helper-module-transforms@^7.11.0": +"@babel/helper-module-transforms@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz#b16f250229e47211abdd84b34b64737c2ab2d359" integrity sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg== @@ -185,28 +90,11 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.8.0": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-regex@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.10.5.tgz#32dfbb79899073c415557053a19bd055aae50ae0" - integrity sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg== - dependencies: - lodash "^4.17.19" - -"@babel/helper-remap-async-to-generator@^7.10.4": - version "7.11.4" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz#4474ea9f7438f18575e30b0cac784045b402a12d" - integrity sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-wrap-function" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" - "@babel/helper-replace-supers@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz#d585cd9388ea06e6031e4cd44b6713cbead9e6cf" @@ -225,14 +113,7 @@ "@babel/template" "^7.10.4" "@babel/types" "^7.10.4" -"@babel/helper-skip-transparent-expression-wrappers@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz#eec162f112c2f58d3af0af125e3bb57665146729" - integrity sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q== - dependencies: - "@babel/types" "^7.11.0" - -"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0": +"@babel/helper-split-export-declaration@^7.11.0": version "7.11.0" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== @@ -244,16 +125,6 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== -"@babel/helper-wrap-function@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz#8a6f701eab0ff39f765b5a1cfef409990e624b87" - integrity sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.10.4" - "@babel/types" "^7.10.4" - "@babel/helpers@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.10.4.tgz#2abeb0d721aff7c0a97376b9e1f6f65d7a475044" @@ -272,133 +143,12 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/node@^7.5.5": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.10.5.tgz#30866322aa2c0251a9bdd73d07a9167bd1f4ed64" - integrity sha512-suosS7zZ2roj+fYVCnDuVezUbRc0sdoyF0Gj/1FzWxD4ebbGiBGtL5qyqHH4NO34B5m4vWWYWgyNhSsrqS8vwA== - dependencies: - "@babel/register" "^7.10.5" - commander "^4.0.1" - core-js "^3.2.1" - lodash "^4.17.19" - node-environment-flags "^1.0.5" - regenerator-runtime "^0.13.4" - resolve "^1.13.1" - v8flags "^3.1.1" - "@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.5", "@babel/parser@^7.9.4": version "7.11.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037" integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q== -"@babel/plugin-proposal-async-generator-functions@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz#3491cabf2f7c179ab820606cec27fed15e0e8558" - integrity sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.10.4" - "@babel/plugin-syntax-async-generators" "^7.8.0" - -"@babel/plugin-proposal-class-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz#a33bf632da390a59c7a8c570045d1115cd778807" - integrity sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-proposal-dynamic-import@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz#ba57a26cb98b37741e9d5bca1b8b0ddf8291f17e" - integrity sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - -"@babel/plugin-proposal-export-namespace-from@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz#570d883b91031637b3e2958eea3c438e62c05f54" - integrity sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - -"@babel/plugin-proposal-json-strings@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz#593e59c63528160233bd321b1aebe0820c2341db" - integrity sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.0" - -"@babel/plugin-proposal-logical-assignment-operators@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz#9f80e482c03083c87125dee10026b58527ea20c8" - integrity sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - -"@babel/plugin-proposal-nullish-coalescing-operator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz#02a7e961fc32e6d5b2db0649e01bf80ddee7e04a" - integrity sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - -"@babel/plugin-proposal-numeric-separator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz#ce1590ff0a65ad12970a609d78855e9a4c1aef06" - integrity sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - -"@babel/plugin-proposal-object-rest-spread@^7.0.0", "@babel/plugin-proposal-object-rest-spread@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz#bd81f95a1f746760ea43b6c2d3d62b11790ad0af" - integrity sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-transform-parameters" "^7.10.4" - -"@babel/plugin-proposal-optional-catch-binding@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz#31c938309d24a78a49d68fdabffaa863758554dd" - integrity sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - -"@babel/plugin-proposal-optional-chaining@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz#de5866d0646f6afdaab8a566382fe3a221755076" - integrity sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - -"@babel/plugin-proposal-private-methods@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz#b160d972b8fdba5c7d111a145fc8c421fc2a6909" - integrity sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-proposal-unicode-property-regex@^7.10.4", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz#4483cda53041ce3413b7fe2f00022665ddfaa75d" - integrity sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-async-generators@^7.8.0", "@babel/plugin-syntax-async-generators@^7.8.4": +"@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== @@ -412,27 +162,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-class-properties@^7.10.4", "@babel/plugin-syntax-class-properties@^7.8.3": +"@babel/plugin-syntax-class-properties@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz#6644e6a0baa55a61f9e3231f6c9eeb6ee46c124c" integrity sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-dynamic-import@^7.8.0": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" @@ -440,416 +176,55 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-json-strings@^7.8.0", "@babel/plugin-syntax-json-strings@^7.8.3": +"@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3": +"@babel/plugin-syntax-numeric-separator@^7.8.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@^7.8.0", "@babel/plugin-syntax-object-rest-spread@^7.8.3": +"@babel/plugin-syntax-object-rest-spread@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-catch-binding@^7.8.0", "@babel/plugin-syntax-optional-catch-binding@^7.8.3": +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-optional-chaining@^7.8.0", "@babel/plugin-syntax-optional-chaining@^7.8.3": +"@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-top-level-await@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz#4bbeb8917b54fcf768364e0a81f560e33a3ef57d" - integrity sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-arrow-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz#e22960d77e697c74f41c501d44d73dbf8a6a64cd" - integrity sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-async-to-generator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz#41a5017e49eb6f3cda9392a51eef29405b245a37" - integrity sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ== - dependencies: - "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-remap-async-to-generator" "^7.10.4" - -"@babel/plugin-transform-block-scoped-functions@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz#1afa595744f75e43a91af73b0d998ecfe4ebc2e8" - integrity sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-block-scoping@^7.10.4": - version "7.11.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz#5b7efe98852bef8d652c0b28144cd93a9e4b5215" - integrity sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-classes@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz#405136af2b3e218bc4a1926228bc917ab1a0adc7" - integrity sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-define-map" "^7.10.4" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.10.4" - globals "^11.1.0" - -"@babel/plugin-transform-computed-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz#9ded83a816e82ded28d52d4b4ecbdd810cdfc0eb" - integrity sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-destructuring@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz#70ddd2b3d1bea83d01509e9bb25ddb3a74fc85e5" - integrity sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-dotall-regex@^7.10.4", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz#469c2062105c1eb6a040eaf4fac4b488078395ee" - integrity sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-duplicate-keys@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz#697e50c9fee14380fe843d1f306b295617431e47" - integrity sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-exponentiation-operator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz#5ae338c57f8cf4001bdb35607ae66b92d665af2e" - integrity sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw== - dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-for-of@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz#c08892e8819d3a5db29031b115af511dbbfebae9" - integrity sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-function-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz#6a467880e0fc9638514ba369111811ddbe2644b7" - integrity sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg== - dependencies: - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz#9f42ba0841100a135f22712d0e391c462f571f3c" - integrity sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-member-expression-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz#b1ec44fcf195afcb8db2c62cd8e551c881baf8b7" - integrity sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-modules-amd@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz#1b9cddaf05d9e88b3aad339cb3e445c4f020a9b1" - integrity sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw== - dependencies: - "@babel/helper-module-transforms" "^7.10.5" - "@babel/helper-plugin-utils" "^7.10.4" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-commonjs@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz#66667c3eeda1ebf7896d41f1f16b17105a2fbca0" - integrity sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w== - dependencies: - "@babel/helper-module-transforms" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-simple-access" "^7.10.4" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-systemjs@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz#6270099c854066681bae9e05f87e1b9cadbe8c85" - integrity sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw== - dependencies: - "@babel/helper-hoist-variables" "^7.10.4" - "@babel/helper-module-transforms" "^7.10.5" - "@babel/helper-plugin-utils" "^7.10.4" - babel-plugin-dynamic-import-node "^2.3.3" - -"@babel/plugin-transform-modules-umd@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz#9a8481fe81b824654b3a0b65da3df89f3d21839e" - integrity sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA== - dependencies: - "@babel/helper-module-transforms" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-named-capturing-groups-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz#78b4d978810b6f3bcf03f9e318f2fc0ed41aecb6" - integrity sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" - -"@babel/plugin-transform-new-target@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz#9097d753cb7b024cb7381a3b2e52e9513a9c6888" - integrity sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-object-super@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz#d7146c4d139433e7a6526f888c667e314a093894" - integrity sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-replace-supers" "^7.10.4" - -"@babel/plugin-transform-parameters@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz#59d339d58d0b1950435f4043e74e2510005e2c4a" - integrity sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw== - dependencies: - "@babel/helper-get-function-arity" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-property-literals@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz#f6fe54b6590352298785b83edd815d214c42e3c0" - integrity sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-regenerator@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz#2015e59d839074e76838de2159db421966fd8b63" - integrity sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw== - dependencies: - regenerator-transform "^0.14.2" - -"@babel/plugin-transform-reserved-words@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz#8f2682bcdcef9ed327e1b0861585d7013f8a54dd" - integrity sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-shorthand-properties@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz#9fd25ec5cdd555bb7f473e5e6ee1c971eede4dd6" - integrity sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-spread@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz#fa84d300f5e4f57752fe41a6d1b3c554f13f17cc" - integrity sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-skip-transparent-expression-wrappers" "^7.11.0" - -"@babel/plugin-transform-sticky-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz#8f3889ee8657581130a29d9cc91d7c73b7c4a28d" - integrity sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/helper-regex" "^7.10.4" - -"@babel/plugin-transform-template-literals@^7.10.4": - version "7.10.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz#78bc5d626a6642db3312d9d0f001f5e7639fde8c" - integrity sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-typeof-symbol@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz#9509f1a7eec31c4edbffe137c16cc33ff0bc5bfc" - integrity sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-unicode-escapes@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz#feae523391c7651ddac115dae0a9d06857892007" - integrity sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-transform-unicode-regex@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz#e56d71f9282fac6db09c82742055576d5e6d80a8" - integrity sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/preset-env@^7.0.0": - version "7.11.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.11.5.tgz#18cb4b9379e3e92ffea92c07471a99a2914e4272" - integrity sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA== - dependencies: - "@babel/compat-data" "^7.11.0" - "@babel/helper-compilation-targets" "^7.10.4" - "@babel/helper-module-imports" "^7.10.4" - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-proposal-async-generator-functions" "^7.10.4" - "@babel/plugin-proposal-class-properties" "^7.10.4" - "@babel/plugin-proposal-dynamic-import" "^7.10.4" - "@babel/plugin-proposal-export-namespace-from" "^7.10.4" - "@babel/plugin-proposal-json-strings" "^7.10.4" - "@babel/plugin-proposal-logical-assignment-operators" "^7.11.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.10.4" - "@babel/plugin-proposal-numeric-separator" "^7.10.4" - "@babel/plugin-proposal-object-rest-spread" "^7.11.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.10.4" - "@babel/plugin-proposal-optional-chaining" "^7.11.0" - "@babel/plugin-proposal-private-methods" "^7.10.4" - "@babel/plugin-proposal-unicode-property-regex" "^7.10.4" - "@babel/plugin-syntax-async-generators" "^7.8.0" - "@babel/plugin-syntax-class-properties" "^7.10.4" - "@babel/plugin-syntax-dynamic-import" "^7.8.0" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-json-strings" "^7.8.0" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.0" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-syntax-top-level-await" "^7.10.4" - "@babel/plugin-transform-arrow-functions" "^7.10.4" - "@babel/plugin-transform-async-to-generator" "^7.10.4" - "@babel/plugin-transform-block-scoped-functions" "^7.10.4" - "@babel/plugin-transform-block-scoping" "^7.10.4" - "@babel/plugin-transform-classes" "^7.10.4" - "@babel/plugin-transform-computed-properties" "^7.10.4" - "@babel/plugin-transform-destructuring" "^7.10.4" - "@babel/plugin-transform-dotall-regex" "^7.10.4" - "@babel/plugin-transform-duplicate-keys" "^7.10.4" - "@babel/plugin-transform-exponentiation-operator" "^7.10.4" - "@babel/plugin-transform-for-of" "^7.10.4" - "@babel/plugin-transform-function-name" "^7.10.4" - "@babel/plugin-transform-literals" "^7.10.4" - "@babel/plugin-transform-member-expression-literals" "^7.10.4" - "@babel/plugin-transform-modules-amd" "^7.10.4" - "@babel/plugin-transform-modules-commonjs" "^7.10.4" - "@babel/plugin-transform-modules-systemjs" "^7.10.4" - "@babel/plugin-transform-modules-umd" "^7.10.4" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.10.4" - "@babel/plugin-transform-new-target" "^7.10.4" - "@babel/plugin-transform-object-super" "^7.10.4" - "@babel/plugin-transform-parameters" "^7.10.4" - "@babel/plugin-transform-property-literals" "^7.10.4" - "@babel/plugin-transform-regenerator" "^7.10.4" - "@babel/plugin-transform-reserved-words" "^7.10.4" - "@babel/plugin-transform-shorthand-properties" "^7.10.4" - "@babel/plugin-transform-spread" "^7.11.0" - "@babel/plugin-transform-sticky-regex" "^7.10.4" - "@babel/plugin-transform-template-literals" "^7.10.4" - "@babel/plugin-transform-typeof-symbol" "^7.10.4" - "@babel/plugin-transform-unicode-escapes" "^7.10.4" - "@babel/plugin-transform-unicode-regex" "^7.10.4" - "@babel/preset-modules" "^0.1.3" - "@babel/types" "^7.11.5" - browserslist "^4.12.0" - core-js-compat "^3.6.2" - invariant "^2.2.2" - levenary "^1.1.1" - semver "^5.5.0" - -"@babel/preset-modules@^0.1.3": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.4.tgz#362f2b68c662842970fdb5e254ffc8fc1c2e415e" - integrity sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.4.4" - "@babel/plugin-transform-dotall-regex" "^7.4.4" - "@babel/types" "^7.4.4" - esutils "^2.0.2" - -"@babel/register@^7.10.5": - version "7.11.5" - resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.11.5.tgz#79becf89e0ddd0fba8b92bc279bc0f5d2d7ce2ea" - integrity sha512-CAml0ioKX+kOAvBQDHa/+t1fgOt3qkTIz0TrRtRAT6XY0m5qYZXR85k6/sLCNPMGhYDlCFHCYuU0ybTJbvlC6w== - dependencies: - find-cache-dir "^2.0.0" - lodash "^4.17.19" - make-dir "^2.1.0" - pirates "^4.0.0" - source-map-support "^0.5.16" - -"@babel/runtime@^7.8.4": - version "7.11.2" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.11.2.tgz#f549c13c754cc40b87644b9fa9f09a6a95fe0736" - integrity sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw== - dependencies: - regenerator-runtime "^0.13.4" - "@babel/template@^7.10.4", "@babel/template@^7.3.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" @@ -874,7 +249,7 @@ globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.10.5", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": +"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3": version "7.11.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d" integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q== @@ -1088,16 +463,64 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" +"@jest/types@^25.5.0": + version "25.5.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.5.0.tgz#4d6a4793f7b9599fc3680877b856a97dbccf2a9d" + integrity sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^15.0.0" + chalk "^3.0.0" + "@jest/types@^26.3.0": version "26.3.0" resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.3.0.tgz#97627bf4bdb72c55346eef98e3b3f7ddc4941f71" integrity sha512-BDPG23U0qDeAvU4f99haztXwdAg3hz4El95LkAM+tHAqqhiVzRpEGHHU8EDxT/AnxOrA65YjLBwDahdJ9pTLJQ== dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^15.0.0" - chalk "^4.0.0" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@rollup/plugin-typescript@^6.0.0": + version "6.0.0" + resolved "https://registry.yarnpkg.com/@rollup/plugin-typescript/-/plugin-typescript-6.0.0.tgz#08635d9d04dc3a099ef0150c289ba5735200bc63" + integrity sha512-Y5U2L4eaF3wUSgCZRMdvNmuzWkKMyN3OwvhAdbzAi5sUqedaBk/XbzO4T7RlViDJ78MOPhwAIv2FtId/jhMtbg== + dependencies: + "@rollup/pluginutils" "^3.1.0" + resolve "^1.17.0" + +"@rollup/pluginutils@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" + integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== + dependencies: + "@types/estree" "0.0.39" + estree-walker "^1.0.1" + picomatch "^2.2.2" "@sinonjs/commons@^1.7.0": version "1.8.1" @@ -1151,6 +574,11 @@ resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/estree@0.0.39": + version "0.0.39" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" + integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== + "@types/graceful-fs@^4.1.2": version "4.1.3" resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.3.tgz#039af35fe26bec35003e8d86d2ee9c586354348f" @@ -1170,6 +598,14 @@ dependencies: "@types/istanbul-lib-coverage" "*" +"@types/istanbul-reports@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz#e875cc689e47bce549ec81f3df5e6f6f11cfaeb2" + integrity sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw== + dependencies: + "@types/istanbul-lib-coverage" "*" + "@types/istanbul-lib-report" "*" + "@types/istanbul-reports@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" @@ -1177,6 +613,19 @@ dependencies: "@types/istanbul-lib-report" "*" +"@types/jest@26.x": + version "26.0.14" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-26.0.14.tgz#078695f8f65cb55c5a98450d65083b2b73e5a3f3" + integrity sha512-Hz5q8Vu0D288x3iWXePSn53W7hAjP0H7EQ6QvDO9c7t46mR0lNOLlfuwQ+JkVxuhygHzlzPX+0jKdA3ZgSh+Vg== + dependencies: + jest-diff "^25.2.1" + pretty-format "^25.2.1" + +"@types/json-schema@^7.0.3": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" + integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" @@ -1214,6 +663,76 @@ dependencies: "@types/yargs-parser" "*" +"@typescript-eslint/eslint-plugin@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.1.1.tgz#78d5b18e259b13c2f4ec41dd9105af269a161a75" + integrity sha512-Hoxyt99EA9LMmqo/5PuWWPeWeB3mKyvibfJ1Hy5SfiUpjE8Nqp+5QNd9fOkzL66+fqvIWSIE+Ett16LGMzCGnQ== + dependencies: + "@typescript-eslint/experimental-utils" "4.1.1" + "@typescript-eslint/scope-manager" "4.1.1" + debug "^4.1.1" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.1.1.tgz#52ff4e37c93113eb96385a4e6d075abece1ea72d" + integrity sha512-jzYsNciHoa4Z3c1URtmeT/bamYm8Dwfw6vuN3WHIE/BXb1iC4KveAnXDErTAZtPVxTYBaYn3n2gbt6F6D2rm1A== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/scope-manager" "4.1.1" + "@typescript-eslint/types" "4.1.1" + "@typescript-eslint/typescript-estree" "4.1.1" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/parser@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.1.1.tgz#324b4b35e314075adbc92bd8330cf3ef0c88cf3e" + integrity sha512-NLIhmicpKGfJbdXyQBz9j48PA6hq6e+SDOoXy7Ak6bq1ebGqbgG+fR1UIDAuay6OjQdot69c/URu2uLlsP8GQQ== + dependencies: + "@typescript-eslint/scope-manager" "4.1.1" + "@typescript-eslint/types" "4.1.1" + "@typescript-eslint/typescript-estree" "4.1.1" + debug "^4.1.1" + +"@typescript-eslint/scope-manager@4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.1.1.tgz#bdb8526e82435f32b4ccd9dd4cec01af97b48850" + integrity sha512-0W8TTobCvIIQ2FsrYTffyZGAAFUyIbEHq5EYJb1m7Rpd005jrnOvKOo8ywCLhs/Bm17C+KsrUboBvBAARQVvyA== + dependencies: + "@typescript-eslint/types" "4.1.1" + "@typescript-eslint/visitor-keys" "4.1.1" + +"@typescript-eslint/types@4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.1.1.tgz#57500c4a86b28cb47094c1a62f1177ea279a09cb" + integrity sha512-zrBiqOKYerMTllKcn+BP+i1b7LW/EbMMYytroXMxUTvFPn1smkCu0D7lSAx29fTUO4jnwV0ljSvYQtn2vNrNxA== + +"@typescript-eslint/typescript-estree@4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.1.1.tgz#2015a84d71303ecdb6f46efd807ac19a51aab490" + integrity sha512-2AUg5v0liVBsqbGxBphbJ0QbGqSRVaF5qPoTPWcxop+66vMdU1h4CCvHxTC47+Qb+Pr4l2RhXDd41JNpwcQEKw== + dependencies: + "@typescript-eslint/types" "4.1.1" + "@typescript-eslint/visitor-keys" "4.1.1" + debug "^4.1.1" + globby "^11.0.1" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/visitor-keys@4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.1.1.tgz#bb05664bf4bea28dc120d1da94f3027d42ab0f6f" + integrity sha512-/EOOXbA2ferGLG6RmCHEQ0lTTLkOlXYDgblCmQk3tIU7mTPLm4gKhFMeeUSe+bcchTUsKeCk8xcpbop5Zr/8Rw== + dependencies: + "@typescript-eslint/types" "4.1.1" + eslint-visitor-keys "^2.0.0" + abab@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" @@ -1341,6 +860,11 @@ array-includes@^3.1.1: es-abstract "^1.17.0" is-string "^1.0.5" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -1376,11 +900,6 @@ astral-regex@^1.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1401,11 +920,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== -babel-core@^7.0.0-0: - version "7.0.0-bridge.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" - integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== - babel-jest@^26.3.0: version "26.3.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.3.0.tgz#10d0ca4b529ca3e7d1417855ef7d7bd6fc0c3463" @@ -1420,13 +934,6 @@ babel-jest@^26.3.0: graceful-fs "^4.2.4" slash "^3.0.0" -babel-plugin-dynamic-import-node@^2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" - integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ== - dependencies: - object.assign "^4.1.0" - babel-plugin-istanbul@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" @@ -1506,18 +1013,6 @@ benchmark@^2.1.4: lodash "^4.17.4" platform "^1.3.3" -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - bluebird@^3.7.2: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -1531,7 +1026,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^2.3.1, braces@^2.3.2: +braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== @@ -1559,15 +1054,12 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserslist@^4.12.0, browserslist@^4.8.5: - version "4.14.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.14.3.tgz#381f9e7f13794b2eb17e1761b4f118e8ae665a53" - integrity sha512-GcZPC5+YqyPO4SFnz48/B0YaCwS47Q9iPChRGi6t7HhflKBcINzFrJvRfC+jp30sRMKxF+d4EHGs27Z0XP1NaQ== +bs-logger@0.x: + version "0.2.6" + resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" + integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== dependencies: - caniuse-lite "^1.0.30001131" - electron-to-chromium "^1.3.570" - escalade "^3.1.0" - node-releases "^1.1.61" + fast-json-stable-stringify "2.x" bser@2.1.1: version "2.1.1" @@ -1576,7 +1068,7 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" -buffer-from@^1.0.0: +buffer-from@1.x, buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== @@ -1611,11 +1103,6 @@ camelcase@^6.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== -caniuse-lite@^1.0.30001131: - version "1.0.30001131" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001131.tgz#afad8a28fc2b7a0d3ae9407e71085a0ead905d54" - integrity sha512-4QYi6Mal4MMfQMSqGIRPGbKIbZygeN83QsWq1ixpUwvtfgAZot5BrCKzGygvZaV+CnELdTwD0S4cqUNozq7/Cw== - capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -1644,6 +1131,14 @@ chalk@^2.0.0, chalk@^2.3.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" @@ -1657,25 +1152,6 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== -chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" @@ -1754,16 +1230,6 @@ commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" @@ -1789,7 +1255,7 @@ contains-path@^0.1.0: resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= -convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== @@ -1801,20 +1267,12 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-js-compat@^3.6.2: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.5.tgz#2a51d9a4e25dfd6e690251aa81f99e3c05481f1c" - integrity sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng== - dependencies: - browserslist "^4.8.5" - semver "7.0.0" - -core-js@^3.1.4, core-js@^3.2.1: +core-js@^3.1.4: version "3.6.5" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== -core-util-is@1.0.2, core-util-is@~1.0.0: +core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= @@ -1961,11 +1419,23 @@ detect-newline@^3.0.0: resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== +diff-sequences@^25.2.6: + version "25.2.6" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" + integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== + diff-sequences@^26.3.0: version "26.3.0" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.3.0.tgz#62a59b1b29ab7fd27cef2a33ae52abe73042d0a2" integrity sha512-5j5vdRcw3CNctePNYN0Wy2e/JbWT6cAYnXv5OuqPhDpyCGc0uLu2TK0zOCJWNB9kOIfYMSpIulRaDgIi4HJ6Ig== +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + docdash@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/docdash/-/docdash-1.2.0.tgz#f99dde5b8a89aa4ed083a3150383e042d06c7f49" @@ -2001,11 +1471,6 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -electron-to-chromium@^1.3.570: - version "1.3.570" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.570.tgz#3f5141cc39b4e3892a276b4889980dabf1d29c7f" - integrity sha512-Y6OCoVQgFQBP5py6A/06+yWxUZHDlNr/gNDGatjH8AZqXl8X0tE4LfjLJsXGz/JmWJz8a6K7bR1k+QzZ+k//fg== - emittery@^0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.1.tgz#c02375a927a40948c0345cc903072597f5270451" @@ -2091,11 +1556,6 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -escalade@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.0.tgz#e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e" - integrity sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig== - escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -2188,7 +1648,7 @@ eslint-plugin-standard@^4.0.1: resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ== -eslint-scope@^5.1.0: +eslint-scope@^5.0.0, eslint-scope@^5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -2208,6 +1668,11 @@ eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + eslint@^7.6.0: version "7.9.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.9.0.tgz#522aeccc5c3a19017cf0cb46ebfd660a79acf337" @@ -2289,10 +1754,10 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== -estree-walker@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.6.1.tgz#53049143f40c6eb918b23671d1fe3219f3a1b362" - integrity sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w== +estree-walker@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700" + integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg== esutils@^2.0.2: version "2.0.3" @@ -2418,7 +1883,19 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-json-stable-stringify@^2.0.0: +fast-glob@^3.1.1: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -2428,6 +1905,13 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fastq@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" + integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + dependencies: + reusify "^1.0.4" + fb-watchman@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" @@ -2442,11 +1926,6 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -2464,15 +1943,6 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -find-cache-dir@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -2480,13 +1950,6 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -2535,24 +1998,11 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fs-readdir-recursive@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" - integrity sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA== - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@^1.2.7: - version "1.2.13" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.13.tgz#f325cb0455592428bcf11b383370ef70e3bfcc38" - integrity sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw== - dependencies: - bindings "^1.5.0" - nan "^2.12.1" - fsevents@^2.1.2, fsevents@~2.1.2: version "2.1.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" @@ -2609,22 +2059,14 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-parent@^5.0.0: +glob-parent@^5.0.0, glob-parent@^5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== dependencies: is-glob "^4.0.1" -glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -2648,7 +2090,19 @@ globals@^12.1.0: dependencies: type-fest "^0.8.1" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.9, graceful-fs@^4.2.4: +globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.9, graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== @@ -2724,13 +2178,6 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -homedir-polyfill@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== - dependencies: - parse-passwd "^1.0.0" - hosted-git-info@^2.1.4: version "2.8.8" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" @@ -2774,7 +2221,7 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1: +ignore@^5.1.1, ignore@^5.1.4: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== @@ -2808,18 +2255,11 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -invariant@^2.2.2, invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -2844,13 +2284,6 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -2922,7 +2355,7 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^2.1.0, is-extglob@^2.1.1: +is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= @@ -2942,13 +2375,6 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - is-glob@^4.0.0, is-glob@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" @@ -3031,7 +2457,7 @@ is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -3151,6 +2577,16 @@ jest-config@^26.4.2: micromatch "^4.0.2" pretty-format "^26.4.2" +jest-diff@^25.2.1: + version "25.5.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.5.0.tgz#1dd26ed64f96667c068cef026b677dfa01afcfa9" + integrity sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A== + dependencies: + chalk "^3.0.0" + diff-sequences "^25.2.6" + jest-get-type "^25.2.6" + pretty-format "^25.5.0" + jest-diff@^26.4.2: version "26.4.2" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.4.2.tgz#a1b7b303bcc534aabdb3bd4a7caf594ac059f5aa" @@ -3204,6 +2640,11 @@ jest-environment-node@^26.3.0: jest-mock "^26.3.0" jest-util "^26.3.0" +jest-get-type@^25.2.6: + version "25.2.6" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" + integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== + jest-get-type@^26.3.0: version "26.3.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" @@ -3414,7 +2855,7 @@ jest-snapshot@^26.4.2: pretty-format "^26.4.2" semver "^7.3.2" -jest-util@^26.3.0: +jest-util@26.x, jest-util@^26.3.0: version "26.3.0" resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.3.0.tgz#a8974b191df30e2bf523ebbfdbaeb8efca535b3e" integrity sha512-4zpn6bwV0+AMFN0IYhH/wnzIQzRaYVrz1A8sYnRnj4UXDXbOVtWmlaZkO9mipFqZ13okIfN87aDoJWB7VH6hcw== @@ -3469,7 +2910,7 @@ jest@^26.3.0: import-local "^3.0.2" jest-cli "^26.4.2" -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: +js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== @@ -3551,11 +2992,6 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" @@ -3581,6 +3017,13 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@2.x, json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -3588,13 +3031,6 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -json5@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" - integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== - dependencies: - minimist "^1.2.5" - jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -3651,13 +3087,6 @@ leven@^3.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== -levenary@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" - integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== - dependencies: - leven "^3.1.0" - levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -3704,14 +3133,6 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -3719,12 +3140,17 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +lodash.memoize@4.x: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= -lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.4: +lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.4: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -3734,21 +3160,6 @@ log-driver@^1.2.7: resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -make-dir@^2.0.0, make-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -3756,6 +3167,11 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" +make-error@1.x: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + makeerror@1.0.x: version "1.0.11" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" @@ -3806,7 +3222,12 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -micromatch@^3.1.10, micromatch@^3.1.4: +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -3870,6 +3291,11 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp@1.x, mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + mkdirp@^0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -3877,11 +3303,6 @@ mkdirp@^0.5.1: dependencies: minimist "^1.2.5" -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -3892,11 +3313,6 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -nan@^2.12.1: - version "2.14.1" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" - integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -3924,14 +3340,6 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-environment-flags@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" - integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== - dependencies: - object.getownpropertydescriptors "^2.0.3" - semver "^5.7.0" - node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -3954,11 +3362,6 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" -node-releases@^1.1.61: - version "1.1.61" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.61.tgz#707b0fca9ce4e11783612ba4a2fcba09047af16e" - integrity sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g== - normalize-package-data@^2.3.2, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -4041,14 +3444,6 @@ object.assign@^4.1.0: has-symbols "^1.0.1" object-keys "^1.1.1" -object.getownpropertydescriptors@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" - integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -4121,7 +3516,7 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0, p-limit@^2.2.0: +p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== @@ -4135,13 +3530,6 @@ p-locate@^2.0.0: dependencies: p-limit "^1.1.0" -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - p-locate@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" @@ -4183,11 +3571,6 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= - parse5@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" @@ -4198,11 +3581,6 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -4240,12 +3618,17 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.0.4, picomatch@^2.0.5: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1, picomatch@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== @@ -4255,12 +3638,7 @@ pify@^2.0.0: resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pirates@^4.0.0, pirates@^4.0.1: +pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== @@ -4274,13 +3652,6 @@ pkg-dir@^2.0.0: dependencies: find-up "^2.1.0" -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -4308,6 +3679,16 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +pretty-format@^25.2.1, pretty-format@^25.5.0: + version "25.5.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a" + integrity sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ== + dependencies: + "@jest/types" "^25.5.0" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^16.12.0" + pretty-format@^26.4.2: version "26.4.2" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.4.2.tgz#d081d032b398e801e2012af2df1214ef75a81237" @@ -4318,11 +3699,6 @@ pretty-format@^26.4.2: ansi-styles "^4.0.0" react-is "^16.12.0" -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -4412,19 +3788,6 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -readable-stream@^2.0.2: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - readable-stream@^3.0.2: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -4434,39 +3797,11 @@ readable-stream@^3.0.2: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -regenerate-unicode-properties@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz#e5de7111d655e7ba60c057dbe9ff37c87e65cdec" - integrity sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA== - dependencies: - regenerate "^1.4.0" - -regenerate@^1.4.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.1.tgz#cad92ad8e6b591773485fbe05a485caf4f457e6f" - integrity sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A== - -regenerator-runtime@^0.13.1, regenerator-runtime@^0.13.4: +regenerator-runtime@^0.13.1: version "0.13.7" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== - dependencies: - "@babel/runtime" "^7.8.4" - regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -4480,30 +3815,6 @@ regexpp@^3.0.0, regexpp@^3.1.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== -regexpu-core@^4.7.0: - version "4.7.1" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" - integrity sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.2.0" - regjsgen "^0.5.1" - regjsparser "^0.6.4" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.2.0" - -regjsgen@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" - integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== - -regjsparser@^0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.4.tgz#a769f8684308401a66e9b529d2436ff4d0666272" - integrity sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw== - dependencies: - jsesc "~0.5.0" - remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -4612,6 +3923,11 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -4626,14 +3942,6 @@ rimraf@^3.0.0: dependencies: glob "^7.1.3" -rollup-plugin-babel@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-4.4.0.tgz#d15bd259466a9d1accbdb2fe2fff17c52d030acb" - integrity sha512-Lek/TYp1+7g7I+uMfJnnSJ7YWoD58ajo6Oarhlex7lvUce+RCKRuGRSgztDO3/MF/PuGKmUL5iTHKf208UNszw== - dependencies: - "@babel/helper-module-imports" "^7.0.0" - rollup-pluginutils "^2.8.1" - rollup-plugin-terser@^7.0.0: version "7.0.2" resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d" @@ -4644,13 +3952,6 @@ rollup-plugin-terser@^7.0.0: serialize-javascript "^4.0.0" terser "^5.0.0" -rollup-pluginutils@^2.8.1: - version "2.8.2" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e" - integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ== - dependencies: - estree-walker "^0.6.1" - rollup@^2.2.0: version "2.27.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.27.1.tgz#372744e1d36eba0fd942d997600c2fc2ca266305" @@ -4663,12 +3964,17 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -4707,26 +4013,21 @@ saxes@^5.0.0: dependencies: xmlchars "^2.2.0" -"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== +semver@7.x, semver@^7.2.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== semver@^6.0.0, semver@^6.1.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.2.1, semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== - serialize-javascript@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" @@ -4788,11 +4089,6 @@ sisteransi@^1.0.4: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" @@ -4861,7 +4157,7 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.16, source-map-support@^0.5.6, source-map-support@~0.5.12: +source-map-support@^0.5.6, source-map-support@~0.5.12: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== @@ -5018,13 +4314,6 @@ string_decoder@^1.1.1: dependencies: safe-buffer "~5.2.0" -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - strip-ansi@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" @@ -5215,6 +4504,23 @@ tr46@^2.0.2: dependencies: punycode "^2.1.1" +ts-jest@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-26.3.0.tgz#6b2845045347dce394f069bb59358253bc1338a9" + integrity sha512-Jq2uKfx6bPd9+JDpZNMBJMdMQUC3sJ08acISj8NXlVgR2d5OqslEHOR2KHMgwymu8h50+lKIm0m0xj/ioYdW2Q== + dependencies: + "@types/jest" "26.x" + bs-logger "0.x" + buffer-from "1.x" + fast-json-stable-stringify "2.x" + jest-util "26.x" + json5 "2.x" + lodash.memoize "4.x" + make-error "1.x" + mkdirp "1.x" + semver "7.x" + yargs-parser "18.x" + tsconfig-paths@^3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" @@ -5225,6 +4531,23 @@ tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" +tslib@^1.8.1: + version "1.13.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" + integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== + +tslib@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" + integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== + +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + dependencies: + tslib "^1.8.1" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -5298,29 +4621,6 @@ underscore@~1.10.2: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.10.2.tgz#73d6aa3668f3188e4adb0f1943bd12cfd7efaaaf" integrity sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg== -unicode-canonical-property-names-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" - integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== - -unicode-match-property-ecmascript@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" - integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== - dependencies: - unicode-canonical-property-names-ecmascript "^1.0.4" - unicode-property-aliases-ecmascript "^1.0.4" - -unicode-match-property-value-ecmascript@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz#0d91f600eeeb3096aa962b1d6fc88876e64ea531" - integrity sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ== - -unicode-property-aliases-ecmascript@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz#dd57a99f6207bedff4628abefb94c50db941c8f4" - integrity sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg== - union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -5339,11 +4639,6 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - uri-js@^4.2.2: version "4.4.0" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" @@ -5361,7 +4656,7 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== -util-deprecate@^1.0.1, util-deprecate@~1.0.1: +util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -5390,13 +4685,6 @@ v8-to-istanbul@^5.0.1: convert-source-map "^1.6.0" source-map "^0.7.3" -v8flags@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656" - integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg== - dependencies: - homedir-polyfill "^1.0.1" - validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -5546,7 +4834,7 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yargs-parser@^18.1.2: +yargs-parser@18.x, yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==