From c15ce0c4f6b9c2343b159348bd296b190a26fefa Mon Sep 17 00:00:00 2001 From: scottinet Date: Fri, 21 May 2021 12:01:25 +0200 Subject: [PATCH 1/2] chore: update dependencies --- lib/transform/canonical.js | 3 +- lib/transform/index.js | 16 +- lib/transform/standardize.js | 89 +- lib/util/convertDistance.js | 3 +- package-lock.json | 1992 ++++++++++++++---------- package.json | 16 +- test/api.test.js | 9 +- test/keywords/equals.test.js | 29 +- test/keywords/exists.test.js | 38 +- test/keywords/geoBoundingBox.test.js | 47 +- test/keywords/geoDistance.test.js | 71 +- test/keywords/geoDistanceRange.test.js | 112 +- test/keywords/geoPolygon.test.js | 24 +- test/keywords/ids.test.js | 22 +- test/keywords/in.test.js | 19 +- test/keywords/range.test.js | 28 +- test/keywords/regexp.test.js | 30 +- test/operands/and.test.js | 46 +- test/operands/bool.test.js | 16 +- test/operands/or.test.js | 37 +- 20 files changed, 1606 insertions(+), 1041 deletions(-) diff --git a/lib/transform/canonical.js b/lib/transform/canonical.js index 811bcc6..5b3d893 100644 --- a/lib/transform/canonical.js +++ b/lib/transform/canonical.js @@ -21,7 +21,6 @@ const Combinatorics = require('js-combinatorics'); -const { BadRequestError } = require('kuzzle-common-objects'); const { Espresso } = require('espresso-logic-minimizer'); const strcmp = require('../util/stringCompare'); @@ -66,7 +65,7 @@ class Canonical { const conditions = this._extractConditions(filters); if (this.config.maxMinTerms && conditions.length > this.config.maxMinTerms) { - throw new BadRequestError('Maximum number of sub conditions reached.'); + throw new Error('Maximum number of sub conditions reached.'); } const normalized = this._normalize(filters, conditions); diff --git a/lib/transform/index.js b/lib/transform/index.js index 71c06cb..96a4ace 100644 --- a/lib/transform/index.js +++ b/lib/transform/index.js @@ -19,11 +19,6 @@ * limitations under the License. */ -const { - KuzzleError, - InternalError: KuzzleInternalError -} = require('kuzzle-common-objects'); - const Standardizer = require('./standardize'); const Canonical = require('./canonical'); @@ -49,16 +44,7 @@ class Transformer { normalize(filters) { const standardized = this.standardizer.standardize(filters); - try { - return this.canonical.convert(standardized); - } - catch (e) { - if (e instanceof KuzzleError) { - throw e; - } - - throw new KuzzleInternalError(e); - } + return this.canonical.convert(standardized); } /** diff --git a/lib/transform/standardize.js b/lib/transform/standardize.js index a5bf74e..ba877c8 100644 --- a/lib/transform/standardize.js +++ b/lib/transform/standardize.js @@ -19,7 +19,6 @@ * limitations under the License. */ -const { BadRequestError } = require('kuzzle-common-objects'); const RE2 = require('re2'); const convertGeopoint = require('../util/convertGeopoint'); @@ -75,11 +74,11 @@ class Standardizer { } if (keywords.length > 1) { - throw new BadRequestError('Invalid filter syntax. Filters must have one keyword only'); + throw new Error('Invalid filter syntax. Filters must have one keyword only'); } if (!this.allowedKeywords.has(keywords[0])) { - throw new BadRequestError(`Unknown DSL keyword: ${keywords[0]}`); + throw new Error(`Unknown DSL keyword: ${keywords[0]}`); } return this[keywords[0]](filters); @@ -107,7 +106,7 @@ class Standardizer { // Syntax: {exists: ''} if (typeof filter[name] === 'string') { if (filter[name].length === 0) { - throw new BadRequestError(`${name}: cannot test empty field name`); + throw new Error(`${name}: cannot test empty field name`); } return parseFieldSyntax(filter[name], name); @@ -115,11 +114,12 @@ class Standardizer { // Syntax: {exists: {field: ''}} const field = mustBeNonEmptyObject(filter[name], name); + requireAttribute(filter[name], 'exists', 'field'); onlyOneFieldAttribute(field, name); mustBeString(filter[name], name, 'field'); if (filter[name].field.length === 0) { - throw new BadRequestError(`${name}: cannot test empty field name`); + throw new Error(`${name}: cannot test empty field name`); } return parseFieldSyntax(filter[name].field, name); @@ -139,7 +139,7 @@ class Standardizer { mustBeNonEmptyArray(filter.ids, 'ids', 'values'); if (filter.ids.values.findIndex(v => typeof v !== 'string') > -1) { - throw new BadRequestError('Array "values" in keyword "ids" can only contain strings'); + throw new Error('Array "values" in keyword "ids" can only contain strings'); } const result = { @@ -191,19 +191,19 @@ class Standardizer { let error = null; if (index > -1) { - throw new BadRequestError(`"range.${rangeField}" accepts only the following attributes : gt, gte, lt, lte`); + throw new Error(`"range.${rangeField}" accepts only the following attributes : gt, gte, lt, lte`); } index = rangeValues.findIndex(v => typeof filter.range[rangeField][v] !== 'number'); if (index > -1) { - throw new BadRequestError(`"range.${rangeField}.${rangeValues[index]}" must be a number`); + throw new Error(`"range.${rangeField}.${rangeValues[index]}" must be a number`); } rangeValues.forEach(rangeType => { if (rangeType.startsWith('lt')) { if (high !== Infinity) { - error = new BadRequestError(`"range.${rangeField}:" only 1 upper boundary allowed`); + error = new Error(`"range.${rangeField}:" only 1 upper boundary allowed`); } else { high = filter.range[rangeField][rangeType]; @@ -212,7 +212,7 @@ class Standardizer { if (rangeType.startsWith('gt')) { if (low !== -Infinity) { - error = new BadRequestError(`"range.${rangeField}:" only 1 lower boundary allowed`); + error = new Error(`"range.${rangeField}:" only 1 lower boundary allowed`); } else { low = filter.range[rangeField][rangeType]; @@ -225,7 +225,7 @@ class Standardizer { } if (high <= low) { - throw new BadRequestError(`"range.${rangeField}:" lower boundary must be strictly inferior to the upper one`); + throw new Error(`"range.${rangeField}:" lower boundary must be strictly inferior to the upper one`); } return filter; @@ -251,7 +251,7 @@ class Standardizer { && Object.keys(filter.regexp[regexpField]).length > 0); if (!isObject && !isString) { - throw new BadRequestError(`regexp.${regexpField} must be either a string or a non-empty object`); + throw new Error(`regexp.${regexpField} must be either a string or a non-empty object`); } let regexValue; @@ -262,7 +262,7 @@ class Standardizer { } else { if (Object.keys(filter.regexp[regexpField]).findIndex(v => ['flags', 'value'].indexOf(v) === -1) > -1) { - throw new BadRequestError('Keyword "regexp" can only contain the following attributes: flags, value'); + throw new Error('Keyword "regexp" can only contain the following attributes: flags, value'); } requireAttribute(filter.regexp[regexpField], 'regexp', 'value'); @@ -279,7 +279,7 @@ class Standardizer { new this.RegExpConstructor(regexValue, flags); //NOSONAR } catch (err) { - throw new BadRequestError(err.message); + throw new Error(`Cannot parse regexp expression "/${regexValue}/${flags}": ${err.message}`); } // standardize regexp to the unique format {: {value, flags}} @@ -320,7 +320,7 @@ class Standardizer { mustBeNonEmptyArray(filter.in, 'in', inValue); if (filter.in[inValue].findIndex(v => typeof v !== 'string') > -1) { - throw new BadRequestError(`Array "${inValue}" in keyword "in" can only contain strings`); + throw new Error(`Array "${inValue}" in keyword "in" can only contain strings`); } const result = { @@ -364,7 +364,7 @@ class Standardizer { const n = Number.parseFloat(bBox[v]); if (isNaN(n)) { - throw new BadRequestError(`Invalid geoBoundingBox format: ${JSON.stringify(bBox)}`); + throw new Error(`Invalid geoBoundingBox format: ${JSON.stringify(bBox)}`); } standardized[v] = n; @@ -386,7 +386,7 @@ class Standardizer { } if (BBOX_PROPERTIES.some(v => standardized[v] === null || standardized[v] === undefined)) { - throw new BadRequestError(`Unrecognized geo-point format in "geoBoundingBox.${field[0]}`); + throw new Error(`Unrecognized geo-point format in "geoBoundingBox.${field[0]}`); } return { @@ -409,7 +409,7 @@ class Standardizer { const fields = mustBeNonEmptyObject(filter.geoDistance, 'geoDistance'); if (fields.length !== 2 || !fields.includes('distance')) { - throw new BadRequestError('"geoDistance" keyword requires a document field and a "distance" attribute'); + throw new Error('"geoDistance" keyword must (only) contain a document field and a "distance" attribute'); } mustBeString(filter.geoDistance, 'geoDistance', 'distance'); @@ -418,7 +418,7 @@ class Standardizer { const point = convertGeopoint(filter.geoDistance[docField]); if (point === null) { - throw new BadRequestError(`geoDistance.${docField}: unrecognized point format`); + throw new Error(`geoDistance.${docField}: unrecognized point format`); } standardized.geospatial.geoDistance[docField] = {lat: point.lat, lon: point.lon}; @@ -436,7 +436,7 @@ class Standardizer { const fields = mustBeNonEmptyObject(filter.geoDistanceRange, 'geoDistanceRange'); if (fields.length !== 3 || !fields.includes('from') || !fields.includes('to')) { - throw new BadRequestError('"geoDistanceRange" keyword requires a document field and the following attributes: "from", "to"'); + throw new Error('"geoDistanceRange" keyword must (only) contain a document field and the following attributes: "from", "to"'); } const docField = Object.keys(filter.geoDistanceRange).find(f => f !== 'from' && f !== 'to'); @@ -447,14 +447,14 @@ class Standardizer { const point = convertGeopoint(filter.geoDistanceRange[docField]); if (point === null) { - throw new BadRequestError(`geoDistanceRange.${docField}: unrecognized point format`); + throw new Error(`geoDistanceRange.${docField}: unrecognized point format`); } const from = convertDistance(filter.geoDistanceRange.from); const to = convertDistance(filter.geoDistanceRange.to); if (from >= to) { - throw new BadRequestError(`geoDistanceRange.${docField}: inner radius must be smaller than outer radius`); + throw new Error(`geoDistanceRange.${docField}: inner radius must be smaller than outer radius`); } return { @@ -487,14 +487,14 @@ class Standardizer { const points = []; if (filter.geoPolygon[docField].points.length < 3) { - throw new BadRequestError(`"geoPolygon.${docField}": at least 3 points are required to build a polygon`); + throw new Error(`"geoPolygon.${docField}": at least 3 points are required to build a polygon`); } for (let i = 0; i < filter.geoPolygon[docField].points.length; ++i) { const point = convertGeopoint(filter.geoPolygon[docField].points[i]); if (point === null) { - throw new BadRequestError(`geoPolygon.${docField}: unrecognized point format (${JSON.stringify(filter.geoPolygon[docField].points[i])})`); + throw new Error(`geoPolygon.${docField}: unrecognized point format (${JSON.stringify(filter.geoPolygon[docField].points[i])})`); } points.push([point.lat, point.lon]); @@ -515,8 +515,8 @@ class Standardizer { * @param {string} [keyword] name - user keyword entry (and, must, should_not).. used to display errors if any * @returns {Object} standardized filter */ - and (filter, keyword = 'and') { - mustBeNonEmptyArray(filter, 'and', keyword); + and (filter) { + mustBeNonEmptyArray(filter, 'and'); return this._standardizeFilterArray(filter, 'and'); } @@ -526,8 +526,8 @@ class Standardizer { * @param {string} [keyword] name - user keyword entry (or, should, must_not).. used to display errors if any * @returns {Object} standardized filter */ - or (filter, keyword = 'or') { - mustBeNonEmptyArray(filter, 'or', keyword); + or (filter) { + mustBeNonEmptyArray(filter, 'or'); return this._standardizeFilterArray(filter, 'or'); } @@ -586,7 +586,7 @@ class Standardizer { const fields = mustBeNonEmptyObject(filter.bool, 'bool'); if (fields.findIndex(field => BOOL_ATTRIBUTES.indexOf(field) === -1) > -1) { - throw new BadRequestError(`"bool" operand accepts only the following attributes: ${BOOL_ATTRIBUTES.join(', ')}`); + throw new Error(`"bool" operand accepts only the following attributes: ${BOOL_ATTRIBUTES.join(', ')}`); } const f = {and: []}; @@ -627,7 +627,7 @@ class Standardizer { }); if (idx > -1) { - throw new BadRequestError(`"${operand}" operand can only contain non-empty objects`); + throw new Error(`"${operand}" operand can only contain non-empty objects`); } const result = { @@ -694,7 +694,7 @@ module.exports = Standardizer; */ function onlyOneFieldAttribute(fieldsList, keyword) { if (fieldsList.length > 1) { - throw new BadRequestError(`"${keyword}" can contain only one attribute`); + throw new Error(`"${keyword}" can contain only one attribute`); } } @@ -705,8 +705,8 @@ function onlyOneFieldAttribute(fieldsList, keyword) { * @param attribute */ function requireAttribute(filter, keyword, attribute) { - if (!filter[attribute]) { - throw new BadRequestError(`"${keyword}" requires the following attribute: ${attribute}`); + if (filter[attribute] === undefined) { + throw new Error(`"${keyword}" requires the following attribute: ${attribute}`); } } @@ -718,13 +718,13 @@ function requireAttribute(filter, keyword, attribute) { */ function mustBeNonEmptyObject(filter, keyword) { if (!filter || typeof filter !== 'object' || Array.isArray(filter)) { - throw new BadRequestError(`"${keyword}" must be a non-empty object`); + throw new Error(`"${keyword}" must be a non-empty object`); } const fields = Object.keys(filter); if (fields.length === 0) { - throw new BadRequestError(`"${keyword}" must be a non-empty object`); + throw new Error(`"${keyword}" must be a non-empty object`); } return fields; @@ -739,7 +739,7 @@ function mustBeNonEmptyObject(filter, keyword) { */ function mustBeScalar (filter, keyword, field) { if (filter[field] instanceof Object || filter[field] === undefined) { - throw new BadRequestError(`"${field}" in "${keyword}" must be either a string, a number, a boolean or null`); + throw new Error(`"${field}" in "${keyword}" must be either a string, a number, a boolean or null`); } } @@ -751,7 +751,7 @@ function mustBeScalar (filter, keyword, field) { */ function mustBeString (filter, keyword, field) { if (typeof filter[field] !== 'string') { - throw new BadRequestError(`Attribute "${field}" in "${keyword}" must be a string`); + throw new Error(`Attribute "${field}" in "${keyword}" must be a string`); } } @@ -762,12 +762,17 @@ function mustBeString (filter, keyword, field) { * @param field */ function mustBeNonEmptyArray (filter, keyword, field) { - if (!Array.isArray(filter[field])) { - throw new BadRequestError(`Attribute "${field}" in "${keyword}" must be an array`); + const prefix = field + ? `Attribute "${field}" in "${keyword}"` + : `Attribute "${keyword}"`; + const value = field ? filter[field] : filter[keyword]; + + if (!Array.isArray(value)) { + throw new Error(`${prefix} must be an array`); } - if (filter[field].length === 0) { - throw new BadRequestError(`Attribute "${field}" in "${keyword}" cannot be empty`); + if (value.length === 0) { + throw new Error(`${prefix} cannot be empty`); } } @@ -807,7 +812,7 @@ function parseFieldSyntax(field, keyword) { value = JSON.parse(rawValue); } catch (error) { - throw new BadRequestError(`[${keyword}] Invalid array value "${rawValue}"`); + throw new Error(`[${keyword}] Invalid array value "${rawValue}"`); } } diff --git a/lib/util/convertDistance.js b/lib/util/convertDistance.js index da7efee..21e874c 100644 --- a/lib/util/convertDistance.js +++ b/lib/util/convertDistance.js @@ -20,7 +20,6 @@ */ const units = require('node-units'); -const { BadRequestError } = require('kuzzle-common-objects'); /** * Converts a distance string value to a number of meters @@ -41,7 +40,7 @@ function convertDistance (distance) { converted = units.convert(cleaned + ' to m'); } catch (e) { - throw new BadRequestError(`unable to parse distance value "${distance}"`); + throw new Error(`unable to parse distance value "${distance}"`); } return converted; diff --git a/package-lock.json b/package-lock.json index b6c8fc4..6980c17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,25 +12,24 @@ "espresso-logic-minimizer": "^2.0.3", "js-combinatorics": "^0.6.1", "json-stable-stringify": "^1.0.1", - "kuzzle-common-objects": "^5.0.2", "murmurhash-native": "^3.5.0", "ngeohash": "^0.6.3", "node-interval-tree": "^1.3.3", "node-units": "^0.1.7", - "re2": "^1.15.9", + "re2": "^1.16.0", "reify": "^0.20.12" }, "devDependencies": { "benchmark": "^2.1.4", - "codecov": "^3.8.1", - "eslint": "^7.20.0", + "codecov": "^3.8.2", + "eslint": "^7.26.0", "geojson-random": "^0.5.0", - "mocha": "^8.3.0", + "mocha": "^8.4.0", "nyc": "^15.1.0", "random-js": "^2.1.0", "should": "^13.2.3", "should-sinon": "0.0.6", - "sinon": "^9.2.4" + "sinon": "^10.0.0" } }, "node_modules/@babel/code-frame": { @@ -410,9 +409,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", - "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz", + "integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -422,7 +421,6 @@ "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^3.13.1", - "lodash": "^4.17.20", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" }, @@ -430,6 +428,21 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "dependencies": { + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -516,6 +529,43 @@ "node": ">=8" } }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@sinonjs/commons": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", @@ -555,7 +605,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, "engines": { "node": ">= 6" } @@ -600,7 +649,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, "dependencies": { "debug": "4" }, @@ -608,11 +656,23 @@ "node": ">= 6.0.0" } }, + "node_modules/agentkeepalive": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz", + "integrity": "sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==", + "dependencies": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -625,6 +685,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -731,22 +792,6 @@ "node": ">=0.6.10" } }, - "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "engines": { - "node": ">=0.8" - } - }, "node_modules/astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", @@ -756,37 +801,11 @@ "node": ">=8" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "node_modules/balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, "node_modules/benchmark": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", @@ -886,6 +905,135 @@ "url": "https://opencollective.com/browserslist" } }, + "node_modules/cacache": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.1.0.tgz", + "integrity": "sha512-mfx0C+mCfWjD1PnwQ9yaOrwG1ou9FkKnx0SvzUHWdFt7r7GaRtzT+9M8HAvLu62zIHtnpQ/1m93nWNDCckJGXQ==", + "dependencies": { + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cacache/node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/tar": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", + "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -925,11 +1073,6 @@ "integrity": "sha512-xJJqzyd+7GCJXkcoBiQ1GuxEiOBCLQ0aVW9HMekifZsAVGdj5eJ4mFB9fEhSHipq9IOk/QXFJUiIr9lZT+EsGw==", "dev": true }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "node_modules/chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -954,7 +1097,6 @@ "dependencies": { "anymatch": "~3.1.1", "braces": "~3.0.2", - "fsevents": "~2.3.1", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", @@ -977,7 +1119,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, "engines": { "node": ">=6" } @@ -1046,15 +1187,15 @@ } }, "node_modules/codecov": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.8.1.tgz", - "integrity": "sha512-Qm7ltx1pzLPsliZY81jyaQ80dcNR4/JpcX0IHCIWrHBXgseySqbdbYfkdiXd7o/xmzQpGRVCKGYeTrHUpn6Dcw==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.8.2.tgz", + "integrity": "sha512-6w/kt/xvmPsWMfDFPE/T054txA9RTgcJEw36PNa6MYX+YV29jCHCRFXwbQ3QZBTOgnex1J2WP8bo2AT8TWWz9g==", "dev": true, "dependencies": { "argv": "0.0.2", "ignore-walk": "3.0.3", - "js-yaml": "3.14.0", - "teeny-request": "6.0.1", + "js-yaml": "3.14.1", + "teeny-request": "7.0.1", "urlgrey": "0.4.4" }, "bin": { @@ -1064,19 +1205,6 @@ "node": ">=4.0" } }, - "node_modules/codecov/node_modules/js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1101,17 +1229,6 @@ "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", "dev": true }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -1156,17 +1273,6 @@ "node": ">= 8" } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -1218,19 +1324,19 @@ "node": ">=8" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -1263,15 +1369,6 @@ "node": ">=6.0.0" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "node_modules/electron-to-chromium": { "version": "1.3.672", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.672.tgz", @@ -1284,6 +1381,27 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -1297,13 +1415,18 @@ } }, "node_modules/env-paths": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", - "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "engines": { "node": ">=6" } }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" + }, "node_modules/es6-error": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", @@ -1332,13 +1455,13 @@ } }, "node_modules/eslint": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz", - "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.26.0.tgz", + "integrity": "sha512-4R1ieRf52/izcZE7AlLy56uIHHDLT74Yzz2Iv2l6kDaYvEu9x+wMB5dZArVL8SYGXSYV2YAg70FcW5Y5nGGNIg==", "dev": true, "dependencies": { "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.3.0", + "@eslint/eslintrc": "^0.4.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -1351,10 +1474,10 @@ "espree": "^7.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^6.0.0", + "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^12.1.0", + "globals": "^13.6.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", @@ -1362,7 +1485,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.20", + "lodash": "^4.17.21", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -1601,28 +1724,17 @@ "node": ">=0.10.0" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "engines": [ - "node >=0.6.0" - ] - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -1748,27 +1860,6 @@ "node": ">=8.0.0" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, "node_modules/from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -1897,14 +1988,6 @@ "node": ">=8.0.0" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -1937,12 +2020,12 @@ } }, "node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", + "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", "dev": true, "dependencies": { - "type-fest": "^0.8.1" + "type-fest": "^0.20.2" }, "engines": { "node": ">=8" @@ -1951,6 +2034,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/graceful-fs": { "version": "4.2.6", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", @@ -1965,27 +2060,6 @@ "node": ">=4.x" } }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2031,11 +2105,15 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, "node_modules/http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, "dependencies": { "@tootallnate/once": "1", "agent-base": "6", @@ -2045,40 +2123,24 @@ "node": ">= 6" } }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, "node_modules/https-proxy-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", - "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", - "dev": true, + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "dependencies": { - "agent-base": "5", + "agent-base": "6", "debug": "4" }, "engines": { - "node": ">= 6.0.0" + "node": ">= 6" } }, - "node_modules/https-proxy-agent/node_modules/agent-base": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", - "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", - "dev": true, - "engines": { - "node": ">= 6.0.0" + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "dependencies": { + "ms": "^2.0.0" } }, "node_modules/iconv-lite": { @@ -2110,9 +2172,9 @@ } }, "node_modules/import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "dependencies": { "parent-module": "^1.0.0", @@ -2120,13 +2182,15 @@ }, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, "engines": { "node": ">=0.8.19" } @@ -2135,11 +2199,15 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, "engines": { "node": ">=8" } }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -2168,6 +2236,11 @@ "save-to-github-cache": "bin/save-to-github-cache.js" } }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -2212,6 +2285,11 @@ "node": ">=0.10.0" } }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=" + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -2242,7 +2320,8 @@ "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true }, "node_modules/is-windows": { "version": "1.0.2", @@ -2263,11 +2342,6 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, "node_modules/istanbul-lib-coverage": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", @@ -2408,9 +2482,9 @@ "dev": true }, "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "dependencies": { "argparse": "^1.0.7", @@ -2420,11 +2494,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -2437,15 +2506,11 @@ "node": ">=4" } }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/json-stable-stringify": { "version": "1.0.1", @@ -2461,11 +2526,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "node_modules/json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", @@ -2511,45 +2571,12 @@ "node": "*" } }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "node_modules/just-extend": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", "dev": true }, - "node_modules/kuzzle-common-objects": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/kuzzle-common-objects/-/kuzzle-common-objects-5.0.2.tgz", - "integrity": "sha512-3XNx1Imgba0UHrtrMCCNc2stsEojyCKEEvhXIhAFOcLDx8vxZb7SUw+43sNtd44CJ+hXqJd7izBfl1hfysUr2A==", - "dependencies": { - "uuid": "^8.3.1" - }, - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/kuzzle-common-objects/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2656,25 +2683,47 @@ "semver": "bin/semver.js" } }, - "node_modules/mime-db": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", - "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", + "node_modules/make-fetch-happen": { + "version": "8.0.14", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz", + "integrity": "sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ==", + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.0.5", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^5.0.0", + "ssri": "^8.0.0" + }, "engines": { - "node": ">= 0.6" + "node": ">= 10" } }, - "node_modules/mime-types": { - "version": "2.1.29", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", - "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", "dependencies": { - "mime-db": "1.46.0" + "yallist": "^4.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">=8" } }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -2700,6 +2749,158 @@ "yallist": "^3.0.0" } }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minipass-fetch": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.3.3.tgz", + "integrity": "sha512-akCrLDWfbdAWkMLBxJEeWTdNsjML+dt5YgOI4gJ53vuO0vrmYQkUPxa6j6V65s9CcePIr2SSWqjT2EcrNseryQ==", + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch/node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/minizlib": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", @@ -2720,9 +2921,9 @@ } }, "node_modules/mocha": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.0.tgz", - "integrity": "sha512-TQqyC89V1J/Vxx0DhJIXlq9gbbL9XFNdeLQ1+JsnZsVaSOV1z3tWfw0qZmQJGQRIfkvZcs7snQnZnOCKoldq1Q==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", "dev": true, "dependencies": { "@ungap/promise-all-settled": "1.1.2", @@ -2898,19 +3099,19 @@ } }, "node_modules/node-gyp": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", - "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.0.0.tgz", + "integrity": "sha512-Jod6NxyWtcwrpAQe0O/aXOpC5QfncotgtG73dg65z6VW/C6g/G4jiajXQUBIJ8pk/VfM6mBYE9BN/HvudTunUQ==", "dependencies": { "env-paths": "^2.2.0", "glob": "^7.1.4", - "graceful-fs": "^4.2.3", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^8.0.14", "nopt": "^5.0.0", "npmlog": "^4.1.2", - "request": "^2.88.2", "rimraf": "^3.0.2", - "semver": "^7.3.2", - "tar": "^6.0.2", + "semver": "^7.3.5", + "tar": "^6.1.0", "which": "^2.0.2" }, "bin": { @@ -3002,9 +3203,9 @@ } }, "node_modules/node-gyp/node_modules/semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -3389,14 +3590,6 @@ "node": ">=6" } }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -3574,11 +3767,6 @@ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "node_modules/picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -3696,27 +3884,32 @@ "node": ">=0.4.0" } }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, "engines": { "node": ">=6" } }, - "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/random-js": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/random-js/-/random-js-2.1.0.tgz", @@ -3755,14 +3948,14 @@ } }, "node_modules/re2": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/re2/-/re2-1.15.9.tgz", - "integrity": "sha512-AXWEhpMTBdC+3oqbjdU07dk0pBCvxh5vbOMLERL6Y8FYBSGn4vXlLe8cYszn64Yy7H8keVMrgPzoSvOd4mePpg==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/re2/-/re2-1.16.0.tgz", + "integrity": "sha512-eizTZL2ZO0ZseLqfD4t3Qd0M3b3Nr0MBWpX81EbPMIud/1d/CSfUIx2GQK8fWiAeHoSekO5EOeFib2udTZLwYw==", "hasInstallScript": true, "dependencies": { "install-artifact-from-github": "^1.2.0", "nan": "^2.14.2", - "node-gyp": "^7.1.2" + "node-gyp": "^8.0.0" } }, "node_modules/readable-stream": { @@ -3829,37 +4022,6 @@ "node": ">=4" } }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3893,6 +4055,14 @@ "node": ">=4" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "engines": { + "node": ">= 4" + } + }, "node_modules/rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -4033,16 +4203,16 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "node_modules/sinon": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", - "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", + "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", "dev": true, "dependencies": { "@sinonjs/commons": "^1.8.1", "@sinonjs/fake-timers": "^6.0.1", "@sinonjs/samsam": "^5.3.1", "diff": "^4.0.2", - "nise": "^4.0.4", + "nise": "^4.1.0", "supports-color": "^7.1.0" }, "funding": { @@ -4085,6 +4255,41 @@ "node": ">=8" } }, + "node_modules/smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", + "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "dependencies": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz", + "integrity": "sha512-lEpa1zsWCChxiynk+lCycKuC502RxDWLKJZoIhnxrWNjLSDGYRFflHA1/228VkRcnv9TIb8w98derGbpKxJRgA==", + "dependencies": { + "agent-base": "6", + "debug": "4", + "socks": "^2.3.3" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -4137,30 +4342,33 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "minipass": "^3.1.1" }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" + "engines": { + "node": ">= 8" + } + }, + "node_modules/ssri/node_modules/minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "dependencies": { + "yallist": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, + "node_modules/ssri/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/stream-events": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", @@ -4340,16 +4548,28 @@ } }, "node_modules/teeny-request": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz", - "integrity": "sha512-TAK0c9a00ELOqLrZ49cFxvPVogMUFaWY8dUsQc/0CuQPGF+BOxOQzXfE413BAk2kLomwNplvdtMpeaeGWmoc2g==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.0.1.tgz", + "integrity": "sha512-sasJmQ37klOlplL4Ia/786M5YlOcoLGQyq2TE4WHSRupbAuDaQW0PfVxV4MtdBtRJ4ngzS+1qim8zP6Zp35qCw==", "dev": true, "dependencies": { "http-proxy-agent": "^4.0.0", - "https-proxy-agent": "^4.0.0", - "node-fetch": "^2.2.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", "stream-events": "^1.0.5", - "uuid": "^3.3.2" + "uuid": "^8.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/teeny-request/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" } }, "node_modules/test-exclude": { @@ -4399,34 +4619,6 @@ "node": ">=8.0" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -4466,10 +4658,27 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -4489,6 +4698,7 @@ "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true, "bin": { "uuid": "bin/uuid" } @@ -4499,19 +4709,6 @@ "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", "dev": true }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5118,9 +5315,9 @@ } }, "@eslint/eslintrc": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", - "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.1.tgz", + "integrity": "sha512-5v7TDE9plVhvxQeWLXDTvFvJBdH6pEsdnl2g/dAptmuFEPedQ4Erq5rsDsX+mvAM610IhNaO2W5V1dOOnDKxkQ==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -5130,9 +5327,19 @@ "ignore": "^4.0.6", "import-fresh": "^3.2.1", "js-yaml": "^3.13.1", - "lodash": "^4.17.20", "minimatch": "^3.0.4", "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + } } }, "@istanbuljs/load-nyc-config": { @@ -5199,6 +5406,30 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, + "@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + } + } + }, "@sinonjs/commons": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", @@ -5237,8 +5468,7 @@ "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" }, "@ungap/promise-all-settled": { "version": "1.1.2", @@ -5272,16 +5502,24 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, "requires": { "debug": "4" } }, + "agentkeepalive": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.1.4.tgz", + "integrity": "sha512-+V/rGa3EuU74H6wR04plBb7Ks10FbtUQgRj/FQOG7uUIEuaINI+AiqJR1k6t3SVNs7o7ZjIdus6706qqzVq8jQ==", + "requires": { + "debug": "^4.1.0", + "depd": "^1.1.2", + "humanize-ms": "^1.2.1" + } + }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, "requires": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -5291,6 +5529,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5372,53 +5611,17 @@ "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=", "dev": true }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" - }, "astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" - }, - "aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "requires": { - "tweetnacl": "^0.14.3" - } - }, "benchmark": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/benchmark/-/benchmark-2.1.4.tgz", @@ -5499,6 +5702,101 @@ "node-releases": "^1.1.70" } }, + "cacache": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.1.0.tgz", + "integrity": "sha512-mfx0C+mCfWjD1PnwQ9yaOrwG1ou9FkKnx0SvzUHWdFt7r7GaRtzT+9M8HAvLu62zIHtnpQ/1m93nWNDCckJGXQ==", + "requires": { + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "dependencies": { + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, + "tar": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.0.tgz", + "integrity": "sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, "caching-transform": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", @@ -5529,11 +5827,6 @@ "integrity": "sha512-xJJqzyd+7GCJXkcoBiQ1GuxEiOBCLQ0aVW9HMekifZsAVGdj5eJ4mFB9fEhSHipq9IOk/QXFJUiIr9lZT+EsGw==", "dev": true }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" - }, "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -5568,8 +5861,7 @@ "clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" }, "cliui": { "version": "7.0.4", @@ -5622,28 +5914,16 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, "codecov": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.8.1.tgz", - "integrity": "sha512-Qm7ltx1pzLPsliZY81jyaQ80dcNR4/JpcX0IHCIWrHBXgseySqbdbYfkdiXd7o/xmzQpGRVCKGYeTrHUpn6Dcw==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.8.2.tgz", + "integrity": "sha512-6w/kt/xvmPsWMfDFPE/T054txA9RTgcJEw36PNa6MYX+YV29jCHCRFXwbQ3QZBTOgnex1J2WP8bo2AT8TWWz9g==", "dev": true, "requires": { "argv": "0.0.2", "ignore-walk": "3.0.3", - "js-yaml": "3.14.0", - "teeny-request": "6.0.1", + "js-yaml": "3.14.1", + "teeny-request": "7.0.1", "urlgrey": "0.4.4" - }, - "dependencies": { - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - } } }, "color-convert": { @@ -5667,14 +5947,6 @@ "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", "dev": true }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, "commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -5716,14 +5988,6 @@ "which": "^2.0.1" } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "debug": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", @@ -5758,16 +6022,16 @@ "strip-bom": "^4.0.0" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" - }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -5788,15 +6052,6 @@ "esutils": "^2.0.2" } }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, "electron-to-chromium": { "version": "1.3.672", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.672.tgz", @@ -5809,6 +6064,26 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "requires": { + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } + } + }, "enquirer": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", @@ -5819,9 +6094,14 @@ } }, "env-paths": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", - "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==" + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" + }, + "err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==" }, "es6-error": { "version": "4.1.1", @@ -5842,13 +6122,13 @@ "dev": true }, "eslint": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.20.0.tgz", - "integrity": "sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.26.0.tgz", + "integrity": "sha512-4R1ieRf52/izcZE7AlLy56uIHHDLT74Yzz2Iv2l6kDaYvEu9x+wMB5dZArVL8SYGXSYV2YAg70FcW5Y5nGGNIg==", "dev": true, "requires": { "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.3.0", + "@eslint/eslintrc": "^0.4.1", "ajv": "^6.10.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -5861,10 +6141,10 @@ "espree": "^7.3.1", "esquery": "^1.4.0", "esutils": "^2.0.2", - "file-entry-cache": "^6.0.0", + "file-entry-cache": "^6.0.1", "functional-red-black-tree": "^1.0.1", "glob-parent": "^5.0.0", - "globals": "^12.1.0", + "globals": "^13.6.0", "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", @@ -5872,7 +6152,7 @@ "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.20", + "lodash": "^4.17.21", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -6043,25 +6323,17 @@ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", "dev": true }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", @@ -6156,21 +6428,6 @@ "signal-exit": "^3.0.2" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", @@ -6266,14 +6523,6 @@ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "dev": true }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "requires": { - "assert-plus": "^1.0.0" - } - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -6297,12 +6546,20 @@ } }, "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.8.0.tgz", + "integrity": "sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } } }, "graceful-fs": { @@ -6311,24 +6568,10 @@ "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" }, "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true }, "has-flag": { "version": "4.0.0", @@ -6363,43 +6606,36 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, "http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, "requires": { "@tootallnate/once": "1", "agent-base": "6", "debug": "4" } }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "agent-base": "6", + "debug": "4" } }, - "https-proxy-agent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz", - "integrity": "sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg==", - "dev": true, + "humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", "requires": { - "agent-base": "5", - "debug": "4" - }, - "dependencies": { - "agent-base": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-5.1.1.tgz", - "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", - "dev": true - } + "ms": "^2.0.0" } }, "iconv-lite": { @@ -6425,9 +6661,9 @@ } }, "import-fresh": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", - "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "requires": { "parent-module": "^1.0.0", @@ -6437,14 +6673,17 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" }, "inflight": { "version": "1.0.6", @@ -6470,6 +6709,11 @@ "resolved": "https://registry.npmjs.org/install-artifact-from-github/-/install-artifact-from-github-1.2.0.tgz", "integrity": "sha512-3OxCPcY55XlVM3kkfIpeCgmoSKnMsz2A3Dbhsq0RXpIknKQmrX1YiznCeW9cD2ItFmDxziA3w6Eg8d80AoL3oA==" }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -6502,6 +6746,11 @@ "is-extglob": "^2.1.1" } }, + "is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -6523,7 +6772,8 @@ "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true }, "is-windows": { "version": "1.0.2", @@ -6541,11 +6791,6 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" - }, "istanbul-lib-coverage": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", @@ -6659,35 +6904,26 @@ "dev": true }, "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" - }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify": { "version": "1.0.1", @@ -6703,11 +6939,6 @@ "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" - }, "json5": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", @@ -6738,38 +6969,12 @@ "through": ">=2.2.7 <3" } }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, "just-extend": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", "dev": true }, - "kuzzle-common-objects": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/kuzzle-common-objects/-/kuzzle-common-objects-5.0.2.tgz", - "integrity": "sha512-3XNx1Imgba0UHrtrMCCNc2stsEojyCKEEvhXIhAFOcLDx8vxZb7SUw+43sNtd44CJ+hXqJd7izBfl1hfysUr2A==", - "requires": { - "uuid": "^8.3.1" - }, - "dependencies": { - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - } - } - }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6856,17 +7061,41 @@ } } }, - "mime-db": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", - "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==" - }, - "mime-types": { - "version": "2.1.29", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", - "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", - "requires": { - "mime-db": "1.46.0" + "make-fetch-happen": { + "version": "8.0.14", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-8.0.14.tgz", + "integrity": "sha512-EsS89h6l4vbfJEtBZnENTOFk8mCRpY5ru36Xe5bcX1KYIli2mkSHqoFsp5O1wMDvTJJzxe/4THpCTtygjeeGWQ==", + "requires": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.0.5", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^5.0.0", + "ssri": "^8.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } } }, "minimatch": { @@ -6891,6 +7120,133 @@ "yallist": "^3.0.0" } }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "minipass-fetch": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.3.3.tgz", + "integrity": "sha512-akCrLDWfbdAWkMLBxJEeWTdNsjML+dt5YgOI4gJ53vuO0vrmYQkUPxa6j6V65s9CcePIr2SSWqjT2EcrNseryQ==", + "requires": { + "encoding": "^0.1.12", + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "requires": { + "yallist": "^4.0.0" + } + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, + "minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } + }, "minizlib": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", @@ -6908,9 +7264,9 @@ } }, "mocha": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.3.0.tgz", - "integrity": "sha512-TQqyC89V1J/Vxx0DhJIXlq9gbbL9XFNdeLQ1+JsnZsVaSOV1z3tWfw0qZmQJGQRIfkvZcs7snQnZnOCKoldq1Q==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", @@ -7048,19 +7404,19 @@ "dev": true }, "node-gyp": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", - "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.0.0.tgz", + "integrity": "sha512-Jod6NxyWtcwrpAQe0O/aXOpC5QfncotgtG73dg65z6VW/C6g/G4jiajXQUBIJ8pk/VfM6mBYE9BN/HvudTunUQ==", "requires": { "env-paths": "^2.2.0", "glob": "^7.1.4", - "graceful-fs": "^4.2.3", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^8.0.14", "nopt": "^5.0.0", "npmlog": "^4.1.2", - "request": "^2.88.2", "rimraf": "^3.0.2", - "semver": "^7.3.2", - "tar": "^6.0.2", + "semver": "^7.3.5", + "tar": "^6.1.0", "which": "^2.0.2" }, "dependencies": { @@ -7116,9 +7472,9 @@ } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "requires": { "lru-cache": "^6.0.0" } @@ -7428,11 +7784,6 @@ } } }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -7567,11 +7918,6 @@ } } }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -7658,20 +8004,25 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", "dev": true }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + }, + "promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "requires": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + } }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "random-js": { "version": "2.1.0", @@ -7707,13 +8058,13 @@ } }, "re2": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/re2/-/re2-1.15.9.tgz", - "integrity": "sha512-AXWEhpMTBdC+3oqbjdU07dk0pBCvxh5vbOMLERL6Y8FYBSGn4vXlLe8cYszn64Yy7H8keVMrgPzoSvOd4mePpg==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/re2/-/re2-1.16.0.tgz", + "integrity": "sha512-eizTZL2ZO0ZseLqfD4t3Qd0M3b3Nr0MBWpX81EbPMIud/1d/CSfUIx2GQK8fWiAeHoSekO5EOeFib2udTZLwYw==", "requires": { "install-artifact-from-github": "^1.2.0", "nan": "^2.14.2", - "node-gyp": "^7.1.2" + "node-gyp": "^8.0.0" } }, "readable-stream": { @@ -7765,33 +8116,6 @@ "es6-error": "^4.0.1" } }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -7816,6 +8140,11 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -7944,16 +8273,16 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "sinon": { - "version": "9.2.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", - "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", + "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", "dev": true, "requires": { "@sinonjs/commons": "^1.8.1", "@sinonjs/fake-timers": "^6.0.1", "@sinonjs/samsam": "^5.3.1", "diff": "^4.0.2", - "nise": "^4.0.4", + "nise": "^4.1.0", "supports-color": "^7.1.0" }, "dependencies": { @@ -7984,6 +8313,30 @@ } } }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" + }, + "socks": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", + "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "requires": { + "ip": "^1.1.5", + "smart-buffer": "^4.1.0" + } + }, + "socks-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-5.0.0.tgz", + "integrity": "sha512-lEpa1zsWCChxiynk+lCycKuC502RxDWLKJZoIhnxrWNjLSDGYRFflHA1/228VkRcnv9TIb8w98derGbpKxJRgA==", + "requires": { + "agent-base": "6", + "debug": "4", + "socks": "^2.3.3" + } + }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -8026,20 +8379,27 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "minipass": "^3.1.1" + }, + "dependencies": { + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", + "requires": { + "yallist": "^4.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } } }, "stream-events": { @@ -8183,16 +8543,24 @@ } }, "teeny-request": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-6.0.1.tgz", - "integrity": "sha512-TAK0c9a00ELOqLrZ49cFxvPVogMUFaWY8dUsQc/0CuQPGF+BOxOQzXfE413BAk2kLomwNplvdtMpeaeGWmoc2g==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.0.1.tgz", + "integrity": "sha512-sasJmQ37klOlplL4Ia/786M5YlOcoLGQyq2TE4WHSRupbAuDaQW0PfVxV4MtdBtRJ4ngzS+1qim8zP6Zp35qCw==", "dev": true, "requires": { "http-proxy-agent": "^4.0.0", - "https-proxy-agent": "^4.0.0", - "node-fetch": "^2.2.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", "stream-events": "^1.0.5", - "uuid": "^3.3.2" + "uuid": "^8.0.0" + }, + "dependencies": { + "uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true + } } }, "test-exclude": { @@ -8233,28 +8601,6 @@ "is-number": "^7.0.0" } }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" - }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -8285,10 +8631,27 @@ "is-typedarray": "^1.0.0" } }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "requires": { + "imurmurhash": "^0.1.4" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -8307,7 +8670,8 @@ "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true }, "v8-compile-cache": { "version": "2.1.0", @@ -8315,16 +8679,6 @@ "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", "dev": true }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 57ff9da..c448313 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,10 @@ "lib": "lib" }, "scripts": { - "test": "npm run --silent lint && npm run unit-test", + "test": "npm run --silent lint && npm run test:unit:coverage", "lint": "eslint --max-warnings=0 ./lib ./test", - "unit-test": "nyc --reporter=text-summary --reporter=lcov mocha", + "test:unit:coverage": "nyc --reporter=text-summary --reporter=lcov mocha", + "test:unit": "DEBUG= npx --node-arg=--trace-warnings mocha --exit", "codecov": "codecov" }, "repository": { @@ -35,24 +36,23 @@ "espresso-logic-minimizer": "^2.0.3", "js-combinatorics": "^0.6.1", "json-stable-stringify": "^1.0.1", - "kuzzle-common-objects": "^5.0.2", "murmurhash-native": "^3.5.0", "ngeohash": "^0.6.3", "node-interval-tree": "^1.3.3", "node-units": "^0.1.7", - "re2": "^1.15.9", + "re2": "^1.16.0", "reify": "^0.20.12" }, "devDependencies": { "benchmark": "^2.1.4", - "codecov": "^3.8.1", - "eslint": "^7.20.0", + "codecov": "^3.8.2", + "eslint": "^7.26.0", "geojson-random": "^0.5.0", - "mocha": "^8.3.0", + "mocha": "^8.4.0", "nyc": "^15.1.0", "random-js": "^2.1.0", "should": "^13.2.3", "should-sinon": "0.0.6", - "sinon": "^9.2.4" + "sinon": "^10.0.0" } } diff --git a/test/api.test.js b/test/api.test.js index cbb847d..a5a0d81 100644 --- a/test/api.test.js +++ b/test/api.test.js @@ -1,7 +1,6 @@ require('reify'); const should = require('should').noConflict(); -const { BadRequestError } = require('kuzzle-common-objects'); const Dsl = require('../'); const sinon = require('sinon'); @@ -70,14 +69,14 @@ describe('DSL API', () => { return should(dsl.validate({equals: {foo: 'bar'}})).be.fulfilledWith(); }); - it('should resolve to a BadRequestError if a filter is not valid', () => { - return should(dsl.validate({equals: {foo: 'bar'}, exists: 'qux'})).be.rejectedWith(BadRequestError); + it('should reject if a filter is not valid', () => { + return should(dsl.validate({equals: {foo: 'bar'}, exists: 'qux'})).be.rejected(); }); }); describe('#register', () => { - it('should resolve to a BadRequestError if a filter is not valid', () => { - return should(dsl.register('i', 'c', {foo: 'bar'})).be.rejectedWith(BadRequestError); + it('should reject if a filter is not valid', () => { + return should(dsl.register('i', 'c', {foo: 'bar'})).be.rejected(); }); it('should resolve to a cluster diff object if the registration succeeds', () => { diff --git a/test/keywords/equals.test.js b/test/keywords/equals.test.js index b5b593e..311eeab 100644 --- a/test/keywords/equals.test.js +++ b/test/keywords/equals.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const FieldOperand = require('../../lib/storage/objects/fieldOperand'); const DSL = require('../../'); @@ -17,49 +16,55 @@ describe('DSL.keyword.equals', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({equals: ['foo', 'bar']})).be.rejectedWith(BadRequestError); + return should(dsl.validate({equals: ['foo', 'bar']})) + .be.rejectedWith('"equals" must be a non-empty object'); }); it('should reject filters with more than 1 field', () => { - return should(dsl.validate({equals: {foo: 'foo', bar: 'bar'}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({equals: {foo: 'foo', bar: 'bar'}})) + .be.rejectedWith('"equals" can contain only one attribute'); }); it('should reject filters with array argument', () => { - return should(dsl.validate({equals: {foo: ['bar']}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({equals: {foo: ['bar']}})) + .be.rejectedWith('"foo" in "equals" must be either a string, a number, a boolean or null'); }); it('should validate filters with number argument', () => { - return should(dsl.validate({equals: {foo: 42}})).be.fulfilledWith(); + return should(dsl.validate({equals: {foo: 42}})).be.fulfilled(); }); it('should reject filters with object argument', () => { - return should(dsl.validate({equals: {foo: {}}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({equals: {foo: {}}})) + .be.rejectedWith('"foo" in "equals" must be either a string, a number, a boolean or null'); }); it('should reject filters with undefined argument', () => { - return should(dsl.validate({equals: {foo: undefined}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({equals: {foo: undefined}})) + .be.rejectedWith('"foo" in "equals" must be either a string, a number, a boolean or null'); }); it('should validate filters with null argument', () => { - return should(dsl.validate({equals: {foo: null}})).be.fulfilledWith(); + return should(dsl.validate({equals: {foo: null}})).be.fulfilled(); }); it('should validate filters with boolean argument', () => { - return should(dsl.validate({equals: {foo: true}})).be.fulfilledWith(); + return should(dsl.validate({equals: {foo: true}})).be.fulfilled(); }); it('should validate filters with a string argument', () => { - return should(dsl.validate({equals: {foo: 'bar'}})).be.fulfilledWith(); + return should(dsl.validate({equals: {foo: 'bar'}})).be.fulfilled(); }); it('should validate filters with an empty string argument', () => { - return should(dsl.validate({equals: {foo: ''}})).be.fulfilledWith(); + return should(dsl.validate({equals: {foo: ''}})).be.fulfilled(); }); }); describe('#standardization', () => { it('should return the same content, unchanged', () => { - should(dsl.transformer.standardizer.standardize({equals: {foo: 'bar'}})).match({equals: {foo: 'bar'}}); + should(dsl.transformer.standardizer.standardize({equals: {foo: 'bar'}})) + .match({equals: {foo: 'bar'}}); }); }); diff --git a/test/keywords/exists.test.js b/test/keywords/exists.test.js index 9b1b7e6..d9d904c 100644 --- a/test/keywords/exists.test.js +++ b/test/keywords/exists.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const FieldOperand = require('../../lib/storage/objects/fieldOperand'); const Koncorde = require('../../'); @@ -15,66 +14,71 @@ describe('Koncorde.keyword.exists', () => { describe('#validation', () => { it('should reject empty filters', () => { return should(koncorde.validate({exists: {}})) - .be.rejectedWith(BadRequestError); + .be.rejectedWith('"exists" must be a non-empty object'); }); it('should reject filters with more than 1 field', () => { return should(koncorde.validate({exists: {field: 'foo', bar: 'bar'}})) - .be.rejectedWith(BadRequestError); + .be.rejectedWith('"exists" can contain only one attribute'); + }); + + it('should reject filters in object-form without a "field" attribute', () => { + return should(koncorde.validate({exists: {foo: 'bar'}})) + .be.rejectedWith('"exists" requires the following attribute: field'); }); it('should reject filters with array argument', () => { return should(koncorde.validate({exists: {field: ['bar']}})) - .be.rejectedWith(BadRequestError); + .be.rejectedWith('Attribute "field" in "exists" must be a string'); }); it('should reject filters with number argument', () => { return should(koncorde.validate({exists: {field: 42}})) - .be.rejectedWith(BadRequestError); + .be.rejectedWith('Attribute "field" in "exists" must be a string'); }); it('should reject filters with object argument', () => { return should(koncorde.validate({exists: {field: {}}})) - .be.rejectedWith(BadRequestError); + .be.rejectedWith('Attribute "field" in "exists" must be a string'); }); it('should reject filters with undefined argument', () => { return should(koncorde.validate({exists: {field: undefined}})) - .be.rejectedWith(BadRequestError); + .be.rejectedWith('"exists" requires the following attribute: field'); }); it('should reject filters with null argument', () => { return should(koncorde.validate({exists: {field: null}})) - .be.rejectedWith(BadRequestError); + .be.rejectedWith('Attribute "field" in "exists" must be a string'); }); it('should reject filters with boolean argument', () => { return should(koncorde.validate({exists: {field: true}})) - .be.rejectedWith(BadRequestError); + .be.rejectedWith('Attribute "field" in "exists" must be a string'); }); it('should validate filters with a string argument', () => { return should(koncorde.validate({exists: {field: 'bar'}})) - .be.fulfilledWith(); + .be.fulfilled(); }); it('should reject filters with an empty string argument', () => { - return should(koncorde.validate({exists: {field: ''}})).be.rejectedWith( - BadRequestError, {message: 'exists: cannot test empty field name'}); + return should(koncorde.validate({exists: {field: ''}})) + .be.rejectedWith('exists: cannot test empty field name'); }); it('should validate filters written in simplified form', () => { - return should(koncorde.validate({exists: 'bar'})).fulfilledWith(); + return should(koncorde.validate({exists: 'bar'})).fulfilled(); }); it('should reject a filter in simplified form with an empty value', () => { - return should(koncorde.validate({exists: ''})).rejectedWith( - BadRequestError, {message: 'exists: cannot test empty field name'}); + return should(koncorde.validate({exists: ''})) + .rejectedWith('exists: cannot test empty field name'); }); it('should reject incorrectly formatted array search filters', () => { - return should(koncorde.validate({exists: 'foo[\'bar\']'})).rejectedWith( - BadRequestError, {message: '[exists] Invalid array value "\'bar\'"'}); + return should(koncorde.validate({exists: 'foo[\'bar\']'})) + .rejectedWith('[exists] Invalid array value "\'bar\'"'); }); }); diff --git a/test/keywords/geoBoundingBox.test.js b/test/keywords/geoBoundingBox.test.js index 3105ce2..bbe12d9 100644 --- a/test/keywords/geoBoundingBox.test.js +++ b/test/keywords/geoBoundingBox.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const FieldOperand = require('../../lib/storage/objects/fieldOperand'); const DSL = require('../../'); @@ -31,11 +30,13 @@ describe('DSL.keyword.geoBoundingBox', () => { describe('#validation/standardization', () => { it('should reject an empty filter', () => { - should(() => standardize({geoBoundingBox: {}})).throw(BadRequestError); + should(() => standardize({geoBoundingBox: {}})) + .throw('"geoBoundingBox" must be a non-empty object'); }); it('should reject a filter with multiple field attributes', () => { - should(() => standardize({geoBoundingBox: {foo: bbox, bar: bbox}})).throw(BadRequestError); + should(() => standardize({geoBoundingBox: {foo: bbox, bar: bbox}})) + .throw('"geoBoundingBox" can contain only one attribute'); }); it('should validate a {top, left, bottom, right} bbox', () => { @@ -125,10 +126,18 @@ describe('DSL.keyword.geoBoundingBox', () => { should(result.geospatial).be.an.Object(); should(result.geospatial.geoBoundingBox).be.an.Object(); should(result.geospatial.geoBoundingBox.foo).be.an.Object(); - should(result.geospatial.geoBoundingBox.foo.top).be.approximately(box.top, 10e-7); - should(result.geospatial.geoBoundingBox.foo.bottom).be.approximately(box.bottom, 10e-7); - should(result.geospatial.geoBoundingBox.foo.left).be.approximately(box.left, 10e-7); - should(result.geospatial.geoBoundingBox.foo.right).be.approximately(box.right, 10e-7); + + should(result.geospatial.geoBoundingBox.foo.top) + .be.approximately(box.top, 10e-7); + + should(result.geospatial.geoBoundingBox.foo.bottom) + .be.approximately(box.bottom, 10e-7); + + should(result.geospatial.geoBoundingBox.foo.left) + .be.approximately(box.left, 10e-7); + + should(result.geospatial.geoBoundingBox.foo.right) + .be.approximately(box.right, 10e-7); }); it('should validate a {top_left: "geohash", bottom_right: "geohash"} bbox', () => { @@ -147,10 +156,18 @@ describe('DSL.keyword.geoBoundingBox', () => { should(result.geospatial).be.an.Object(); should(result.geospatial.geoBoundingBox).be.an.Object(); should(result.geospatial.geoBoundingBox.foo).be.an.Object(); - should(result.geospatial.geoBoundingBox.foo.top).be.approximately(box.top, 10e-7); - should(result.geospatial.geoBoundingBox.foo.bottom).be.approximately(box.bottom, 10e-7); - should(result.geospatial.geoBoundingBox.foo.left).be.approximately(box.left, 10e-7); - should(result.geospatial.geoBoundingBox.foo.right).be.approximately(box.right, 10e-7); + + should(result.geospatial.geoBoundingBox.foo.top) + .be.approximately(box.top, 10e-7); + + should(result.geospatial.geoBoundingBox.foo.bottom) + .be.approximately(box.bottom, 10e-7); + + should(result.geospatial.geoBoundingBox.foo.left) + .be.approximately(box.left, 10e-7); + + should(result.geospatial.geoBoundingBox.foo.right) + .be.approximately(box.right, 10e-7); }); it('should reject an unrecognized bbox format', () => { @@ -159,7 +176,8 @@ describe('DSL.keyword.geoBoundingBox', () => { bottom_right: '40.01 / -71.12', }; - should(() => standardize({geoBoundingBox: {foo: box}})).throw(BadRequestError); + should(() => standardize({geoBoundingBox: {foo: box}})) + .throw('Unrecognized geo-point format in "geoBoundingBox.foo'); }); it('should reject a non-convertible bbox point string', () => { @@ -170,9 +188,8 @@ describe('DSL.keyword.geoBoundingBox', () => { right: 'foobar' }; - should(() => standardize({geoBoundingBox: {foo: box}})).throw( - BadRequestError, - { message: `Invalid geoBoundingBox format: ${JSON.stringify(box)}` }); + should(() => standardize({geoBoundingBox: {foo: box}})) + .throw(`Invalid geoBoundingBox format: ${JSON.stringify(box)}`); }); }); diff --git a/test/keywords/geoDistance.test.js b/test/keywords/geoDistance.test.js index 59d1224..6c0899e 100644 --- a/test/keywords/geoDistance.test.js +++ b/test/keywords/geoDistance.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const FieldOperand = require('../../lib/storage/objects/fieldOperand'); const DSL = require('../../'); @@ -27,94 +26,124 @@ describe('DSL.keyword.geoDistance', () => { describe('#validation/standardization', () => { it('should reject an empty filter', () => { - should(() => standardize({geoDistance: {}})).throw(BadRequestError); + should(() => standardize({geoDistance: {}})) + .throw('"geoDistance" must be a non-empty object'); }); it('should reject a filter with multiple field attributes', () => { - should(() => standardize({geoDistance: {foo: point, bar: point, distance: '1km'}})).throw(BadRequestError); + const filter = {geoDistance: {foo: point, bar: point, distance: '1km'}}; + + should(() => standardize(filter)).throw('"geoDistance" keyword must (only) contain a document field and a "distance" attribute'); }); it('should validate a {lat, lon} point', () => { - should(standardize({geoDistance: {foo: point, distance: '1km'}})).match(distanceStandardized); + should(standardize({geoDistance: {foo: point, distance: '1km'}})) + .match(distanceStandardized); }); it('should validate a {latLon: [lat, lon]} point', () => { const p = {latLon: [point.lat, point.lon]}; - should(standardize({geoDistance: {foo: p, distance: '1km'}})).match(distanceStandardized); + should(standardize({geoDistance: {foo: p, distance: '1km'}})) + .match(distanceStandardized); }); it('should validate a {lat_lon: [lat, lon]} point', () => { const p = {lat_lon: [point.lat, point.lon]}; - should(standardize({geoDistance: {foo: p, distance: '1km'}})).match(distanceStandardized); + + should(standardize({geoDistance: {foo: p, distance: '1km'}})) + .match(distanceStandardized); }); it('should validate a {latLon: {lat: lat, lon: lon}} point', () => { const p = {latLon: {lat: point.lat, lon: point.lon}}; - should(standardize({geoDistance: {foo: p, distance: '1km'}})).match(distanceStandardized); + + should(standardize({geoDistance: {foo: p, distance: '1km'}})) + .match(distanceStandardized); }); it('should validate a {lat_lon: {lat: lat, lon: lon}} point', () => { const p = {lat_lon: {lat: point.lat, lon: point.lon}}; - should(standardize({geoDistance: {foo: p, distance: '1km'}})).match(distanceStandardized); + + should(standardize({geoDistance: {foo: p, distance: '1km'}})) + .match(distanceStandardized); }); it('should validate a {latLon: "lat, lon"} point', () => { const p = {latLon: `${point.lat}, ${point.lon}`}; - should(standardize({geoDistance: {foo: p, distance: '1km'}})).match(distanceStandardized); + + should(standardize({geoDistance: {foo: p, distance: '1km'}})) + .match(distanceStandardized); }); it('should validate a {lat_lon: "lat, lon"} point', () => { const p = {lat_lon: `${point.lat}, ${point.lon}`}; - should(standardize({geoDistance: {foo: p, distance: '1km'}})).match(distanceStandardized); + should(standardize({geoDistance: {foo: p, distance: '1km'}})) + .match(distanceStandardized); }); it('should validate a {latLon: "geohash"} point', () => { const p = {latLon: 'spf8prntv18e'}; - const result = standardize({geoDistance: {foo: p, distance: '1km'}}); + should(result).be.an.Object(); should(result.geospatial).be.an.Object(); should(result.geospatial.geoDistance).be.an.Object(); should(result.geospatial.geoDistance.foo).be.an.Object(); should(result.geospatial.geoDistance.foo.distance).be.eql(1000); - should(result.geospatial.geoDistance.foo.lat).be.approximately(point.lat, 10e-7); - should(result.geospatial.geoDistance.foo.lon).be.approximately(point.lon, 10e-7); + + should(result.geospatial.geoDistance.foo.lat) + .be.approximately(point.lat, 10e-7); + + should(result.geospatial.geoDistance.foo.lon) + .be.approximately(point.lon, 10e-7); }); it('should validate a {lat_lon: "geohash"} point', () => { const p = {lat_lon: 'spf8prntv18e'}; - const result = standardize({geoDistance: {foo: p, distance: '1km'}}); + should(result).be.an.Object(); should(result.geospatial).be.an.Object(); should(result.geospatial.geoDistance).be.an.Object(); should(result.geospatial.geoDistance.foo).be.an.Object(); should(result.geospatial.geoDistance.foo.distance).be.eql(1000); - should(result.geospatial.geoDistance.foo.lat).be.approximately(point.lat, 10e-7); - should(result.geospatial.geoDistance.foo.lon).be.approximately(point.lon, 10e-7); + + should(result.geospatial.geoDistance.foo.lat) + .be.approximately(point.lat, 10e-7); + + should(result.geospatial.geoDistance.foo.lon) + .be.approximately(point.lon, 10e-7); }); it('should reject an unrecognized point format', () => { const p = {foo: 'bar'}; - should(() => standardize({geoDistance: {foo: p, distance: '1km'}})).throw(BadRequestError); + + should(() => standardize({geoDistance: {foo: p, distance: '1km'}})) + .throw('geoDistance.foo: unrecognized point format'); }); it('should reject an invalid latLon argument type', () => { const p = {latLon: 42}; - should(() => standardize({geoDistance: {foo: p, distance: '1km'}})).throw(BadRequestError); + + should(() => standardize({geoDistance: {foo: p, distance: '1km'}})) + .throw('geoDistance.foo: unrecognized point format'); }); it('should reject an invalid latLon argument string', () => { const p = {latLon: '[10, 10]'}; - should(() => standardize({geoDistance: {foo: p, distance: '1km'}})).throw(BadRequestError); + + should(() => standardize({geoDistance: {foo: p, distance: '1km'}})) + .throw('geoDistance.foo: unrecognized point format'); }); it('should reject a filter with a non-string distance value', () => { - should(() => standardize({geoDistance: {foo: point, distance: 42}})).throw(BadRequestError); + should(() => standardize({geoDistance: {foo: point, distance: 42}})) + .throw('Attribute "distance" in "geoDistance" must be a string'); }); it('should reject a filter with incorrect distance value', () => { - should(() => standardize({geoDistance: {foo: point, distance: '1 ly'}})).throw(BadRequestError); + should(() => standardize({geoDistance: {foo: point, distance: '1 ly'}})) + .throw('unable to parse distance value "1 ly"'); }); }); diff --git a/test/keywords/geoDistanceRange.test.js b/test/keywords/geoDistanceRange.test.js index 6ab880a..1392ddb 100644 --- a/test/keywords/geoDistanceRange.test.js +++ b/test/keywords/geoDistanceRange.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const FieldOperand = require('../../lib/storage/objects/fieldOperand'); const DSL = require('../../'); @@ -28,108 +27,173 @@ describe('DSL.keyword.geoDistanceRange', () => { describe('#validation/standardization', () => { it('should reject an empty filter', () => { - should(() => standardize({geoDistanceRange: {}})).throw(BadRequestError); + should(() => standardize({geoDistanceRange: {}})) + .throw('"geoDistanceRange" must be a non-empty object'); }); it('should reject a filter with multiple field attributes', () => { - should(() => standardize({geoDistanceRange: {foo: point, bar: point, from: '1km', to: '10km'}})).throw(BadRequestError); + const filter = {foo: point, bar: point, from: '1km', to: '10km'}; + + should(() => standardize({geoDistanceRange: filter})) + .throw('"geoDistanceRange" keyword must (only) contain a document field and the following attributes: "from", "to"'); }); it('should validate a {lat, lon} point', () => { - should(standardize({geoDistanceRange: {foo: point, from: '1km', to: '10km'}})).match(distanceStandardized); + const filter = {foo: point, from: '1km', to: '10km'}; + + should(standardize({geoDistanceRange: filter})) + .match(distanceStandardized); }); it('should validate a {latLon: [lat, lon]} point', () => { const p = {latLon: [point.lat, point.lon]}; - should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})).match(distanceStandardized); + + should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})) + .match(distanceStandardized); }); it('should validate a {lat_lon: [lat, lon]} point', () => { const p = {lat_lon: [point.lat, point.lon]}; - should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})).match(distanceStandardized); + + should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})) + .match(distanceStandardized); }); it('should validate a {latLon: {lat: lat, lon: lon}} point', () => { const p = {latLon: {lat: point.lat, lon: point.lon}}; - should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})).match(distanceStandardized); + + should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})) + .match(distanceStandardized); }); it('should validate a {lat_lon: {lat: lat, lon: lon}} point', () => { const p = {lat_lon: {lat: point.lat, lon: point.lon}}; - should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})).match(distanceStandardized); + + should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})) + .match(distanceStandardized); }); it('should validate a {latLon: "lat, lon"} point', () => { const p = {latLon: `${point.lat}, ${point.lon}`}; - should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})).match(distanceStandardized); + + should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})) + .match(distanceStandardized); }); it('should validate a {lat_lon: "lat, lon"} point', () => { const p = {lat_lon: `${point.lat}, ${point.lon}`}; - should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})).match(distanceStandardized); + + should(standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})) + .match(distanceStandardized); }); it('should validate a {latLon: "geohash"} point', () => { const p = {latLon: 'spf8prntv18e'}; - const result = standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}}); + const result = standardize({ + geoDistanceRange: { + foo: p, + from: '1km', + to: '10km', + } + }); + should(result).be.an.Object(); should(result.geospatial).be.an.Object(); should(result.geospatial.geoDistanceRange).be.an.Object(); should(result.geospatial.geoDistanceRange.foo).be.an.Object(); should(result.geospatial.geoDistanceRange.foo.from).be.eql(1000); should(result.geospatial.geoDistanceRange.foo.to).be.eql(10000); - should(result.geospatial.geoDistanceRange.foo.lat).be.approximately(point.lat, 10e-7); - should(result.geospatial.geoDistanceRange.foo.lon).be.approximately(point.lon, 10e-7); + + should(result.geospatial.geoDistanceRange.foo.lat) + .be.approximately(point.lat, 10e-7); + + should(result.geospatial.geoDistanceRange.foo.lon) + .be.approximately(point.lon, 10e-7); }); it('should validate a {lat_lon: "geohash"} point', () => { const p = {lat_lon: 'spf8prntv18e'}; - const result = standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}}); + const result = standardize({ + geoDistanceRange: { + foo: p, + from: '1km', + to: '10km', + }, + }); + should(result).be.an.Object(); should(result.geospatial).be.an.Object(); should(result.geospatial.geoDistanceRange).be.an.Object(); should(result.geospatial.geoDistanceRange.foo).be.an.Object(); should(result.geospatial.geoDistanceRange.foo.from).be.eql(1000); should(result.geospatial.geoDistanceRange.foo.to).be.eql(10000); - should(result.geospatial.geoDistanceRange.foo.lat).be.approximately(point.lat, 10e-7); - should(result.geospatial.geoDistanceRange.foo.lon).be.approximately(point.lon, 10e-7); + + should(result.geospatial.geoDistanceRange.foo.lat) + .be.approximately(point.lat, 10e-7); + + should(result.geospatial.geoDistanceRange.foo.lon) + .be.approximately(point.lon, 10e-7); }); it('should reject an unrecognized point format', () => { const p = {foo: 'bar'}; - should(() => standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})).throw(BadRequestError); + const filter = {foo: p, from: '1km', to: '10km'}; + + should(() => standardize({geoDistanceRange: filter})) + .throw('geoDistanceRange.foo: unrecognized point format'); }); it('should reject an invalid latLon argument type', () => { const p = {latLon: 42}; - should(() => standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})).throw(BadRequestError); + const filter = {foo: p, from: '1km', to: '10km'}; + + should(() => standardize({geoDistanceRange: filter})) + .throw('geoDistanceRange.foo: unrecognized point format'); }); it('should reject an invalid latLon argument string', () => { const p = {latLon: '[10, 10]'}; - should(() => standardize({geoDistanceRange: {foo: p, from: '1km', to: '10km'}})).throw(BadRequestError); + const filter = {foo: p, from: '1km', to: '10km'}; + + should(() => standardize({geoDistanceRange: filter})) + .throw('geoDistanceRange.foo: unrecognized point format'); }); it('should reject a filter with a non-string from value', () => { - should(() => standardize({geoDistanceRange: {foo: point, from: 42, to: '10km'}})).throw(BadRequestError); + const filter = {foo: point, from: 42, to: '10km'}; + + should(() => standardize({geoDistanceRange: filter})) + .throw('Attribute "from" in "geoDistanceRange" must be a string'); }); it('should reject a filter with a non-string to value', () => { - should(() => standardize({geoDistanceRange: {foo: point, from: '1km', to: 42}})).throw(BadRequestError); + const filter = {foo: point, from: '1km', to: 42}; + + should(() => standardize({geoDistanceRange: filter})) + .throw('Attribute "to" in "geoDistanceRange" must be a string'); }); it('should reject a filter with incorrect from value', () => { - should(() => standardize({geoDistanceRange: {foo: point, from: '1 micronanomillimeter', to: '1km'}})).throw(BadRequestError); + const filter = {foo: point, from: '1 micronanomillimeter', to: '1km'}; + + should(() => standardize({geoDistanceRange: filter})) + .throw('unable to parse distance value "1 micronanomillimeter"'); }); it('should reject a filter with incorrect to value', () => { - should(() => standardize({geoDistanceRange: {foo: point, from: '1 km', to: '1 ly'}})).throw(BadRequestError); + const filter = {foo: point, from: '1 km', to: '1 ly'}; + + should(() => standardize({geoDistanceRange: filter})) + .throw('unable to parse distance value "1 ly"'); }); it('should reject a filter with a negative range', () => { - should(() => standardize({geoDistanceRange: {foo: point, from: '10 km', to: '1km'}})).throw(BadRequestError); + const filter = {foo: point, from: '10 km', to: '1km'}; + + should(() => standardize({geoDistanceRange: filter})) + .throw('geoDistanceRange.foo: inner radius must be smaller than outer radius'); }); }); diff --git a/test/keywords/geoPolygon.test.js b/test/keywords/geoPolygon.test.js index ca2a9e9..f8f2b17 100644 --- a/test/keywords/geoPolygon.test.js +++ b/test/keywords/geoPolygon.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const FieldOperand = require('../../lib/storage/objects/fieldOperand'); const DSL = require('../../'); @@ -45,33 +44,42 @@ describe('DSL.keyword.geoPolygon', () => { describe('#validation/standardization', () => { it('should reject an empty filter', () => { - should(() => standardize({geoPolygon: {}})).throw(BadRequestError); + should(() => standardize({geoPolygon: {}})) + .throw('"geoPolygon" must be a non-empty object'); }); it('should reject a filter with multiple field attributes', () => { - should(() => standardize({geoPolygon: {foo: polygon, bar: polygon}})).throw(BadRequestError); + should(() => standardize({geoPolygon: {foo: polygon, bar: polygon}})) + .throw('"geoPolygon" can contain only one attribute'); }); it('should reject a filter without a points field', () => { - should(() => standardize({geoPolygon: {foo: {bar: [[0, 0], [5, 5], [5, 0]]}}})).throw(BadRequestError); + const filter = {foo: {bar: [[0, 0], [5, 5], [5, 0]]}}; + + should(() => standardize({geoPolygon: filter})) + .throw('"geoPolygon.foo" requires the following attribute: points'); }); it('should reject a filter with an empty points field', () => { - should(() => standardize({geoPolygon: {foo: {points: []}}})).throw(BadRequestError); + should(() => standardize({geoPolygon: {foo: {points: []}}})) + .throw('Attribute "points" in "geoPolygon.foo" cannot be empty'); }); it('should reject a polygon with less than 3 points defined', () => { - should(() => standardize({geoPolygon: {foo: {points: [[0, 0], [5, 5]]}}})).throw(BadRequestError); + should(() => standardize({geoPolygon: {foo: {points: [[0, 0], [5, 5]]}}})) + .throw('"geoPolygon.foo": at least 3 points are required to build a polygon'); }); it('should reject a polygon with a non-array points field', () => { - should(() => standardize({geoPolygon: {foo: {points: 'foobar'}}})).throw(BadRequestError); + should(() => standardize({geoPolygon: {foo: {points: 'foobar'}}})) + .throw('Attribute "points" in "geoPolygon.foo" must be an array'); }); it('should reject a polygon containing an invalid point format', () => { const p = polygon.points.slice(); p.push(42); - should(() => standardize({geoPolygon: {foo: {points: p}}})).throw(BadRequestError); + should(() => standardize({geoPolygon: {foo: {points: p}}})) + .throw(/^geoPolygon.foo: unrecognized point format/); }); it('should standardize all geopoint types in a single points array', () => { diff --git a/test/keywords/ids.test.js b/test/keywords/ids.test.js index c742f12..2e9e22d 100644 --- a/test/keywords/ids.test.js +++ b/test/keywords/ids.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const DSL = require('../../'); describe('DSL.keyword.ids', () => { @@ -11,31 +10,38 @@ describe('DSL.keyword.ids', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({ids: {}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({ids: {}})) + .be.rejectedWith('"ids" must be a non-empty object'); }); it('should reject filters with other fields other than the "values" one', () => { - return should(dsl.validate({ids: {foo: ['foo']}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({ids: {foo: ['foo']}})) + .be.rejectedWith('"ids" requires the following attribute: values'); }); it('should reject filters with multiple defined attributes', () => { - return should(dsl.validate({ids: {values: ['foo'], foo: ['foo']}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({ids: {values: ['foo'], foo: ['foo']}})) + .be.rejectedWith('"ids" can contain only one attribute'); }); it('should reject filters with an empty value list', () => { - return should(dsl.validate({ids: {values: []}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({ids: {values: []}})) + .be.rejectedWith('Attribute "values" in "ids" cannot be empty'); }); it('should reject filters with non-array values attribute', () => { - return should(dsl.validate({ids: {values: 'foo'}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({ids: {values: 'foo'}})) + .be.rejectedWith('Attribute "values" in "ids" must be an array'); }); it('should reject filters containing a non-string value', () => { - return should(dsl.validate({ids: {values: ['foo', 'bar', 42, 'baz']}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({ids: {values: ['foo', 'bar', 42, 'baz']}})) + .be.rejectedWith('Array "values" in keyword "ids" can only contain strings'); }); it('should validate a well-formed ids filter', () => { - return should(dsl.validate({ids: {values: ['foo', 'bar', 'baz']}})).be.fulfilledWith(); + return should(dsl.validate({ids: {values: ['foo', 'bar', 'baz']}})) + .be.fulfilled(); }); }); diff --git a/test/keywords/in.test.js b/test/keywords/in.test.js index 1a7e5b3..98e7e14 100644 --- a/test/keywords/in.test.js +++ b/test/keywords/in.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const DSL = require('../../'); describe('DSL.keyword.in', () => { @@ -11,27 +10,33 @@ describe('DSL.keyword.in', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({in: {}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({in: {}})) + .be.rejectedWith('"in" must be a non-empty object'); }); it('should reject filters with multiple defined attributes', () => { - return should(dsl.validate({in: {bar: ['foo'], foo: ['foo']}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({in: {bar: ['foo'], foo: ['foo']}})) + .be.rejectedWith('"in" can contain only one attribute'); }); it('should reject filters with an empty value list', () => { - return should(dsl.validate({in: {foo: []}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({in: {foo: []}})) + .be.rejectedWith('Attribute "foo" in "in" cannot be empty'); }); it('should reject filters with non-array values attribute', () => { - return should(dsl.validate({in: {foo: 'foo'}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({in: {foo: 'foo'}})) + .be.rejectedWith('Attribute "foo" in "in" must be an array'); }); it('should reject filters containing a non-string value', () => { - return should(dsl.validate({in: {foo: ['foo', 'bar', 42, 'baz']}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({in: {foo: ['foo', 'bar', 42, 'baz']}})) + .be.rejectedWith('Array "foo" in keyword "in" can only contain strings'); }); it('should validate a well-formed ids filter', () => { - return should(dsl.validate({in: {foo: ['foo', 'bar', 'baz']}})).be.fulfilledWith(); + return should(dsl.validate({in: {foo: ['foo', 'bar', 'baz']}})) + .be.fulfilled(); }); }); diff --git a/test/keywords/range.test.js b/test/keywords/range.test.js index f574540..b0410e9 100644 --- a/test/keywords/range.test.js +++ b/test/keywords/range.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const FieldOperand = require('../../lib/storage/objects/fieldOperand'); const RangeCondition = require('../../lib/storage/objects/rangeCondition'); @@ -14,39 +13,48 @@ describe('DSL.keyword.range', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({range: {}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({range: {}})) + .be.rejectedWith('"range" must be a non-empty object'); }); it('should reject filters with more than 1 field', () => { - return should(dsl.validate({range: {foo: 'foo', bar: 'bar'}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({range: {foo: 'foo', bar: 'bar'}})) + .be.rejectedWith('"range" can contain only one attribute'); }); it('should reject an empty field definition', () => { - return should(dsl.validate({range: {foo: {}}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({range: {foo: {}}})) + .be.rejectedWith('"range.foo" must be a non-empty object'); }); it('should reject a field definition containing an unrecognized range keyword', () => { - return should(dsl.validate({range: {foo: {gt: 42, lt: 113, bar: 'baz'}}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({range: {foo: {gt: 42, lt: 113, bar: 'baz'}}})) + .be.rejectedWith('"range.foo" accepts only the following attributes : gt, gte, lt, lte'); }); it('should reject a field definition with a range keyword not containing a number', () => { - return should(dsl.validate({range: {foo: {gt: '42', lt: 113}}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({range: {foo: {gt: '42', lt: 113}}})) + .be.rejectedWith('"range.foo.gt" must be a number'); }); it('should reject a field definition containing more than 1 lower boundary', () => { - return should(dsl.validate({range: {foo: {gt: 42, gte: 13, lt: 113}}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({range: {foo: {gt: 42, gte: 13, lt: 113}}})) + .be.rejectedWith('"range.foo:" only 1 lower boundary allowed'); }); it('should reject a field definition containing more than 1 upper boundary', () => { - return should(dsl.validate({range: {foo: {gt: 42, lt: 113, lte: 200}}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({range: {foo: {gt: 42, lt: 113, lte: 200}}})) + .be.rejectedWith('"range.foo:" only 1 upper boundary allowed'); }); it('should validate a valid range filter', () => { - return should(dsl.validate({range: {foo: {gt: 42, lte: 200}}})).be.fulfilledWith(); + return should(dsl.validate({range: {foo: {gt: 42, lte: 200}}})) + .be.fulfilled(); }); it('should reject a range filter with inverted boundaries', () => { - return should(dsl.validate({range: {foo: {lt: 42, gt: 200}}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({range: {foo: {lt: 42, gt: 200}}})) + .be.rejectedWith('"range.foo:" lower boundary must be strictly inferior to the upper one'); }); }); diff --git a/test/keywords/regexp.test.js b/test/keywords/regexp.test.js index 5973a9a..4568cb1 100644 --- a/test/keywords/regexp.test.js +++ b/test/keywords/regexp.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const FieldOperand = require('../../lib/storage/objects/fieldOperand'); const RegexpCondition = require('../../lib/storage/objects/regexpCondition'); const DSL = require('../../'); @@ -13,31 +12,42 @@ describe('DSL.keyword.regexp', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({regexp: {}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({regexp: {}})) + .be.rejectedWith('"regexp" must be a non-empty object'); }); it('should reject filters with more than 1 field', () => { - return should(dsl.validate({regexp: {foo: {value: 'foo'}, bar: {value: 'foo'}}})).be.rejectedWith(BadRequestError); + const filter = {foo: {value: 'foo'}, bar: {value: 'foo'}}; + + return should(dsl.validate({regexp: filter})) + .be.rejectedWith('"regexp" can contain only one attribute'); }); it('should reject filters with an empty field object', () => { - return should(dsl.validate({regexp: {foo: {}}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({regexp: {foo: {}}})) + .be.rejectedWith('regexp.foo must be either a string or a non-empty object'); }); it('should reject filters with other fields defined other than the accepted ones', () => { - return should(dsl.validate({regexp: {foo: {value: 'foo', flags: 'ig', bar: 'qux'}}})).be.rejectedWith(BadRequestError); + const filter = {foo: {value: 'foo', flags: 'ig', bar: 'qux'}}; + + return should(dsl.validate({regexp: filter})) + .be.rejectedWith('Keyword "regexp" can only contain the following attributes: flags, value'); }); it('should reject filters if the "value" attribute is not defined', () => { - return should(dsl.validate({regexp: {foo: {flags: 'ig'}}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({regexp: {foo: {flags: 'ig'}}})) + .be.rejectedWith('"regexp" requires the following attribute: value'); }); it('should reject filters with a non-string "flags" attribute', () => { - return should(dsl.validate({regexp: {foo: {value: 'foo', flags: 42}}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({regexp: {foo: {value: 'foo', flags: 42}}})) + .be.rejectedWith('Attribute "flags" in "regexp" must be a string'); }); it('should reject filters with an invalid regular expression value', () => { - return should(dsl.validate({regexp: {foo: {value: 'foo(', flags: 'i'}}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({regexp: {foo: {value: 'foo(', flags: 'i'}}})) + .be.rejectedWith(/^Cannot parse regexp expression/); }); it('should reject filters with invalid flags (js engine only)', () => { @@ -50,7 +60,7 @@ describe('DSL.keyword.regexp', () => { } } })) - .be.rejectedWith(BadRequestError); + .be.rejectedWith(/^Cannot parse regexp expression/); }); it('should validate a well-formed regular expression filter w/ flags', () => { @@ -80,7 +90,7 @@ describe('DSL.keyword.regexp', () => { foo: '++' } })) - .be.rejectedWith(BadRequestError); + .be.rejectedWith(/^Cannot parse regexp expression/); }); }); diff --git a/test/operands/and.test.js b/test/operands/and.test.js index 2aea39e..eb4582d 100644 --- a/test/operands/and.test.js +++ b/test/operands/and.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const Koncorde = require('../../'); describe('koncorde.operands.and', () => { @@ -11,27 +10,60 @@ describe('koncorde.operands.and', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(koncorde.validate({and: []})).be.rejectedWith(BadRequestError); + return should(koncorde.validate({and: []})) + .be.rejectedWith('Attribute "and" cannot be empty'); }); it('should reject non-array content', () => { - return should(koncorde.validate({and: {foo: 'bar'}})).be.rejectedWith(BadRequestError); + return should(koncorde.validate({and: {foo: 'bar'}})) + .be.rejectedWith('Attribute "and" must be an array'); }); it('should reject if one of the content is not an object', () => { - return should(koncorde.validate({and: [{equals: {foo: 'bar'}}, [{exists: {field: 'foo'}}]]})).be.rejectedWith(BadRequestError); + const filter = { + and: [ + {equals: {foo: 'bar'}}, + [ {exists: {field: 'foo'}} ], + ], + }; + + return should(koncorde.validate(filter)) + .be.rejectedWith('"and" operand can only contain non-empty objects'); }); it('should reject if one of the content object does not refer to a valid keyword', () => { - return should(koncorde.validate({and: [{equals: {foo: 'bar'}}, {foo: 'bar'}]})).be.rejectedWith(BadRequestError); + const filter = { + and: [ + {equals: {foo: 'bar'}}, + {foo: 'bar'}, + ], + }; + + return should(koncorde.validate(filter)) + .be.rejectedWith('Unknown DSL keyword: foo'); }); it('should reject if one of the content object is not a well-formed keyword', () => { - return should(koncorde.validate({and: [{equals: {foo: 'bar'}}, {exists: {foo: 'bar'}}]})).be.rejectedWith(BadRequestError); + const filter = { + and: [ + {equals: {foo: 'bar'}}, + {exists: {foo: 'bar'}}, + ], + }; + + return should(koncorde.validate(filter)) + .be.rejectedWith('"exists" requires the following attribute: field'); }); it('should validate a well-formed "and" operand', () => { - return should(koncorde.validate({and: [{equals: {foo: 'bar'}}, {exists: {field: 'bar'}}]})).be.fulfilledWith(); + const filter = { + and: [ + {equals: {foo: 'bar'}}, + {exists: {field: 'bar'}}, + ], + }; + + return should(koncorde.validate(filter)).be.fulfilled(); }); }); diff --git a/test/operands/bool.test.js b/test/operands/bool.test.js index 2f08fc8..b922ad2 100644 --- a/test/operands/bool.test.js +++ b/test/operands/bool.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const DSL = require('../../'); const NormalizedExists = require('../../lib/transform/normalizedExists'); @@ -13,11 +12,22 @@ describe('DSL.operands.bool', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({bool: {}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({bool: {}})) + .be.rejectedWith('"bool" must be a non-empty object'); }); it('should reject filters with unrecognized bool attributes', () => { - return should(dsl.validate({bool: {must: [{exists: {foo: 'bar'}}], foo: 'bar'}})).be.rejectedWith(BadRequestError); + const filter = { + bool: { + must: [ + {exists: {foo: 'bar'}}, + ], + foo: 'bar', + }, + }; + + return should(dsl.validate(filter)) + .be.rejectedWith('"bool" operand accepts only the following attributes: must, must_not, should, should_not'); }); }); diff --git a/test/operands/or.test.js b/test/operands/or.test.js index 2c3542b..b89139a 100644 --- a/test/operands/or.test.js +++ b/test/operands/or.test.js @@ -1,5 +1,4 @@ const should = require('should/as-function'); -const { BadRequestError } = require('kuzzle-common-objects'); const DSL = require('../../'); describe('DSL.operands.or', () => { @@ -11,23 +10,49 @@ describe('DSL.operands.or', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({or: []})).be.rejectedWith(BadRequestError); + return should(dsl.validate({or: []})) + .be.rejectedWith('Attribute "or" cannot be empty'); }); it('should reject non-array content', () => { - return should(dsl.validate({or: {foo: 'bar'}})).be.rejectedWith(BadRequestError); + return should(dsl.validate({or: {foo: 'bar'}})) + .be.rejectedWith('Attribute "or" must be an array'); }); it('should reject if one of the content is not an object', () => { - return should(dsl.validate({or: [{equals: {foo: 'bar'}}, [{exists: {field: 'foo'}}]]})).be.rejectedWith(BadRequestError); + const filter = { + or: [ + {equals: {foo: 'bar'}}, + [ {exists: {field: 'foo'}} ], + ], + }; + + return should(dsl.validate(filter)) + .be.rejectedWith('"or" operand can only contain non-empty objects'); }); it('should reject if one of the content object does not refer to a valid keyword', () => { - return should(dsl.validate({or: [{equals: {foo: 'bar'}}, {foo: 'bar'}]})).be.rejectedWith(BadRequestError); + const filter = { + or: [ + {equals: {foo: 'bar'}}, + {foo: 'bar'}, + ], + }; + + return should(dsl.validate(filter)) + .be.rejectedWith('Unknown DSL keyword: foo'); }); it('should reject if one of the content object is not a well-formed keyword', () => { - return should(dsl.validate({or: [{equals: {foo: 'bar'}}, {exists: {foo: 'bar'}}]})).be.rejectedWith(BadRequestError); + const filter = { + or: [ + {equals: {foo: 'bar'}}, + {exists: {foo: 'bar'}}, + ], + }; + + return should(dsl.validate(filter)) + .be.rejectedWith('"exists" requires the following attribute: field'); }); it('should validate a well-formed "or" operand', () => { From e8a765bbf3ef13812c8ab80aef34914954a6c5f5 Mon Sep 17 00:00:00 2001 From: scottinet Date: Tue, 25 May 2021 15:58:52 +0200 Subject: [PATCH 2/2] feat: remove all promises from the API --- README.md | 131 +++--- benchmark.js | 22 +- lib/index.js | 18 +- lib/util/convertDistance.js | 2 +- package.json | 4 +- test/api.test.js | 385 +++++++++-------- test/keywords/equals.test.js | 399 ++++++++--------- test/keywords/everything.test.js | 59 ++- test/keywords/exists.test.js | 575 +++++++++++-------------- test/keywords/geoBoundingBox.test.js | 204 +++++---- test/keywords/geoDistance.test.js | 172 +++++--- test/keywords/geoDistanceRange.test.js | 195 ++++++--- test/keywords/geoPolygon.test.js | 159 ++++--- test/keywords/geospatial.test.js | 115 ++--- test/keywords/ids.test.js | 28 +- test/keywords/in.test.js | 24 +- test/keywords/missing.test.js | 68 ++- test/keywords/notequals.test.js | 289 ++++++++----- test/keywords/notgeospatial.test.js | 408 ++++++++++-------- test/keywords/nothing.test.js | 16 +- test/keywords/notrange.test.js | 475 ++++++++++++-------- test/keywords/notregexp.test.js | 214 ++++++--- test/keywords/range.test.js | 406 ++++++++++------- test/keywords/regexp.test.js | 529 ++++++++++++++--------- test/operands/and.test.js | 96 ++--- test/operands/bool.test.js | 42 +- test/operands/or.test.js | 91 ++-- 27 files changed, 2850 insertions(+), 2276 deletions(-) diff --git a/README.md b/README.md index 2d6141a..47b6315 100644 --- a/README.md +++ b/README.md @@ -95,39 +95,38 @@ const filter = { }; // More on index/collection parameters later -engine.register('index', 'collection', filter) - .then(result => { - // The filter identifier depends on a random seed (see below) - // For now, let's pretend its value is 5db7052792b18cb2 - console.log(`Filter identifier: ${result.id}`); - - // *** Now, let's test data with our engine *** - - // Returns: [] (distance is greater than 500m) - console.log(engine.test('index', 'collection', { - position: { - lat: 43.6073913, - lon: 5.7 - } - })); - - // Returns: ['5db7052792b18cb2'] - console.log(engine.test('index', 'collection', { - position: { - lat: 43.608, - lon: 3.905 - } - })); - - - // Returns: [] (the geopoint is not stored in a "position" field) - console.log(engine.test('index', 'collection', { - point: { - lat: 43.608, - lon: 3.905 - } - })); - }); +const result = engine.register('index', 'collection', filter); + +// The filter identifier depends on a random seed (see below) +// For now, let's pretend its value is 5db7052792b18cb2 +console.log(`Filter identifier: ${result.id}`); + +// *** Now, let's test data with our engine *** + +// Returns: [] (distance is greater than 500m) +console.log(engine.test('index', 'collection', { + position: { + lat: 43.6073913, + lon: 5.7, + }, +})); + +// Returns: ['5db7052792b18cb2'] +console.log(engine.test('index', 'collection', { + position: { + lat: 43.608, + lon: 3.905, + }, +})); + + +// Returns: [] (the geopoint is not stored in a "position" field) +console.log(engine.test('index', 'collection', { + point: { + lat: 43.608, + lon: 3.905, + }, +})); ``` ## Install @@ -175,42 +174,35 @@ In the following example, we provide a fixed random seed. Replaying this example ```js const Koncorde = require('koncorde'); -const - seed = Buffer.from('ac1bb751a1e5b3dce4a5d58e3e5e317677f780f57f8ca27b624345808b3e0e86', 'hex'), - engine = new Koncorde({seed}); +const seed = Buffer.from( + 'ac1bb751a1e5b3dce4a5d58e3e5e317677f780f57f8ca27b624345808b3e0e86', + 'hex'); +const engine = new Koncorde({seed}); // filter1 and filter2 are equivalent -const - filter1 = { - and:[ - {equals: {firstname: 'Grace'}}, - {exists: {field: 'hobby'}} - ] +const filter1 = { + and: [ + { equals: { firstname: 'Grace' } }, + { exists: { field: 'hobby' } }, + ] +}; +const filter2 = { + not: { + bool: { + should_not: [ + { in: { firstname: [ 'Grace' ] } }, + { exists: { field: 'hobby' } }, + ], }, - filter2 = { - not: { - bool: { - should_not: [ - {in: {firstname: ['Grace']}}, - {exists: {field: 'hobby'}} - ] - } - } - }; - -let filterId1; - -engine.register('index', 'collection', filter1) - .then(result => { - filterId1 = result.id; - return engine.register('index', 'collection', filter2); - }) - .then(result => { - console.log(`Filter ID 1: ${filterId1}, Filter ID 2: ${result.id}, Equals: ${filterId1 === result.id}`); - }); + }, +}; + +const subscription1 = engine.register('index', 'collection', filter1); +const subscription2 = engine.register('index', 'collection', filter2); // Prints: // Filter ID 1: b4ee9ece4d7b1398, Filter ID 2: b4ee9ece4d7b1398, Equals: true +console.log(`Filter ID 1: ${subscription1.id}, Filter ID 2: ${subscription2.id}, Equals: ${subscription1.id === subscription2.id}`); ``` ## Field syntax @@ -1280,8 +1272,7 @@ An `array` of index names. ### `normalize` -Returns a promise resolved if the provided filter are well-formed. -The resolved object contains the provided filter in its canonical form, along with the corresponding filter unique identifier. +Returns an object containing the provided filter in its canonical form, along with the corresponding filter unique identifier. This method does not modify the internal storage. To save a filter, the [store](#store) method must be called afterward. If you do not need the filter unique identifier prior to save a filter in the engine, then consider using the all-in-one [register](#register) method instead. @@ -1298,7 +1289,7 @@ If you do not need the filter unique identifier prior to save a filter in the en #### Returns -A `promise` resolving to an object containing the following attributes: +An object containing the following attributes: * `index`: data index name * `collection`: data collection name @@ -1323,7 +1314,7 @@ Registers a filter to the engine instance. This method is equivalent to executin #### Returns -A `promise` resolving to an object containing the following attributes: +An object containing the following attributes: * `id`: the filter unique identifier * `diff`: `false` if the filter already exists in the engine. Otherwise, contains an object with the canonical version of the provided filter @@ -1342,10 +1333,6 @@ Removes all references to a given filter from the engine. |------|------|----------------------------------| |`filterId`|`string`| Filter unique ID. Obtained by using `register`| -#### Returns - -A `promise` resolved once the filter has been completely removed from the engine. - --- ### `store` @@ -1405,7 +1392,7 @@ Tests the provided filter without storing it in the engine, to check whether it #### Returns -A resolved promise if the provided filter is valid, or a rejected one with the appropriate error object otherwise. +Throws with an appropriate error if the provided filter is invalid. --- diff --git a/benchmark.js b/benchmark.js index 4c30769..a8a323a 100644 --- a/benchmark.js +++ b/benchmark.js @@ -47,7 +47,7 @@ function removeFilters() { console.log(`\tFilters removal: time = ${(Date.now() - removalStart)/1000}s`); } -async function test (name, generator, document) { +function test (name, generator, document) { const baseHeap = v8.getHeapStatistics().total_heap_size; console.log(`\n> Benchmarking keyword: ${name}`); @@ -56,7 +56,7 @@ async function test (name, generator, document) { for (let i = 0;i < max; i++) { // Using the filter name as a collection to isolate // benchmark calculation per keyword - filters.push((await koncorde.register('i', name, generator())).id); + filters.push(koncorde.register('i', name, generator()).id); } const filterEndTime = (Date.now() - filterStartTime) / 1000; @@ -65,18 +65,18 @@ async function test (name, generator, document) { matching(name, document); } -async function run () { - await test( +function run () { + test( 'equals', () => ({equals: {str: rgen.string(engine, 20)}}), { str: rgen.string(engine, 20) }); - await test( + test( 'exists', () => ({exists: {field: rgen.string(engine, 20)}}), { [rgen.string(engine, 20)]: true }); - await test('geoBoundingBox', + test('geoBoundingBox', () => { const pos = georandom.position(); @@ -93,7 +93,7 @@ async function run () { }, { point: [0, 0] }); - await test('geoDistance', + test('geoDistance', () => { const pos = georandom.position(); @@ -106,7 +106,7 @@ async function run () { }, { point: [0, 0] }); - await test('geoDistanceRange', + test('geoDistanceRange', () => { const pos = georandom.position(); @@ -120,7 +120,7 @@ async function run () { }, { point: [0, 0] }); - await test('geoPolygon (10 vertices)', + test('geoPolygon (10 vertices)', () => { const polygon = georandom .polygon(1) @@ -137,7 +137,7 @@ async function run () { }, { point: [0, 0] }); - await test('in (5 random values)', + test('in (5 random values)', () => { const values = []; @@ -149,7 +149,7 @@ async function run () { }, { str: rgen.string(engine, 20) }); - await test('range (random bounds)', + test('range (random bounds)', () => { const bound = rgen.int(engine); diff --git a/lib/index.js b/lib/index.js index 115d843..e863daa 100644 --- a/lib/index.js +++ b/lib/index.js @@ -61,9 +61,9 @@ class Koncorde { * Checks if the provided filter is valid * * @param {object} filter - * @return {Promise} + * @return {Object} */ - async validate (filter) { + validate (filter) { return this.transformer.check(filter); } @@ -74,10 +74,10 @@ class Koncorde { * @param {string} index * @param {string} collection * @param {object} filters - * @return {Promise} + * @return {Object} */ - async register (index, collection, filter) { - const normalized = await this.transformer.normalize(filter); + register (index, collection, filter) { + const normalized = this.transformer.normalize(filter); return this.storage.store(index, collection, normalized); } @@ -90,10 +90,10 @@ class Koncorde { * @param {string} index index * @param {[type]} collection collection * @param {[type]} filter filter - * @return {Promise.<{index: String, collection: String, id: String, normalized: Object}>} + * @return {{index: String, collection: String, id: String, normalized: Object}} */ - async normalize(index, collection, filter) { - const normalized = await this.transformer.normalize(filter); + normalize(index, collection, filter) { + const normalized = this.transformer.normalize(filter); return { collection, @@ -196,7 +196,7 @@ class Koncorde { /** * Converts a distance string value to a number of meters * @param {string} distance - client-provided distance - * @returns {number} resolves to converted distance + * @returns {number} converted distance */ static convertDistance(distance) { return convertDistance(distance); diff --git a/lib/util/convertDistance.js b/lib/util/convertDistance.js index 21e874c..dca3be1 100644 --- a/lib/util/convertDistance.js +++ b/lib/util/convertDistance.js @@ -24,7 +24,7 @@ const units = require('node-units'); /** * Converts a distance string value to a number of meters * @param {string} distance - client-provided distance - * @returns {number} resolves to converted distance + * @returns {number} converted distance */ function convertDistance (distance) { // clean up to ensure node-units will be able to convert it diff --git a/package.json b/package.json index c448313..50df7cb 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,8 @@ "lib": "lib" }, "scripts": { - "test": "npm run --silent lint && npm run test:unit:coverage", - "lint": "eslint --max-warnings=0 ./lib ./test", + "test": "npm run --silent test:lint && npm run test:unit:coverage", + "test:lint": "eslint --max-warnings=0 ./lib ./test", "test:unit:coverage": "nyc --reporter=text-summary --reporter=lcov mocha", "test:unit": "DEBUG= npx --node-arg=--trace-warnings mocha --exit", "codecov": "codecov" diff --git a/test/api.test.js b/test/api.test.js index a5a0d81..290ba93 100644 --- a/test/api.test.js +++ b/test/api.test.js @@ -66,146 +66,151 @@ describe('DSL API', () => { describe('#validate', () => { it('should resolve to "true" if a filter is valid', () => { - return should(dsl.validate({equals: {foo: 'bar'}})).be.fulfilledWith(); + should(() => dsl.validate({equals: {foo: 'bar'}})).not.throw(); }); it('should reject if a filter is not valid', () => { - return should(dsl.validate({equals: {foo: 'bar'}, exists: 'qux'})).be.rejected(); + should(() => dsl.validate({equals: {foo: 'bar'}, exists: 'qux'})).throw(); }); }); describe('#register', () => { it('should reject if a filter is not valid', () => { - return should(dsl.register('i', 'c', {foo: 'bar'})).be.rejected(); + should(() => dsl.register('i', 'c', {foo: 'bar'})).throw(); }); it('should resolve to a cluster diff object if the registration succeeds', () => { - return dsl.register('i', 'c', {not: {and: [{exists: 'bar'}, {equals: {foo: 'bar'}}]}}) - .then(result => { - should(result).be.an.Object(); - should(result.diff).be.an.Object().and.match({ - index: 'i', - collection: 'c', - filters: [ - [ { exists: { path: 'bar', array: false, value: null }, not: true } ], - [ { equals: { foo: 'bar' }, not: true } ] - ] - }); + const result = dsl.register('i', 'c', { + not: { + and: [ + {exists: 'bar'}, + {equals: {foo: 'bar'}}, + ], + }, + }); + + should(result).be.an.Object(); + should(result.diff).be.an.Object().and.match({ + index: 'i', + collection: 'c', + filters: [ + [ { exists: { path: 'bar', array: false, value: null }, not: true } ], + [ { equals: { foo: 'bar' }, not: true } ] + ] + }); - should(result.id).be.a.String(); - }); + should(result.id).be.a.String(); }); it('should resolve to a "no diff" object if the room already exists', () => { - let id; - - return dsl.register('i', 'c', {not: {and: [{exists: 'bar'}, {equals: {foo: 'bar'}}]}}) - .then(result => { - id = result.id; - return dsl.register('i', 'c', { - or: [ - {not: { exists: 'bar'}}, - {not: { equals: { foo: 'bar' }}} - ] - }); - }) - .then(result => { - const bool = { - bool: { - should_not: [ - {exists: { field: 'bar' }}, - {equals: { foo: 'bar' }} - ] - } - }; - - should(result.diff) - .eql({ - index: 'i', - collection: 'c', - filters: [ - [ {exists: {path: 'bar', array: false, value: null}, not: true}], - [ {equals: {foo: 'bar'}, not: true}] - ] - }); - should(result.id).be.eql(id); - - return dsl.register('i', 'c', bool); - }) - .then(result => { - should(result.id).be.eql(id); + let result = dsl.register('i', 'c', { + not: { + and: [ + {exists: 'bar'}, + {equals: {foo: 'bar'}}, + ], + }, + }); + + const id = result.id; + + result = dsl.register('i', 'c', { + or: [ + {not: { exists: 'bar'}}, + {not: { equals: { foo: 'bar' }}}, + ], + }); + + const bool = { + bool: { + should_not: [ + {exists: { field: 'bar' }}, + {equals: { foo: 'bar' }} + ] + } + }; + + should(result.diff) + .eql({ + index: 'i', + collection: 'c', + filters: [ + [ {exists: {path: 'bar', array: false, value: null}, not: true}], + [ {equals: {foo: 'bar'}, not: true}], + ], }); + should(result.id).be.eql(id); + + result = dsl.register('i', 'c', bool); + + should(result.id).be.eql(id); }); it('should not recreate an already existing subfilter', () => { let ids = []; - return dsl.register('i', 'c', {or: [{equals: {foo: 'bar'}}, {exists: 'bar'}]}) - .then(subscription => { - ids.push(subscription.id); - return dsl.register('i', 'c', {equals: {foo: 'bar'}}); - }) - .then(subscription => { - const sfs = dsl.storage.filters.get(subscription.id).subfilters; + let subscription = dsl.register('i', 'c', { + or: [ + {equals: {foo: 'bar'}}, + {exists: 'bar'}, + ], + }); - ids.push(subscription.id); - should(sfs).instanceOf(Set); - should(sfs.size).be.eql(1); + ids.push(subscription.id); - const filterIds = []; + subscription = dsl.register('i', 'c', {equals: {foo: 'bar'}}); - for (const sf of sfs.values()) { - sf.filters.forEach(f => filterIds.push(f.id)); - } + const sfs = dsl.storage.filters.get(subscription.id).subfilters; - should(filterIds.sort()).match(ids.sort()); - }); + ids.push(subscription.id); + should(sfs).instanceOf(Set); + should(sfs.size).be.eql(1); + + const filterIds = []; + + for (const sf of sfs.values()) { + sf.filters.forEach(f => filterIds.push(f.id)); + } + + should(filterIds.sort()).match(ids.sort()); }); }); describe('#exists', () => { it('should return true if a filter exists on the provided index and collection', () => { should(dsl.exists('i', 'c')).be.false(); - return dsl.register('i', 'c', {equals: {foo: 'bar'}}) - .then(() => { - should(dsl.exists('i', 'c')).be.true(); - }); + + dsl.register('i', 'c', {equals: {foo: 'bar'}}); + should(dsl.exists('i', 'c')).be.true(); }); it('should return false if no filter exists on a provided collection', () => { - return dsl.register('i', 'c', {equals: {foo: 'bar'}}) - .then(() => { - should(dsl.exists('i', 'foo')).be.false(); - }); + dsl.register('i', 'c', {equals: {foo: 'bar'}}); + should(dsl.exists('i', 'foo')).be.false(); }); it('should return false if no filter exists on a provided index', () => { - return dsl.register('i', 'c', {equals: {foo: 'bar'}}) - .then(() => { - should(dsl.exists('foo', 'c')).be.false(); - }); + dsl.register('i', 'c', {equals: {foo: 'bar'}}); + should(dsl.exists('foo', 'c')).be.false(); }); }); describe('#getFilterIds', () => { it('should return an empty array if no filter exist on the provided index and collection', () => { - return dsl.register('i', 'c', {equals: {foo: 'bar'}}) - .then(() => { - should(dsl.getFilterIds('foo', 'bar')).be.an.Array().and.be.empty(); - }); + dsl.register('i', 'c', {equals: {foo: 'bar'}}); + should(dsl.getFilterIds('foo', 'bar')).be.an.Array().and.be.empty(); }); it('should return the list of registered filter IDs on the provided index and collection', () => { let ids = []; - return dsl.register('i', 'c', {equals: {foo: 'bar'}}) - .then(result => { - ids.push(result.id); - return dsl.register('i', 'c', {exists: 'foo'}); - }) - .then(result => { - ids.push(result.id); - should(dsl.getFilterIds('i', 'c').sort()).match(ids.sort()); - }); + + let result = dsl.register('i', 'c', {equals: {foo: 'bar'}}); + ids.push(result.id); + + result = dsl.register('i', 'c', {exists: 'foo'}); + ids.push(result.id); + + should(dsl.getFilterIds('i', 'c').sort()).match(ids.sort()); }); }); @@ -215,42 +220,36 @@ describe('DSL API', () => { }); it('should return the list of registered indexes on the provided index and collection', () => { - return dsl.register('i', 'c', {equals: {foo: 'bar'}}) - .then(() => dsl.register('i', 'c', {exists: 'foo'})) - .then(() => dsl.register('i2', 'c', {exists: 'foo'})) - .then(() => should(dsl.getIndexes().sort()).match(['i', 'i2'])); + dsl.register('i', 'c', {equals: {foo: 'bar'}}); + dsl.register('i', 'c', {exists: 'foo'}); + dsl.register('i2', 'c', {exists: 'foo'}); + + should(dsl.getIndexes().sort()).match(['i', 'i2']); }); }); describe('#getCollections', () => { it('should return an empty array if no filter exist on the provided index and collection', () => { - return dsl.register('i', 'c', {equals: {foo: 'bar'}}) - .then(() => { - should(dsl.getCollections('foo')).be.an.Array().and.be.empty(); - }); + dsl.register('i', 'c', {equals: {foo: 'bar'}}); + should(dsl.getCollections('foo')).be.an.Array().and.be.empty(); }); it('should return the list of registered collections on the provided index and collection', () => { - return dsl.register('i', 'c', {equals: {foo: 'bar'}}) - .then(() => dsl.register('i', 'c', {exists: 'foo'})) - .then(() => dsl.register('i', 'c2', {exists: 'foo'})) - .then(() => should(dsl.getCollections('i').sort()).match(['c', 'c2'])); + dsl.register('i', 'c', {equals: {foo: 'bar'}}); + dsl.register('i', 'c', {exists: 'foo'}); + dsl.register('i', 'c2', {exists: 'foo'}); + should(dsl.getCollections('i').sort()).match(['c', 'c2']); }); }); describe('#hasFilter', () => { it('should return false if the filter does not exist', () => { - should(dsl.hasFilter('i dont exist')) - .be.false(); + should(dsl.hasFilter('i dont exist')).be.false(); }); it('should return true if the filter exists', () => { - return dsl.register('i', 'c', {equals: {foo: 'bar'}}) - .then(response => { - should(dsl.hasFilter(response.id)) - .be.true(); - }); - + const response = dsl.register('i', 'c', {equals: {foo: 'bar'}}); + should(dsl.hasFilter(response.id)).be.true(); }); }); @@ -267,46 +266,44 @@ describe('DSL API', () => { it('should flatten submitted documents', () => { const stub = sinon.stub(dsl.matcher, 'match'); - return dsl.register('i', 'c', {}) - .then(() => { - dsl.test('i', 'c', { - bar: 'bar', - qux: 'qux', - obj: { - hello: 'world', - nested: { - another: 'one', - bites: 'the dust' - }, - bottlesOfBeer: 99 - }, - arr: ['foo', 'bar'], - foo: 'bar' - }); - - should(stub.calledWith('i', 'c', { - bar: 'bar', - qux: 'qux', - obj: { - hello: 'world', - nested: { - another: 'one', - bites: 'the dust' - }, - bottlesOfBeer: 99 - }, - 'obj.hello': 'world', - 'obj.nested': { - another: 'one', - bites: 'the dust' - }, - 'obj.nested.another': 'one', - 'obj.nested.bites': 'the dust', - 'obj.bottlesOfBeer': 99, - arr: ['foo', 'bar'], - foo: 'bar' - })).be.true(); - }); + dsl.register('i', 'c', {}); + dsl.test('i', 'c', { + bar: 'bar', + qux: 'qux', + obj: { + hello: 'world', + nested: { + another: 'one', + bites: 'the dust' + }, + bottlesOfBeer: 99 + }, + arr: ['foo', 'bar'], + foo: 'bar' + }); + + should(stub.calledWith('i', 'c', { + bar: 'bar', + qux: 'qux', + obj: { + hello: 'world', + nested: { + another: 'one', + bites: 'the dust' + }, + bottlesOfBeer: 99 + }, + 'obj.hello': 'world', + 'obj.nested': { + another: 'one', + bites: 'the dust' + }, + 'obj.nested.another': 'one', + 'obj.nested.bites': 'the dust', + 'obj.bottlesOfBeer': 99, + arr: ['foo', 'bar'], + foo: 'bar' + })).be.true(); }); }); @@ -320,54 +317,60 @@ describe('DSL API', () => { }); it('should unsubscribe a filter from a multi-filter subfilter', () => { - let sf; const ids = []; - return dsl.register('i', 'c', {or: [{equals: {foo: 'bar'}}, {exists: {field: 'bar'}}]}) - .then(subscription => { - ids.push(subscription.id); - return dsl.register('i', 'c', {equals: {foo: 'bar'}}); - }) - .then(subscription => { - const sfs = dsl.storage.filters.get(subscription.id).subfilters; - - ids.push(subscription.id); - should(sfs).instanceOf(Set); - should(sfs.size).be.eql(1); - - sf = Array.from(sfs.values())[0]; - should(sf.filters.size).be.eql(2); - - const filterIds = Array.from(sf.filters).map(f => f.id); - should(filterIds.sort()).match(Array.from(ids).sort()); - - return dsl.remove(subscription.id); - }) - .then(() => { - should(sf.filters.size).be.eql(1); - const fid = Array.from(sf.filters)[0].id; - should(fid).match(ids[0]); - }); + let subscription = dsl.register('i', 'c', { + or: [ + {equals: {foo: 'bar'}}, + {exists: {field: 'bar'}}, + ], + }); + + ids.push(subscription.id); + subscription = dsl.register('i', 'c', {equals: {foo: 'bar'}}); + + const sfs = dsl.storage.filters.get(subscription.id).subfilters; + + ids.push(subscription.id); + should(sfs).instanceOf(Set); + should(sfs.size).be.eql(1); + + const sf = Array.from(sfs.values())[0]; + should(sf.filters.size).be.eql(2); + + const filterIds = Array.from(sf.filters).map(f => f.id); + should(filterIds.sort()).match(Array.from(ids).sort()); + + dsl.remove(subscription.id); + + should(sf.filters.size).be.eql(1); + const fid = Array.from(sf.filters)[0].id; + should(fid).match(ids[0]); }); }); describe('#normalize', () => { it('should invoke the normalizer', () => { - const - f = {not: {and: [{exists: {field: 'bar'}}, {equals: {foo: 'bar'}}]}}, - n = {}; + const f = { + not: { + and: [ + {exists: {field: 'bar'}}, + {equals: {foo: 'bar'}}, + ], + }, + }; + const n = {}; - sinon.stub(dsl.transformer, 'normalize').resolves(n); + sinon.stub(dsl.transformer, 'normalize').returns(n); sinon.stub(dsl.storage, 'getFilterId'); - return dsl.normalize('i', 'c', f) - .then(() => { - should(dsl.transformer.normalize.calledOnce).be.true(); - should(dsl.transformer.normalize.calledWith(f)).be.true(); + dsl.normalize('i', 'c', f); - should(dsl.storage.getFilterId.calledOnce).be.true(); - should(dsl.storage.getFilterId).calledWith('i', 'c', n); - }); + should(dsl.transformer.normalize.calledOnce).be.true(); + should(dsl.transformer.normalize.calledWith(f)).be.true(); + + should(dsl.storage.getFilterId.calledOnce).be.true(); + should(dsl.storage.getFilterId).calledWith('i', 'c', n); }); }); diff --git a/test/keywords/equals.test.js b/test/keywords/equals.test.js index 311eeab..6362e88 100644 --- a/test/keywords/equals.test.js +++ b/test/keywords/equals.test.js @@ -16,48 +16,48 @@ describe('DSL.keyword.equals', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({equals: ['foo', 'bar']})) - .be.rejectedWith('"equals" must be a non-empty object'); + should(() => dsl.validate({equals: ['foo', 'bar']})) + .throw('"equals" must be a non-empty object'); }); it('should reject filters with more than 1 field', () => { - return should(dsl.validate({equals: {foo: 'foo', bar: 'bar'}})) - .be.rejectedWith('"equals" can contain only one attribute'); + should(() => dsl.validate({equals: {foo: 'foo', bar: 'bar'}})) + .throw('"equals" can contain only one attribute'); }); it('should reject filters with array argument', () => { - return should(dsl.validate({equals: {foo: ['bar']}})) - .be.rejectedWith('"foo" in "equals" must be either a string, a number, a boolean or null'); + should(() => dsl.validate({equals: {foo: ['bar']}})) + .throw('"foo" in "equals" must be either a string, a number, a boolean or null'); }); it('should validate filters with number argument', () => { - return should(dsl.validate({equals: {foo: 42}})).be.fulfilled(); + should(() => dsl.validate({equals: {foo: 42}})).not.throw(); }); it('should reject filters with object argument', () => { - return should(dsl.validate({equals: {foo: {}}})) - .be.rejectedWith('"foo" in "equals" must be either a string, a number, a boolean or null'); + should(() => dsl.validate({equals: {foo: {}}})) + .throw('"foo" in "equals" must be either a string, a number, a boolean or null'); }); it('should reject filters with undefined argument', () => { - return should(dsl.validate({equals: {foo: undefined}})) - .be.rejectedWith('"foo" in "equals" must be either a string, a number, a boolean or null'); + should(() => dsl.validate({equals: {foo: undefined}})) + .throw('"foo" in "equals" must be either a string, a number, a boolean or null'); }); it('should validate filters with null argument', () => { - return should(dsl.validate({equals: {foo: null}})).be.fulfilled(); + should(() => dsl.validate({equals: {foo: null}})).not.throw(); }); it('should validate filters with boolean argument', () => { - return should(dsl.validate({equals: {foo: true}})).be.fulfilled(); + should(() => dsl.validate({equals: {foo: true}})).not.throw(); }); it('should validate filters with a string argument', () => { - return should(dsl.validate({equals: {foo: 'bar'}})).be.fulfilled(); + should(() => dsl.validate({equals: {foo: 'bar'}})).not.throw(); }); it('should validate filters with an empty string argument', () => { - return should(dsl.validate({equals: {foo: ''}})).be.fulfilled(); + should(() => dsl.validate({equals: {foo: ''}})).not.throw(); }); }); @@ -70,273 +70,232 @@ describe('DSL.keyword.equals', () => { describe('#storage', () => { it('should store a single condition correctly', () => { - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(subscription => { - const - subfilter = getSubfilter(subscription.id), - storage = dsl.storage.foPairs.get('index', 'collection', 'equals'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo')) - .instanceOf(Map) - .have.value('bar', new Set([subfilter])); - }); + const subscription = dsl.register('index', 'collection', { + equals: { foo: 'bar' }, + }); + const subfilter = getSubfilter(subscription.id); + const storage = dsl.storage.foPairs.get('index', 'collection', 'equals'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo')) + .instanceOf(Map) + .have.value('bar', new Set([subfilter])); }); it('should store multiple conditions on the same field correctly', () => { - let barSubfilter; - - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(subscription => { - barSubfilter = getSubfilter(subscription.id); - - return dsl.register('index', 'collection', {equals: {foo: 'qux'}}); - }) - .then(subscription => { - const quxSubfilter = getSubfilter(subscription.id); - const equals = dsl.storage.foPairs.get( - 'index', - 'collection', - 'equals'); - - should(equals).be.an.instanceof(FieldOperand); - should(equals.fields.get('foo')) - .have.value('bar', new Set([barSubfilter])); - should(equals.fields.get('foo')) - .have.value('qux', new Set([quxSubfilter])); - }); + let subscription = dsl.register('index', 'collection', { + equals: {foo: 'bar'}, + }); + + const barSubfilter = getSubfilter(subscription.id); + + subscription = dsl.register('index', 'collection', {equals: {foo: 'qux'}}); + + const quxSubfilter = getSubfilter(subscription.id); + const equals = dsl.storage.foPairs.get('index', 'collection', 'equals'); + + should(equals).be.an.instanceof(FieldOperand); + should(equals.fields.get('foo')) + .have.value('bar', new Set([barSubfilter])); + should(equals.fields.get('foo')) + .have.value('qux', new Set([quxSubfilter])); }); it('should store multiple subfilters on the same condition correctly', () => { - let barSubfilter; - - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(subscription => { - barSubfilter = getSubfilter(subscription.id); - - return dsl.register('index', 'collection', { - and: [ - { equals: { baz: 'qux' } }, - { equals: { foo: 'bar' } } - ] - }); - }) - .then(subscription => { - const multiSubfilter = getSubfilter(subscription.id); - const equals = dsl.storage.foPairs.get('index', 'collection', 'equals'); - - should(equals).be.an.instanceof(FieldOperand); - should(equals.fields.get('foo')) - .have.value('bar', new Set([barSubfilter, multiSubfilter])); - should(equals.fields.get('baz')) - .have.value('qux', new Set([multiSubfilter])); - }); + let subscription = dsl.register('index', 'collection', { + equals: {foo: 'bar'}, + }); + const barSubfilter = getSubfilter(subscription.id); + + subscription = dsl.register('index', 'collection', { + and: [ + { equals: { baz: 'qux' } }, + { equals: { foo: 'bar' } } + ] + }); + + const multiSubfilter = getSubfilter(subscription.id); + const equals = dsl.storage.foPairs.get('index', 'collection', 'equals'); + + should(equals).be.an.instanceof(FieldOperand); + should(equals.fields.get('foo')) + .have.value('bar', new Set([barSubfilter, multiSubfilter])); + should(equals.fields.get('baz')) + .have.value('qux', new Set([multiSubfilter])); }); }); describe('#matching', () => { it('should match a document with the subscribed keyword', () => { - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: 'bar'}); + const subscription = dsl.register('index', 'collection', { + equals: {foo: 'bar'}, + }); + const result = dsl.test('index', 'collection', {foo: 'bar'}); - should(result).be.an.Array().and.not.empty(); - should(result[0]).be.eql(subscription.id); - }); + should(result).be.an.Array().and.not.empty(); + should(result[0]).be.eql(subscription.id); }); it('should match a document on its provided id', () => { - return dsl.register('index', 'collection', {equals: {_id: 'foo'}}) - .then(subscription => { - var result = dsl.test('index', 'collection', {foo: 'bar'}, 'foo'); + const subscription = dsl.register('index', 'collection', { + equals: {_id: 'foo'}, + }); + const result = dsl.test('index', 'collection', {foo: 'bar'}, 'foo'); - should(result).be.an.Array().and.not.empty(); - should(result[0]).be.eql(subscription.id); - }); + should(result).be.an.Array().and.not.empty(); + should(result[0]).be.eql(subscription.id); }); it('should not match if the document contains the field with another value', () => { - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(() => { - should(dsl.test('index', 'collection', {foo: 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {equals: {foo: 'bar'}}); + + should(dsl.test('index', 'collection', {foo: 'qux'})) + .be.an.Array() + .and.be.empty(); }); it('should not match if the document contains another field with the registered value', () => { - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(() => { - should(dsl.test('index', 'collection', {qux: 'bar'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {equals: {foo: 'bar'}}); + should(dsl.test('index', 'collection', {qux: 'bar'})) + .be.an.Array() + .and.be.empty(); }); // see https://github.com/kuzzleio/koncorde/issues/13 it('should skip the matching if the document tested property is not of the same type than the known values', () => { - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(() => { - should(dsl.test('index', 'collection', {foo: ['bar']})).be.an.Array().and.empty(); - should(dsl.test('index', 'collection', {foo: {bar: true}})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {equals: {foo: 'bar'}}); + + should(dsl.test('index', 'collection', {foo: ['bar']})) + .be.an.Array().and.empty(); + + should(dsl.test('index', 'collection', {foo: {bar: true}})) + .be.an.Array().and.empty(); }); it('should match a document with the subscribed nested keyword', () => { - return dsl.register('index', 'collection', {equals: {'foo.bar.baz': 'qux'}}) - .then(subscription => { - var result = dsl.test('index', 'collection', {foo: {bar: {baz: 'qux'}}}); + const subscription = dsl.register('index', 'collection', { + equals: {'foo.bar.baz': 'qux'}, + }); + const result = dsl.test('index', 'collection', {foo: {bar: {baz: 'qux'}}}); - should(result).be.an.Array().and.not.empty(); - should(result[0]).be.eql(subscription.id); - }); + should(result).be.an.Array().and.not.empty(); + should(result[0]).be.eql(subscription.id); }); it('should not match if the document is in another index', () => { - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(() => { - should(dsl.test('foobar', 'collection', {foo: 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {equals: {foo: 'bar'}}); + should(dsl.test('foobar', 'collection', {foo: 'qux'})) + .be.an.Array().and.empty(); }); it('should not match if the document is in another collection', () => { - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(() => { - should(dsl.test('index', 'foobar', {foo: 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {equals: {foo: 'bar'}}); + should(dsl.test('index', 'foobar', {foo: 'qux'})) + .be.an.Array().and.empty(); }); it('should match 0 equality', () => { - return dsl.register('i', 'c', {equals: {a: 0}}) - .then(() => { - should(dsl.test('i', 'c', {a: 0})) - .be.an.Array() - .length(1); - }); + dsl.register('i', 'c', {equals: {a: 0}}); + should(dsl.test('i', 'c', {a: 0})).be.an.Array().length(1); }); it('should match false equality', () => { - return dsl.register('i', 'c', {equals: {a: false}}) - .then(() => { - should(dsl.test('i', 'c', {a: false})) - .be.an.Array() - .length(1); - }); + dsl.register('i', 'c', {equals: {a: false}}); + should(dsl.test('i', 'c', {a: false})).be.an.Array().length(1); }); it('should match null equality', () => { - return dsl.register('i', 'c', {equals: {a: null}}) - .then(() => { - should(dsl.test('i', 'c', {a: null})) - .be.an.Array() - .length(1); - }); + dsl.register('i', 'c', {equals: {a: null}}); + should(dsl.test('i', 'c', {a: null})).be.an.Array().length(1); }); }); describe('#removal', () => { it('should destroy the whole structure when removing the last item', () => { - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(subscription => dsl.remove(subscription.id)) - .then(() => { - should(dsl.storage.foPairs._cache).be.an.Object().and.be.empty(); - }); + const subscription = dsl.register('index', 'collection', { + equals: {foo: 'bar'}, + }); + + dsl.remove(subscription.id); + + should(dsl.storage.foPairs._cache).be.an.Object().and.be.empty(); }); it('should remove a single subfilter from a multi-filter condition', () => { - let - idToRemove, - multiSubfilter; - - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(subscription => { - idToRemove = subscription.id; - - return dsl.register('index', 'collection', { - and: [ - {equals: {baz: 'qux'}}, - {equals: {foo: 'bar'}} - ] - }); - }) - .then(subscription => { - multiSubfilter = getSubfilter(subscription.id); - - return dsl.remove(idToRemove); - }) - .then(() => { - const equals = dsl.storage.foPairs - .get('index', 'collection', 'equals'); - - should(equals).be.an.instanceof(FieldOperand); - should(equals.fields.get('foo')) - .have.value('bar', new Set([multiSubfilter])); - should(equals.fields.get('baz')) - .have.value('qux', new Set([multiSubfilter])); - }); + const sub1 = dsl.register('index', 'collection', { + equals: {foo: 'bar'}, + }); + + const sub2 = dsl.register('index', 'collection', { + and: [ + {equals: {baz: 'qux'}}, + {equals: {foo: 'bar'}}, + ], + }); + + dsl.remove(sub1.id); + + const equals = dsl.storage.foPairs.get('index', 'collection', 'equals'); + const multiSubfilter = getSubfilter(sub2.id); + + should(equals).be.an.instanceof(FieldOperand); + should(equals.fields.get('foo')) + .have.value('bar', new Set([multiSubfilter])); + should(equals.fields.get('baz')) + .have.value('qux', new Set([multiSubfilter])); }); it('should remove a value from the list if its last subfilter is removed', () => { - let - equals, - barSubfilter; - - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(subscription => { - equals = dsl.storage.foPairs.get('index', 'collection', 'equals'); - - barSubfilter = getSubfilter(subscription.id); - - return dsl.register('index', 'collection', {equals: {foo: 'qux'}}); - }) - .then(subscription => { - should(equals.fields.get('foo').get('bar')).eql(new Set([barSubfilter])); - should(equals.fields.get('foo').get('qux')).eql(new Set([getSubfilter(subscription.id)])); - return dsl.remove(subscription.id); - }) - .then(() => { - should(equals).be.an.instanceof(FieldOperand); - should(equals.fields.get('foo')) - .have.value('bar', new Set([barSubfilter])) - .not.have.key('qux'); - }); + const sub1 = dsl.register('index', 'collection', {equals: {foo: 'bar'}}); + const equals = dsl.storage.foPairs.get('index', 'collection', 'equals'); + const barSubfilter = getSubfilter(sub1.id); + + const sub2 = dsl.register('index', 'collection', {equals: {foo: 'qux'}}); + + should(equals.fields.get('foo').get('bar')).eql(new Set([barSubfilter])); + + should(equals.fields.get('foo').get('qux')) + .eql(new Set([getSubfilter(sub2.id)])); + + dsl.remove(sub2.id); + + should(equals).be.an.instanceof(FieldOperand); + should(equals.fields.get('foo')) + .have.value('bar', new Set([barSubfilter])) + .not.have.key('qux'); }); it('should remove a field from the list if its last value to test is removed', () => { - let - barSubfilter, - equals; - - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(subscription => { - barSubfilter = getSubfilter(subscription.id); - - return dsl.register('index', 'collection', {equals: {baz: 'qux'}}); - }) - .then(subscription => { - equals = dsl.storage.foPairs.get('index', 'collection', 'equals'); - - should(equals.fields.get('baz')) - .have.value('qux', new Set([getSubfilter(subscription.id)])); - - return dsl.remove(subscription.id); - }) - .then(() => { - should(equals).be.an.instanceof(FieldOperand); - should(equals.fields.get('foo')) - .have.value('bar', new Set([barSubfilter])); - should(equals.fields).not.have.key('baz'); - }); + const sub1 = dsl.register('index', 'collection', {equals: {foo: 'bar'}}); + const barSubfilter = getSubfilter(sub1.id); + + const sub2 = dsl.register('index', 'collection', {equals: {baz: 'qux'}}); + const equals = dsl.storage.foPairs.get('index', 'collection', 'equals'); + + should(equals.fields.get('baz')) + .have.value('qux', new Set([getSubfilter(sub2.id)])); + + dsl.remove(sub2.id); + + should(equals).be.an.instanceof(FieldOperand); + + should(equals.fields.get('foo')) + .have.value('bar', new Set([barSubfilter])); + + should(equals.fields).not.have.key('baz'); }); it('should remove a single collection if other collections are registered', () => { - return dsl.register('index', 'collection', {equals: {foo: 'bar'}}) - .then(() => dsl.register('index', 'collection2', {equals: {foo: 'bar'}})) - .then(subscription => { - should(dsl.storage.foPairs.has('index', 'collection')).be.true(); - should(dsl.storage.foPairs.has('index', 'collection2')).be.true(); - return dsl.remove(subscription.id); - }) - .then(() => { - should(dsl.storage.foPairs.has('index', 'collection')).be.true(); - should(dsl.storage.foPairs.has('index', 'collection2')).be.false(); - }); + dsl.register('index', 'collection', {equals: {foo: 'bar'}}); + const sub = dsl.register('index', 'collection2', {equals: {foo: 'bar'}}); + + should(dsl.storage.foPairs.has('index', 'collection')).be.true(); + should(dsl.storage.foPairs.has('index', 'collection2')).be.true(); + + dsl.remove(sub.id); + + should(dsl.storage.foPairs.has('index', 'collection')).be.true(); + should(dsl.storage.foPairs.has('index', 'collection2')).be.false(); }); }); }); diff --git a/test/keywords/everything.test.js b/test/keywords/everything.test.js index ac1b6e0..29a884a 100644 --- a/test/keywords/everything.test.js +++ b/test/keywords/everything.test.js @@ -11,66 +11,63 @@ describe('DSL.keyword.everything', () => { describe('#validation', () => { it('should validate an empty filter', () => { - return should(dsl.validate({})).be.fulfilledWith(); + should(() => dsl.validate({})).not.throw(); }); it('should validate a null filter', () => { - return should(dsl.validate(null)).be.fulfilledWith(); + should(() => dsl.validate(null)).not.throw(); }); it('should validate an undefined filter', () => { - return should(dsl.validate(null)).be.fulfilledWith(); + should(() => dsl.validate(null)).not.throw(); }); }); describe('#storage', () => { it('should register an empty filter correctly', () => { - return dsl.register('index', 'collection', {}) - .then(subscription => { - const storeEntry = dsl.storage.foPairs - .get('index', 'collection', 'everything'); + const sub = dsl.register('index', 'collection', {}); + const storeEntry = dsl.storage.foPairs.get( + 'index', + 'collection', + 'everything'); - should(storeEntry).be.instanceof(FieldOperand); - should(storeEntry.fields).have.value( - 'all', - Array.from(dsl.storage.filters.get(subscription.id).subfilters)); - }); + should(storeEntry).be.instanceof(FieldOperand); + should(storeEntry.fields).have.value( + 'all', + Array.from(dsl.storage.filters.get(sub.id).subfilters)); }); }); describe('#matching', () => { it('should match as long as a document is in the right index and collection', () => { - return dsl.register('index', 'collection', {}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: 'bar'}); + const sub = dsl.register('index', 'collection', {}); + const result = dsl.test('index', 'collection', {foo: 'bar'}); - should(result).be.an.Array().and.not.empty(); - should(result[0]).be.eql(subscription.id); - }); + should(result).be.an.Array().and.not.empty(); + should(result[0]).be.eql(sub.id); }); it('should not match if the document is in another index', () => { - return dsl.register('index', 'collection', {}) - .then(() => { - should(dsl.test('foobar', 'collection', {foo: 'bar'})) - .be.an.Array() - .be.empty(); - }); + dsl.register('index', 'collection', {}); + should(dsl.test('foobar', 'collection', {foo: 'bar'})) + .be.an.Array() + .be.empty(); }); it('should not match if the document is in another collection', () => { - return dsl.register('index', 'collection', {}) - .then(() => should(dsl.test('index', 'foobar', {foo: 'bar'})) - .be.an.Array() - .be.empty()); + dsl.register('index', 'collection', {}); + should(dsl.test('index', 'foobar', {foo: 'bar'})) + .be.an.Array() + .be.empty(); }); }); describe('#removal', () => { it('should remove the whole f-o pair on delete', () => { - return dsl.register('index', 'collection', {}) - .then(subscription => dsl.remove(subscription.id)) - .then(() => should(dsl.storage.foPairs._cache).and.be.empty()); + const sub = dsl.register('index', 'collection', {}); + dsl.remove(sub.id); + + should(dsl.storage.foPairs._cache).and.be.empty(); }); }); }); diff --git a/test/keywords/exists.test.js b/test/keywords/exists.test.js index d9d904c..cd07f8e 100644 --- a/test/keywords/exists.test.js +++ b/test/keywords/exists.test.js @@ -5,86 +5,88 @@ const Koncorde = require('../../'); const NormalizedExists = require('../../lib/transform/normalizedExists'); describe('Koncorde.keyword.exists', () => { - let koncorde; + let dsl; + let filters; beforeEach(() => { - koncorde = new Koncorde(); + dsl = new Koncorde(); + filters = dsl.storage.filters; }); describe('#validation', () => { it('should reject empty filters', () => { - return should(koncorde.validate({exists: {}})) - .be.rejectedWith('"exists" must be a non-empty object'); + should(() => dsl.validate({exists: {}})) + .throw('"exists" must be a non-empty object'); }); it('should reject filters with more than 1 field', () => { - return should(koncorde.validate({exists: {field: 'foo', bar: 'bar'}})) - .be.rejectedWith('"exists" can contain only one attribute'); + should(() => dsl.validate({exists: {field: 'foo', bar: 'bar'}})) + .throw('"exists" can contain only one attribute'); }); it('should reject filters in object-form without a "field" attribute', () => { - return should(koncorde.validate({exists: {foo: 'bar'}})) - .be.rejectedWith('"exists" requires the following attribute: field'); + should(() => dsl.validate({exists: {foo: 'bar'}})) + .throw('"exists" requires the following attribute: field'); }); it('should reject filters with array argument', () => { - return should(koncorde.validate({exists: {field: ['bar']}})) - .be.rejectedWith('Attribute "field" in "exists" must be a string'); + should(() => dsl.validate({exists: {field: ['bar']}})) + .throw('Attribute "field" in "exists" must be a string'); }); it('should reject filters with number argument', () => { - return should(koncorde.validate({exists: {field: 42}})) - .be.rejectedWith('Attribute "field" in "exists" must be a string'); + should(() => dsl.validate({exists: {field: 42}})) + .throw('Attribute "field" in "exists" must be a string'); }); it('should reject filters with object argument', () => { - return should(koncorde.validate({exists: {field: {}}})) - .be.rejectedWith('Attribute "field" in "exists" must be a string'); + should(() => dsl.validate({exists: {field: {}}})) + .throw('Attribute "field" in "exists" must be a string'); }); it('should reject filters with undefined argument', () => { - return should(koncorde.validate({exists: {field: undefined}})) - .be.rejectedWith('"exists" requires the following attribute: field'); + should(() => dsl.validate({exists: {field: undefined}})) + .throw('"exists" requires the following attribute: field'); }); it('should reject filters with null argument', () => { - return should(koncorde.validate({exists: {field: null}})) - .be.rejectedWith('Attribute "field" in "exists" must be a string'); + should(() => dsl.validate({exists: {field: null}})) + .throw('Attribute "field" in "exists" must be a string'); }); it('should reject filters with boolean argument', () => { - return should(koncorde.validate({exists: {field: true}})) - .be.rejectedWith('Attribute "field" in "exists" must be a string'); + should(() => dsl.validate({exists: {field: true}})) + .throw('Attribute "field" in "exists" must be a string'); }); it('should validate filters with a string argument', () => { - return should(koncorde.validate({exists: {field: 'bar'}})) - .be.fulfilled(); + should(() => dsl.validate({exists: {field: 'bar'}})) + .not.throw(); }); it('should reject filters with an empty string argument', () => { - return should(koncorde.validate({exists: {field: ''}})) - .be.rejectedWith('exists: cannot test empty field name'); + should(() => dsl.validate({exists: {field: ''}})) + .throw('exists: cannot test empty field name'); }); it('should validate filters written in simplified form', () => { - return should(koncorde.validate({exists: 'bar'})).fulfilled(); + should(() => dsl.validate({exists: 'bar'})).not.throw(); }); it('should reject a filter in simplified form with an empty value', () => { - return should(koncorde.validate({exists: ''})) - .rejectedWith('exists: cannot test empty field name'); + should(() => dsl.validate({exists: ''})) + .throw('exists: cannot test empty field name'); }); it('should reject incorrectly formatted array search filters', () => { - return should(koncorde.validate({exists: 'foo[\'bar\']'})) - .rejectedWith('[exists] Invalid array value "\'bar\'"'); + should(() => dsl.validate({exists: 'foo[\'bar\']'})) + .throw('[exists] Invalid array value "\'bar\'"'); }); }); describe('#standardization', () => { it('should return the normalized filter (from old syntax)', () => { - const result = koncorde.transformer.standardizer.standardize({ + const result = dsl.transformer.standardizer.standardize({ exists: { field: 'bar' }, }); @@ -92,7 +94,7 @@ describe('Koncorde.keyword.exists', () => { }); it('should return the normalized filter (from simplified syntax)', () => { - const result = koncorde.transformer.standardizer.standardize({ + const result = dsl.transformer.standardizer.standardize({ exists: 'bar', }); should(result).match({exists: new NormalizedExists('bar', false, null)}); @@ -112,7 +114,7 @@ describe('Koncorde.keyword.exists', () => { ]; for (const value of values) { - const result = koncorde.transformer.standardizer.standardize({ + const result = dsl.transformer.standardizer.standardize({ exists: `foo.bar[${value}]`, }); @@ -129,7 +131,7 @@ describe('Koncorde.keyword.exists', () => { }); it('should not interpret unclosed brackets as an array value', () => { - const res = koncorde.transformer.standardizer.standardize({ + const res = dsl.transformer.standardizer.standardize({ exists: 'foo[bar' }); @@ -139,7 +141,7 @@ describe('Koncorde.keyword.exists', () => { }); it('should properly interpret escaped brackets as an object field name', () => { - const res = koncorde.transformer.standardizer.standardize({ + const res = dsl.transformer.standardizer.standardize({ exists: 'foo.ba\\[true\\]' }); @@ -151,359 +153,282 @@ describe('Koncorde.keyword.exists', () => { describe('#storage', () => { it('should store a single condition correctly', () => { - return koncorde.register('index', 'collection', {exists: 'foo'}) - .then(subscription => { - const - subfilter = koncorde.storage.filters.get(subscription.id).subfilters, - storage = koncorde.storage.foPairs.get('index', 'collection', 'exists'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').subfilters).eql(subfilter); - should(storage.fields.get('foo').values).instanceOf(Map); - should(storage.fields.get('foo').values.size).eql(0); - }); + const sub = dsl.register('index', 'collection', {exists: 'foo'}); + const subfilter = dsl.storage.filters.get(sub.id).subfilters; + const storage = dsl.storage.foPairs.get('index', 'collection', 'exists'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').subfilters).eql(subfilter); + should(storage.fields.get('foo').values).instanceOf(Map); + should(storage.fields.get('foo').values.size).eql(0); }); it('should store multiple subfilters on the same condition correctly', () => { - const filters = koncorde.storage.filters; - let barSubfilter; - - return koncorde.register('index', 'collection', {exists: 'foo'}) - .then(subscription => { - barSubfilter = Array.from(filters.get(subscription.id).subfilters)[0]; - - return koncorde.register('index', 'collection', { - and: [ - {equals: {bar: 'qux'}}, - {exists: 'foo'} - ] - }); - }) - .then(subscription => { - const - quxSubfilter = Array.from( - filters.get(subscription.id).subfilters)[0], - storage = koncorde.storage.foPairs.get('index', 'collection', 'exists'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').subfilters) - .eql(new Set([barSubfilter, quxSubfilter])); - should(storage.fields.get('foo').values).instanceOf(Map); - should(storage.fields.get('foo').values.size).eql(0); - }); + const sub1 = dsl.register('index', 'collection', {exists: 'foo'}); + const sub2 = dsl.register('index', 'collection', { + and: [ + {equals: {bar: 'qux'}}, + {exists: 'foo'} + ] + }); + + const storage = dsl.storage.foPairs.get('index', 'collection', 'exists'); + + should(storage).be.instanceOf(FieldOperand); + + const barSubfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + const quxSubfilter = Array.from(filters.get(sub2.id).subfilters)[0]; + should(storage.fields.get('foo').subfilters) + .eql(new Set([barSubfilter, quxSubfilter])); + + should(storage.fields.get('foo').values).instanceOf(Map); + should(storage.fields.get('foo').values.size).eql(0); }); it('should store a single array search correctly', () => { - return koncorde.register('index', 'collection', {exists: 'foo["bar"]'}) - .then(subscription => { - const - subfilter = Array.from( - koncorde.storage.filters.get(subscription.id).subfilters)[0], - storage = koncorde.storage.foPairs.get('index', 'collection', 'exists'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').subfilters.size).eql(0); - should(storage.fields.get('foo').values).instanceOf(Map); - should(storage.fields.get('foo').values.size).eql(1); - should(storage.fields.get('foo').values.get('bar')) - .eql(new Set([subfilter])); - }); + const sub = dsl.register('index', 'collection', {exists: 'foo["bar"]'}); + const subfilter = Array.from(filters.get(sub.id).subfilters)[0]; + const storage = dsl.storage.foPairs.get('index', 'collection', 'exists'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').subfilters.size).eql(0); + should(storage.fields.get('foo').values).instanceOf(Map); + should(storage.fields.get('foo').values.size).eql(1); + should(storage.fields.get('foo').values.get('bar')) + .eql(new Set([subfilter])); }); it('should multiple array searches correctly', () => { - let barSubfilter; - - return koncorde.register('index', 'collection', {exists: 'foo["bar"]'}) - .then(subscription => { - barSubfilter = Array.from( - koncorde.storage.filters.get(subscription.id).subfilters)[0]; - - return koncorde.register('index', 'collection', { - and: [ - {exists: 'qux["bar"]'}, - {exists: 'foo["bar"]'} - ] - }); - }) - .then(subscription => { - const - quxSubfilter = Array.from( - koncorde.storage.filters.get(subscription.id).subfilters)[0], - storage = koncorde.storage.foPairs.get('index', 'collection', 'exists'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').subfilters.size).eql(0); - should(storage.fields.get('foo').values).instanceOf(Map); - should(storage.fields.get('foo').values.size).eql(1); - should(storage.fields.get('foo').values.get('bar')) - .eql(new Set([barSubfilter, quxSubfilter])); - should(storage.fields.get('qux').values.get('bar')) - .eql(new Set([quxSubfilter])); - }); + const sub1 = dsl.register('index', 'collection', {exists: 'foo["bar"]'}); + + const sub2 = dsl.register('index', 'collection', { + and: [ + {exists: 'qux["bar"]'}, + {exists: 'foo["bar"]'} + ] + }); + + const storage = dsl.storage.foPairs.get('index', 'collection', 'exists'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').subfilters.size).eql(0); + should(storage.fields.get('foo').values).instanceOf(Map); + should(storage.fields.get('foo').values.size).eql(1); + + const barSubfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + const quxSubfilter = Array.from(filters.get(sub2.id).subfilters)[0]; + should(storage.fields.get('foo').values.get('bar')) + .eql(new Set([barSubfilter, quxSubfilter])); + + should(storage.fields.get('qux').values.get('bar')) + .eql(new Set([quxSubfilter])); }); }); describe('#matching', () => { it('should match a document with the subscribed field', () => { - return koncorde.register('index', 'collection', {exists: 'foo'}) - .then(subscription => { - const result = koncorde.test('index', 'collection', {foo: 'bar'}); + const sub = dsl.register('index', 'collection', {exists: 'foo'}); + const result = dsl.test('index', 'collection', {foo: 'bar'}); - should(result).eql([subscription.id]); - }); + should(result).eql([sub.id]); }); it('should not match if the document does not contain the searched field', () => { - return koncorde.register('index', 'collection', {exists: 'foo'}) - .then(() => { - should(koncorde.test('index', 'collection', {fooo: 'baz'})) - .be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {exists: 'foo'}); + should(dsl.test('index', 'collection', {fooo: 'baz'})) + .be.an.Array().and.empty(); }); it('should match a document with the subscribed nested keyword', () => { - return koncorde.register('index', 'collection', {exists: 'foo.bar.baz'}) - .then(subscription => { - const result = koncorde.test( - 'index', 'collection', {foo: {bar: {baz: 'qux'}}}); + const sub = dsl.register('index', 'collection', {exists: 'foo.bar.baz'}); + const result = dsl.test('index', 'collection', {foo: {bar: {baz: 'qux'}}}); - should(result).eql([subscription.id]); - }); + should(result).eql([sub.id]); }); it('should not match if the document is in another index', () => { - return koncorde.register('index', 'collection', {exists: 'foo'}) - .then(() => { - should(koncorde.test('foobar', 'collection', {foo: 'qux'})) - .be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {exists: 'foo'}); + should(dsl.test('foobar', 'collection', {foo: 'qux'})) + .be.an.Array().and.empty(); }); it('should not match if the document is in another collection', () => { - return koncorde.register('index', 'collection', {exists: 'foo'}) - .then(() => { - should(koncorde.test('index', 'foobar', {foo: 'qux'})) - .be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {exists: 'foo'}); + should(dsl.test('index', 'foobar', {foo: 'qux'})) + .be.an.Array().and.empty(); }); it('should match if a searched value is in the document', () => { - const - values = ['"foo"', '"bar"', 3.14, 42, false, true, null], - promises = values.map( - v => koncorde.register('i', 'c', {exists: `foo[${v}]`})); - - return Promise.all(promises) - .then(subscriptions => { - for (let i = 0; i < subscriptions.length; i++) { - const expected = typeof values[i] === 'string' ? - values[i].replace(/"/g, '') : - values[i]; - - should(koncorde.test('i', 'c', {foo: ['hello', expected, 'world']})) - .eql([subscriptions[i].id]); - } - }); + const values = ['"foo"', '"bar"', 3.14, 42, false, true, null]; + const subscriptions = values + .map(v => dsl.register('i', 'c', {exists: `foo[${v}]`})); + + for (let i = 0; i < subscriptions.length; i++) { + const expected = typeof values[i] === 'string' + ? values[i].replace(/"/g, '') + : values[i]; + + should(dsl.test('i', 'c', {foo: ['hello', expected, 'world']})) + .eql([subscriptions[i].id]); + } }); it('should not match if an array search is not of the right type', () => { - return koncorde.register('i', 'c', {exists: 'foo[null]'}) - .then(subscription => { - should(koncorde.test('i', 'c', {foo: [null]})).eql([subscription.id]); - should(koncorde.test('i', 'c', {foo: ['null']})).empty(); - }); + const sub = dsl.register('i', 'c', {exists: 'foo[null]'}); + should(dsl.test('i', 'c', {foo: [null]})).eql([sub.id]); + should(dsl.test('i', 'c', {foo: ['null']})).empty(); }); it('(see issue #24) should handle duplicates gracefully', () => { - const filters = { + dsl.register('index', 'collection', { and: [ { equals: { name: 'Leo' } }, - { exists: 'skills.languages["javascript"]' } - ] - }; - - return koncorde.register('index', 'collection', filters) - .then(() => { - const matches = koncorde.test('index', 'collection', { - name: 'Bob', - skills: { - languages: ['pascal', 'javascript', 'python', 'javascript'] - } - }); - - should(matches).be.an.Array().and.empty(); - }); + { exists: 'skills.languages["javascript"]' }, + ], + }); + + const matches = dsl.test('index', 'collection', { + name: 'Bob', + skills: { + languages: ['pascal', 'javascript', 'python', 'javascript'] + } + }); + + should(matches).be.an.Array().and.empty(); }); }); describe('#removal', () => { it('should destroy the whole structure when removing the last item', () => { - return koncorde.register('index', 'collection', {exists: 'foo'}) - .then(subscription => koncorde.remove(subscription.id)) - .then(() => should(koncorde.storage.foPairs._cache).be.empty()); + const sub = dsl.register('index', 'collection', {exists: 'foo'}); + + dsl.remove(sub.id); + should(dsl.storage.foPairs._cache).be.empty(); }); it('should remove a single subfilter from a multi-filter condition', () => { - let - idToRemove, - multiSubfilter; - - return koncorde.register('index', 'collection', {exists: 'foo'}) - .then(subscription => { - idToRemove = subscription.id; - - return koncorde.register('index', 'collection', { - and: [ - {equals: {foo: 'qux'}}, - {exists: {field: 'foo'}} - ] - }); - }) - .then(subscription => { - multiSubfilter = Array.from(koncorde.storage.filters.get(subscription.id).subfilters)[0]; - - return koncorde.remove(idToRemove); - }) - .then(() => { - const storage = koncorde.storage.foPairs.get('index', 'collection', 'exists'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').subfilters) - .match(new Set([multiSubfilter])); - should(storage.fields.get('foo').values).be.instanceOf(Map); - should(storage.fields.get('foo').values.size).eql(0); - }); + const sub1 = dsl.register('index', 'collection', {exists: 'foo'}); + + const sub2 = dsl.register('index', 'collection', { + and: [ + {equals: {foo: 'qux'}}, + {exists: {field: 'foo'}}, + ], + }); + + + dsl.remove(sub1.id); + + const storage = dsl.storage.foPairs.get('index', 'collection', 'exists'); + + should(storage).be.instanceOf(FieldOperand); + + const multiSubfilter = Array.from(filters.get(sub2.id).subfilters)[0]; + should(storage.fields.get('foo').subfilters) + .match(new Set([multiSubfilter])); + + should(storage.fields.get('foo').values).be.instanceOf(Map); + should(storage.fields.get('foo').values.size).eql(0); }); it('should remove a single subfilter from a multi-filter array condition', () => { - let - storage, - idToRemove, - singleSubfilter, - multiSubfilter; - - return koncorde.register('index', 'collection', {exists: 'foo["bar"]'}) - .then(subscription => { - idToRemove = subscription.id; - storage = koncorde.storage.foPairs.get('index', 'collection', 'exists'); - singleSubfilter = Array.from(koncorde.storage.filters.get(subscription.id).subfilters)[0]; - - return koncorde.register('index', 'collection', { - and: [ - {equals: {foo: 'qux'}}, - {exists: {field: 'foo["bar"]'}} - ] - }); - }) - .then(subscription => { - multiSubfilter = Array.from( - koncorde.storage.filters.get(subscription.id).subfilters)[0]; - should(storage.fields.get('foo').values.get('bar')) - .match(new Set([singleSubfilter, multiSubfilter])); - should(storage.fields.get('foo').subfilters.size).eql(0); - return koncorde.remove(idToRemove); - }) - .then(() => { - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').subfilters.size).eql(0); - should(storage.fields.get('foo').values.get('bar')) - .match(new Set([multiSubfilter])); - }); + const sub1 = dsl.register('index', 'collection', {exists: 'foo["bar"]'}); + const storage = dsl.storage.foPairs.get('index', 'collection', 'exists'); + + const sub2 = dsl.register('index', 'collection', { + and: [ + {equals: {foo: 'qux'}}, + {exists: {field: 'foo["bar"]'}}, + ], + }); + + const singleSubfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + const multiSubfilter = Array.from(filters.get(sub2.id).subfilters)[0]; + should(storage.fields.get('foo').values.get('bar')) + .match(new Set([singleSubfilter, multiSubfilter])); + + should(storage.fields.get('foo').subfilters.size).eql(0); + + dsl.remove(sub1.id); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').subfilters.size).eql(0); + should(storage.fields.get('foo').values.get('bar')) + .match(new Set([multiSubfilter])); }); it('should remove a field from the list if its last subfilter is removed', () => { - let - fooSubfilter; - - return koncorde.register('index', 'collection', {exists: 'foo'}) - .then(subscription => { - fooSubfilter = Array.from(koncorde.storage.filters.get(subscription.id).subfilters)[0]; - - return koncorde.register('index', 'collection', {exists: 'bar'}); - }) - .then(subscription => { - const operand = koncorde.storage.foPairs - .get('index', 'collection', 'exists'); - - should(operand.fields).have.keys('foo', 'bar'); - return koncorde.remove(subscription.id); - }) - .then(() => { - const storage = koncorde.storage.foPairs.get('index', 'collection', 'exists'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').subfilters) - .match(new Set([fooSubfilter])); - should(storage.fields.get('foo').values).be.instanceOf(Map); - should(storage.fields.get('foo').values.size).eql(0); - should(storage.fields.get('bar')).be.undefined(); - }); + const sub1 = dsl.register('index', 'collection', {exists: 'foo'}); + const sub2 = dsl.register('index', 'collection', {exists: 'bar'}); + const operand = dsl.storage.foPairs.get('index', 'collection', 'exists'); + + should(operand.fields).have.keys('foo', 'bar'); + dsl.remove(sub2.id); + + const storage = dsl.storage.foPairs.get('index', 'collection', 'exists'); + + should(storage).be.instanceOf(FieldOperand); + + const fooSubfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + should(storage.fields.get('foo').subfilters) + .match(new Set([fooSubfilter])); + + should(storage.fields.get('foo').values).be.instanceOf(Map); + should(storage.fields.get('foo').values.size).eql(0); + should(storage.fields.get('bar')).be.undefined(); }); it('should remove a field from the list if its last array search value is removed', () => { - let - fooSubfilter; - - return koncorde.register('index', 'collection', {exists: 'foo'}) - .then(subscription => { - fooSubfilter = Array.from(koncorde.storage.filters.get(subscription.id).subfilters)[0]; - - return koncorde.register('index', 'collection', {exists: 'bar["foo"]'}); - }) - .then(subscription => koncorde.remove(subscription.id)) - .then(() => { - const storage = koncorde.storage.foPairs.get('index', 'collection', 'exists'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').subfilters).match(new Set([fooSubfilter])); - should(storage.fields.get('foo').values).be.instanceOf(Map); - should(storage.fields.get('foo').values.size).eql(0); - should(storage.fields.get('bar')).be.undefined(); - }); + const sub1 = dsl.register('index', 'collection', {exists: 'foo'}); + const sub2 = dsl.register('index', 'collection', {exists: 'bar["foo"]'}); + + dsl.remove(sub2.id); + + const storage = dsl.storage.foPairs.get('index', 'collection', 'exists'); + + should(storage).be.instanceOf(FieldOperand); + + const fooSubfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + should(storage.fields.get('foo').subfilters).match(new Set([fooSubfilter])); + + should(storage.fields.get('foo').values).be.instanceOf(Map); + should(storage.fields.get('foo').values.size).eql(0); + should(storage.fields.get('bar')).be.undefined(); }); it('should keep a field if a field existence test remains', () => { - let - fooSubfilter; - - return koncorde.register('index', 'collection', {exists: 'foo'}) - .then(subscription => { - fooSubfilter = Array.from(koncorde.storage.filters.get(subscription.id).subfilters)[0]; - - return koncorde.register('index', 'collection', {exists: 'foo["bar"]'}); - }) - .then(subscription => koncorde.remove(subscription.id)) - .then(() => { - const storage = koncorde.storage.foPairs.get('index', 'collection', 'exists'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').subfilters).match(new Set([fooSubfilter])); - should(storage.fields.get('foo').values).be.instanceOf(Map); - should(storage.fields.get('foo').values.size).eql(0); - }); + const sub1 = dsl.register('index', 'collection', {exists: 'foo'}); + const sub2 = dsl.register('index', 'collection', {exists: 'foo["bar"]'}); + + dsl.remove(sub2.id); + + const storage = dsl.storage.foPairs.get('index', 'collection', 'exists'); + + should(storage).be.instanceOf(FieldOperand); + + const fooSubfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + should(storage.fields.get('foo').subfilters).match(new Set([fooSubfilter])); + + should(storage.fields.get('foo').values).be.instanceOf(Map); + should(storage.fields.get('foo').values.size).eql(0); }); it('should keep a field if an array search test remains', () => { - let - fooSubfilter; - - return koncorde.register('index', 'collection', {exists: 'foo["bar"]'}) - .then(subscription => { - fooSubfilter = Array.from(koncorde.storage.filters.get(subscription.id).subfilters)[0]; - - return koncorde.register('index', 'collection', {exists: 'foo'}); - }) - .then(subscription => koncorde.remove(subscription.id)) - .then(() => { - const storage = koncorde.storage.foPairs.get('index', 'collection', 'exists'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').subfilters.size).eql(0); - should(storage.fields.get('foo').values).be.instanceOf(Map); - should(storage.fields.get('foo').values.size).eql(1); - should(storage.fields.get('foo').values.get('bar')) - .eql(new Set([fooSubfilter])); - }); + const sub1 = dsl.register('index', 'collection', {exists: 'foo["bar"]'}); + const sub2 = dsl.register('index', 'collection', {exists: 'foo'}); + + dsl.remove(sub2.id); + + const storage = dsl.storage.foPairs.get('index', 'collection', 'exists'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').subfilters.size).eql(0); + should(storage.fields.get('foo').values).be.instanceOf(Map); + should(storage.fields.get('foo').values.size).eql(1); + + const fooSubfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + should(storage.fields.get('foo').values.get('bar')) + .eql(new Set([fooSubfilter])); }); }); }); diff --git a/test/keywords/geoBoundingBox.test.js b/test/keywords/geoBoundingBox.test.js index bbe12d9..bdd62c4 100644 --- a/test/keywords/geoBoundingBox.test.js +++ b/test/keywords/geoBoundingBox.test.js @@ -5,6 +5,8 @@ const DSL = require('../../'); describe('DSL.keyword.geoBoundingBox', () => { let dsl; + let filters; + let foPairs; let standardize; const bbox = { topLeft: { lat: 43.6331979, lon: 3.8433703 }, @@ -25,6 +27,8 @@ describe('DSL.keyword.geoBoundingBox', () => { beforeEach(() => { dsl = new DSL(); + filters = dsl.storage.filters; + foPairs = dsl.storage.foPairs; standardize = dsl.transformer.standardizer.standardize.bind(dsl.transformer.standardizer); }); @@ -195,126 +199,156 @@ describe('DSL.keyword.geoBoundingBox', () => { describe('#storage', () => { it('should store a single geoBoundingBox correctly', () => { - return dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}) - .then(subscription => { - const - subfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo')).have.value( - Array.from(subfilter.conditions)[0].id, - new Set([subfilter])); - }); + const sub = dsl.register('index', 'collection', { + geoBoundingBox: { foo: bbox }, + }); + const subfilter = Array.from(filters.get(sub.id).subfilters)[0]; + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo')).have.value( + Array.from(subfilter.conditions)[0].id, + new Set([subfilter])); }); it('should add a subfilter to an already existing condition', () => { - let sf1; - return dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}) - .then(subscription => { - sf1 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - return dsl.register('index', 'collection', {and: [{geoBoundingBox: {foo: bbox}}, {equals: {foo: 'bar'}}]}); - }) - .then(subscription => { - const - sf2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo')).have.value( - Array.from(sf1.conditions)[0].id, - new Set([sf1, sf2])); - }); + const sub1 = dsl.register('index', 'collection', { + geoBoundingBox: { foo: bbox }, + }); + + const sub2 = dsl.register('index', 'collection', { + and: [ + { geoBoundingBox: { foo: bbox } }, + { equals: { foo: 'bar' } }, + ], + }); + + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage).be.instanceOf(FieldOperand); + + const sf1 = Array.from(filters.get(sub1.id).subfilters)[0]; + const sf2 = Array.from(filters.get(sub2.id).subfilters)[0]; + should(storage.fields.get('foo')).have.value( + Array.from(sf1.conditions)[0].id, + new Set([sf1, sf2])); }); it('should add another condition to an already existing field', () => { - let cond1, sf1; - - return dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}) - .then(subscription => { - sf1 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - cond1 = Array.from(sf1.conditions)[0].id; - return dsl.register('index', 'collection', {geoBoundingBox: {foo: {topLeft: 'dr5r9ydj2y73', bottomRight: 'drj7teegpus6'}}}); - }) - .then(subscription => { - const - sf2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(cond1)).match(new Set([sf1])); - should(storage.fields.get('foo').get(Array.from(sf2.conditions)[0].id)).match(new Set([sf2])); - }); + const sub1 = dsl.register('index', 'collection', { + geoBoundingBox: {foo: bbox}, + }); + + const sub2 = dsl.register('index', 'collection', { + geoBoundingBox: { + foo: { + bottomRight: 'drj7teegpus6', + topLeft: 'dr5r9ydj2y73', + }, + }, + }); + + const sf1 = Array.from(filters.get(sub1.id).subfilters)[0]; + const sf2 = Array.from(filters.get(sub2.id).subfilters)[0]; + const cond1 = Array.from(sf1.conditions)[0].id; + const cond2 = Array.from(sf2.conditions)[0].id; + + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(cond1)).match(new Set([sf1])); + should(storage.fields.get('foo').get(cond2)).match(new Set([sf2])); }); }); describe('#matching', () => { it('should match a point inside the bbox', () => { - return dsl - .register('index', 'collection', { geoBoundingBox: { foo: bbox } }) - .then(subscription => { - const result = dsl.test('index', 'collection', { - foo: { - latLon: [ 43.6073913, 3.9109057 ] - } - }); - - should(result).eql([subscription.id]); - }); + const sub = dsl.register('index', 'collection', { + geoBoundingBox: { foo: bbox }, + }); + + const result = dsl.test('index', 'collection', { + foo: { + latLon: [ 43.6073913, 3.9109057 ] + } + }); + + should(result).eql([sub.id]); }); it('should convert points to float before trying to match them', () => { - return dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: {latLon: ['43.6073913', '3.9109057']}}); + const sub = dsl.register('index', 'collection', { + geoBoundingBox: { foo: bbox }, + }); + + const result = dsl.test('index', 'collection', { + foo: { + latLon: ['43.6073913', '3.9109057'], + }, + }); - should(result).eql([subscription.id]); - }); + should(result).eql([sub.id]); }); it('should match a point exactly on a bbox corner', () => { - return dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: bbox.topLeft}); + const sub = dsl.register('index', 'collection', { + geoBoundingBox: { foo: bbox }, + }); + + const result = dsl.test('index', 'collection', {foo: bbox.topLeft}); - should(result).eql([subscription.id]); - }); + should(result).eql([sub.id]); }); it('should match a point on one of the bbox border', () => { - return dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: {lat: bbox.topLeft.lat, lon: 3.9}}); + const sub = dsl.register('index', 'collection', { + geoBoundingBox: { foo: bbox }, + }); + + const result = dsl.test('index', 'collection', { + foo: { + lat: bbox.topLeft.lat, + lon: 3.9, + }, + }); - should(result).eql([subscription.id]); - }); + should(result).eql([sub.id]); }); it('should not match if a point is outside the bbox', () => { - return dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}) - .then(() => { - const result = dsl.test('index', 'collection', {foo: {lat: bbox.topLeft.lat + 10e-6, lon: 3.9}}); + dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}); + + const result = dsl.test('index', 'collection', { + foo: { + lat: bbox.topLeft.lat + 10e-6, + lon: 3.9, + }, + }); - should(result).be.an.Array().and.be.empty(); - }); + should(result).be.an.Array().and.be.empty(); }); it('should return an empty array if the document does not contain a geopoint', () => { - return dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}) - .then(() => { - const result = dsl.test('index', 'collection', {bar: {lat: bbox.topLeft.lat + 10e-6, lon: 3.9}}); + dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}); - should(result).be.an.Array().and.be.empty(); - }); + const result = dsl.test('index', 'collection', { + bar: { + lat: bbox.topLeft.lat + 10e-6, + lon: 3.9, + }, + }); + + should(result).be.an.Array().and.be.empty(); }); it('should return an empty array if the document contain an invalid geopoint', () => { - return dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}) - .then(() => { - const result = dsl.test('index', 'collection', {foo: '43.6331979 / 3.8433703'}); + dsl.register('index', 'collection', {geoBoundingBox: {foo: bbox}}); + + const result = dsl.test('index', 'collection', { + foo: '43.6331979 / 3.8433703', + }); - should(result).be.an.Array().and.be.empty(); - }); + should(result).be.an.Array().and.be.empty(); }); }); }); diff --git a/test/keywords/geoDistance.test.js b/test/keywords/geoDistance.test.js index 6c0899e..b2fc055 100644 --- a/test/keywords/geoDistance.test.js +++ b/test/keywords/geoDistance.test.js @@ -5,6 +5,8 @@ const DSL = require('../../'); describe('DSL.keyword.geoDistance', () => { let dsl; + let filters; + let foPairs; let standardize; const point = { lat: 43.6331979, lon: 3.8433703 }; const distanceStandardized = { @@ -21,6 +23,8 @@ describe('DSL.keyword.geoDistance', () => { beforeEach(() => { dsl = new DSL(); + filters = dsl.storage.filters; + foPairs = dsl.storage.foPairs; standardize = dsl.transformer.standardizer.standardize.bind(dsl.transformer.standardizer); }); @@ -149,90 +153,136 @@ describe('DSL.keyword.geoDistance', () => { describe('#storage', () => { it('should store a single geoDistance correctly', () => { - return dsl.register('index', 'collection', {geoDistance: {foo: point, distance: '1km'}}) - .then(subscription => { - const - subfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(Array.from(subfilter.conditions)[0].id)).match(new Set([subfilter])); - }); + const sub = dsl.register('index', 'collection', { + geoDistance: { + distance: '1km', + foo: point, + }, + }); + + const subfilter = Array.from(filters.get(sub.id).subfilters)[0]; + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage).be.instanceOf(FieldOperand); + const sfs = storage.fields + .get('foo') + .get(Array.from(subfilter.conditions)[0].id); + + should(sfs).match(new Set([subfilter])); }); it('should add a subfilter to an already existing condition', () => { - let sf1; - return dsl.register('index', 'collection', {geoDistance: {foo: point, distance: '1km'}}) - .then(subscription => { - sf1 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - return dsl.register('index', 'collection', {and: [{geoDistance: {foo: point, distance: '1km'}}, {equals: {foo: 'bar'}}]}); - }) - .then(subscription => { - const - sf2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(Array.from(sf1.conditions)[0].id)).match(new Set([sf1, sf2])); - }); + const sub1 = dsl.register('index', 'collection', { + geoDistance: { + distance: '1km', + foo: point, + }, + }); + const sub2 = dsl.register('index', 'collection', { + and: [ + { geoDistance: { foo: point, distance: '1km' } }, + { equals: { foo: 'bar' } }, + ], + }); + + const sf1 = Array.from(filters.get(sub1.id).subfilters)[0]; + const sf2 = Array.from(filters.get(sub2.id).subfilters)[0]; + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(Array.from(sf1.conditions)[0].id)) + .match(new Set([sf1, sf2])); }); it('should add another condition to an already existing field', () => { - let cond1, sf1; - - return dsl.register('index', 'collection', {geoDistance: {foo: point, distance: '1km'}}) - .then(subscription => { - sf1 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - cond1 = Array.from(sf1.conditions)[0].id; - return dsl.register('index', 'collection', {geoDistance: {foo: point, distance: '10km'}}); - }) - .then(subscription => { - const - sf2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(cond1)).match(new Set([sf1])); - should(storage.fields.get('foo').get(Array.from(sf2.conditions)[0].id)).match(new Set([sf2])); - }); + const sub1 = dsl.register('index', 'collection', { + geoDistance: { + distance: '1km', + foo: point, + }, + }); + const sub2 = dsl.register('index', 'collection', { + geoDistance: { + distance: '10km', + foo: point, + }, + }); + + const sf1 = Array.from(filters.get(sub1.id).subfilters)[0]; + const cond1 = Array.from(sf1.conditions)[0].id; + const sf2 = Array.from(filters.get(sub2.id).subfilters)[0]; + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(cond1)).match(new Set([sf1])); + should(storage.fields.get('foo').get(Array.from(sf2.conditions)[0].id)) + .match(new Set([sf2])); }); }); describe('#matching', () => { it('should match a point inside the circle', () => { - return dsl.register('index', 'collection', {geoDistance: {foo: point, distance: '1km'}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: {lat: 43.634, lon: 3.8432 }}); + const sub = dsl.register('index', 'collection', { + geoDistance: { + foo: point, + distance: '1km', + }, + }); + + const result = dsl.test('index', 'collection', { + foo: { + lat: 43.634, + lon: 3.8432, + }, + }); - should(result).eql([subscription.id]); - }); + should(result).eql([sub.id]); }); it('should not match if a point is outside the circle', () => { - return dsl.register('index', 'collection', {geoDistance: {foo: point, distance: '1km'}}) - .then(() => { - const result = dsl.test('index', 'collection', {foo: {lat: point.lat, lon: 3.9}}); + dsl.register('index', 'collection', { + geoDistance: { + distance: '1km', + foo: point, + }, + }); + + const result = dsl.test('index', 'collection', { + foo: { + lat: point.lat, + lon: 3.9, + }, + }); - should(result).be.an.Array().and.be.empty(); - }); + should(result).be.an.Array().and.be.empty(); }); it('should return an empty array if the document does not contain the searched geopoint', () => { - return dsl.register('index', 'collection', {geoDistance: {foo: point, distance: '1km'}}) - .then(() => { - const result = dsl.test('index', 'collection', {bar: point}); + dsl.register('index', 'collection', { + geoDistance: { + distance: '1km', + foo: point, + }, + }); - should(result).be.an.Array().and.be.empty(); - }); + const result = dsl.test('index', 'collection', {bar: point}); + + should(result).be.an.Array().and.be.empty(); }); it('should return an empty array if the document contain an invalid geopoint', () => { - return dsl.register('index', 'collection', {geoDistance: {foo: point, distance: '1km'}}) - .then(() => { - const result = dsl.test('index', 'collection', {foo: '43.6331979 / 3.8433703'}); - - should(result).be.an.Array().and.be.empty(); - }); + dsl.register('index', 'collection', { + geoDistance: { + distance: '1km', + foo: point, + }, + }); + + const result = dsl.test('index', 'collection', { + foo: '43.6331979 / 3.8433703', + }); + + should(result).be.an.Array().and.be.empty(); }); }); }); diff --git a/test/keywords/geoDistanceRange.test.js b/test/keywords/geoDistanceRange.test.js index 1392ddb..398d704 100644 --- a/test/keywords/geoDistanceRange.test.js +++ b/test/keywords/geoDistanceRange.test.js @@ -5,6 +5,8 @@ const DSL = require('../../'); describe('DSL.keyword.geoDistanceRange', () => { let dsl; + let filters; + let foPairs; let standardize; const point = { lat: 43.6331979, lon: 3.8433703 }; const distanceStandardized = { @@ -22,7 +24,10 @@ describe('DSL.keyword.geoDistanceRange', () => { beforeEach(() => { dsl = new DSL(); - standardize = dsl.transformer.standardizer.standardize.bind(dsl.transformer.standardizer); + filters = dsl.storage.filters; + foPairs = dsl.storage.foPairs; + standardize = dsl.transformer.standardizer.standardize + .bind(dsl.transformer.standardizer); }); describe('#validation/standardization', () => { @@ -199,99 +204,157 @@ describe('DSL.keyword.geoDistanceRange', () => { describe('#storage', () => { it('should store a single geoDistanceRange correctly', () => { - return dsl.register('index', 'collection', {geoDistanceRange: {foo: point, from: '1km', to: '10km'}}) - .then(subscription => { - const - subfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(Array.from(subfilter.conditions)[0].id)).match(new Set([subfilter])); - }); + const sub = dsl.register('index', 'collection', { + geoDistanceRange: { + foo: point, + from: '1km', + to: '10km', + }, + }); + + const subfilter = Array.from(filters.get(sub.id).subfilters)[0]; + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(Array.from(subfilter.conditions)[0].id)) + .match(new Set([subfilter])); }); it('should add a subfilter to an already existing condition', () => { - let sf1; - return dsl.register('index', 'collection', {geoDistanceRange: {foo: point, from: '1km', to: '10km'}}) - .then(subscription => { - sf1 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - return dsl.register('index', 'collection', {and: [{geoDistanceRange: {foo: point, from: '1km', to: '10km'}}, {equals: {foo: 'bar'}}]}); - }) - .then(subscription => { - const - sf2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(Array.from(sf1.conditions)[0].id)).match(new Set([sf1, sf2])); - }); + const sub1 = dsl.register('index', 'collection', { + geoDistanceRange: { + foo: point, + from: '1km', + to: '10km', + }, + }); + + const sub2 = dsl.register('index', 'collection', { + and: [ + { geoDistanceRange: { foo: point, from: '1km', to: '10km' } }, + { equals: { foo: 'bar' } }, + ], + }); + + const sf1 = Array.from(filters.get(sub1.id).subfilters)[0]; + const sf2 = Array.from(filters.get(sub2.id).subfilters)[0]; + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(Array.from(sf1.conditions)[0].id)) + .match(new Set([sf1, sf2])); }); it('should add another condition to an already existing field', () => { - let cond1, sf1; - - return dsl.register('index', 'collection', {geoDistanceRange: {foo: point, from: '1km', to: '10km'}}) - .then(subscription => { - sf1 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - cond1 = Array.from(sf1.conditions)[0].id; - return dsl.register('index', 'collection', {geoDistanceRange: {foo: point, from: '10km', to: '100km'}}); - }) - .then(subscription => { - const - sf2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(cond1)).match(new Set([sf1])); - should(storage.fields.get('foo').get(Array.from(sf2.conditions)[0].id)).match(new Set([sf2])); - }); + const sub1 = dsl.register('index', 'collection', { + geoDistanceRange: { + foo: point, + from: '1km', + to: '10km', + }, + }); + + const sub2 = dsl.register('index', 'collection', { + geoDistanceRange: { + foo: point, + from: '10km', + to: '100km', + }, + }); + + const sf1 = Array.from(filters.get(sub1.id).subfilters)[0]; + const cond1 = Array.from(sf1.conditions)[0].id; + const sf2 = Array.from(filters.get(sub2.id).subfilters)[0]; + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(cond1)).match(new Set([sf1])); + should(storage.fields.get('foo').get(Array.from(sf2.conditions)[0].id)) + .match(new Set([sf2])); }); }); describe('#matching', () => { it('should match a point inside the circle', () => { - return dsl.register('index', 'collection', {geoDistanceRange: {foo: point, from: '1km', to: '10km'}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: {lat: 43.634, lon: 3.9 }}); + const sub = dsl.register('index', 'collection', { + geoDistanceRange: { + foo: point, + from: '1km', + to: '10km', + }, + }); - should(result).eql([subscription.id]); - }); + const result = dsl.test('index', 'collection', { + foo: { + lat: 43.634, + lon: 3.9, + }, + }); + + should(result).eql([sub.id]); }); it('should not match if a point is outside the outer radius', () => { - return dsl.register('index', 'collection', {geoDistanceRange: {foo: point, from: '1km', to: '10km'}}) - .then(() => { - const result = dsl.test('index', 'collection', {foo: {lat: point.lat, lon: 5}}); + dsl.register('index', 'collection', { + geoDistanceRange: { + foo: point, + from: '1km', + to: '10km', + }, + }); + + const result = dsl.test('index', 'collection', { + foo: { + lat: point.lat, + lon: 5, + }, + }); - should(result).be.an.Array().and.be.empty(); - }); + should(result).be.an.Array().and.be.empty(); }); it('should not match if a point is inside the inner radius', () => { - return dsl.register('index', 'collection', {geoDistanceRange: {foo: point, from: '1km', to: '10km'}}) - .then(() => { - const result = dsl.test('index', 'collection', {foo: point}); + dsl.register('index', 'collection', { + geoDistanceRange: { + foo: point, + from: '1km', + to: '10km', + }, + }); - should(result).be.an.Array().and.be.empty(); - }); + const result = dsl.test('index', 'collection', {foo: point}); + + should(result).be.an.Array().and.be.empty(); }); it('should return an empty array if the document does not contain the searched geopoint', () => { - return dsl.register('index', 'collection', {geoDistanceRange: {foo: point, from: '1km', to: '10km'}}) - .then(() => { - const result = dsl.test('index', 'collection', {bar: point}); + dsl.register('index', 'collection', { + geoDistanceRange: { + foo: point, + from: '1km', + to: '10km', + }, + }); - should(result).be.an.Array().and.be.empty(); - }); + const result = dsl.test('index', 'collection', {bar: point}); + + should(result).be.an.Array().and.be.empty(); }); it('should return an empty array if the document contain an invalid geopoint', () => { - return dsl.register('index', 'collection', {geoDistanceRange: {foo: point, from: '1km', to: '10km'}}) - .then(() => { - const result = dsl.test('index', 'collection', {foo: '43.6331979 / 3.8433703'}); + dsl.register('index', 'collection', { + geoDistanceRange: { + foo: point, + from: '1km', + to: '10km', + }, + }); + + const result = dsl.test('index', 'collection', { + foo: '43.6331979 / 3.8433703', + }); - should(result).be.an.Array().and.be.empty(); - }); + should(result).be.an.Array().and.be.empty(); }); }); }); diff --git a/test/keywords/geoPolygon.test.js b/test/keywords/geoPolygon.test.js index f8f2b17..5856283 100644 --- a/test/keywords/geoPolygon.test.js +++ b/test/keywords/geoPolygon.test.js @@ -5,6 +5,8 @@ const DSL = require('../../'); describe('DSL.keyword.geoPolygon', () => { let dsl; + let filters; + let foPairs; let standardize; const polygon = { points: [ @@ -39,6 +41,8 @@ describe('DSL.keyword.geoPolygon', () => { beforeEach(() => { dsl = new DSL(); + filters = dsl.storage.filters; + foPairs = dsl.storage.foPairs; standardize = dsl.transformer.standardizer.standardize.bind(dsl.transformer.standardizer); }); @@ -111,99 +115,126 @@ describe('DSL.keyword.geoPolygon', () => { describe('#storage', () => { it('should store a single geoPolygon correctly', () => { - return dsl.register('index', 'collection', {geoPolygon: {foo: polygon}}) - .then(subscription => { - const - subfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); + const sub = dsl.register('index', 'collection', { + geoPolygon: { + foo: polygon, + }, + }); + + const subfilter = Array.from(filters.get(sub.id).subfilters)[0]; + const storage = foPairs.get('index', 'collection', 'geospatial'); - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(Array.from(subfilter.conditions)[0].id)).match(new Set([subfilter])); - }); + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(Array.from(subfilter.conditions)[0].id)) + .match(new Set([subfilter])); }); it('should add a subfilter to an already existing condition', () => { - let sf1; - return dsl.register('index', 'collection', {geoPolygon: {foo: polygon}}) - .then(subscription => { - sf1 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - return dsl.register('index', 'collection', {and: [{geoPolygon: {foo: polygon}}, {equals: {foo: 'bar'}}]}); - }) - .then(subscription => { - const - sf2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(Array.from(sf1.conditions)[0].id)).match(new Set([sf1, sf2])); - }); + const sub1 = dsl.register('index', 'collection', { + geoPolygon: { + foo: polygon, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + and: [ + {geoPolygon: {foo: polygon}}, + {equals: {foo: 'bar'}}, + ], + }); + + const sf1 = Array.from(filters.get(sub1.id).subfilters)[0]; + const sf2 = Array.from(filters.get(sub2.id).subfilters)[0]; + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(Array.from(sf1.conditions)[0].id)) + .match(new Set([sf1, sf2])); }); it('should add another condition to an already existing field', () => { - let cond1, sf1; - - return dsl.register('index', 'collection', {geoPolygon: {foo: polygon}}) - .then(subscription => { - sf1 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - cond1 = Array.from(sf1.conditions)[0].id; - return dsl.register('index', 'collection', {geoBoundingBox: {foo: {topLeft: 'dr5r9ydj2y73', bottomRight: 'drj7teegpus6'}}}); - }) - .then(subscription => { - const - sf2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(cond1)).match(new Set([sf1])); - should(storage.fields.get('foo').get(Array.from(sf2.conditions)[0].id)).match(new Set([sf2])); - }); + const sub1 = dsl.register('index', 'collection', { + geoPolygon: { + foo: polygon, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + geoBoundingBox: { + foo: { + bottomRight: 'drj7teegpus6', + topLeft: 'dr5r9ydj2y73', + }, + }, + }); + + const sf1 = Array.from(filters.get(sub1.id).subfilters)[0]; + const cond1 = Array.from(sf1.conditions)[0].id; + const sf2 = Array.from(filters.get(sub2.id).subfilters)[0]; + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(cond1)).match(new Set([sf1])); + should(storage.fields.get('foo').get(Array.from(sf2.conditions)[0].id)) + .match(new Set([sf2])); }); }); describe('#matching', () => { it('should match a point inside the polygon', () => { - return dsl.register('index', 'collection', {geoPolygon: {foo: polygon}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: {latLon: [43.6073913, 3.9109057]}}); + const sub = dsl.register('index', 'collection', { + geoPolygon: {foo: polygon}, + }); + + const result = dsl.test('index', 'collection', { + foo: {latLon: [43.6073913, 3.9109057]}, + }); - should(result).eql([subscription.id]); - }); + should(result).eql([sub.id]); }); it('should match a point exactly on a polygon corner', () => { - return dsl.register('index', 'collection', {geoPolygon: {foo: polygon}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: {latLon: polygon.points[0]}}); + const sub = dsl.register('index', 'collection', { + geoPolygon: {foo: polygon}, + }); + + const result = dsl.test('index', 'collection', { + foo: {latLon: polygon.points[0]}, + }); - should(result).eql([subscription.id]); - }); + should(result).eql([sub.id]); }); it('should not match if a point is outside the bbox', () => { - return dsl.register('index', 'collection', {geoPolygon: {foo: polygon}}) - .then(() => { - const result = dsl.test('index', 'collection', {foo: {lat: polygon.points[0][0] + 10e-6, lon: polygon.points[0][1] + 10e-6}}); + dsl.register('index', 'collection', {geoPolygon: {foo: polygon}}); + const result = dsl.test('index', 'collection', { + foo: { + lat: polygon.points[0][0] + 10e-6, + lon: polygon.points[0][1] + 10e-6, + }, + }); - should(result).be.an.Array().and.be.empty(); - }); + should(result).be.an.Array().and.be.empty(); }); it('should return an empty array if the document does not contain a geopoint', () => { - return dsl.register('index', 'collection', {geoPolygon: {foo: polygon}}) - .then(() => { - const result = dsl.test('index', 'collection', {bar: {latLon: polygon.points[0]}}); + dsl.register('index', 'collection', {geoPolygon: {foo: polygon}}); + + const result = dsl.test('index', 'collection', { + bar: { latLon: polygon.points[0] }, + }); - should(result).be.an.Array().and.be.empty(); - }); + should(result).be.an.Array().and.be.empty(); }); it('should return an empty array if the document contain an invalid geopoint', () => { - return dsl.register('index', 'collection', {geoPolygon: {foo: polygon}}) - .then(() => { - const result = dsl.test('index', 'collection', {foo: '43.6331979 / 3.8433703'}); + dsl.register('index', 'collection', {geoPolygon: {foo: polygon}}); + + const result = dsl.test('index', 'collection', { + foo: '43.6331979 / 3.8433703', + }); - should(result).be.an.Array().and.be.empty(); - }); + should(result).be.an.Array().and.be.empty(); }); }); }); diff --git a/test/keywords/geospatial.test.js b/test/keywords/geospatial.test.js index fedbf3a..218dea2 100644 --- a/test/keywords/geospatial.test.js +++ b/test/keywords/geospatial.test.js @@ -6,74 +6,93 @@ const DSL = require('../../'); */ describe('DSL.keyword.geospatial', () => { let dsl; - const - geoFilter = { - geoBoundingBox: { - foo: { - bottom: 43.5810609, - left: 3.8433703, - top: 43.6331979, - right: 3.9282093 - } + let filters; + let foPairs; + const geoFilter = { + geoBoundingBox: { + foo: { + bottom: 43.5810609, + left: 3.8433703, + top: 43.6331979, + right: 3.9282093 } - }; + } + }; beforeEach(() => { dsl = new DSL(); + filters = dsl.storage.filters; + foPairs = dsl.storage.foPairs; }); describe('#removal', () => { it('should destroy the whole structure when removing the last item', () => { - return dsl.register('index', 'collection', geoFilter) - .then(subscription => dsl.remove(subscription.id)) - .then(() => should(dsl.storage.foPairs._cache).be.empty()); + const sub = dsl.register('index', 'collection', geoFilter); + dsl.remove(sub.id); + should(foPairs._cache).be.empty(); }); it('should remove the entire field if its last condition is removed', () => { - return dsl.register('index', 'collection', {geoDistance: {bar: {lat: 13, lon: 42}, distance: '1km'}}) - .then(() => dsl.register('index', 'collection', geoFilter)) - .then(subscription => dsl.remove(subscription.id)) - .then(() => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage.fields.get('bar')).be.an.Object(); - should(storage.fields.get('foo')).be.undefined(); - }); + dsl.register('index', 'collection', { + geoDistance: { + bar: { + lat: 13, + lon: 42, + }, + distance: '1km', + }, + }); + + const sub = dsl.register('index', 'collection', geoFilter); + + dsl.remove(sub.id); + + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage.fields.get('bar')).be.an.Object(); + should(storage.fields.get('foo')).be.undefined(); }); it('should remove a single condition from a field if other conditions exist', () => { - let cond, sf; - - return dsl.register('index', 'collection', {geoDistance: {foo: {lat: 13, lon: 42}, distance: '1km'}}) - .then(subscription => { - sf = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - cond = Array.from(sf.conditions)[0].id; - return dsl.register('index', 'collection', geoFilter); - }) - .then(subscription => dsl.remove(subscription.id)) - .then(() => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - - should(storage.fields.get('foo').get(cond)).match(new Set([sf])); - }); + const sub1 = dsl.register('index', 'collection', { + geoDistance: { + foo: { + lat: 13, + lon: 42, + }, + distance: '1km', + }, + }); + + const sub2 = dsl.register('index', 'collection', geoFilter); + + const sf = Array.from(filters.get(sub1.id).subfilters)[0]; + const cond = Array.from(sf.conditions)[0].id; + + dsl.remove(sub2.id); + + const storage = foPairs.get('index', 'collection', 'geospatial'); + + should(storage.fields.get('foo').get(cond)).match(new Set([sf])); }); it('should remove a subfilter from a condition if other subfilters exist', () => { - let cond, sf; + const sub1 = dsl.register('index', 'collection', geoFilter); + const sf = Array.from(filters.get(sub1.id).subfilters)[0]; + const cond = Array.from(sf.conditions)[0].id; + + const sub2 = dsl.register('index', 'collection', { + and: [ + geoFilter, + {exists: {field: 'bar'}}, + ], + }); - return dsl.register('index', 'collection', geoFilter) - .then(subscription => { - sf = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - cond = Array.from(sf.conditions)[0].id; + dsl.remove(sub2.id); - return dsl.register('index', 'collection', {and: [geoFilter, {exists: {field: 'bar'}}]}); - }) - .then(subscription => dsl.remove(subscription.id)) - .then(() => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); + const storage = dsl.storage.foPairs.get('index', 'collection', 'geospatial'); - should(storage.fields.get('foo').get(cond)).match(new Set([sf])); - }); + should(storage.fields.get('foo').get(cond)).match(new Set([sf])); }); }); }); diff --git a/test/keywords/ids.test.js b/test/keywords/ids.test.js index 2e9e22d..0226de5 100644 --- a/test/keywords/ids.test.js +++ b/test/keywords/ids.test.js @@ -10,38 +10,38 @@ describe('DSL.keyword.ids', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({ids: {}})) - .be.rejectedWith('"ids" must be a non-empty object'); + should(() => dsl.validate({ids: {}})) + .throw('"ids" must be a non-empty object'); }); it('should reject filters with other fields other than the "values" one', () => { - return should(dsl.validate({ids: {foo: ['foo']}})) - .be.rejectedWith('"ids" requires the following attribute: values'); + should(() => dsl.validate({ids: {foo: ['foo']}})) + .throw('"ids" requires the following attribute: values'); }); it('should reject filters with multiple defined attributes', () => { - return should(dsl.validate({ids: {values: ['foo'], foo: ['foo']}})) - .be.rejectedWith('"ids" can contain only one attribute'); + should(() => dsl.validate({ids: {values: ['foo'], foo: ['foo']}})) + .throw('"ids" can contain only one attribute'); }); it('should reject filters with an empty value list', () => { - return should(dsl.validate({ids: {values: []}})) - .be.rejectedWith('Attribute "values" in "ids" cannot be empty'); + should(() => dsl.validate({ids: {values: []}})) + .throw('Attribute "values" in "ids" cannot be empty'); }); it('should reject filters with non-array values attribute', () => { - return should(dsl.validate({ids: {values: 'foo'}})) - .be.rejectedWith('Attribute "values" in "ids" must be an array'); + should(() => dsl.validate({ids: {values: 'foo'}})) + .throw('Attribute "values" in "ids" must be an array'); }); it('should reject filters containing a non-string value', () => { - return should(dsl.validate({ids: {values: ['foo', 'bar', 42, 'baz']}})) - .be.rejectedWith('Array "values" in keyword "ids" can only contain strings'); + should(() => dsl.validate({ids: {values: ['foo', 'bar', 42, 'baz']}})) + .throw('Array "values" in keyword "ids" can only contain strings'); }); it('should validate a well-formed ids filter', () => { - return should(dsl.validate({ids: {values: ['foo', 'bar', 'baz']}})) - .be.fulfilled(); + should(() => dsl.validate({ids: {values: ['foo', 'bar', 'baz']}})) + .not.throw(); }); }); diff --git a/test/keywords/in.test.js b/test/keywords/in.test.js index 98e7e14..4302fcd 100644 --- a/test/keywords/in.test.js +++ b/test/keywords/in.test.js @@ -10,33 +10,33 @@ describe('DSL.keyword.in', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({in: {}})) - .be.rejectedWith('"in" must be a non-empty object'); + should(() => dsl.validate({in: {}})) + .throw('"in" must be a non-empty object'); }); it('should reject filters with multiple defined attributes', () => { - return should(dsl.validate({in: {bar: ['foo'], foo: ['foo']}})) - .be.rejectedWith('"in" can contain only one attribute'); + should(() => dsl.validate({in: {bar: ['foo'], foo: ['foo']}})) + .throw('"in" can contain only one attribute'); }); it('should reject filters with an empty value list', () => { - return should(dsl.validate({in: {foo: []}})) - .be.rejectedWith('Attribute "foo" in "in" cannot be empty'); + should(() => dsl.validate({in: {foo: []}})) + .throw('Attribute "foo" in "in" cannot be empty'); }); it('should reject filters with non-array values attribute', () => { - return should(dsl.validate({in: {foo: 'foo'}})) - .be.rejectedWith('Attribute "foo" in "in" must be an array'); + should(() => dsl.validate({in: {foo: 'foo'}})) + .throw('Attribute "foo" in "in" must be an array'); }); it('should reject filters containing a non-string value', () => { - return should(dsl.validate({in: {foo: ['foo', 'bar', 42, 'baz']}})) - .be.rejectedWith('Array "foo" in keyword "in" can only contain strings'); + should(() => dsl.validate({in: {foo: ['foo', 'bar', 42, 'baz']}})) + .throw('Array "foo" in keyword "in" can only contain strings'); }); it('should validate a well-formed ids filter', () => { - return should(dsl.validate({in: {foo: ['foo', 'bar', 'baz']}})) - .be.fulfilled(); + should(() => dsl.validate({in: {foo: ['foo', 'bar', 'baz']}})) + .not.throw(); }); }); diff --git a/test/keywords/missing.test.js b/test/keywords/missing.test.js index 1b2dc42..2bbf6e1 100644 --- a/test/keywords/missing.test.js +++ b/test/keywords/missing.test.js @@ -29,76 +29,64 @@ describe('DSL.keyword.missing', () => { describe('#matching', () => { it('should match a document without the subscribed field', () => { - return dsl.register('index', 'collection', {not: {exists: 'foo'}}) - .then(subscription => { - should(dsl.test('index', 'collection', {bar: 'qux'})).eql([subscription.id]); - }); + const sub = dsl.register('index', 'collection', {not: {exists: 'foo'}}); + + should(dsl.test('index', 'collection', {bar: 'qux'})).eql([sub.id]); }); it('should not match if the document contain the searched field', () => { - return dsl.register('index', 'collection', {not: {exists: 'foo'}}) - .then(() => { - should(dsl.test('index', 'collection', {foo: 'bar'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {not: {exists: 'foo'}}); + should(dsl.test('index', 'collection', {foo: 'bar'})) + .be.an.Array().and.empty(); }); it('should match if the document contains an explicitly undefined field', () => { - return dsl.register('index', 'collection', {not: {exists: 'foo'}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: undefined})).eql([subscription.id]); - }); + const sub = dsl.register('index', 'collection', {not: {exists: 'foo'}}); + + should(dsl.test('index', 'collection', {foo: undefined})).eql([sub.id]); }); it('should match a document with the subscribed nested keyword', () => { - return dsl.register('index', 'collection', {not: {exists: 'foo.bar.baz'}}) - .then(() => { - should(dsl.test('index', 'collection', {foo: {bar: {baz: 'qux'}}})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {not: {exists: 'foo.bar.baz'}}); + should(dsl.test('index', 'collection', {foo: {bar: {baz: 'qux'}}})) + .be.an.Array().and.empty(); }); it('should match if a document has the searched field, but not the searched array value', () => { - return dsl.register('i', 'c', {not: {exists: 'foo.bar["baz"]'}}) - .then(subscription => { - should(dsl.test('i', 'c', {foo: {bar: ['qux']}})).eql([subscription.id]); - }); + const sub = dsl.register('i', 'c', {not: {exists: 'foo.bar["baz"]'}}); + should(dsl.test('i', 'c', {foo: {bar: ['qux']}})).eql([sub.id]); }); it('should not match if a document has the searched field, and the searched array value', () => { - return dsl.register('i', 'c', {not: {exists: 'foo.bar["baz"]'}}) - .then(() => { - should(dsl.test('i', 'c', {foo: {bar: ['baz']}})).Array().empty(); - }); + dsl.register('i', 'c', {not: {exists: 'foo.bar["baz"]'}}); + should(dsl.test('i', 'c', {foo: {bar: ['baz']}})).Array().empty(); }); it('should match if a field is entirely missing, while looking for an array value only', () => { - return dsl.register('i', 'c', {missing: 'foo.bar["baz"'}) - .then(subscription => should(dsl.test('i', 'c', {bar: 'foo'})).eql([subscription.id])); + const sub = dsl.register('i', 'c', {missing: 'foo.bar["baz"'}); + should(dsl.test('i', 'c', {bar: 'foo'})).eql([sub.id]); }); it('should match if looking for an array value, and the field is not an array', () => { - return dsl.register('i', 'c', {missing: 'foo.bar["baz"]'}) - .then(subscription => should(dsl.test('i', 'c', {foo: {bar: 42}})).eql([subscription.id])); + const sub = dsl.register('i', 'c', {missing: 'foo.bar["baz"]'}); + should(dsl.test('i', 'c', {foo: {bar: 42}})).eql([sub.id]); }); it('should match if there is a type mismatch', () => { - return dsl.register('i', 'c', {not: {exists: 'foo.bar["true"]'}}) - .then(subscription => { - should(dsl.test('i', 'c', {foo: {bar: [true]}})).eql([subscription.id]); - }); + const sub = dsl.register('i', 'c', {not: {exists: 'foo.bar["true"]'}}); + should(dsl.test('i', 'c', {foo: {bar: [true]}})).eql([sub.id]); }); it('should not match if the document is in another index', () => { - return dsl.register('index', 'collection', {not: {exists: 'foo'}}) - .then(() => { - should(dsl.test('foobar', 'collection', {'qux': 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {not: {exists: 'foo'}}); + should(dsl.test('foobar', 'collection', {'qux': 'qux'})) + .be.an.Array().and.empty(); }); it('should not match if the document is in another collection', () => { - return dsl.register('index', 'collection', {not: {exists: 'foo'}}) - .then(() => { - should(dsl.test('index', 'foobar', {'qux': 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {not: {exists: 'foo'}}); + should(dsl.test('index', 'foobar', {'qux': 'qux'})) + .be.an.Array().and.empty(); }); }); }); diff --git a/test/keywords/notequals.test.js b/test/keywords/notequals.test.js index 7126eb3..ee5ea24 100644 --- a/test/keywords/notequals.test.js +++ b/test/keywords/notequals.test.js @@ -6,175 +6,232 @@ const DSL = require('../../'); describe('DSL.keyword.notequals', () => { let dsl; + let filters; + let foPairs; beforeEach(() => { dsl = new DSL(); + filters = dsl.storage.filters; + foPairs = dsl.storage.foPairs; }); describe('#standardization', () => { it('should return the same content, unchanged', () => { - should(dsl.transformer.standardizer.standardize({not: {equals: {foo: 'bar'}}})).match({not: {equals: {foo: 'bar'}}}); + const result = dsl.transformer.standardizer.standardize({ + not: { + equals: { + foo: 'bar', + }, + }, + }); + + should(result).match({not: {equals: {foo: 'bar'}}}); }); }); describe('#matching', () => { it('should not match a document with the subscribed keyword', () => { - return dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}) - .then(() => { - should(dsl.test('index', 'collection', {foo: 'bar'})).be.an.Array().and.be.empty(); - }); + dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}); + + should(dsl.test('index', 'collection', {foo: 'bar'})) + .be.an.Array().and.be.empty(); }); it('should match if the document contains the field with another value', () => { - return dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: 'qux'}); - should(result).eql([subscription.id]); - }); + const sub = dsl.register('index', 'collection', { + not: { + equals: { + foo: 'bar', + }, + }, + }); + + const result = dsl.test('index', 'collection', {foo: 'qux'}); + + should(result).eql([sub.id]); }); it('should match if the document do not contain the registered field', () => { - return dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {qux: 'bar'}); - should(result).eql([subscription.id]); - }); + const sub = dsl.register('index', 'collection', { + not: { + equals: { + foo: 'bar', + }, + }, + }); + + const result = dsl.test('index', 'collection', {qux: 'bar'}); + + should(result).eql([sub.id]); }); it('should match a document with the subscribed nested keyword', () => { - return dsl.register('index', 'collection', {not: {equals: {'foo.bar.baz': 'qux'}}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: {bar: {baz: 'foobar'}}}); - - should(result).be.eql([subscription.id]); - }); + const sub = dsl.register('index', 'collection', { + not: { + equals: { + 'foo.bar.baz': 'qux', + }, + }, + }); + + const result = dsl.test('index', 'collection', { + foo: { + bar: { + baz: 'foobar', + }, + }, + }); + + should(result).be.eql([sub.id]); }); it('should not match if the document is in another index', () => { - return dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}) - .then(() => { - should(dsl.test('foobar', 'collection', {foo: 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}); + + should(dsl.test('foobar', 'collection', {foo: 'qux'})) + .be.an.Array().and.empty(); }); it('should not match if the document is in another collection', () => { - return dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}) - .then(() => { - should(dsl.test('index', 'foobar', {foo: 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}); + + should(dsl.test('index', 'foobar', {foo: 'qux'})) + .be.an.Array().and.empty(); }); it('should match even if another field was hit before', () => { - return dsl.register('i', 'c', {not: {equals: {a: 'Jennifer Cardini'}}}) - .then(() => dsl.register('i', 'c', {not: {equals: {b: 'Shonky'}}})) - .then(() => { - should(dsl.test('i', 'c', {a: 'Jennifer Cardini'})) - .be.an.Array() - .length(1); - }); + dsl.register('i', 'c', {not: {equals: {a: 'Jennifer Cardini'}}}); + dsl.register('i', 'c', {not: {equals: {b: 'Shonky'}}}); + + should(dsl.test('i', 'c', {a: 'Jennifer Cardini'})) + .be.an.Array() + .length(1); }); it('should match 0 equality', () => { - return dsl.register('i', 'c', {not: {equals: {a: 0}}}) - .then(() => { - should(dsl.test('i', 'c', {a: 0})) - .be.an.Array() - .be.empty(); - }); + dsl.register('i', 'c', {not: {equals: {a: 0}}}); + + should(dsl.test('i', 'c', {a: 0})) + .be.an.Array() + .be.empty(); }); it('should match false equality', () => { - return dsl.register('i', 'c', {not: {equals: {a: false}}}) - .then(() => { - should(dsl.test('i', 'c', {a: false})) - .be.an.Array() - .be.empty(); - }); + dsl.register('i', 'c', {not: {equals: {a: false}}}); + + should(dsl.test('i', 'c', {a: false})) + .be.an.Array() + .be.empty(); }); it('should match null equality', () => { - return dsl.register('i', 'c', {not: {equals: {a: null}}}) - .then(() => { - should(dsl.test('i', 'c', {a: null})) - .be.an.Array() - .be.empty(); - }); - }); + dsl.register('i', 'c', {not: {equals: {a: null}}}); + should(dsl.test('i', 'c', {a: null})) + .be.an.Array() + .be.empty(); + }); }); describe('#removal', () => { it('should destroy the whole structure when removing the last item', () => { - return dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}) - .then(subscription => dsl.remove(subscription.id)) - .then(() => should(dsl.storage.foPairs._cache).be.empty()); + const sub = dsl.register('index', 'collection', { + not: { + equals: { + foo: 'bar', + }, + }, + }); + + dsl.remove(sub.id); + + should(foPairs._cache).be.empty(); }); it('should remove a single subfilter from a multi-filter condition', () => { - let - idToRemove, - subfilter; - - return dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}) - .then(subscription => { - idToRemove = subscription.id; - return dsl.register('index', 'collection', {and: [{not: {equals: {foo: 'qux'}}}, {not: {equals: {foo: 'bar'}}}]}); - }) - .then(subscription => { - subfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - return dsl.remove(idToRemove); - }) - .then(() => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'notequals'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo')).instanceOf(Map); - should(storage.fields.get('foo').size).eql(2); - should(storage.fields.get('foo').get('bar')).eql(new Set([subfilter])); - should(storage.fields.get('foo').get('qux')).eql(new Set([subfilter])); - }); + const sub1 = dsl.register('index', 'collection', { + not: { + equals: { + foo: 'bar', + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + and: [ + {not: {equals: {foo: 'qux'}}}, + {not: {equals: {foo: 'bar'}}}, + ], + }); + + const subfilter = Array.from(filters.get(sub2.id).subfilters)[0]; + + dsl.remove(sub1.id); + + const storage = foPairs.get('index', 'collection', 'notequals'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo')).instanceOf(Map); + should(storage.fields.get('foo').size).eql(2); + should(storage.fields.get('foo').get('bar')).eql(new Set([subfilter])); + should(storage.fields.get('foo').get('qux')).eql(new Set([subfilter])); }); it('should remove a value from the list if its last subfilter is removed', () => { - let barSubfilter; - - return dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}) - .then(subscription => { - barSubfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - - return dsl.register('index', 'collection', {and: [{not: {equals: {foo: 'qux'}}}, {not: {equals: {foo: 'bar'}}}]}); - }) - .then(subscription => dsl.remove(subscription.id)) - .then(() => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'notequals'); - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get('bar')).match(new Set([barSubfilter])); - should(storage.fields.get('foo').get('qux')).undefined(); - }); + const sub1 = dsl.register('index', 'collection', { + not: { + equals: { + foo: 'bar', + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + and: [ + {not: {equals: {foo: 'qux'}}}, + {not: {equals: {foo: 'bar'}}}, + ], + }); + + + dsl.remove(sub2.id); + + const storage = foPairs.get('index', 'collection', 'notequals'); + const barSubfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get('bar')).match(new Set([barSubfilter])); + should(storage.fields.get('foo').get('qux')).undefined(); }); it('should remove a field from the list if its last value to test is removed', () => { - let barSubfilter; - - return dsl.register('index', 'collection', {not: {equals: {foo: 'bar'}}}) - .then(subscription => { - barSubfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - - return dsl.register('index', 'collection', {not: {equals: {baz: 'qux'}}}); - }) - .then(subscription => { - const operand = dsl.storage.foPairs - .get('index', 'collection', 'notequals'); - - should(operand.fields).have.keys('foo', 'baz'); - return dsl.remove(subscription.id); - }) - .then(() => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'notequals'); - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get('bar')).match(new Set([barSubfilter])); - should(storage.fields.get('baz')).be.undefined(); - }); + const sub1 = dsl.register('index', 'collection', { + not: { + equals: { + foo: 'bar', + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + not: { + equals: { + baz: 'qux', + }, + }, + }); + + const barSubfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + const operand = foPairs.get('index', 'collection', 'notequals'); + + should(operand.fields).have.keys('foo', 'baz'); + + dsl.remove(sub2.id); + + const storage = foPairs.get('index', 'collection', 'notequals'); + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get('bar')).match(new Set([barSubfilter])); + should(storage.fields.get('baz')).be.undefined(); }); }); }); diff --git a/test/keywords/notgeospatial.test.js b/test/keywords/notgeospatial.test.js index dcecfdd..ea3a049 100644 --- a/test/keywords/notgeospatial.test.js +++ b/test/keywords/notgeospatial.test.js @@ -13,150 +13,201 @@ const DSL = require('../../'); describe('DSL.keyword.notgeospatial', () => { let dsl; + let filters; + let foPairs; beforeEach(() => { dsl = new DSL(); + filters = dsl.storage.filters; + foPairs = dsl.storage.foPairs; }); describe('#storage', () => { it('should store a single geospatial keyword correctly', () => { - return dsl.register('index', 'collection', {not: {geoDistance: {foo: {lat: 13, lon: 42}, distance: '1000m'}}}) - .then(subscription => { - const - storage = dsl.storage.foPairs.get('index', 'collection', 'notgeospatial'), - subfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - id = Array.from(subfilter.conditions)[0].id; - - should(storage).be.instanceOf(FieldOperand); - should(storage.custom.index).be.an.Object(); - should(storage.fields.get('foo')).be.instanceOf(Map); - should(storage.fields.get('foo').size).be.eql(1); - should(storage.fields.get('foo').get(id)).eql(new Set([subfilter])); - }); + const sub = dsl.register('index', 'collection', { + not: { + geoDistance: { + foo: { + lat: 13, + lon: 42, + }, + distance: '1000m', + }, + }, + }); + + const storage = foPairs.get('index', 'collection', 'notgeospatial'); + const subfilter = Array.from(filters.get(sub.id).subfilters)[0]; + const id = Array.from(subfilter.conditions)[0].id; + + should(storage).be.instanceOf(FieldOperand); + should(storage.custom.index).be.an.Object(); + should(storage.fields.get('foo')).be.instanceOf(Map); + should(storage.fields.get('foo').size).be.eql(1); + should(storage.fields.get('foo').get(id)).eql(new Set([subfilter])); }); it('should add another condition to an already tested field', () => { - let id1, subfilter1; - - return dsl.register('index', 'collection', {not: {geoDistance: {foo: {lat: 13, lon: 42}, distance: '1000m'}}}) - .then(subscription => { - subfilter1 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - id1 = Array.from(subfilter1.conditions)[0].id; - - return dsl.register('index', 'collection', {not: {geoBoundingBox: {foo: {top: 13, left: 0, right: 42, bottom: -14}}}}); - }) - .then(subscription => { - const - subfilter2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - id2 = Array.from(subfilter2.conditions)[0].id, - storage = dsl.storage.foPairs.get('index', 'collection', 'notgeospatial'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.custom.index).be.an.Object(); - should(storage.fields.get('foo')).be.instanceOf(Map); - should(storage.fields.get('foo').size).be.eql(2); - should(storage.fields.get('foo').get(id1)).eql(new Set([subfilter1])); - should(storage.fields.get('foo').get(id2)).eql(new Set([subfilter2])); - }); + const sub1 = dsl.register('index', 'collection', { + not: { + geoDistance: { + foo: { + lat: 13, + lon: 42, + }, + distance: '1000m', + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + not: { + geoBoundingBox: { + foo: { + bottom: -14, + left: 0, + right: 42, + top: 13, + }, + }, + }, + }); + + const subfilter1 = Array.from(filters.get(sub1.id).subfilters)[0]; + const subfilter2 = Array.from(filters.get(sub2.id).subfilters)[0]; + const id1 = Array.from(subfilter1.conditions)[0].id; + const id2 = Array.from(subfilter2.conditions)[0].id; + const storage = foPairs.get('index', 'collection', 'notgeospatial'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.custom.index).be.an.Object(); + should(storage.fields.get('foo')).be.instanceOf(Map); + should(storage.fields.get('foo').size).be.eql(2); + should(storage.fields.get('foo').get(id1)).eql(new Set([subfilter1])); + should(storage.fields.get('foo').get(id2)).eql(new Set([subfilter2])); }); it('should add another subfilter to an already tested shape', () => { - let - filter = {not: {geoDistance: {foo: {lat: 13, lon: 42}, distance: '1000m'}}}, - id, - subfilter; - - return dsl.register('index', 'collection', filter) - .then(subscription => { - subfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - id = Array.from(subfilter.conditions)[0].id; - - return dsl.register('index', 'collection', {and: [{equals: {bar: 'baz'}}, filter]}); - }) - .then(subscription => { - const - storage = dsl.storage.foPairs.get('index', 'collection', 'notgeospatial'), - subfilter2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - - should(storage).be.instanceOf(FieldOperand); - should(storage.custom.index).be.an.Object(); - should(storage.fields.get('foo')).be.instanceOf(Map); - should(storage.fields.get('foo').size).be.eql(1); - should(storage.fields.get('foo').get(id)).eql(new Set([subfilter, subfilter2])); - }); + const filter = { + not: { + geoDistance: { + foo: { + lat: 13, + lon: 42, + }, + distance: '1000m', + }, + }, + }; + + const sub1 = dsl.register('index', 'collection', filter); + const sub2 = dsl.register('index', 'collection', { + and: [ + {equals: {bar: 'baz'}}, + filter, + ], + }); + + const storage = foPairs.get('index', 'collection', 'notgeospatial'); + const subfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + const subfilter2 = Array.from(filters.get(sub2.id).subfilters)[0]; + const id = Array.from(subfilter.conditions)[0].id; + + should(storage).be.instanceOf(FieldOperand); + should(storage.custom.index).be.an.Object(); + should(storage.fields.get('foo')).be.instanceOf(Map); + should(storage.fields.get('foo').size).be.eql(1); + + should(storage.fields.get('foo').get(id)) + .eql(new Set([subfilter, subfilter2])); }); }); describe('#match', () => { - let - distanceId, - distanceRangeId, - polygonId; + let distanceId; + let distanceRangeId; + let polygonId; beforeEach(() => { - return dsl.register('index', 'collection', {not: {geoBoundingBox: {foo: {bottom: 43.5810609, left: 3.8433703, top: 43.6331979, right: 3.9282093}}}}) - .then(() => { - return dsl.register('index', 'collection', { - not: { - geoDistance: { - foo: { - lat: 43.5764455, - lon: 3.948711 - }, - distance: '2000m' - } - } - }); - }) - .then(subscription => { - distanceId = subscription.id; - return dsl.register('index', 'collection', { - not: { - geoDistanceRange: { - foo: { - lat: 43.6073913, - lon: 3.9109057 - }, - from: '10m', - to: '1500m' - } - } - }); - }) - .then(subscription => { - distanceRangeId = subscription.id; - return dsl.register('index', 'collection', { - not: { - geoPolygon: { - foo: { - points: [ - {latLon: [43.6021299, 3.8989713]}, - {latLon: [43.6057389, 3.8968173]}, - {latLon: [43.6092889, 3.8970423]}, - {latLon: [43.6100359, 3.9040853]}, - {latLon: [43.6069619, 3.9170343]}, - {latLon: [43.6076479, 3.9230133]}, - {latLon: [43.6038779, 3.9239153]}, - {latLon: [43.6019189, 3.9152403]}, - {latLon: [43.6036049, 3.9092313]} - ] - } - } + dsl.register('index', 'collection', { + not: { + geoBoundingBox: { + foo: { + bottom: 43.5810609, + left: 3.8433703, + right: 3.9282093, + top: 43.6331979, + }, + }, + }, + }); + + let subscription = dsl.register('index', 'collection', { + not: { + geoDistance: { + foo: { + lat: 43.5764455, + lon: 3.948711 + }, + distance: '2000m', + } + } + }); + + distanceId = subscription.id; + + subscription = dsl.register('index', 'collection', { + not: { + geoDistanceRange: { + foo: { + lat: 43.6073913, + lon: 3.9109057 + }, + from: '10m', + to: '1500m', + } + } + }); + + distanceRangeId = subscription.id; + + subscription = dsl.register('index', 'collection', { + not: { + geoPolygon: { + foo: { + points: [ + {latLon: [43.6021299, 3.8989713]}, + {latLon: [43.6057389, 3.8968173]}, + {latLon: [43.6092889, 3.8970423]}, + {latLon: [43.6100359, 3.9040853]}, + {latLon: [43.6069619, 3.9170343]}, + {latLon: [43.6076479, 3.9230133]}, + {latLon: [43.6038779, 3.9239153]}, + {latLon: [43.6019189, 3.9152403]}, + {latLon: [43.6036049, 3.9092313]}, + ] } - }); - }) - .then(subscription => { - polygonId = subscription.id; - }); + } + } + }); + + polygonId = subscription.id; }); it('should match shapes not containing the provided point', () => { - let result = dsl.test('index', 'collection', {foo: {lat: 43.6073913, lon: 3.9109057}}); + let result = dsl.test('index', 'collection', { + foo: { + lat: 43.6073913, + lon: 3.9109057, + }, + }); + should(result.sort()).match([distanceId, distanceRangeId].sort()); }); it('should return an empty array if the provided point is invalid', () => { - should(dsl.test('index', 'collection', {foo: {lat: 'foo', lon: 'bar'}})).be.an.Array().and.be.empty(); + should(dsl.test('index', 'collection', {foo: {lat: 'foo', lon: 'bar'}})) + .be.an.Array().and.be.empty(); }); it('should return all subscriptions if the document does not contain the registered field', () => { @@ -166,40 +217,61 @@ describe('DSL.keyword.notgeospatial', () => { }); it('should reject a shape if the point is right on its border', () => { - let result = dsl.test('index', 'collection', {foo: {lat: 43.5810609, lon: 3.8433703}}); + const result = dsl.test('index', 'collection', { + foo: { + lat: 43.5810609, + lon: 3.8433703, + }, + }); + should(result.sort()).match([distanceId, distanceRangeId, polygonId].sort()); }); }); describe('#removal', () => { - let filter, filterId, storage; + let filter; + let filterId; + let storage; beforeEach(() => { - filter = {not: {geoBoundingBox: {foo: {bottom: 43.5810609, left: 3.8433703, top: 43.6331979, right: 3.9282093}}}}; - return dsl.register('index', 'collection', filter) - .then(subscription => { - filterId = subscription.id; - storage = dsl.storage.foPairs.get('index', 'collection', 'notgeospatial'); - }); + filter = { + not: { + geoBoundingBox: { + foo: { + bottom: 43.5810609, + left: 3.8433703, + top: 43.6331979, + right: 3.9282093, + }, + }, + }, + }; + + const subscription = dsl.register('index', 'collection', filter); + + filterId = subscription.id; + storage = foPairs.get('index', 'collection', 'notgeospatial'); }); it('should destroy the whole structure when removing the last item', () => { dsl.remove(filterId); - should(dsl.storage.foPairs._cache).be.empty(); + should(foPairs._cache).be.empty(); }); it('should remove a single subfilter from a multi-filter condition', () => { - let sf; - - return dsl.register('index', 'collection', {and: [filter, {equals: {foo: 'bar'}}]}) - .then(subscription => { - sf = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - return dsl.remove(filterId); - }) - .then(() => { - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(Array.from(sf.conditions)[1].id)).match(new Set([sf])); - }); + const subscription = dsl.register('index', 'collection', { + and: [ + filter, + {equals: {foo: 'bar'}}, + ], + }); + + const sf = Array.from(filters.get(subscription.id).subfilters)[0]; + dsl.remove(filterId); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(Array.from(sf.conditions)[1].id)) + .match(new Set([sf])); }); it('should remove a value from the list if its last subfilter is removed', () => { @@ -208,24 +280,21 @@ describe('DSL.keyword.notgeospatial', () => { geoDistance: { foo: { lat: 43.5764455, - lon: 3.948711 + lon: 3.948711, }, - distance: '2000m' - } - } + distance: '2000m', + }, + }, }; - let id, subfilter; - return dsl.register('index', 'collection', geofilter) - .then(subscription => { - subfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - id = Array.from(subfilter.conditions)[0].id; - return dsl.remove(filterId); - }) - .then(() => { - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(id)).match(new Set([subfilter])); - }); + const subscription = dsl.register('index', 'collection', geofilter); + const subfilter = Array.from(filters.get(subscription.id).subfilters)[0]; + const id = Array.from(subfilter.conditions)[0].id; + + dsl.remove(filterId); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(id)).match(new Set([subfilter])); }); it('should remove a field from the list if its last value to test is removed', () => { @@ -234,29 +303,24 @@ describe('DSL.keyword.notgeospatial', () => { geoDistance: { bar: { lat: 43.5764455, - lon: 3.948711 + lon: 3.948711, }, - distance: '2000m' - } - } + distance: '2000m', + }, + }, }; - let id, subfilter; - return dsl.register('index', 'collection', geofilter) - .then(subscription => { - subfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - id = Array.from(subfilter.conditions)[0].id; - - const operand = dsl.storage.foPairs - .get('index', 'collection', 'notgeospatial'); - - should(operand.fields).have.keys('foo', 'bar'); - return dsl.remove(filterId); - }) - .then(() => { - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('bar').get(id)).match(new Set([subfilter])); - }); + const subscription = dsl.register('index', 'collection', geofilter); + const subfilter = Array.from(filters.get(subscription.id).subfilters)[0]; + const id = Array.from(subfilter.conditions)[0].id; + const operand = foPairs.get('index', 'collection', 'notgeospatial'); + + should(operand.fields).have.keys('foo', 'bar'); + + dsl.remove(filterId); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('bar').get(id)).match(new Set([subfilter])); }); }); }); diff --git a/test/keywords/nothing.test.js b/test/keywords/nothing.test.js index f3921b7..3caec87 100644 --- a/test/keywords/nothing.test.js +++ b/test/keywords/nothing.test.js @@ -12,15 +12,15 @@ describe('DSL.keyword.nothing', () => { describe('#storage', () => { it('should register in the store', () => { - return dsl.register('index', 'collection', {nothing: 'anything'}) - .then(subscription => { - const storeEntry = dsl.storage.foPairs.get('index', 'collection', 'nothing'); + const subscription = dsl.register('index', 'collection', { + nothing: 'anything', + }); - should(storeEntry) - .be.instanceof(FieldOperand); - should(storeEntry.fields.get('all')) - .eql([Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]]); - }); + const storeEntry = dsl.storage.foPairs.get('index', 'collection', 'nothing'); + + should(storeEntry).be.instanceof(FieldOperand); + should(storeEntry.fields.get('all')) + .eql([Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]]); }); }); }); diff --git a/test/keywords/notrange.test.js b/test/keywords/notrange.test.js index 5480bef..7ebcd6a 100644 --- a/test/keywords/notrange.test.js +++ b/test/keywords/notrange.test.js @@ -6,240 +6,347 @@ const RangeCondition = require('../../lib/storage/objects/rangeCondition'); describe('DSL.keyword.notrange', () => { let dsl; + let filters; + let foPairs; beforeEach(() => { dsl = new DSL(); + filters = dsl.storage.filters; + foPairs = dsl.storage.foPairs; }); describe('#storage', () => { it('should store a single condition correctly', () => { - return dsl.register('index', 'collection', {not: {range: {foo: {gt: 42, lt: 100}}}}) - .then(subscription => { - const - subfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - store = dsl.storage.foPairs.get('index', 'collection', 'notrange'); - - should(store).be.instanceOf(FieldOperand); - should(store.fields.get('foo').conditions.size).be.eql(1); - - const rangeCondition = Array.from(store.fields.get('foo').conditions.values())[0]; - should(rangeCondition).instanceOf(RangeCondition); - should(rangeCondition.subfilters).eql(new Set([subfilter])); - should(rangeCondition.low).approximately(42, 1e-9); - should(rangeCondition.high).approximately(100, 1e-9); - should(store.fields.get('foo').tree).be.an.Object(); - }); + const subscription = dsl.register('index', 'collection', { + not: { + range: { + foo: { + gt: 42, + lt: 100, + }, + }, + }, + }); + const subfilter = Array.from(filters.get(subscription.id).subfilters)[0]; + const store = foPairs.get('index', 'collection', 'notrange'); + + should(store).be.instanceOf(FieldOperand); + should(store.fields.get('foo').conditions.size).be.eql(1); + + const rangeCondition = Array.from(store.fields.get('foo').conditions.values())[0]; + should(rangeCondition).instanceOf(RangeCondition); + should(rangeCondition.subfilters).eql(new Set([subfilter])); + should(rangeCondition.low).approximately(42, 1e-9); + should(rangeCondition.high).approximately(100, 1e-9); + should(store.fields.get('foo').tree).be.an.Object(); }); it('should store multiple conditions on the same field correctly', () => { - let sf1; - - return dsl.register('index', 'collection', {not: {range: {foo: {gt: 42, lt: 100}}}}) - .then(subscription => { - sf1 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - - return dsl.register('index', 'collection', { - and: [ - {not: {range: {foo: {gte: 10, lte: 78}}}}, - {not: {range: {foo: {gt: 0, lt: 50}}}} - ] - }); - }) - .then(subscription => { - const - sf2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - store = dsl.storage.foPairs.get('index', 'collection', 'notrange'); - - should(store).be.instanceOf(FieldOperand); - should(store.fields.get('foo').conditions.size).be.eql(3); - - const cd1 = store.fields.get('foo').conditions.get( - Array.from(sf1.conditions)[0].id); - - should(cd1).instanceOf(RangeCondition); - should(cd1.subfilters).eql(new Set([sf1])); - should(cd1.low).exactly(42); - should(cd1.high).exactly(100); - - const cd2 = store.fields.get('foo').conditions.get( - Array.from(sf2.conditions)[0].id); - - should(cd2).instanceOf(RangeCondition); - should(cd2.subfilters).eql(new Set([sf2])); - should(cd2.low).approximately(10, 1e-9); - should(cd2.high).approximately(78, 1e-9); - - const cd3 = store.fields.get('foo').conditions.get( - Array.from(sf2.conditions)[1].id); - - should(cd3).instanceOf(RangeCondition); - should(cd3.subfilters).eql(new Set([sf2])); - should(cd3.low).exactly(0); - should(cd3.high).exactly(50); - - should(store.fields.get('foo').tree).be.an.Object(); - }); + const sub1 = dsl.register('index', 'collection', { + not: { + range: { + foo: { + gt: 42, + lt: 100, + }, + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + and: [ + {not: {range: {foo: {gte: 10, lte: 78}}}}, + {not: {range: {foo: {gt: 0, lt: 50}}}}, + ], + }); + + const sf1 = Array.from(filters.get(sub1.id).subfilters)[0]; + const sf2 = Array.from(filters.get(sub2.id).subfilters)[0]; + const store = foPairs.get('index', 'collection', 'notrange'); + + should(store).be.instanceOf(FieldOperand); + should(store.fields.get('foo').conditions.size).be.eql(3); + + const cd1 = store.fields.get('foo').conditions + .get(Array.from(sf1.conditions)[0].id); + + should(cd1).instanceOf(RangeCondition); + should(cd1.subfilters).eql(new Set([sf1])); + should(cd1.low).exactly(42); + should(cd1.high).exactly(100); + + const cd2 = store.fields.get('foo').conditions + .get(Array.from(sf2.conditions)[0].id); + + should(cd2).instanceOf(RangeCondition); + should(cd2.subfilters).eql(new Set([sf2])); + should(cd2.low).approximately(10, 1e-9); + should(cd2.high).approximately(78, 1e-9); + + const cd3 = store.fields.get('foo').conditions + .get(Array.from(sf2.conditions)[1].id); + + should(cd3).instanceOf(RangeCondition); + should(cd3.subfilters).eql(new Set([sf2])); + should(cd3.low).exactly(0); + should(cd3.high).exactly(50); + + should(store.fields.get('foo').tree).be.an.Object(); }); }); describe('#matching', () => { it('should match a document with its value outside the range', () => { - return dsl.register('index', 'collection', {not: {range: {foo: {gt: 42, lt: 110}}}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: -89})).eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + not: { + range: { + foo: { + gt: 42, + lt: 110, + }, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: -89})).eql([subscription.id]); }); it('should match a document with its value exactly on the lower exclusive boundary', () => { - return dsl.register('index', 'collection', {not: {range: {foo: {gt: 42, lt: 110}}}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: 42})).eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + not: { + range: { + foo: { + gt: 42, + lt: 110, + }, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 42})).eql([subscription.id]); }); it('should match a document with its value exactly on the upper exclusive boundary', () => { - return dsl.register('index', 'collection', {not: {range: {foo: {gt: 42, lt: 110}}}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: 110})).be.eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + not: { + range: { + foo: { + gt: 42, + lt: 110, + }, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 110})) + .be.eql([subscription.id]); }); it('should not match a document with its value exactly on the lower inclusive boundary', () => { - return dsl.register('index', 'collection', {not: {range: {foo: {gte: 42, lt: 110}}}}) - .then(() => { - should(dsl.test('index', 'collection', {foo: 42})).be.an.Array().and.be.empty(); - }); + dsl.register('index', 'collection', { + not: { + range: { + foo: { + gte: 42, + lt: 110, + }, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 42})) + .be.an.Array().and.be.empty(); }); it('should not match a document with its value exactly on the upper inclusive boundary', () => { - return dsl.register('index', 'collection', {not: {range: {foo: {gt: 42, lte: 110}}}}) - .then(() => { - should(dsl.test('index', 'collection', {foo: 110})).be.an.Array().and.be.empty(); - }); + dsl.register('index', 'collection', { + not: { + range: { + foo: { + gt: 42, + lte: 110, + }, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 110})) + .be.an.Array().and.be.empty(); }); it('should match a document with only a lower boundary range', () => { - return dsl.register('index', 'collection', {not: {range: {foo: {gt: -10}}}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: -25})).be.eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + not: { + range: { + foo: { gt: -10 }, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: -25})) + .be.eql([subscription.id]); }); it('should match a document with only an upper boundary range', () => { - return dsl.register('index', 'collection', {not: {range: {foo: {lt: -10}}}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: 105})).be.eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + not: { + range: { + foo: { lt: -10 }, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 105})) + .be.eql([subscription.id]); }); it('should return all notrange filters attached to the field if the document does not contain the registered field', () => { - return dsl.register('i', 'c', {not: {range: {foo: {lt: -10}}}}) - .then(() => dsl.register('i', 'c', {not: {range: {foo: {gt: 42}}}})) - .then(() => dsl.register('i', 'c', {not: {range: {foo: {gte: -20, lt: 9999999}}}})) - .then(() => { - should(dsl.test('i', 'c', {bar: 105})) - .be.an.Array() - .length(3); - }); + dsl.register('i', 'c', { + not: { + range: { + foo: { lt: -10 }, + }, + }, + }); + + dsl.register('i', 'c', { + not: { + range: { + foo: { gt: 42 }, + }, + }, + }); + + dsl.register('i', 'c', { + not: { + range: { + foo: { + gte: -20, + lt: 9999999, + }, + }, + }, + }); + + should(dsl.test('i', 'c', {bar: 105})) + .be.an.Array() + .length(3); }); it('should return all notrange filters attached to the field if the document searched field is not a number', () => { - return dsl.register('index', 'collection', {not: {range: {foo: {lt: -10}}}}) - .then(response => { - should(dsl.test('index', 'collection', {bar: 'baz'})) - .be.eql([response.id]); - }); + const subscription = dsl.register('index', 'collection', { + not: { + range: { + foo: { lt: -10 }, + }, + }, + }); + + should(dsl.test('index', 'collection', {bar: 'baz'})) + .be.eql([subscription.id]); }); }); describe('#removal', () => { it('should destroy the whole structure when removing the last item', () => { - return dsl.register('index', 'collection', {not: {range: {foo: {gte: 42, lte: 110}}}}) - .then(subscription => dsl.remove(subscription.id)) - .then(() => should(dsl.storage.foPairs._cache).be.empty()); + const subscription = dsl.register('index', 'collection', { + not: { + range: { + foo: { + gte: 42, + lte: 110, + }, + }, + }, + }); + + dsl.remove(subscription.id); + should(foPairs._cache).be.empty(); }); it('should remove a single subfilter from a multi-filter condition', () => { - let - storage, - multiSubfilter; - - return dsl.register('index', 'collection', {not: {range: {foo: {gte: 42, lte: 110}}}}) - .then(subscription => { - storage = dsl.storage.foPairs.get('index', 'collection', 'notrange'); - multiSubfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - - return dsl.register('index', 'collection', { - and: [ - {not: {range: {foo: {lt: 50}}}}, - {not: {range: {foo: {gt: 2}}}}, - {not: {range: {foo: {gte: 42, lte: 110}}}} - ] - }); - }) - .then(subscription => { - should(storage.fields.get('foo').conditions.size).eql(3); - return dsl.remove(subscription.id); - }) - .then(() => { - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').conditions.size).eql(1); - - const rcd = storage.fields.get('foo').conditions.get( - Array.from(multiSubfilter.conditions)[0].id); - should(rcd).instanceOf(RangeCondition); - should(rcd.subfilters).match(new Set([multiSubfilter])); - should(rcd.low).approximately(42, 1e-9); - should(rcd.high).approximately(110, 1e-9); - }); + const sub1 = dsl.register('index', 'collection', { + not: { + range: { + foo: { + gte: 42, + lte: 110, + }, + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + and: [ + {not: {range: {foo: {lt: 50}}}}, + {not: {range: {foo: {gt: 2}}}}, + {not: {range: {foo: {gte: 42, lte: 110}}}}, + ] + }); + + const storage = foPairs.get('index', 'collection', 'notrange'); + + should(storage.fields.get('foo').conditions.size).eql(3); + + dsl.remove(sub2.id); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').conditions.size).eql(1); + + const multiSubfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + const rcd = storage.fields.get('foo').conditions + .get(Array.from(multiSubfilter.conditions)[0].id); + + should(rcd).instanceOf(RangeCondition); + should(rcd.subfilters).match(new Set([multiSubfilter])); + should(rcd.low).approximately(42, 1e-9); + should(rcd.high).approximately(110, 1e-9); }); it('should remove a field from the list if its last subfilter is removed', () => { - let - idToRemove, - multiSubfilter; - - return dsl - .register('index', 'collection', { - not: { - range: { - bar: { gt: 42, lt: 110 } - } - } - }) - .then(subscription => { - idToRemove = subscription.id; - - return dsl.register('index', 'collection', { - not: { - range: { - foo: { gt: 42, lt: 110 } - } - } - }); - }) - .then(subscription => { - multiSubfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - const operand = dsl.storage.foPairs - .get('index', 'collection', 'notrange'); - - should(operand.fields).have.keys('bar', 'foo'); - return dsl.remove(idToRemove); - }) - .then(() => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'notrange'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').conditions.size).eql(1); - - const rcd = storage.fields.get('foo').conditions.get(Array.from(multiSubfilter.conditions)[0].id); - - should(rcd).instanceOf(RangeCondition); - should(rcd.subfilters).match(new Set([multiSubfilter])); - should(rcd.low).eql(42); - should(rcd.high).eql(110); - should(storage.fields.get('bar')).be.undefined(); - }); + const sub1 = dsl.register('index', 'collection', { + not: { + range: { + bar: { + gt: 42, + lt: 110, + }, + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + not: { + range: { + foo: { + gt: 42, + lt: 110, + }, + }, + }, + }); + + const operand = dsl.storage.foPairs + .get('index', 'collection', 'notrange'); + + should(operand.fields).have.keys('bar', 'foo'); + + dsl.remove(sub1.id); + + const storage = foPairs.get('index', 'collection', 'notrange'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').conditions.size).eql(1); + + const multiSubfilter = Array.from(filters.get(sub2.id).subfilters)[0]; + const rcd = storage.fields.get('foo').conditions + .get(Array.from(multiSubfilter.conditions)[0].id); + + should(rcd).instanceOf(RangeCondition); + should(rcd.subfilters).match(new Set([multiSubfilter])); + should(rcd.low).eql(42); + should(rcd.high).eql(110); + should(storage.fields.get('bar')).be.undefined(); }); }); }); diff --git a/test/keywords/notregexp.test.js b/test/keywords/notregexp.test.js index dd0352e..197b839 100644 --- a/test/keywords/notregexp.test.js +++ b/test/keywords/notregexp.test.js @@ -7,103 +7,172 @@ const DSL = require('../../'); describe('DSL.keyword.notregexp', () => { let dsl; + let filters; + let foPairs; beforeEach(() => { dsl = new DSL(); + filters = dsl.storage.filters; + foPairs = dsl.storage.foPairs; }); describe('#storage', () => { it('should invoke regexp storage function', () => { const spy = sinon.spy(dsl.storage.storeOperand, 'regexp'); - return dsl.register('index', 'collection', {not: {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}}) - .then(subscription => { - const - storage = dsl.storage.foPairs.get('index', 'collection', 'notregexp'), - condition = new RegexpCondition( - { regExpEngine: 're2' }, - '^\\w{2}oba\\w$', - Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - 'i' - ); - - should(spy.called).be.true(); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(condition.stringValue)).eql(condition); - }); + const subscription = dsl.register('index', 'collection', { + not: { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }, + }); + + const storage = foPairs.get('index', 'collection', 'notregexp'); + const condition = new RegexpCondition( + { regExpEngine: 're2' }, + '^\\w{2}oba\\w$', + Array.from(filters.get(subscription.id).subfilters)[0], + 'i'); + + should(spy.called).be.true(); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(condition.stringValue)) + .eql(condition); }); it('should invoke regexp storage function (js engine)', () => { dsl = new DSL({ regExpEngine: 'js' }); const spy = sinon.spy(dsl.storage.storeOperand, 'regexp'); - return dsl.register('index', 'collection', {not: {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}}) - .then(subscription => { - const - storage = dsl.storage.foPairs.get('index', 'collection', 'notregexp'), - condition = new RegexpCondition( - { regExpEngine: 'js' }, - '^\\w{2}oba\\w$', - Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - 'i' - ); - - should(spy.called).be.true(); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(condition.stringValue)).eql(condition); - }); + const subscription = dsl.register('index', 'collection', { + not: { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }, + }); + + const storage = dsl.storage.foPairs.get('index', 'collection', 'notregexp'); + const condition = new RegexpCondition( + { regExpEngine: 'js' }, + '^\\w{2}oba\\w$', + Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], + 'i'); + + should(spy.called).be.true(); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(condition.stringValue)) + .eql(condition); }); }); describe('#matching', () => { it('should not match a document if its registered field matches the regexp', () => { - return dsl.register('index', 'collection', {not: {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}}) - .then(() => { - should(dsl.test('index', 'collection', {foo: 'foobar'})).be.an.Array().and.be.empty(); - }); + dsl.register('index', 'collection', { + not: { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 'foobar'})) + .be.an.Array().and.be.empty(); }); it('should match a document if its registered field does not match the regexp', () => { - return dsl.register('index', 'collection', {not: {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: 'bar'}); - - should(result).eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + not: { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }, + }); + + const result = dsl.test('index', 'collection', {foo: 'bar'}); + + should(result).eql([subscription.id]); }); it('should match if the document does not contain the registered field', () => { - return dsl.register('index', 'collection', {not: {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}}) - .then(() => { - should(dsl.test('index', 'collection', {bar: 'qux'})) - .be.an.Array() - .and.have.length(1); - }); + dsl.register('index', 'collection', { + not: { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }, + }); + + should(dsl.test('index', 'collection', {bar: 'qux'})) + .be.an.Array() + .and.have.length(1); }); it('should match a document with the subscribed nested keyword', () => { - return dsl.register('index', 'collection', {not: {regexp: {'foo.bar.baz': {value: '^\\w{2}oba\\w$', flags: 'i'}}}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: {bar: {baz: 'bar'}}}); - - should(result).eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + not: { + regexp: { + 'foo.bar.baz': { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }, + }); + + const result = dsl.test('index', 'collection', {foo: {bar: {baz: 'bar'}}}); + + should(result).eql([subscription.id]); }); it('should not match if the document is in another index', () => { - return dsl.register('index', 'collection', {not: {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}}) - .then(() => { - should(dsl.test('foobar', 'collection', {foo: 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', { + not: { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }, + }); + + should(dsl.test('foobar', 'collection', {foo: 'qux'})) + .be.an.Array().and.empty(); }); it('should not match if the document is in another collection', () => { - return dsl.register('index', 'collection', {not: {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}}) - .then(() => { - should(dsl.test('index', 'foobar', {foo: 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', { + not: { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }, + }); + + should(dsl.test('index', 'foobar', {foo: 'qux'})) + .be.an.Array().and.empty(); }); }); @@ -111,12 +180,21 @@ describe('DSL.keyword.notregexp', () => { it('should invoke regexp removal function', () => { const spy = sinon.spy(dsl.storage.removeOperand, 'regexp'); - return dsl.register('index', 'collection', {not: {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}}) - .then(subscription => dsl.remove(subscription.id)) - .then(() => { - should(spy.called).be.true(); - should(dsl.storage.foPairs._cache).be.empty(); - }); + const subscription = dsl.register('index', 'collection', { + not: { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }, + }); + + dsl.remove(subscription.id); + + should(spy.called).be.true(); + should(dsl.storage.foPairs._cache).be.empty(); }); }); }); diff --git a/test/keywords/range.test.js b/test/keywords/range.test.js index b0410e9..ca96a83 100644 --- a/test/keywords/range.test.js +++ b/test/keywords/range.test.js @@ -6,55 +6,59 @@ const DSL = require('../../'); describe('DSL.keyword.range', () => { let dsl; + let filters; + let foPairs; beforeEach(() => { dsl = new DSL(); + filters = dsl.storage.filters; + foPairs = dsl.storage.foPairs; }); describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({range: {}})) - .be.rejectedWith('"range" must be a non-empty object'); + should(() => dsl.validate({range: {}})) + .throw('"range" must be a non-empty object'); }); it('should reject filters with more than 1 field', () => { - return should(dsl.validate({range: {foo: 'foo', bar: 'bar'}})) - .be.rejectedWith('"range" can contain only one attribute'); + should(() => dsl.validate({range: {foo: 'foo', bar: 'bar'}})) + .throw('"range" can contain only one attribute'); }); it('should reject an empty field definition', () => { - return should(dsl.validate({range: {foo: {}}})) - .be.rejectedWith('"range.foo" must be a non-empty object'); + should(() => dsl.validate({range: {foo: {}}})) + .throw('"range.foo" must be a non-empty object'); }); it('should reject a field definition containing an unrecognized range keyword', () => { - return should(dsl.validate({range: {foo: {gt: 42, lt: 113, bar: 'baz'}}})) - .be.rejectedWith('"range.foo" accepts only the following attributes : gt, gte, lt, lte'); + should(() => dsl.validate({range: {foo: {gt: 42, lt: 113, bar: 'baz'}}})) + .throw('"range.foo" accepts only the following attributes : gt, gte, lt, lte'); }); it('should reject a field definition with a range keyword not containing a number', () => { - return should(dsl.validate({range: {foo: {gt: '42', lt: 113}}})) - .be.rejectedWith('"range.foo.gt" must be a number'); + should(() => dsl.validate({range: {foo: {gt: '42', lt: 113}}})) + .throw('"range.foo.gt" must be a number'); }); it('should reject a field definition containing more than 1 lower boundary', () => { - return should(dsl.validate({range: {foo: {gt: 42, gte: 13, lt: 113}}})) - .be.rejectedWith('"range.foo:" only 1 lower boundary allowed'); + should(() => dsl.validate({range: {foo: {gt: 42, gte: 13, lt: 113}}})) + .throw('"range.foo:" only 1 lower boundary allowed'); }); it('should reject a field definition containing more than 1 upper boundary', () => { - return should(dsl.validate({range: {foo: {gt: 42, lt: 113, lte: 200}}})) - .be.rejectedWith('"range.foo:" only 1 upper boundary allowed'); + should(() => dsl.validate({range: {foo: {gt: 42, lt: 113, lte: 200}}})) + .throw('"range.foo:" only 1 upper boundary allowed'); }); it('should validate a valid range filter', () => { - return should(dsl.validate({range: {foo: {gt: 42, lte: 200}}})) - .be.fulfilled(); + should(() => dsl.validate({range: {foo: {gt: 42, lte: 200}}})) + .not.throw(); }); it('should reject a range filter with inverted boundaries', () => { - return should(dsl.validate({range: {foo: {lt: 42, gt: 200}}})) - .be.rejectedWith('"range.foo:" lower boundary must be strictly inferior to the upper one'); + should(() => dsl.validate({range: {foo: {lt: 42, gt: 200}}})) + .throw('"range.foo:" lower boundary must be strictly inferior to the upper one'); }); }); @@ -67,201 +71,269 @@ describe('DSL.keyword.range', () => { describe('#storage', () => { it('should store a single condition correctly', () => { - return dsl.register('index', 'collection', {range: {foo: {gt: 42, lt: 100}}}) - .then(subscription => { - const - subfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - store = dsl.storage.foPairs.get('index', 'collection', 'range'); - - should(store).be.instanceOf(FieldOperand); - should(store.fields.get('foo').conditions.size).be.eql(1); - - const rangeInfo = Array.from( - store.fields.get('foo').conditions.values())[0]; - should(rangeInfo).instanceOf(RangeCondition); - should(rangeInfo.subfilters).match(new Set([subfilter])); - should(rangeInfo.low).approximately(42, 1e-9); - should(rangeInfo.high).approximately(100, 1e-9); - }); + const subscription = dsl.register('index', 'collection', { + range: { + foo: { + gt: 42, + lt: 100, + }, + }, + }); + + const subfilter = Array.from(filters.get(subscription.id).subfilters)[0]; + const store = foPairs.get('index', 'collection', 'range'); + + should(store).be.instanceOf(FieldOperand); + should(store.fields.get('foo').conditions.size).be.eql(1); + + const rangeInfo = Array + .from(store.fields.get('foo').conditions.values())[0]; + + should(rangeInfo).instanceOf(RangeCondition); + should(rangeInfo.subfilters).match(new Set([subfilter])); + should(rangeInfo.low).approximately(42, 1e-9); + should(rangeInfo.high).approximately(100, 1e-9); }); it('should store multiple conditions on the same field correctly', () => { - let sf1; - - return dsl.register('index', 'collection', {range: {foo: {gt: 42, lt: 100}}}) - .then(subscription => { - sf1 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - - return dsl.register('index', 'collection', {range: {foo: {gte: 10, lte: 78}}}); - }) - .then(subscription => { - const - sf2 = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - store = dsl.storage.foPairs.get('index', 'collection', 'range'); - - should(store).be.instanceOf(FieldOperand); - should(store.fields.get('foo').conditions.size).be.eql(2); - - let rangeInfo = store.fields.get('foo').conditions.get( - Array.from(sf1.conditions)[0].id); - should(rangeInfo).instanceOf(RangeCondition); - should(rangeInfo.subfilters).match(new Set([sf1])); - should(rangeInfo.low).approximately(42, 1e-9); - should(rangeInfo.high).approximately(100, 1e-9); - - rangeInfo = store.fields.get('foo').conditions.get( - Array.from(sf2.conditions)[0].id); - should(rangeInfo).instanceOf(RangeCondition); - should(rangeInfo.subfilters).match(new Set([sf2])); - should(rangeInfo.low).be.exactly(10); - should(rangeInfo.high).be.exactly(78); - - should(store.fields.get('foo').tree).be.an.Object(); - }); + const sub1 = dsl.register('index', 'collection', { + range: { + foo: { + gt: 42, + lt: 100, + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + range: { + foo: { + gte: 10, + lte: 78, + }, + }, + }); + + const sf1 = Array.from(filters.get(sub1.id).subfilters)[0]; + const sf2 = Array.from(filters.get(sub2.id).subfilters)[0]; + const store = foPairs.get('index', 'collection', 'range'); + + should(store).be.instanceOf(FieldOperand); + should(store.fields.get('foo').conditions.size).be.eql(2); + + let rangeInfo = store.fields.get('foo').conditions + .get(Array.from(sf1.conditions)[0].id); + should(rangeInfo).instanceOf(RangeCondition); + should(rangeInfo.subfilters).match(new Set([sf1])); + should(rangeInfo.low).approximately(42, 1e-9); + should(rangeInfo.high).approximately(100, 1e-9); + + rangeInfo = store.fields.get('foo').conditions + .get(Array.from(sf2.conditions)[0].id); + should(rangeInfo).instanceOf(RangeCondition); + should(rangeInfo.subfilters).match(new Set([sf2])); + should(rangeInfo.low).be.exactly(10); + should(rangeInfo.high).be.exactly(78); + + should(store.fields.get('foo').tree).be.an.Object(); }); }); describe('#matching', () => { it('should match a document with its value in the range', () => { - return dsl.register('index', 'collection', {range: {foo: {gt: 42, lt: 110}}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: 73})).eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + range: { + foo: { + gt: 42, + lt: 110, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 73})).eql([subscription.id]); }); it('should match a document with its value exactly on the lower inclusive boundary', () => { - return dsl.register('index', 'collection', {range: {foo: {gte: 42, lt: 110}}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: 42})).eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + range: { + foo: { + gte: 42, + lt: 110, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 42})).eql([subscription.id]); }); it('should match a document with its value exactly on the upper inclusive boundary', () => { - return dsl.register('index', 'collection', {range: {foo: {gt: 42, lte: 110}}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: 110})).eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + range: { + foo: { + gt: 42, + lte: 110, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 110})).eql([subscription.id]); }); it('should not match a document with its value exactly on the lower exclusive boundary', () => { - return dsl.register('index', 'collection', {range: {foo: {gt: 42, lt: 110}}}) - .then(() => { - should(dsl.test('index', 'collection', {foo: 42})).be.an.Array().and.be.empty(); - }); + dsl.register('index', 'collection', { + range: { + foo: { + gt: 42, + lt: 110, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 42})) + .be.an.Array().and.be.empty(); }); it('should not match a document with its value exactly on the upper exclusive boundary', () => { - return dsl.register('index', 'collection', {range: {foo: {gt: 42, lt: 110}}}) - .then(() => { - should(dsl.test('index', 'collection', {foo: 110})).be.an.Array().and.be.empty(); - }); + dsl.register('index', 'collection', { + range: { + foo: { + gt: 42, + lt: 110, + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 110})) + .be.an.Array().and.be.empty(); }); it('should match a document with only a lower boundary range', () => { - return dsl.register('index', 'collection', {range: {foo: {gt: -10}}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: -5})).eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + range: { + foo: {gt: -10}, + }, + }); + + should(dsl.test('index', 'collection', {foo: -5})).eql([subscription.id]); }); it('should match a document with only an upper boundary range', () => { - return dsl.register('index', 'collection', {range: {foo: {lt: -10}}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: -105})).eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + range: { + foo: {lt: -10}, + }, + }); + + should(dsl.test('index', 'collection', {foo: -105})).eql([subscription.id]); }); it('should return an empty array if the document does not contain the registered field', () => { - return dsl.register('index', 'collection', {range: {foo: {lt: -10}}}) - .then(() => { - should(dsl.test('index', 'collection', {bar: -105})).be.an.Array().and.be.empty(); - }); + dsl.register('index', 'collection', {range: {foo: {lt: -10}}}); + + should(dsl.test('index', 'collection', {bar: -105})) + .be.an.Array().and.be.empty(); }); it('should return an empty array if the document searched field is not a number', () => { - return dsl.register('index', 'collection', {range: {foo: {lt: -10}}}) - .then(() => { - should(dsl.test('index', 'collection', {bar: 'baz'})).be.an.Array().and.be.empty(); - }); + dsl.register('index', 'collection', {range: {foo: {lt: -10}}}); + + should(dsl.test('index', 'collection', {bar: 'baz'})) + .be.an.Array().and.be.empty(); }); it('should consider 0 as a valid value', () => { - return dsl.register('i', 'c', {range: {foo: {lt: 42}}}) - .then(response => { - should(dsl.test('i', 'c', {foo: 0})) - .be.eql([response.id]); - }); + const subscription = dsl.register('i', 'c', {range: {foo: {lt: 42}}}); + + should(dsl.test('i', 'c', {foo: 0})).be.eql([subscription.id]); }); }); describe('#removal', () => { it('should destroy the whole structure when removing the last item', () => { - return dsl.register('index', 'collection', {range: {foo: {gte: 42, lte: 110}}}) - .then(subscription => dsl.remove(subscription.id)) - .then(() => should(dsl.storage.foPairs._cache).be.empty()); + const subscription = dsl.register('index', 'collection', { + range: { + foo: { + gte: 42, + lte: 110, + }, + }, + }); + + dsl.remove(subscription.id); + + should(dsl.storage.foPairs._cache).be.empty(); }); it('should remove a single subfilter from a multi-filter condition', () => { - let - storage, - multiSubfilter; - - return dsl.register('index', 'collection', {range: {foo: {gt: 42, lt: 110}}}) - .then(subscription => { - storage = dsl.storage.foPairs.get('index', 'collection', 'range'); - multiSubfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - return dsl.register('index', 'collection', { - and: [ - {range: {foo: {gt: 42, lt: 110}}}, - {range: {foo: {lt: 50}}} - ] - }); - }) - .then(subscription => { - should(storage.fields.get('foo').conditions.size).eql(2); - return dsl.remove(subscription.id); - }) - .then(() => { - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').conditions.size).eql(1); - - const rangeInfo = Array.from(storage.fields.get('foo').conditions.values())[0]; - should(rangeInfo.subfilters).match(new Set([multiSubfilter])); - should(rangeInfo.low).approximately(42, 1e-9); - should(rangeInfo.high).approximately(110, 1e-9); - }); + const sub1 = dsl.register('index', 'collection', { + range: { + foo: { + gt: 42, + lt: 110, + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + and: [ + {range: {foo: {gt: 42, lt: 110}}}, + {range: {foo: {lt: 50}}}, + ], + }); + + const storage = foPairs.get('index', 'collection', 'range'); + const multiSubfilter = Array.from(filters.get(sub1.id).subfilters)[0]; + + should(storage.fields.get('foo').conditions.size).eql(2); + + dsl.remove(sub2.id); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').conditions.size).eql(1); + + const rangeInfo = Array + .from(storage.fields.get('foo').conditions.values())[0]; + + should(rangeInfo.subfilters).match(new Set([multiSubfilter])); + should(rangeInfo.low).approximately(42, 1e-9); + should(rangeInfo.high).approximately(110, 1e-9); }); it('should remove a field from the list if its last subfilter is removed', () => { - let - idToRemove, - multiSubfilter; - - return dsl.register('index', 'collection', {range: {bar: {gt: 42, lt: 110}}}) - .then(subscription => { - idToRemove = subscription.id; - - return dsl.register('index', 'collection', {range: {foo: {gte: 42, lte: 110}}}); - }) - .then(subscription => { - multiSubfilter = Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]; - const operand = dsl.storage.foPairs.get('index', 'collection', 'range'); - - should(operand.fields).have.keys('bar', 'foo'); - return dsl.remove(idToRemove); - }) - .then(() => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'range'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').conditions.size).eql(1); - - const rangeInfo = Array.from(storage.fields.get('foo').conditions.values())[0]; - should(rangeInfo.subfilters).match(new Set([multiSubfilter])); - should(rangeInfo.low).approximately(42, 1e-9); - should(rangeInfo.high).approximately(110, 1e-9); - should(storage.fields.get('bar')).be.undefined(); - }); + const sub1 = dsl.register('index', 'collection', { + range: { + bar: { + gt: 42, + lt: 110, + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + range: { + foo: { + gte: 42, + lte: 110, + }, + }, + }); + + const multiSubfilter = Array.from(filters.get(sub2.id).subfilters)[0]; + const operand = foPairs.get('index', 'collection', 'range'); + + should(operand.fields).have.keys('bar', 'foo'); + + dsl.remove(sub1.id); + const storage = foPairs.get('index', 'collection', 'range'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').conditions.size).eql(1); + + const rangeInfo = Array.from(storage.fields.get('foo').conditions.values())[0]; + should(rangeInfo.subfilters).match(new Set([multiSubfilter])); + should(rangeInfo.low).approximately(42, 1e-9); + should(rangeInfo.high).approximately(110, 1e-9); + should(storage.fields.get('bar')).be.undefined(); }); }); }); diff --git a/test/keywords/regexp.test.js b/test/keywords/regexp.test.js index 4568cb1..b55714b 100644 --- a/test/keywords/regexp.test.js +++ b/test/keywords/regexp.test.js @@ -5,54 +5,59 @@ const DSL = require('../../'); describe('DSL.keyword.regexp', () => { let dsl; + let filters; + let foPairs; beforeEach(() => { dsl = new DSL(); + filters = dsl.storage.filters; + foPairs = dsl.storage.foPairs; }); describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({regexp: {}})) - .be.rejectedWith('"regexp" must be a non-empty object'); + should(() => dsl.validate({regexp: {}})) + .throw('"regexp" must be a non-empty object'); }); it('should reject filters with more than 1 field', () => { const filter = {foo: {value: 'foo'}, bar: {value: 'foo'}}; - return should(dsl.validate({regexp: filter})) - .be.rejectedWith('"regexp" can contain only one attribute'); + should(() => dsl.validate({regexp: filter})) + .throw('"regexp" can contain only one attribute'); }); it('should reject filters with an empty field object', () => { - return should(dsl.validate({regexp: {foo: {}}})) - .be.rejectedWith('regexp.foo must be either a string or a non-empty object'); + should(() => dsl.validate({regexp: {foo: {}}})) + .throw('regexp.foo must be either a string or a non-empty object'); }); it('should reject filters with other fields defined other than the accepted ones', () => { const filter = {foo: {value: 'foo', flags: 'ig', bar: 'qux'}}; - return should(dsl.validate({regexp: filter})) - .be.rejectedWith('Keyword "regexp" can only contain the following attributes: flags, value'); + should(() => dsl.validate({regexp: filter})) + .throw('Keyword "regexp" can only contain the following attributes: flags, value'); }); it('should reject filters if the "value" attribute is not defined', () => { - return should(dsl.validate({regexp: {foo: {flags: 'ig'}}})) - .be.rejectedWith('"regexp" requires the following attribute: value'); + should(() => dsl.validate({regexp: {foo: {flags: 'ig'}}})) + .throw('"regexp" requires the following attribute: value'); }); it('should reject filters with a non-string "flags" attribute', () => { - return should(dsl.validate({regexp: {foo: {value: 'foo', flags: 42}}})) - .be.rejectedWith('Attribute "flags" in "regexp" must be a string'); + should(() => dsl.validate({regexp: {foo: {value: 'foo', flags: 42}}})) + .throw('Attribute "flags" in "regexp" must be a string'); }); it('should reject filters with an invalid regular expression value', () => { - return should(dsl.validate({regexp: {foo: {value: 'foo(', flags: 'i'}}})) - .be.rejectedWith(/^Cannot parse regexp expression/); + should(() => dsl.validate({regexp: {foo: {value: 'foo(', flags: 'i'}}})) + .throw(/^Cannot parse regexp expression/); }); it('should reject filters with invalid flags (js engine only)', () => { dsl = new DSL({ regExpEngine: 'js' }); - return should(dsl.validate({ + + should(() => dsl.validate({ regexp: { foo: { value: 'a', @@ -60,260 +65,372 @@ describe('DSL.keyword.regexp', () => { } } })) - .be.rejectedWith(/^Cannot parse regexp expression/); + .throw(/^Cannot parse regexp expression/); }); it('should validate a well-formed regular expression filter w/ flags', () => { - return dsl.normalize('foo', 'bar', {regexp: {foo: {value: 'foo', flags: 'i'}}}) - .then(res => { - should(res.normalized).match([[{regexp:{foo:{flags:'i',value:'foo'}}}]]); - }); + const res = dsl.normalize('foo', 'bar', { + regexp: { + foo: { + value: 'foo', + flags: 'i', + }, + }, + }); + + should(res.normalized).match([[{regexp:{foo:{flags:'i',value:'foo'}}}]]); }); it('should validate a well-formed regular expression filter without flags', () => { - return dsl.normalize('foo', 'bar', {regexp: {foo: {value: 'foo'}}}) - .then(res => { - should(res.normalized).match([[{regexp:{foo:{flags:undefined,value:'foo'}}}]]); - }); + const res = dsl.normalize('foo', 'bar', {regexp: {foo: {value: 'foo'}}}); + + should(res.normalized).match([ + [ + { + regexp: { + foo: { + flags: undefined, + value: 'foo', + }, + }, + }, + ], + ]); }); it('should accept a simplified form', () => { - return dsl.normalize('foo', 'bar', {regexp: {foo: '^bar'}}) - .then(res => { - should(res.normalized).match([[{regexp:{foo:{flags:undefined,value:'^bar'}}}]]); - }); + const res = dsl.normalize('foo', 'bar', {regexp: {foo: '^bar'}}); + + should(res.normalized).match([ + [ + { + regexp: { + foo: { + flags: undefined, + value: '^bar', + }, + }, + }, + ], + ]); }); it('should reject an invalid simple form regex', () => { - return should(dsl.validate({ - regexp: { - foo: '++' - } - })) - .be.rejectedWith(/^Cannot parse regexp expression/); + should(() => dsl.validate({ regexp: { foo: '++' } })) + .throw(/^Cannot parse regexp expression/); }); }); describe('#standardization', () => { it('should return the same content, unchanged', () => { - const filter = {regexp: {foo: {value: 'foo', flags: 'i'}}}; + const filter = { + regexp: { + foo: { + value: 'foo', + flags: 'i', + }, + }, + }; + should(dsl.transformer.standardizer.standardize(filter)).match(filter); }); }); describe('#storage', () => { it('should store a single condition correctly', () => { - return dsl.register('index', 'collection', {regexp: {foo: {value: 'foo', flags: 'i'}}}) - .then(subscription => { - const - storage = dsl.storage.foPairs.get('index', 'collection', 'regexp'), - regexp = new RegexpCondition( - { regExpEngine: 're2' }, - 'foo', - Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - 'i' - ); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(regexp.stringValue)).eql(regexp); - }); + const subscription = dsl.register('index', 'collection', { + regexp: { + foo: { + value: 'foo', + flags: 'i', + }, + }, + }); + + const storage = foPairs.get('index', 'collection', 'regexp'); + const regexp = new RegexpCondition( + { regExpEngine: 're2' }, + 'foo', + Array.from(filters.get(subscription.id).subfilters)[0], + 'i'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(regexp.stringValue)).eql(regexp); }); it('should store multiple conditions on the same field correctly', () => { - let cond1; - - return dsl.register('index', 'collection', {regexp: {foo: {value: 'foo', flags: 'i'}}}) - .then(subscription => { - cond1 = new RegexpCondition( - { regExpEngine: 're2' }, - 'foo', - Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - 'i' - ); - - return dsl.register('index', 'collection', {regexp: {foo: {value: 'bar'}}}); - }) - .then(subscription => { - const - storage = dsl.storage.foPairs.get('index', 'collection', 'regexp'), - cond2 = new RegexpCondition( - { regExpEngine: 're2' }, - 'bar', - Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0] - ); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').size).eql(2); - should(storage.fields.get('foo').get(cond1.stringValue)).eql(cond1); - should(storage.fields.get('foo').get(cond2.stringValue)).eql(cond2); - }); + const sub1 = dsl.register('index', 'collection', { + regexp: { + foo: { + value: 'foo', + flags: 'i', + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + regexp: { + foo: { + value: 'bar', + }, + }, + }); + + const cond1 = new RegexpCondition( + { regExpEngine: 're2' }, + 'foo', + Array.from(filters.get(sub1.id).subfilters)[0], + 'i'); + const storage = foPairs.get('index', 'collection', 'regexp'); + const cond2 = new RegexpCondition( + { regExpEngine: 're2' }, + 'bar', + Array.from(filters.get(sub2.id).subfilters)[0]); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').size).eql(2); + should(storage.fields.get('foo').get(cond1.stringValue)).eql(cond1); + should(storage.fields.get('foo').get(cond2.stringValue)).eql(cond2); }); it('should store multiple subfilters on the same condition correctly', () => { - let cond; - const filter = {regexp: {foo: {value: 'foo', flags: 'i'}}}; - - return dsl.register('index', 'collection', filter) - .then(subscription => { - cond = new RegexpCondition( - { regExpEngine: 're2' }, - 'foo', - Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - 'i' - ); - - return dsl.register('index', 'collection', {and: [filter, {equals: {foo: 'bar'}}]}); - }) - .then(subscription => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'regexp'); - cond.subfilters.add(Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0]); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').size).eql(1); - should(storage.fields.get('foo').get(cond.stringValue)).eql(cond); - }); + const filter = { + regexp: { + foo: { + value: 'foo', + flags: 'i', + }, + }, + }; + + + const sub2 = dsl.register('index', 'collection', { + and: [ + filter, + {equals: {foo: 'bar'}}, + ], + }); + + const storage = foPairs.get('index', 'collection', 'regexp'); + const sub1 = dsl.register('index', 'collection', filter); + const cond = new RegexpCondition( + { regExpEngine: 're2' }, + 'foo', + Array.from(filters.get(sub1.id).subfilters)[0], + 'i'); + + cond.subfilters.add(Array.from(filters.get(sub2.id).subfilters)[0]); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').size).eql(1); + should(storage.fields.get('foo').get(cond.stringValue)).eql(cond); }); }); describe('#matching', () => { it('should match a document if its registered field matches the regexp', () => { - return dsl.register('index', 'collection', {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}) - .then(subscription => { - should(dsl.test('index', 'collection', {foo: 'FOOBAR'})).eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 'FOOBAR'})) + .eql([subscription.id]); }); it('should not match a document if its registered field does not match the regexp', () => { - return dsl.register('index', 'collection', {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}) - .then(() => { - should(dsl.test('index', 'collection', {foo: 'Saskatchewan'})).be.an.Array().and.be.empty(); - }); + dsl.register('index', 'collection', { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }); + + should(dsl.test('index', 'collection', {foo: 'Saskatchewan'})) + .be.an.Array().and.be.empty(); }); it('should not match if the document does not contain the registered field', () => { - return dsl.register('index', 'collection', {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}) - .then(() => { - should(dsl.test('index', 'collection', {bar: 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }); + + should(dsl.test('index', 'collection', {bar: 'qux'})) + .be.an.Array().and.empty(); }); it('should match a document with the subscribed nested keyword', () => { - return dsl.register('index', 'collection', {regexp: {'foo.bar.baz': {value: '^\\w{2}oba\\w$', flags: 'i'}}}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: {bar: {baz: 'FOOBAR'}}}); - - should(result).eql([subscription.id]); - }); + const subscription = dsl.register('index', 'collection', { + regexp: { + 'foo.bar.baz': { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }); + + const result = dsl.test('index', 'collection', { + foo: { + bar: {baz: 'FOOBAR'}, + }, + }); + + should(result).eql([subscription.id]); }); it('should not match if the document is in another index', () => { - return dsl.register('index', 'collection', {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}) - .then(() => { - should(dsl.test('foobar', 'collection', {foo: 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }); + + should(dsl.test('foobar', 'collection', {foo: 'qux'})) + .be.an.Array().and.empty(); }); it('should not match if the document is in another collection', () => { - return dsl.register('index', 'collection', {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}) - .then(() => { - should(dsl.test('index', 'foobar', {foo: 'qux'})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }); + + should(dsl.test('index', 'foobar', {foo: 'qux'})).be.an.Array().and.empty(); }); }); describe('#removal', () => { it('should destroy the whole structure when removing the last item', () => { - return dsl.register('index', 'collection', {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}) - .then(subscription => dsl.remove(subscription.id)) - .then(() => should(dsl.storage.foPairs._cache).be.empty()); + const subscription = dsl.register('index', 'collection', { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }); + + dsl.remove(subscription.id); + + should(foPairs._cache).be.empty(); }); it('should remove a single subfilter from a multi-filter condition', () => { - const filter = {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}; - let - idToRemove, - cond; - - return dsl.register('index', 'collection', filter) - .then(subscription => { - idToRemove = subscription.id; - - return dsl.register('index', 'collection', {and: [filter, {equals: {foo: 'bar'}}]}); - }) - .then(subscription => { - cond = new RegexpCondition( - { regExpEngine: 're2' }, - '^\\w{2}oba\\w$', - Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - 'i' - ); - - return dsl.remove(idToRemove); - }) - .then(() => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'regexp'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(cond.stringValue)).match(cond); - }); + const filter = { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }; + + const sub1 = dsl.register('index', 'collection', filter); + const sub2 = dsl.register('index', 'collection', { + and: [ + filter, + {equals: {foo: 'bar'}}, + ], + }); + + const cond = new RegexpCondition( + { regExpEngine: 're2' }, + '^\\w{2}oba\\w$', + Array.from(filters.get(sub2.id).subfilters)[0], + 'i'); + + dsl.remove(sub1.id); + + const storage = foPairs.get('index', 'collection', 'regexp'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(cond.stringValue)).match(cond); }); it('should remove a value from the list if its last subfilter is removed', () => { - let - idToRemove, - cond; - - return dsl.register('index', 'collection', {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}) - .then(subscription => { - cond = new RegexpCondition( - { regExpEngine: 're2' }, - '^\\w{2}oba\\w$', - Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - 'i' - ); - - return dsl.register('index', 'collection', {regexp: {foo: {value: '^$'}}}); - }) - .then(subscription => { - idToRemove = subscription.id; - return dsl.remove(idToRemove); - }) - .then(() => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'regexp'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(cond.stringValue)).match(cond); - should(storage.fields.get('foo').size).eql(1); - }); + const sub1 = dsl.register('index', 'collection', { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + regexp: { + foo: {value: '^$'}, + }, + }); + + const cond = new RegexpCondition( + { regExpEngine: 're2' }, + '^\\w{2}oba\\w$', + Array.from(filters.get(sub1.id).subfilters)[0], + 'i'); + + dsl.remove(sub2.id); + + const storage = foPairs.get('index', 'collection', 'regexp'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(cond.stringValue)).match(cond); + should(storage.fields.get('foo').size).eql(1); }); it('should remove a field from the list if its last value to test is removed', () => { - let cond; - - return dsl.register('index', 'collection', {regexp: {foo: {value: '^\\w{2}oba\\w$', flags: 'i'}}}) - .then(subscription => { - cond = new RegexpCondition( - { regExpEngine: 're2' }, - '^\\w{2}oba\\w$', - Array.from(dsl.storage.filters.get(subscription.id).subfilters)[0], - 'i' - ); - - return dsl.register('index', 'collection', {regexp: {bar: {value: '^\\w{2}oba\\w$', flags: 'i'}}}); - }) - .then(subscription => { - const operand = dsl.storage.foPairs.get('index', 'collection', 'regexp'); - should (operand.fields).have.keys('foo', 'bar'); - - return dsl.remove(subscription.id); - }) - .then(() => { - const storage = dsl.storage.foPairs.get('index', 'collection', 'regexp'); - - should(storage).be.instanceOf(FieldOperand); - should(storage.fields.get('foo').get(cond.stringValue)).match(cond); - should(storage.fields.get('bar')).be.undefined(); - }); + const sub1 = dsl.register('index', 'collection', { + regexp: { + foo: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }); + + const sub2 = dsl.register('index', 'collection', { + regexp: { + bar: { + value: '^\\w{2}oba\\w$', + flags: 'i', + }, + }, + }); + + const cond = new RegexpCondition( + { regExpEngine: 're2' }, + '^\\w{2}oba\\w$', + Array.from(filters.get(sub1.id).subfilters)[0], + 'i'); + + const operand = foPairs.get('index', 'collection', 'regexp'); + should (operand.fields).have.keys('foo', 'bar'); + + dsl.remove(sub2.id); + + const storage = foPairs.get('index', 'collection', 'regexp'); + + should(storage).be.instanceOf(FieldOperand); + should(storage.fields.get('foo').get(cond.stringValue)).match(cond); + should(storage.fields.get('bar')).be.undefined(); }); }); }); diff --git a/test/operands/and.test.js b/test/operands/and.test.js index eb4582d..288e24f 100644 --- a/test/operands/and.test.js +++ b/test/operands/and.test.js @@ -10,13 +10,13 @@ describe('koncorde.operands.and', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(koncorde.validate({and: []})) - .be.rejectedWith('Attribute "and" cannot be empty'); + should(() => koncorde.validate({and: []})) + .throw('Attribute "and" cannot be empty'); }); it('should reject non-array content', () => { - return should(koncorde.validate({and: {foo: 'bar'}})) - .be.rejectedWith('Attribute "and" must be an array'); + should(() => koncorde.validate({and: {foo: 'bar'}})) + .throw('Attribute "and" must be an array'); }); it('should reject if one of the content is not an object', () => { @@ -27,8 +27,8 @@ describe('koncorde.operands.and', () => { ], }; - return should(koncorde.validate(filter)) - .be.rejectedWith('"and" operand can only contain non-empty objects'); + should(() => koncorde.validate(filter)) + .throw('"and" operand can only contain non-empty objects'); }); it('should reject if one of the content object does not refer to a valid keyword', () => { @@ -39,8 +39,8 @@ describe('koncorde.operands.and', () => { ], }; - return should(koncorde.validate(filter)) - .be.rejectedWith('Unknown DSL keyword: foo'); + should(() => koncorde.validate(filter)) + .throw('Unknown DSL keyword: foo'); }); it('should reject if one of the content object is not a well-formed keyword', () => { @@ -51,8 +51,8 @@ describe('koncorde.operands.and', () => { ], }; - return should(koncorde.validate(filter)) - .be.rejectedWith('"exists" requires the following attribute: field'); + should(() => koncorde.validate(filter)) + .throw('"exists" requires the following attribute: field'); }); it('should validate a well-formed "and" operand', () => { @@ -63,7 +63,7 @@ describe('koncorde.operands.and', () => { ], }; - return should(koncorde.validate(filter)).be.fulfilled(); + should(koncorde.validate(filter)).not.throw(); }); }); @@ -73,23 +73,19 @@ describe('koncorde.operands.and', () => { and: [ { equals: { name: 'bar' } }, { exists: 'skills.languages["javascript"]' }, - // { range: { baz: { lt: 42 } } } ] }; - return koncorde.register('index', 'collection', filters) - .then(subscription => { - const result = koncorde.test( - 'index', - 'collection', - { - name: 'bar', - // baz: 13, - skills: { languages: ['c++', 'javascript', 'c#'] } - }); - - should(result).eql([subscription.id]); + const subscription = koncorde.register('index', 'collection', filters); + const result = koncorde.test( + 'index', + 'collection', + { + name: 'bar', + skills: { languages: ['c++', 'javascript', 'c#'] } }); + + should(result).eql([subscription.id]); }); it('should not match if the document misses at least 1 condition', () => { @@ -97,42 +93,40 @@ describe('koncorde.operands.and', () => { and: [ { equals: { name: 'bar' } }, { exists: 'skills.languages["javascript"]' }, - // { range: { baz: { lt: 42 } } } ] }; - return koncorde.register('index', 'collection', filters) - .then(() => { - const result = koncorde.test( - 'index', - 'collection', - { - name: 'qux', - // baz: 13, - skills: { languages: ['ruby', 'php', 'elm', 'javascript'] } - }); - - should(result).be.an.Array().and.empty(); + koncorde.register('index', 'collection', filters); + const result = koncorde.test( + 'index', + 'collection', + { + name: 'qux', + skills: { languages: ['ruby', 'php', 'elm', 'javascript'] }, }); + + should(result).be.an.Array().and.empty(); }); }); describe('#removal', () => { it('should destroy all associated keywords to an AND operand', () => { - let id; - - return koncorde.register('index', 'collection', {and: [{equals: {foo: 'bar'}}, {missing: {field: 'bar'}}, {range: {baz: {lt: 42}}}]}) - .then(subscription => { - id = subscription.id; - return koncorde.register('index', 'collection', {exists: {field: 'foo'}}); - }) - .then(() => koncorde.remove(id)) - .then(() => { - should(koncorde.storage.foPairs.get('index', 'collection', 'exists')).be.an.Object(); - should(koncorde.storage.foPairs.get('index', 'collection', 'equals')).be.undefined(); - should(koncorde.storage.foPairs.get('index', 'collection', 'notexists')).be.undefined(); - should(koncorde.storage.foPairs.get('index', 'collection', 'range')).be.undefined(); - }); + const subscription = koncorde.register('index', 'collection', { + and: [ + {equals: {foo: 'bar'}}, + {missing: {field: 'bar'}}, + {range: {baz: {lt: 42}}}, + ], + }); + + koncorde.register('index', 'collection', {exists: {field: 'foo'}}); + + koncorde.remove(subscription.id); + + should(koncorde.storage.foPairs.get('index', 'collection', 'exists')).be.an.Object(); + should(koncorde.storage.foPairs.get('index', 'collection', 'equals')).be.undefined(); + should(koncorde.storage.foPairs.get('index', 'collection', 'notexists')).be.undefined(); + should(koncorde.storage.foPairs.get('index', 'collection', 'range')).be.undefined(); }); }); }); diff --git a/test/operands/bool.test.js b/test/operands/bool.test.js index b922ad2..919c096 100644 --- a/test/operands/bool.test.js +++ b/test/operands/bool.test.js @@ -12,8 +12,8 @@ describe('DSL.operands.bool', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({bool: {}})) - .be.rejectedWith('"bool" must be a non-empty object'); + should(() => dsl.validate({bool: {}})) + .throw('"bool" must be a non-empty object'); }); it('should reject filters with unrecognized bool attributes', () => { @@ -26,8 +26,8 @@ describe('DSL.operands.bool', () => { }, }; - return should(dsl.validate(filter)) - .be.rejectedWith('"bool" operand accepts only the following attributes: must, must_not, should, should_not'); + should(() => dsl.validate(filter)) + .throw('"bool" operand accepts only the following attributes: must, must_not, should, should_not'); }); }); @@ -83,20 +83,26 @@ describe('DSL.operands.bool', () => { const result = dsl.transformer.standardizer.standardize(bool); should(result).match({ and: [ - {or: [ - {equals: {firstName: 'Grace'}}, - {equals: {firstName: 'Ada'}} - ]}, - {or: [ - {equals: {hobby: 'computer'}}, - {exists: new NormalizedExists('lastName', false, null)} - ]}, - {and: [ - {range: {age: {gte: 36, lt: 85}}}, - {not: {equals: {city: 'NYC'}}}, - {not: {regexp: {hobby: {value: '^.*ball', flags: 'i'}}}} - ]} - ] + { + or: [ + {equals: {firstName: 'Grace'}}, + {equals: {firstName: 'Ada'}}, + ], + }, + { + or: [ + {equals: {hobby: 'computer'}}, + {exists: new NormalizedExists('lastName', false, null)}, + ], + }, + { + and: [ + {range: {age: {gte: 36, lt: 85}}}, + {not: {equals: {city: 'NYC'}}}, + {not: {regexp: {hobby: {value: '^.*ball', flags: 'i'}}}}, + ], + }, + ], }); }); }); diff --git a/test/operands/or.test.js b/test/operands/or.test.js index b89139a..7eae97b 100644 --- a/test/operands/or.test.js +++ b/test/operands/or.test.js @@ -10,13 +10,13 @@ describe('DSL.operands.or', () => { describe('#validation', () => { it('should reject empty filters', () => { - return should(dsl.validate({or: []})) - .be.rejectedWith('Attribute "or" cannot be empty'); + should(() => dsl.validate({or: []})) + .throw('Attribute "or" cannot be empty'); }); it('should reject non-array content', () => { - return should(dsl.validate({or: {foo: 'bar'}})) - .be.rejectedWith('Attribute "or" must be an array'); + should(() => dsl.validate({or: {foo: 'bar'}})) + .throw('Attribute "or" must be an array'); }); it('should reject if one of the content is not an object', () => { @@ -27,8 +27,8 @@ describe('DSL.operands.or', () => { ], }; - return should(dsl.validate(filter)) - .be.rejectedWith('"or" operand can only contain non-empty objects'); + should(() => dsl.validate(filter)) + .throw('"or" operand can only contain non-empty objects'); }); it('should reject if one of the content object does not refer to a valid keyword', () => { @@ -39,8 +39,7 @@ describe('DSL.operands.or', () => { ], }; - return should(dsl.validate(filter)) - .be.rejectedWith('Unknown DSL keyword: foo'); + should(() => dsl.validate(filter)).throw('Unknown DSL keyword: foo'); }); it('should reject if one of the content object is not a well-formed keyword', () => { @@ -51,49 +50,73 @@ describe('DSL.operands.or', () => { ], }; - return should(dsl.validate(filter)) - .be.rejectedWith('"exists" requires the following attribute: field'); + should(() => dsl.validate(filter)) + .throw('"exists" requires the following attribute: field'); }); it('should validate a well-formed "or" operand', () => { - return should(dsl.validate({or: [{equals: {foo: 'bar'}}, {exists: {field: 'bar'}}]})).be.fulfilledWith(); + const filters = { + or: [ + {equals: {foo: 'bar'}}, + {exists: {field: 'bar'}}, + ], + }; + + should(() => dsl.validate(filters)).not.throw(); }); }); describe('#matching', () => { it('should match a document if at least 1 condition is fulfilled', () => { - return dsl.register('index', 'collection', {or: [{equals: {foo: 'bar'}}, {missing: {field: 'bar'}}, {range: {baz: {lt: 42}}}]}) - .then(subscription => { - const result = dsl.test('index', 'collection', {foo: 'foo', bar: 'baz', baz: 13}); + const subscription = dsl.register('index', 'collection', { + or: [ + {equals: {foo: 'bar'}}, + {missing: {field: 'bar'}}, + {range: {baz: {lt: 42}}}, + ], + }); - should(result).eql([subscription.id]); - }); + const result = dsl.test('index', 'collection', { + foo: 'foo', + bar: 'baz', + baz: 13, + }); + + should(result).eql([subscription.id]); }); it('should not match if the document misses all conditions', () => { - return dsl.register('index', 'collection', {or: [{equals: {foo: 'bar'}}, {missing: {field: 'bar'}}, {range: {baz: {lt: 42}}}]}) - .then(() => { - should(dsl.test('index', 'collection', {foo: 'foo', bar: 'baz', baz: 42})).be.an.Array().and.empty(); - }); + dsl.register('index', 'collection', { + or: [ + {equals: {foo: 'bar'}}, + {missing: {field: 'bar'}}, + {range: {baz: {lt: 42}}}, + ], + }); + + should(dsl.test('index', 'collection', {foo: 'foo', bar: 'baz', baz: 42})) + .be.an.Array().and.empty(); }); }); describe('#removal', () => { it('should destroy all associated keywords to an OR operand', () => { - let id; - - return dsl.register('index', 'collection', {or: [{equals: {foo: 'bar'}}, {missing: {field: 'bar'}}, {range: {baz: {lt: 42}}}]}) - .then(subscription => { - id = subscription.id; - return dsl.register('index', 'collection', {exists: {field: 'foo'}}); - }) - .then(() => dsl.remove(id)) - .then(() => { - should(dsl.storage.foPairs.get('index', 'collection', 'exists')).be.an.Object(); - should(dsl.storage.foPairs.get('index', 'collection', 'equals')).be.undefined(); - should(dsl.storage.foPairs.get('index', 'collection', 'notexists')).be.undefined(); - should(dsl.storage.foPairs.get('index', 'collection', 'range')).be.undefined(); - }); + const subscription = dsl.register('index', 'collection', { + or: [ + {equals: {foo: 'bar'}}, + {missing: {field: 'bar'}}, + {range: {baz: {lt: 42}}}, + ], + }); + + dsl.register('index', 'collection', {exists: {field: 'foo'}}); + + dsl.remove(subscription.id); + + should(dsl.storage.foPairs.get('index', 'collection', 'exists')).be.an.Object(); + should(dsl.storage.foPairs.get('index', 'collection', 'equals')).be.undefined(); + should(dsl.storage.foPairs.get('index', 'collection', 'notexists')).be.undefined(); + should(dsl.storage.foPairs.get('index', 'collection', 'range')).be.undefined(); }); }); });