diff --git a/.ci/doc/docker-compose.yml b/.ci/doc/docker-compose.yml index 4c77f6188..86019e68c 100644 --- a/.ci/doc/docker-compose.yml +++ b/.ci/doc/docker-compose.yml @@ -49,7 +49,7 @@ services: ash -c ' mkdir -p /var/snippets/node; apk add --no-cache curl; - npm install -g eslint; + npm install -g eslint@6.8.0; cd /var/snippets/node; npm install \ bluebird \ @@ -76,7 +76,7 @@ services: apt-get update; apt-get install -y curl; npm install -g \ - eslint; + eslint@6.8.0; cd /mnt; npm install; cd /var/snippets/web; @@ -105,7 +105,7 @@ services: apt-get update; apt-get install -y curl; npm install -g \ - eslint; + eslint@6.8.0; cd /var/snippets/webpack; cp /mnt/.ci/doc/puppeteer.js /var/snippets/webpack/; cp /mnt/.ci/doc/webpackBuild.js /var/snippets/webpack/; diff --git a/.ci/doc/templates/print-result-successes.tpl.js b/.ci/doc/templates/print-result-successes.tpl.js new file mode 100644 index 000000000..92dca79e5 --- /dev/null +++ b/.ci/doc/templates/print-result-successes.tpl.js @@ -0,0 +1,31 @@ +// Loads the Kuzzle SDK module and the websocket protocol +const { + Kuzzle, + WebSocket +} = require('kuzzle-sdk'); + +// Instantiates a Kuzzle client +const + kuzzle = new Kuzzle( + new WebSocket('kuzzle', { autoReconnect: false }) + ); + +// Adds a listener to detect connection problems +kuzzle.on('networkError', error => { + console.error(`Network Error: ${error.message}`); +}); + +(async () => { + let result; + try { + await kuzzle.connect(); + } catch (error) { + console.log(`Cannot connect to Kuzzle: ${error.message}`); + } + [snippet-code] finally { + kuzzle.disconnect(); + } + for (const elem of result.successes) { + console.log(elem); + } +})(); diff --git a/.eslintc-ts.json b/.eslintc-ts.json new file mode 100644 index 000000000..d1ec2e84a --- /dev/null +++ b/.eslintc-ts.json @@ -0,0 +1,16 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "plugins": [ + "@typescript-eslint" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@typescript-eslint/no-explicit-any": 0, + "@typescript-eslint/explicit-module-boundary-types": 0 + } +} \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..d849ec6cc --- /dev/null +++ b/.eslintignore @@ -0,0 +1,14 @@ +# JS generated files from TS +src/**/*.d.ts +src/**/*.js.map + +src/Kuzzle.js +src/controllers/Auth.js +src/controllers/Document.js +src/controllers/Base.js +src/core/security/User.js +src/core/security/Profile.js +src/core/security/Role.js +src/utils/interfaces.js +src/core/searchResult/SearchResultBase.js +src/core/searchResult/Document.js diff --git a/.gitignore b/.gitignore index 3c3324c0e..1a1af6994 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,19 @@ doc/7/getting-started/.vuejs/cypress/screenshots doc/7/getting-started/.vuejs/cypress/videos # Debug snippets -test-*.js \ No newline at end of file +test-*.js + +# Typescript related files +*.d.ts +*.js.map +index.js +src/Kuzzle.js +src/controllers/Auth.js +src/controllers/Document.js +src/controllers/Base.js +src/core/security/User.js +src/core/security/Profile.js +src/core/security/Role.js +src/utils/interfaces.js +src/core/searchResult/SearchResultBase.js +src/core/searchResult/Document.js diff --git a/.mocharc.json b/.mocharc.json index 4237f1313..79c73899e 100644 --- a/.mocharc.json +++ b/.mocharc.json @@ -3,5 +3,5 @@ "recursive": true, "slow": 2000, "timeout": 10000, - "require": ["should-sinon"] + "require": ["should-sinon", "ts-node/register"] } diff --git a/.travis.yml b/.travis.yml index c919ddfa9..aa2ac4cef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,8 +34,8 @@ jobs: - npm install script: - - npm run lint - - npm run unit-testing + - npm run test:lint + - npm run test:unit after_success: - cat ./coverage/lcov.info | ./node_modules/.bin/codecov @@ -65,7 +65,7 @@ jobs: - npm run build script: - - npm run functional-testing + - npm run test:functional - stage: Tests name: Documentation Tests @@ -103,6 +103,7 @@ jobs: env: - BRANCH=dev - NODE_ENV=production + - NODE_OPTIONS="--max_old_space_size=4096" - S3_BUCKET=docs-next.kuzzle.io - CLOUDFRONT_DISTRIBUTION_ID=E2ZCCEK9GRB49U - AWS_DEFAULT_REGION=us-west-2 @@ -140,6 +141,7 @@ jobs: node_js: 10 env: - NODE_ENV=production + - NODE_OPTIONS="--max_old_space_size=4096" - S3_BUCKET=docs.kuzzle.io - CLOUDFRONT_DISTRIBUTION_ID=E3D6RP0POLCJMM - AWS_DEFAULT_REGION=us-west-2 diff --git a/doc/7/controllers/auth/check-token/index.md b/doc/7/controllers/auth/check-token/index.md index 896cf22f4..36c214a00 100644 --- a/doc/7/controllers/auth/check-token/index.md +++ b/doc/7/controllers/auth/check-token/index.md @@ -31,7 +31,7 @@ An `object` representing the token validity status | ------------- | ------------------ | --------------------------------- | | `valid` |
boolean
| Tell if the token is valid or not | | `state` |
string
| Explain why the token is invalid | -|  `expires_at` |
number
| Token expiration timestamp | +|  `expiresAt` |
number
| Token expiration timestamp | ## Usage diff --git a/doc/7/controllers/auth/create-api-key/index.md b/doc/7/controllers/auth/create-api-key/index.md index 3f21770ef..d7a2ca918 100644 --- a/doc/7/controllers/auth/create-api-key/index.md +++ b/doc/7/controllers/auth/create-api-key/index.md @@ -56,7 +56,7 @@ The API key content has the following properties: | Name | Type | Description | | --------- | ----------------- | ---------------- | | `userId` |
string
| User kuid | -| `expiresAt` |
number
| Aexpiration date in UNIX micro-timestamp format (`-1` if the token never expires) | +| `expiresAt` |
number
| Expiration date in UNIX micro-timestamp format (`-1` if the token never expires) | | `ttl` |
number
| Original TTL | | `description` |
string
| API key description | | `token` |
string
| Authentication token associated with this API key | diff --git a/doc/7/controllers/auth/get-my-rights/index.md b/doc/7/controllers/auth/get-my-rights/index.md index f8fa73bdb..6e338c44f 100644 --- a/doc/7/controllers/auth/get-my-rights/index.md +++ b/doc/7/controllers/auth/get-my-rights/index.md @@ -31,7 +31,9 @@ Additional query options ## Resolves -An `object[]` containing: +An array containing user rights objects. + +Each user right object has the following properties: | Property | Type | Description | | ------------- | ----------------- | ------------------------------------------- | diff --git a/doc/7/controllers/bulk/delete-by-query/index.md b/doc/7/controllers/bulk/delete-by-query/index.md new file mode 100644 index 000000000..8a44b45a3 --- /dev/null +++ b/doc/7/controllers/bulk/delete-by-query/index.md @@ -0,0 +1,43 @@ +--- +code: true +type: page +title: deleteByQuery +--- + +# deleteByQuery + +Deletes documents matching the provided search query. + +This is a low level route intended to bypass Kuzzle actions on document deletion, notably: + - check document write limit + - trigger [realtime notifications](/core/2/guides/essentials/real-time) + +--- + +```js +deleteByQuery(index, collection, [query], [options]); +``` + +| Argument | Type | Description | +| ------------ | ----------------- | --------------- | +| `index` |
string
| Index name | +| `collection` |
string
| Collection name | +| `query` |
object
| documents matching this search query will be deleted. Uses the [ElasticSearch Query DSL](https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl.html) syntax. | +| `options` |
object
| Query options | + +### Options + +Additional query options + +| Options | Type
(default) | Description | +| ---------- | ------------------------------- | ---------------------------------------------------------------------------------- | +| `queuable` |
boolean

(`true`) | If true, queues the request during downtime, until connected to Kuzzle again | +| `refresh` |
string

(`""`) | If set to `wait_for`, waits for the change to be reflected for `search` (up to 1s) | + +## Resolves + +Resolves to the number of the deleted documents. + +## Usage + +<<< ./snippets/delete-by-query.js diff --git a/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.js b/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.js new file mode 100644 index 000000000..16cfba6ff --- /dev/null +++ b/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.js @@ -0,0 +1,15 @@ +try { + const deleted = await kuzzle.bulk.deleteByQuery( + 'nyc-open-data', + 'yellow-taxi', + { + query: { + term: { capacity: 7 } + } + } + ); + + console.log(`Successfully deleted ${deleted} documents`); +} catch (error) { + console.error(error.message); +} \ No newline at end of file diff --git a/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.test.yml b/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.test.yml new file mode 100644 index 000000000..f1a308132 --- /dev/null +++ b/doc/7/controllers/bulk/delete-by-query/snippets/delete-by-query.test.yml @@ -0,0 +1,20 @@ +name: bulk#deleteByQuery +description: Delete documents matching query +hooks: + before: | + curl -XDELETE kuzzle:7512/nyc-open-data + curl -XPOST kuzzle:7512/nyc-open-data/_create + curl -XPUT kuzzle:7512/nyc-open-data/yellow-taxi + + for i in 1 2 3 4 5; do + curl -H "Content-type: application/json" -d '{"capacity": 4}' kuzzle:7512/nyc-open-data/yellow-taxi/_create + done + + for i in 1 2 3 4 5; do + curl -H "Content-type: application/json" -d '{"capacity": 7}' kuzzle:7512/nyc-open-data/yellow-taxi/_create + done + + curl -XPOST kuzzle:7512/nyc-open-data/yellow-taxi/_refresh + after: +template: default +expected: Successfully deleted 5 documents diff --git a/doc/7/controllers/collection/update-mapping/index.md b/doc/7/controllers/collection/update-mapping/index.md index 518288531..343f955ea 100644 --- a/doc/7/controllers/collection/update-mapping/index.md +++ b/doc/7/controllers/collection/update-mapping/index.md @@ -7,7 +7,10 @@ description: Update the collection mapping # updateMapping - + + + +__Use [collection:update](/sdk/js/7/controllers/collection/update/) instead.__ You can define the collection [dynamic mapping policy](/core/2/guides/essentials/database-mappings#dynamic-mapping-policy) by setting the `dynamic` field to the desired value. diff --git a/doc/7/controllers/collection/update/index.md b/doc/7/controllers/collection/update/index.md new file mode 100644 index 000000000..f7edd238a --- /dev/null +++ b/doc/7/controllers/collection/update/index.md @@ -0,0 +1,57 @@ +--- +code: true +type: page +title: update +description: Update the collection mapping +--- + +# update + + + +You can define the collection [dynamic mapping policy](/core/2/guides/essentials/database-mappings#dynamic-mapping-policy) by setting the `dynamic` field to the desired value. + +You can define [collection additional metadata](/core/2/guides/essentials/database-mappings#collection-metadata) within the `_meta` root field. + +
+ +```js +update(index, collection, mapping); +``` + +
+ +| Arguments | Type | Description | +| ------------ | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `index` |
string
| Index name | +| `collection` |
string
| Collection name | +| `mapping` |
object
| Describes the collection mapping | + +### mapping + +An object representing the collection data mapping. + +This object must have a root field `properties` that contain the mapping definition: + +```js +const mapping = { + properties: { + field1: { type: 'text' }, + field2: { + properties: { + nestedField: { type: 'keyword' } + } + } + } +}; +``` + +More informations about database mappings [here](/core/2/guides/essentials/database-mappings). + +## Resolves + +Resolve if the collection is successfully updated. + +## Usage + +<<< ./snippets/update.js diff --git a/doc/7/controllers/collection/update/snippets/update.js b/doc/7/controllers/collection/update/snippets/update.js new file mode 100644 index 000000000..16c624f13 --- /dev/null +++ b/doc/7/controllers/collection/update/snippets/update.js @@ -0,0 +1,17 @@ +const mapping = { + dynamic: 'false', + _meta: { + area: 'Panipokhari' + }, + properties: { + plate: { type: 'keyword' } + } +}; + +try { + await kuzzle.collection.update('nyc-open-data', 'yellow-taxi', mapping); + + console.log('Success'); +} catch (error) { + console.error(error.message); +} diff --git a/doc/7/controllers/collection/update/snippets/update.test.yml b/doc/7/controllers/collection/update/snippets/update.test.yml new file mode 100644 index 000000000..db5aed5bd --- /dev/null +++ b/doc/7/controllers/collection/update/snippets/update.test.yml @@ -0,0 +1,10 @@ +name: collection#update +description: Update the collection mapping +hooks: + before: curl -X POST kuzzle:7512/nyc-open-data/_create && curl -X PUT kuzzle:7512/nyc-open-data/yellow-taxi + after: +template: default +expected: Success + +sdk: js +version: 7 diff --git a/doc/7/controllers/document/delete-by-query/snippets/delete-by-query.test.yml b/doc/7/controllers/document/delete-by-query/snippets/delete-by-query.test.yml index 89da56819..a95123d23 100644 --- a/doc/7/controllers/document/delete-by-query/snippets/delete-by-query.test.yml +++ b/doc/7/controllers/document/delete-by-query/snippets/delete-by-query.test.yml @@ -14,7 +14,7 @@ hooks: curl -H "Content-type: application/json" -d '{"capacity": 7}' kuzzle:7512/nyc-open-data/yellow-taxi/_create done - curl -XPOST kuzzle:7512/nyc-open-data/_refresh + curl -XPOST kuzzle:7512/nyc-open-data/yellow-taxi/_refresh after: template: default expected: Successfully deleted 5 documents diff --git a/doc/7/controllers/document/search/index.md b/doc/7/controllers/document/search/index.md index 7d294e7b4..ff11d3dd6 100644 --- a/doc/7/controllers/document/search/index.md +++ b/doc/7/controllers/document/search/index.md @@ -50,6 +50,12 @@ Additional query options | `from` |
number

(`0`) | Offset of the first document to fetch | | `size` |
number

(`10`) | Maximum number of documents to retrieve per page | | `scroll` |
string

(`""`) | When set, gets a forward-only cursor having its ttl set to the given value (ie `30s`; cf [elasticsearch time limits](https://www.elastic.co/guide/en/elasticsearch/reference/7.3/common-options.html#time-units)) | +| `verb` |
string
| (HTTP only) Forces the verb of the route | + +#### verb + +When instantiated with a HTTP protocol object, the SDK uses the POST API by default for this API route. +You can set the `verb` option to `GET` to force the SDK to use the GET API instead. ## Body properties diff --git a/doc/7/controllers/document/update-by-query/index.md b/doc/7/controllers/document/update-by-query/index.md new file mode 100644 index 000000000..41e6469c4 --- /dev/null +++ b/doc/7/controllers/document/update-by-query/index.md @@ -0,0 +1,64 @@ +--- +code: true +type: page +title: updateByQuery +description: Updates documents matching query +--- + +# updateByQuery + +Updates documents matching the provided search query. + +Kuzzle uses the [ElasticSearch Query DSL](https://www.elastic.co/guide/en/elasticsearch/reference/7.4/query-dsl.html) syntax. + +An empty or null query will match all documents in the collection. + +
+ +```js +updateByQuery(index, collection, searchQuery, changes, [options]) +``` + +| Argument | Type | Description | +| ------------------ | -------------------------------------------- | --------------- | +| `index` |
string
| Index name | +| `collection` |
string
| Collection name | +| `searchQuery` |
object
| Query to match | +| `changes` |
object
| Partial changes to apply to the documents | +| `options` |
object
| Optional parameters | + +--- + +### options + +Additional query options. + +| Options | Type
(default) | Description | +| ----------------- | ------------------------------- | ---------------------------------------------------------------------------------- | +| `refresh` |
string

(`""`) | If set to `wait_for`, waits for the change to be reflected for `search` (up to 1s) | +| `source` |
boolean

(`false`)| If true, returns the updated document inside the response + +## Resolves + +Returns an object containing 2 arrays: `successes` and `errors` + +Each updated document is an object of the `successes` array with the following properties: + +| Property | Type | Description | +|------------- |--------------------------------------------- |--------------------------------- | +| `_source` |
object
| Updated document (if `source` option set to true) | +| `_id` |
string
| ID of the udated document | +| `_version` |
number
| Version of the document in the persistent data storage | +| `status` |
number
| HTTP status code | + +Each errored document is an object of the `errors` array with the following properties: + +| Property | Type | Description | +|------------- |--------------------------------------------- |--------------------------------- | +| `document` |
object
| Document that causes the error | +| `status` |
number
| HTTP error status | +| `reason` |
string
| Human readable reason | + +## Usage + +<<< ./snippets/update-by-query.js \ No newline at end of file diff --git a/doc/7/controllers/document/update-by-query/snippets/update-by-query.js b/doc/7/controllers/document/update-by-query/snippets/update-by-query.js new file mode 100644 index 000000000..ec7994850 --- /dev/null +++ b/doc/7/controllers/document/update-by-query/snippets/update-by-query.js @@ -0,0 +1,31 @@ +try { + result = await kuzzle.document.updateByQuery( + 'nyc-open-data', + 'yellow-taxi', + { + match: { + capacity: 4 + } + }, { + capacity: 42 + }); +/* +{ +successes: [ + { + _id: , + _source: // if source set to true + status: 200 + }, + { + _id: , + _source: // if source set to true + status: 200 + } +], +errors: [] +} +*/ +} catch (error) { + console.log(error.message); +} diff --git a/doc/7/controllers/document/update-by-query/snippets/update-by-query.test.yml b/doc/7/controllers/document/update-by-query/snippets/update-by-query.test.yml new file mode 100644 index 000000000..a51c40859 --- /dev/null +++ b/doc/7/controllers/document/update-by-query/snippets/update-by-query.test.yml @@ -0,0 +1,19 @@ +name: document#updateByQuery +description: Update documents matching query +hooks: + before: | + curl -XDELETE kuzzle:7512/nyc-open-data + curl -XPOST kuzzle:7512/nyc-open-data/_create + curl -XPUT kuzzle:7512/nyc-open-data/yellow-taxi + for i in 1 2 ; do + curl -H "Content-type: application/json" -d '{"capacity": 4}' kuzzle:7512/nyc-open-data/yellow-taxi/document_$i/_create + done + for i in 1 2 3 4 5; do + curl -H "Content-type: application/json" -d '{"capacity": 7}' kuzzle:7512/nyc-open-data/yellow-taxi/_create + done + curl -XPOST kuzzle:7512/nyc-open-data/yellow-taxi/_refresh + after: +template: print-result-successes +expected: + - "{ _id: 'document_1', _version: 2, status: 200 }" + - "{ _id: 'document_2', _version: 2, status: 200 }" \ No newline at end of file diff --git a/doc/7/controllers/document/validate/index.md b/doc/7/controllers/document/validate/index.md index e274a21c1..b87199cda 100644 --- a/doc/7/controllers/document/validate/index.md +++ b/doc/7/controllers/document/validate/index.md @@ -7,7 +7,7 @@ description: Validate a document # validate -Validates data against existing validation rules. +Validates a document against existing validation rules. Note that if no validation specifications are set for the ``/``, the document will always be valid. diff --git a/doc/7/controllers/ms/mexecute/index.md b/doc/7/controllers/ms/mexecute/index.md new file mode 100644 index 000000000..06aa9afd6 --- /dev/null +++ b/doc/7/controllers/ms/mexecute/index.md @@ -0,0 +1,47 @@ +--- +code: true +type: page +title: mexecute +--- + +# mexecute + +Allows the execution of multiple commands or 'actions' in a single step. + +It creates a Redis **transaction** block and **executes** it immediately, all actions will be executed sequentially and as a single atomic and isolated operation. + +[[_Redis documentation_]](https://redis.io/topics/transactions) + +::: warning +Only already valid actions of the memoryStorage controller can be executed using **mexecute**. +::: + +## Arguments + +```js +mexecute(actions, [options]); +``` + +
+ +| Arguments | Type | Description | +| --------- | ------------------- | ------------------------------ | +| `actions` |
object[]
| List of actions to execute | +| `options` |
object
| Optional query arguments | + +### actions + +The `actions` argument is an array of objects. Each object describes an action to be executed, using the following properties: + +| Property | Type | Description | +| -------- | ----------------- | ----------- | +| `action` |
string
| Action name | +| `args` |
object
| Arguments | + +## Resolve + +Returns an array of error & result pairs for each executed action, in order. + +## Usage + +<<< ./snippets/mexecute.js diff --git a/doc/7/controllers/ms/mexecute/snippets/mexecute.js b/doc/7/controllers/ms/mexecute/snippets/mexecute.js new file mode 100644 index 000000000..5df892766 --- /dev/null +++ b/doc/7/controllers/ms/mexecute/snippets/mexecute.js @@ -0,0 +1,13 @@ +try { + + const actions = [ + { 'action': 'set', 'args': { '_id': 'list:a', 'body': { 'value': 1, 'ex': 100, 'nx': true } } }, + { 'action': 'get', 'args': { '_id': 'list:a' } }, + { 'action': 'del', 'args': { 'body': { 'keys': ['list:a'] } } }]; + + // Prints: "[ [ null, 'OK' ], [ null, '1' ], [ null, 1 ] ]" + console.log(await kuzzle.ms.mexecute(actions)); + +} catch (error) { + console.error(error.message); +} diff --git a/doc/7/controllers/ms/mexecute/snippets/mexecute.test.yml b/doc/7/controllers/ms/mexecute/snippets/mexecute.test.yml new file mode 100644 index 000000000..1ba5492fd --- /dev/null +++ b/doc/7/controllers/ms/mexecute/snippets/mexecute.test.yml @@ -0,0 +1,7 @@ +name: ms#mexecute +description: Executes multiple commands in a single step +hooks: + before: curl -X POST kuzzle:7512/ms/_flushdb + after: +template: default +expected: "\\[ \\[ null, 'OK' ], \\[ null, '1' ], \\[ null, 1 ] ]" diff --git a/doc/7/controllers/security/m-delete-profiles/snippets/m-delete-profiles.test.yml b/doc/7/controllers/security/m-delete-profiles/snippets/m-delete-profiles.test.yml index b017d8aea..6fbf0d363 100644 --- a/doc/7/controllers/security/m-delete-profiles/snippets/m-delete-profiles.test.yml +++ b/doc/7/controllers/security/m-delete-profiles/snippets/m-delete-profiles.test.yml @@ -8,4 +8,4 @@ hooks: }' kuzzle:7512/profiles/profile${i}/_create done template: default -expected: '^\[ ''profile1'', ''profile2'', ''profile3'', ''profile4'', ''profile5'' \]$' +expected: '^\[ ''profile\d'', ''profile\d'', ''profile\d'', ''profile\d', ''profile\d'' \]$' diff --git a/doc/7/controllers/security/m-get-profiles/snippets/m-get-profiles.test.yml b/doc/7/controllers/security/m-get-profiles/snippets/m-get-profiles.test.yml index d20ca0ba1..35652db1e 100644 --- a/doc/7/controllers/security/m-get-profiles/snippets/m-get-profiles.test.yml +++ b/doc/7/controllers/security/m-get-profiles/snippets/m-get-profiles.test.yml @@ -12,4 +12,4 @@ hooks: curl -XDELETE kuzzle:7512/profiles/profile${i} done template: default -expected: '^ policies: \[ \[Object\] \] } \]$' +expected: '.*Profile.*_id.*rateLimit.*policies.*' diff --git a/doc/7/controllers/security/m-get-roles/snippets/m-get-roles.test.yml b/doc/7/controllers/security/m-get-roles/snippets/m-get-roles.test.yml index ea2870d33..6f2dc043b 100644 --- a/doc/7/controllers/security/m-get-roles/snippets/m-get-roles.test.yml +++ b/doc/7/controllers/security/m-get-roles/snippets/m-get-roles.test.yml @@ -18,4 +18,4 @@ hooks: curl -XDELETE kuzzle:7512/roles/role${i} done template: default -expected: '^ _id: ''role3'',$' +expected: '.*Role.*_id.*controllers.*' diff --git a/doc/7/controllers/security/m-get-users/snippets/m-get-users.test.yml b/doc/7/controllers/security/m-get-users/snippets/m-get-users.test.yml index b482c7fc0..58bcc9ee9 100644 --- a/doc/7/controllers/security/m-get-users/snippets/m-get-users.test.yml +++ b/doc/7/controllers/security/m-get-users/snippets/m-get-users.test.yml @@ -21,4 +21,4 @@ hooks: curl -XDELETE kuzzle:7512/users/user${i} done template: default -expected: '^ _id: ''user3'',$' +expected: '.*User.*' diff --git a/doc/7/core-classes/profile/properties/index.md b/doc/7/core-classes/profile/properties/index.md index c6dddc9eb..c404b9ec3 100644 --- a/doc/7/core-classes/profile/properties/index.md +++ b/doc/7/core-classes/profile/properties/index.md @@ -12,6 +12,7 @@ order: 10 |--- |--- |--- | | `_id` |
string
| Profile ID | | `policies` |
object[]
| Array of policies for this profile | +| `rateLimit` |
number
| Maximum number of requests per second and per node with this profile | ### policies diff --git a/features/steps/document.js b/features/steps/document.js index f7a3c8ea3..8cb4002eb 100644 --- a/features/steps/document.js +++ b/features/steps/document.js @@ -334,7 +334,7 @@ Then('the document is successfully deleted', function (cb) { Then(/^the document is (successfully|not) found$/, function (yesno) { should(this.error).be.null(); - should(this.content.constructor.name).eql('DocumentsSearchResult'); + should(this.content.constructor.name).eql('DocumentSearchResult'); should(this.content.total).eql(yesno === 'successfully' ? 1 : 0); }); @@ -386,7 +386,7 @@ Then('the documents should be retrieved', function () { }); Then(/^The search result should have (fetched|a total of) (\d+) documents$/, function (what, number) { - should(this.content.constructor.name).eql('DocumentsSearchResult'); + should(this.content.constructor.name).eql('DocumentSearchResult'); let field; switch (what) { diff --git a/index.js b/index.js deleted file mode 100644 index 123891a4e..000000000 --- a/index.js +++ /dev/null @@ -1,34 +0,0 @@ -const Kuzzle = require('./src/Kuzzle'); -const { Http, WebSocket } = require('./src/protocols'); -const BaseController = require('./src/controllers/Base'); -const KuzzleAbstractProtocol = require('./src/protocols/abstract/Base'); -const KuzzleEventEmitter = require('./src/core/KuzzleEventEmitter'); - -const SearchResultBase = require('./src/core/searchResult/SearchResultBase'); -const DocumentSearchResult = require('./src/core/searchResult/Document'); -const ProfileSearchResult = require('./src/core/searchResult/Profile'); -const RoleSearchResult = require('./src/core/searchResult/Role'); -const SpecificationSearchResult = require('./src/core/searchResult/Specifications'); -const UserSearchResult = require('./src/core/searchResult/User'); - -if (typeof window !== 'undefined' && typeof BUILT === 'undefined') { - throw new Error('It looks like you are using the Nodejs version of Kuzzle SDK ' + - 'in a browser. ' + - 'It is strongly recommended to use the browser-specific build instead. ' + - 'Learn more at https://github.com/kuzzleio/sdk-javascript/tree/master#browser'); -} - -module.exports = { - Kuzzle, - Http, - WebSocket, - BaseController, - KuzzleAbstractProtocol, - KuzzleEventEmitter, - SearchResultBase, - DocumentSearchResult, - ProfileSearchResult, - RoleSearchResult, - SpecificationSearchResult, - UserSearchResult -}; diff --git a/index.ts b/index.ts new file mode 100644 index 000000000..b88efa680 --- /dev/null +++ b/index.ts @@ -0,0 +1,41 @@ +// defined by webpack plugin +declare var BUILT: any; + +if (typeof window !== 'undefined' && typeof BUILT === 'undefined') { + throw new Error('It looks like you are using the Nodejs version of Kuzzle SDK ' + + 'in a browser. ' + + 'It is strongly recommended to use the browser-specific build instead. ' + + 'Learn more at https://github.com/kuzzleio/sdk-javascript/tree/master#browser'); +} + +import { Kuzzle } from './src/Kuzzle'; +import { Http, WebSocket } from './src/protocols'; +import { BaseController } from './src/controllers/Base'; +import { KuzzleAbstractProtocol } from './src/protocols/abstract/Base'; +import { KuzzleEventEmitter } from './src/core/KuzzleEventEmitter'; + +import { SearchResultBase } from './src/core/searchResult/SearchResultBase'; +import { DocumentSearchResult } from './src/core/searchResult/Document'; +import { ProfileSearchResult } from './src/core/searchResult/Profile'; +import { RoleSearchResult } from './src/core/searchResult/Role'; +import { SpecificationSearchResult } from './src/core/searchResult/Specifications'; +import { UserSearchResult } from './src/core/searchResult/User'; + +const exported = { + Kuzzle, + Http, + WebSocket, + BaseController, + KuzzleAbstractProtocol, + KuzzleEventEmitter, + SearchResultBase, + DocumentSearchResult, + ProfileSearchResult, + RoleSearchResult, + SpecificationSearchResult, + UserSearchResult +} + +export default exported; + +module.exports = exported; diff --git a/package-lock.json b/package-lock.json index ae4166032..ed174757a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,478 +1,460 @@ { "name": "kuzzle-sdk", - "version": "7.2.0", + "version": "7.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", "dev": true, "requires": { - "@babel/highlight": "^7.8.3" + "@babel/highlight": "^7.10.4" } }, "@babel/compat-data": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.9.0.tgz", - "integrity": "sha512-zeFQrr+284Ekvd9e7KAX954LkapWiOmQtsfHirhxqfdlX6MEC32iRE+pqUGlYIBchdevaCwvzxWGSy/YBNI85g==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.10.5.tgz", + "integrity": "sha512-mPVoWNzIpYJHbWje0if7Ck36bpbtTvIxOi9+6WSK9wjGEXearAqlwBoTQvVjsAY2VIwgcs8V940geY3okzRCEw==", "dev": true, "requires": { - "browserslist": "^4.9.1", + "browserslist": "^4.12.0", "invariant": "^2.2.4", "semver": "^5.5.0" } }, "@babel/core": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", - "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.0", - "@babel/helper-module-transforms": "^7.9.0", - "@babel/helpers": "^7.9.0", - "@babel/parser": "^7.9.0", - "@babel/template": "^7.8.6", - "@babel/traverse": "^7.9.0", - "@babel/types": "^7.9.0", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.5.tgz", + "integrity": "sha512-O34LQooYVDXPl7QWCdW9p4NR+QlzOr7xShPPJz8GsuCU3/8ua/wqTr7gmnxXv+WBESiGU/G5s16i6tUvHkNb+w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.10.5", + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.10.5", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.5", + "@babel/types": "^7.10.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", "json5": "^2.1.2", - "lodash": "^4.17.13", + "lodash": "^4.17.19", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + } } }, "@babel/generator": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.4.tgz", - "integrity": "sha512-rjP8ahaDy/ouhrvCoU1E5mqaitWrxwuNGU+dy1EpaoK48jZay4MdkskKGIMHLZNewg8sAsqpGSREJwP0zH3YQA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.5.tgz", + "integrity": "sha512-3vXxr3FEW7E7lJZiWQ3bM4+v/Vyr9C+hpolQ8BGFr9Y8Ri2tFLWTixmwKBafDujO1WVah4fhZBeU1bieKdghig==", "dev": true, "requires": { - "@babel/types": "^7.9.0", + "@babel/types": "^7.10.5", "jsesc": "^2.5.1", - "lodash": "^4.17.13", "source-map": "^0.5.0" - }, - "dependencies": { - "@babel/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", - "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.9.0", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } } }, "@babel/helper-annotate-as-pure": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", - "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", + "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", - "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-compilation-targets": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz", - "integrity": "sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", + "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", "dev": true, "requires": { - "@babel/compat-data": "^7.8.6", - "browserslist": "^4.9.1", + "@babel/compat-data": "^7.10.4", + "browserslist": "^4.12.0", "invariant": "^2.2.4", "levenary": "^1.1.1", "semver": "^5.5.0" } }, + "@babel/helper-create-class-features-plugin": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", + "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.10.5", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4" + } + }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz", - "integrity": "sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", + "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-regex": "^7.8.3", + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-regex": "^7.10.4", "regexpu-core": "^4.7.0" } }, "@babel/helper-define-map": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz", - "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/types": "^7.8.3", - "lodash": "^4.17.13" + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + } } }, "@babel/helper-explode-assignable-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", - "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.10.4.tgz", + "integrity": "sha512-4K71RyRQNPRrR85sr5QY4X3VwG4wtVoXZB9+L3r1Gp38DhELyHCtovqydRi7c1Ovb17eRGiQ/FD5s8JdU0Uy5A==", "dev": true, "requires": { - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", - "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.9.0", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", "dev": true, "requires": { - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", - "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.9.0", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.10.4" } }, "@babel/helper-hoist-variables": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz", - "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", - "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.5.tgz", + "integrity": "sha512-HiqJpYD5+WopCXIAbQDG0zye5XYVvcO9w/DHp5GsaGkRUaamLj2bEtu6i8rnGGprAhHM3qidCMgp71HF4endhA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.5" } }, "@babel/helper-module-imports": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", - "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-module-transforms": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", - "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.6", - "@babel/helper-simple-access": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/template": "^7.8.6", - "@babel/types": "^7.9.0", - "lodash": "^4.17.13" + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.5.tgz", + "integrity": "sha512-4P+CWMJ6/j1W915ITJaUkadLObmCRRSC234uctJfn/vHrsLNxsR8dwlcXv9ZhJWzl77awf+mWXSZEKt5t0OnlA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + } } }, "@babel/helper-optimise-call-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", - "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", "dev": true }, "@babel/helper-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz", - "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", "dev": true, "requires": { - "lodash": "^4.17.13" + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + } } }, "@babel/helper-remap-async-to-generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz", - "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.10.4.tgz", + "integrity": "sha512-86Lsr6NNw3qTNl+TBcF1oRZMaVzJtbWTyTko+CQL/tvNvcGYEFKbLXDPxtW0HKk3McNOk4KzY55itGWCAGK5tg==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-wrap-function": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-replace-supers": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", - "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/traverse": "^7.8.6", - "@babel/types": "^7.8.6" + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-simple-access": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", - "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", "dev": true, "requires": { - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.4.tgz", + "integrity": "sha512-pySBTeoUff56fL5CBU2hWm9TesA4r/rOkI9DyJLvvgz09MB9YtfIYe3iBriVaYNaPe+Alua0vBIOVOLs2buWhg==", "dev": true, "requires": { - "@babel/types": "^7.8.3" - }, - "dependencies": { - "@babel/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", - "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.9.0", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } + "@babel/types": "^7.10.4" } }, "@babel/helper-validator-identifier": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.0.tgz", - "integrity": "sha512-6G8bQKjOh+of4PV/ThDm/rRqlU7+IGoJuofpagU5GlEl29Vv0RGqqt86ZGRV8ZuSOY3o+8yXl5y782SMcG7SHw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, "@babel/helper-wrap-function": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", - "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", + "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helpers": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz", - "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", "dev": true, "requires": { - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.9.0", - "@babel/types": "^7.9.0" + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/highlight": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", - "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.9.0", + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, "@babel/parser": { - "version": "7.9.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", - "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.5.tgz", + "integrity": "sha512-wfryxy4bE1UivvQKSQDU4/X6dr+i8bctjUjj8Zyt3DQy7NtPizJXT8M52nqpNKL+nq2PW8lxk4ZqLj0fD4B4hQ==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz", - "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", + "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-remap-async-to-generator": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4", "@babel/plugin-syntax-async-generators": "^7.8.0" } }, + "@babel/plugin-proposal-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz", + "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz", - "integrity": "sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", + "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-dynamic-import": "^7.8.0" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz", - "integrity": "sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", + "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.0" } }, "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", + "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" } }, "@babel/plugin-proposal-numeric-separator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz", - "integrity": "sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", + "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.9.5.tgz", - "integrity": "sha512-VP2oXvAf7KCYTthbUHwBlewbl1Iq059f6seJGsxMizaCdgHIeczOr7FBqELhSqfkIl04Fi8okzWzl63UKbQmmg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.10.4.tgz", + "integrity": "sha512-6vh4SqRuLLarjgeOf4EaROJAHjvu9Gl+/346PbDH9yWbJyfnJ/ah3jmYKYtswEyCoWZiidvVHjHshd4WgjB9BA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-transform-parameters": "^7.9.5" + "@babel/plugin-transform-parameters": "^7.10.4" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", + "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz", - "integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.10.4.tgz", + "integrity": "sha512-ZIhQIEeavTgouyMSdZRap4VPPHqJJ3NEs2cuHs5p0erH+iz6khB0qfgU8g7UuJkG88+fBMy23ZiU+nuHvekJeQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-optional-chaining": "^7.8.0" } }, + "@babel/plugin-proposal-private-methods": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz", + "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.8.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz", - "integrity": "sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", + "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.8", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-async-generators": { @@ -484,6 +466,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", + "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", @@ -512,12 +503,12 @@ } }, "@babel/plugin-syntax-numeric-separator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz", - "integrity": "sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-object-rest-spread": { @@ -548,395 +539,394 @@ } }, "@babel/plugin-syntax-top-level-await": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz", - "integrity": "sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", + "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", - "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", + "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz", - "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", + "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-remap-async-to-generator": "^7.8.3" + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz", - "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", + "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz", - "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.10.5.tgz", + "integrity": "sha512-6Ycw3hjpQti0qssQcA6AMSFDHeNJ++R6dIMnpRqUjFeBBTmTDPa8zgF90OVfTvAo11mXZTlVUViY1g8ffrURLg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "lodash": "^4.17.13" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-classes": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.9.5.tgz", - "integrity": "sha512-x2kZoIuLC//O5iA7PEvecB105o7TLzZo8ofBVhP79N+DO3jaX+KYfww9TQcfBEZD0nikNyYcGB1IKtRq36rdmg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-define-map": "^7.8.3", - "@babel/helper-function-name": "^7.9.5", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.6", - "@babel/helper-split-export-declaration": "^7.8.3", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", + "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", "globals": "^11.1.0" - }, - "dependencies": { - "@babel/helper-function-name": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz", - "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.9.5" - } - } } }, "@babel/plugin-transform-computed-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz", - "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", + "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-destructuring": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.9.5.tgz", - "integrity": "sha512-j3OEsGel8nHL/iusv/mRd5fYZ3DrOxWC82x0ogmdN/vHfAP4MYw+AFKYanzWlktNwikKvlzUV//afBW5FTp17Q==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", + "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz", - "integrity": "sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", + "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz", - "integrity": "sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", + "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", - "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", + "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-for-of": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.9.0.tgz", - "integrity": "sha512-lTAnWOpMwOXpyDx06N+ywmF3jNbafZEqZ96CGYabxHrxNX8l5ny7dt4bK/rGwAh9utyP2b2Hv7PlZh1AAS54FQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", + "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz", - "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", + "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz", - "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", + "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz", - "integrity": "sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", + "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.9.0.tgz", - "integrity": "sha512-vZgDDF003B14O8zJy0XXLnPH4sg+9X5hFBBGN1V+B2rgrB+J2xIypSN6Rk9imB2hSTHQi5OHLrFWsZab1GMk+Q==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", + "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.9.0", - "@babel/helper-plugin-utils": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz", - "integrity": "sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", + "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.9.0", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-simple-access": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.9.0.tgz", - "integrity": "sha512-FsiAv/nao/ud2ZWy4wFacoLOm5uxl0ExSQ7ErvP7jpoihLR6Cq90ilOFyX9UXct3rbtKsAiZ9kFt5XGfPe/5SQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", + "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.8.3", - "@babel/helper-module-transforms": "^7.9.0", - "@babel/helper-plugin-utils": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.9.0.tgz", - "integrity": "sha512-uTWkXkIVtg/JGRSIABdBoMsoIeoHQHPTL0Y2E7xf5Oj7sLqwVsNXOkNk0VJc7vF0IMBsPeikHxFjGe+qmwPtTQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", + "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.9.0", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", - "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", + "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.10.4" } }, "@babel/plugin-transform-new-target": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz", - "integrity": "sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", + "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-object-super": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz", - "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", + "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4" } }, "@babel/plugin-transform-parameters": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.9.5.tgz", - "integrity": "sha512-0+1FhHnMfj6lIIhVvS4KGQJeuhe1GI//h5uptK4PvLt+BGBxsoUJbd3/IW002yk//6sZPlFgsG1hY6OHLcy6kA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", + "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-property-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz", - "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", + "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-regenerator": { - "version": "7.8.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.7.tgz", - "integrity": "sha512-TIg+gAl4Z0a3WmD3mbYSk+J9ZUH6n/Yc57rtKRnlA/7rcCvpekHXe0CMZHP1gYp7/KLe9GHTuIba0vXmls6drA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", + "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", "dev": true, "requires": { "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz", - "integrity": "sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", + "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", - "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", + "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz", - "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.10.4.tgz", + "integrity": "sha512-1e/51G/Ni+7uH5gktbWv+eCED9pP8ZpRhZB3jOaI3mmzfvJTWHkuyYTv0Z5PYtyM+Tr2Ccr9kUdQxn60fI5WuQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz", - "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", + "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-regex": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" } }, "@babel/plugin-transform-template-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz", - "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", + "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz", - "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", + "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz", + "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", - "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", + "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/preset-env": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.5.tgz", - "integrity": "sha512-eWGYeADTlPJH+wq1F0wNfPbVS1w1wtmMJiYk55Td5Yu28AsdR9AsC97sZ0Qq8fHqQuslVSIYSGJMcblr345GfQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.9.0", - "@babel/helper-compilation-targets": "^7.8.7", - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-proposal-async-generator-functions": "^7.8.3", - "@babel/plugin-proposal-dynamic-import": "^7.8.3", - "@babel/plugin-proposal-json-strings": "^7.8.3", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-proposal-numeric-separator": "^7.8.3", - "@babel/plugin-proposal-object-rest-spread": "^7.9.5", - "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", - "@babel/plugin-proposal-optional-chaining": "^7.9.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.4.tgz", + "integrity": "sha512-tcmuQ6vupfMZPrLrc38d0sF2OjLT3/bZ0dry5HchNCQbrokoQi4reXqclvkkAT5b+gWc23meVWpve5P/7+w/zw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.10.4", + "@babel/helper-compilation-targets": "^7.10.4", + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-proposal-async-generator-functions": "^7.10.4", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-dynamic-import": "^7.10.4", + "@babel/plugin-proposal-json-strings": "^7.10.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", + "@babel/plugin-proposal-numeric-separator": "^7.10.4", + "@babel/plugin-proposal-object-rest-spread": "^7.10.4", + "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", + "@babel/plugin-proposal-optional-chaining": "^7.10.4", + "@babel/plugin-proposal-private-methods": "^7.10.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.10.4", "@babel/plugin-syntax-dynamic-import": "^7.8.0", "@babel/plugin-syntax-json-strings": "^7.8.0", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-numeric-separator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.0", "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.8.3", - "@babel/plugin-transform-async-to-generator": "^7.8.3", - "@babel/plugin-transform-block-scoped-functions": "^7.8.3", - "@babel/plugin-transform-block-scoping": "^7.8.3", - "@babel/plugin-transform-classes": "^7.9.5", - "@babel/plugin-transform-computed-properties": "^7.8.3", - "@babel/plugin-transform-destructuring": "^7.9.5", - "@babel/plugin-transform-dotall-regex": "^7.8.3", - "@babel/plugin-transform-duplicate-keys": "^7.8.3", - "@babel/plugin-transform-exponentiation-operator": "^7.8.3", - "@babel/plugin-transform-for-of": "^7.9.0", - "@babel/plugin-transform-function-name": "^7.8.3", - "@babel/plugin-transform-literals": "^7.8.3", - "@babel/plugin-transform-member-expression-literals": "^7.8.3", - "@babel/plugin-transform-modules-amd": "^7.9.0", - "@babel/plugin-transform-modules-commonjs": "^7.9.0", - "@babel/plugin-transform-modules-systemjs": "^7.9.0", - "@babel/plugin-transform-modules-umd": "^7.9.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", - "@babel/plugin-transform-new-target": "^7.8.3", - "@babel/plugin-transform-object-super": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.9.5", - "@babel/plugin-transform-property-literals": "^7.8.3", - "@babel/plugin-transform-regenerator": "^7.8.7", - "@babel/plugin-transform-reserved-words": "^7.8.3", - "@babel/plugin-transform-shorthand-properties": "^7.8.3", - "@babel/plugin-transform-spread": "^7.8.3", - "@babel/plugin-transform-sticky-regex": "^7.8.3", - "@babel/plugin-transform-template-literals": "^7.8.3", - "@babel/plugin-transform-typeof-symbol": "^7.8.4", - "@babel/plugin-transform-unicode-regex": "^7.8.3", + "@babel/plugin-syntax-top-level-await": "^7.10.4", + "@babel/plugin-transform-arrow-functions": "^7.10.4", + "@babel/plugin-transform-async-to-generator": "^7.10.4", + "@babel/plugin-transform-block-scoped-functions": "^7.10.4", + "@babel/plugin-transform-block-scoping": "^7.10.4", + "@babel/plugin-transform-classes": "^7.10.4", + "@babel/plugin-transform-computed-properties": "^7.10.4", + "@babel/plugin-transform-destructuring": "^7.10.4", + "@babel/plugin-transform-dotall-regex": "^7.10.4", + "@babel/plugin-transform-duplicate-keys": "^7.10.4", + "@babel/plugin-transform-exponentiation-operator": "^7.10.4", + "@babel/plugin-transform-for-of": "^7.10.4", + "@babel/plugin-transform-function-name": "^7.10.4", + "@babel/plugin-transform-literals": "^7.10.4", + "@babel/plugin-transform-member-expression-literals": "^7.10.4", + "@babel/plugin-transform-modules-amd": "^7.10.4", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-modules-systemjs": "^7.10.4", + "@babel/plugin-transform-modules-umd": "^7.10.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", + "@babel/plugin-transform-new-target": "^7.10.4", + "@babel/plugin-transform-object-super": "^7.10.4", + "@babel/plugin-transform-parameters": "^7.10.4", + "@babel/plugin-transform-property-literals": "^7.10.4", + "@babel/plugin-transform-regenerator": "^7.10.4", + "@babel/plugin-transform-reserved-words": "^7.10.4", + "@babel/plugin-transform-shorthand-properties": "^7.10.4", + "@babel/plugin-transform-spread": "^7.10.4", + "@babel/plugin-transform-sticky-regex": "^7.10.4", + "@babel/plugin-transform-template-literals": "^7.10.4", + "@babel/plugin-transform-typeof-symbol": "^7.10.4", + "@babel/plugin-transform-unicode-escapes": "^7.10.4", + "@babel/plugin-transform-unicode-regex": "^7.10.4", "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.9.5", - "browserslist": "^4.9.1", + "@babel/types": "^7.10.4", + "browserslist": "^4.12.0", "core-js-compat": "^3.6.2", "invariant": "^2.2.2", "levenary": "^1.1.1", @@ -957,9 +947,9 @@ } }, "@babel/runtime": { - "version": "7.9.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz", - "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.5.tgz", + "integrity": "sha512-otddXKhdNn7d0ptoFRHtMLa8LqDxLYwTjB4nYgM1yy5N6gU/MUf8zqyyLltCH3yAVitBzmwK4us+DD0l/MauAg==", "dev": true, "requires": { "regenerator-runtime": "^0.13.4" @@ -976,86 +966,69 @@ } }, "@babel/template": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", - "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", "dev": true, "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.6", - "@babel/types": "^7.8.6" - }, - "dependencies": { - "@babel/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", - "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.9.0", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - } + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/traverse": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.0.tgz", - "integrity": "sha512-jAZQj0+kn4WTHO5dUZkZKhbFrqZE7K5LAQ5JysMnmvGij+wOdr+8lWqPeW0BcF4wFwrEXXtdGO7wcV6YPJcf3w==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.5.tgz", + "integrity": "sha512-yc/fyv2gUjPqzTz0WHeRJH2pv7jA9kA7mBX2tXl/x5iOE81uaVPuGPtaYk7wmkx4b67mQ7NqI8rmT2pF47KYKQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.0", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.9.0", - "@babel/types": "^7.9.0", + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.10.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "@babel/parser": "^7.10.5", + "@babel/types": "^7.10.5", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.13" + "lodash": "^4.17.19" }, "dependencies": { - "@babel/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.0.tgz", - "integrity": "sha512-BS9JKfXkzzJl8RluW4JGknzpiUV7ZrvTayM6yfqLTVBEnFtyowVIOu6rqxRd5cVO6yGoWf4T8u8dgK9oB+GCng==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.9.0", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true } } }, "@babel/types": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", - "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.5.tgz", + "integrity": "sha512-ixV66KWfCI6GKoA/2H9v6bQdbfXEwwpOdQ8cRvb4F+eyvhlaHxWFMQB4+3d9QFJXZsiiiqVrewNV0DFEQpyT4Q==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.9.5", - "lodash": "^4.17.13", + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" }, "dependencies": { - "@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true } } }, "@istanbuljs/load-nyc-config": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", - "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "requires": { "camelcase": "^5.3.1", "find-up": "^4.1.0", + "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" }, @@ -1328,9 +1301,9 @@ "dev": true }, "@tootallnate/once": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.0.0.tgz", - "integrity": "sha512-KYyTT/T6ALPkIRd2Ge080X/BsXvy9O0hcWTtMWkPvwAwF99+vn6Dv4GzrFT/Nn1LePr+FFDbRXXlqmsy9lw2zA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true }, "@types/color-name": { @@ -1339,6 +1312,18 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", + "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", + "dev": true + }, "@types/listr": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/@types/listr/-/listr-0.14.2.tgz", @@ -1350,11 +1335,110 @@ } }, "@types/node": { - "version": "13.11.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.11.1.tgz", - "integrity": "sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g==", + "version": "14.0.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.24.tgz", + "integrity": "sha512-btt/oNOiDWcSuI721MdL8VQGnjsKjlTMdrKyTcLCKeQp/n4AAMFJ961wMbp+09y8WuGPClDEv07RIItdXKIXAA==", "dev": true }, + "@typescript-eslint/eslint-plugin": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.7.0.tgz", + "integrity": "sha512-4OEcPON3QIx0ntsuiuFP/TkldmBGXf0uKxPQlGtS/W2F3ndYm8Vgdpj/woPJkzUc65gd3iR+qi3K8SDQP/obFg==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "3.7.0", + "debug": "^4.1.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "@typescript-eslint/experimental-utils": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.7.0.tgz", + "integrity": "sha512-xpfXXAfZqhhqs5RPQBfAFrWDHoNxD5+sVB5A46TF58Bq1hRfVROrWHcQHHUM9aCBdy9+cwATcvCbRg8aIRbaHQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/types": "3.7.0", + "@typescript-eslint/typescript-estree": "3.7.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + }, + "dependencies": { + "eslint-scope": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.7.0.tgz", + "integrity": "sha512-2LZauVUt7jAWkcIW7djUc3kyW+fSarNEuM3RF2JdLHR9BfX/nDEnyA4/uWz0wseoWVZbDXDF7iF9Jc342flNqQ==", + "dev": true, + "requires": { + "@types/eslint-visitor-keys": "^1.0.0", + "@typescript-eslint/experimental-utils": "3.7.0", + "@typescript-eslint/types": "3.7.0", + "@typescript-eslint/typescript-estree": "3.7.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "@typescript-eslint/types": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.7.0.tgz", + "integrity": "sha512-reCaK+hyKkKF+itoylAnLzFeNYAEktB0XVfSQvf0gcVgpz1l49Lt6Vo9x4MVCCxiDydA0iLAjTF/ODH0pbfnpg==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.7.0.tgz", + "integrity": "sha512-xr5oobkYRebejlACGr1TJ0Z/r0a2/HUf0SXqPvlgUMwiMqOCu/J+/Dr9U3T0IxpE5oLFSkqMx1FE/dKaZ8KsOQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "3.7.0", + "@typescript-eslint/visitor-keys": "3.7.0", + "debug": "^4.1.1", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.7.0.tgz", + "integrity": "sha512-k5PiZdB4vklUpUX4NBncn5RBKty8G3ihTY+hqJsCdMuD0v4jofI5xuqwnVcWxfv6iTm2P/dfEa2wMUnsUY8ODw==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, "@webassemblyjs/ast": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", @@ -1553,9 +1637,9 @@ } }, "acorn": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", - "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", + "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==", "dev": true }, "acorn-jsx": { @@ -1565,9 +1649,9 @@ "dev": true }, "agent-base": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz", - "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", + "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", "dev": true, "requires": { "debug": "4" @@ -1622,9 +1706,9 @@ "dev": true }, "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, "ansi-escapes": { @@ -1697,6 +1781,12 @@ "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1742,6 +1832,18 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "array.prototype.map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.2.tgz", + "integrity": "sha512-Az3OYxgsa1g7xDYp86l0nnN4bcmuEITGe1rbdEBVkrqkzMgDcbdQ2R7r41pNzti+4NMces3H8gMmuioZUilLgw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.4" + } + }, "asn1.js": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", @@ -1844,9 +1946,9 @@ } }, "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", "dev": true, "requires": { "object.assign": "^4.1.0" @@ -2117,15 +2219,15 @@ } }, "browserslist": { - "version": "4.11.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.11.1.tgz", - "integrity": "sha512-DCTr3kDrKEYNw6Jb9HFxVLQNaue8z+0ZfRBRjmCunKDEXEBajKDj2Y+Uelg+Pi29OnvaSGwjOsnRyNEkXzHg5g==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.13.0.tgz", + "integrity": "sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001038", - "electron-to-chromium": "^1.3.390", - "node-releases": "^1.1.53", - "pkg-up": "^2.0.0" + "caniuse-lite": "^1.0.30001093", + "electron-to-chromium": "^1.3.488", + "escalade": "^3.0.1", + "node-releases": "^1.1.58" } }, "buffer": { @@ -2224,9 +2326,9 @@ }, "dependencies": { "make-dir": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", - "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "requires": { "semver": "^6.0.0" @@ -2253,9 +2355,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001040", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001040.tgz", - "integrity": "sha512-Ep0tEPeI5wCvmJNrXjE3etgfI+lkl1fTDU6Y3ZH1mhrjkPlVI9W4pcKbMo+BQLpEWKVYYp2EmYaRsqpPC3k7lQ==", + "version": "1.0.30001105", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001105.tgz", + "integrity": "sha512-JupOe6+dGMr7E20siZHIZQwYqrllxotAhiaej96y6x00b/48rPt42o+SzOSCPbrpsDWvRja40Hwrj0g0q6LZJg==", "dev": true }, "cardinal": { @@ -2550,9 +2652,9 @@ } }, "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true }, "cliui": { @@ -2566,12 +2668,6 @@ "wrap-ansi": "^5.1.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -2582,15 +2678,6 @@ "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^5.1.0" } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } } } }, @@ -2607,9 +2694,9 @@ "dev": true }, "codecov": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.6.5.tgz", - "integrity": "sha512-v48WuDMUug6JXwmmfsMzhCHRnhUf8O3duqXvltaYJKrO1OekZWpB/eH6iIoaxMl8Qli0+u3OxptdsBOYiD7VAQ==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.7.2.tgz", + "integrity": "sha512-fmCjAkTese29DUX3GMIi4EaKGflHa4K51EoMc29g8fBHawdk/+KEq5CWOeXLdd9+AT7o1wO4DIpp/Z1KCqCz1g==", "dev": true, "requires": { "argv": "0.0.2", @@ -3132,9 +3219,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.403", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.403.tgz", - "integrity": "sha512-JaoxV4RzdBAZOnsF4dAlZ2ijJW72MbqO5lNfOBHUWiBQl3Rwe+mk2RCUMrRI3rSClLJ8HSNQNqcry12H+0ZjFw==", + "version": "1.3.505", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.505.tgz", + "integrity": "sha512-Aunrp3HWtmdiJLIl+IPSFtEvJ/4Q9a3eKaxmzCthaZF1gbTbpHUTCU2zOVnFPH7r/AD7zQXyuFidYXzSHXBdsw==", "dev": true }, "elegant-spinner": { @@ -3208,6 +3295,15 @@ } } }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -3227,22 +3323,51 @@ } }, "es-abstract": { - "version": "1.17.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", - "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", "has-symbols": "^1.0.1", - "is-callable": "^1.1.5", - "is-regex": "^1.0.5", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", "object-inspect": "^1.7.0", "object-keys": "^1.1.1", "object.assign": "^4.1.0", - "string.prototype.trimleft": "^2.1.1", - "string.prototype.trimright": "^2.1.1" + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "es-get-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", + "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", + "dev": true, + "requires": { + "es-abstract": "^1.17.4", + "has-symbols": "^1.0.1", + "is-arguments": "^1.0.4", + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } } }, "es-to-primitive": { @@ -3294,6 +3419,12 @@ "ext": "^1.1.2" } }, + "escalade": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", + "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -3307,22 +3438,23 @@ "dev": true }, "eslint": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", - "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.5.0.tgz", + "integrity": "sha512-vlUP10xse9sWt9SGRtcr1LAC67BENcQMFeV+w5EvLEoFe3xJ8cF1Skd0msziRx/VMC+72B4DxreCE+OR12OA6Q==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "ajv": "^6.10.0", - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", - "eslint-scope": "^5.0.0", - "eslint-utils": "^1.4.3", - "eslint-visitor-keys": "^1.1.0", - "espree": "^6.1.2", - "esquery": "^1.0.1", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.0", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^1.3.0", + "espree": "^7.2.0", + "esquery": "^1.2.0", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", "functional-red-black-tree": "^1.0.1", @@ -3331,56 +3463,80 @@ "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", "is-glob": "^4.0.0", "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.14", + "levn": "^0.4.1", + "lodash": "^4.17.19", "minimatch": "^3.0.4", - "mkdirp": "^0.5.1", "natural-compare": "^1.4.0", - "optionator": "^0.8.3", + "optionator": "^0.9.1", "progress": "^2.0.0", - "regexpp": "^2.0.1", - "semver": "^6.1.2", - "strip-ansi": "^5.2.0", - "strip-json-comments": "^3.0.1", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", "table": "^5.2.3", "text-table": "^0.2.0", "v8-compile-cache": "^2.0.3" }, "dependencies": { "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-name": "~1.1.4" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, "eslint-scope": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", - "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", "dev": true, "requires": { "esrecurse": "^4.1.0", @@ -3405,28 +3561,61 @@ "type-fest": "^0.8.1" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } }, "type-fest": { @@ -3434,6 +3623,15 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -3626,29 +3824,29 @@ } }, "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" } }, "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true }, "espree": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", - "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.2.0.tgz", + "integrity": "sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==", "dev": true, "requires": { - "acorn": "^7.1.1", + "acorn": "^7.3.1", "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.1.0" + "eslint-visitor-keys": "^1.3.0" } }, "esprima": { @@ -3658,18 +3856,18 @@ "dev": true }, "esquery": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.2.0.tgz", - "integrity": "sha512-weltsSqdeWIX9G2qQZz7KlTRJdkkOCTPgLYJUz1Hacf48R4YOwGPHO3+ORfWedqJKbq5WQmsgK90n+pFLIKt/Q==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "dev": true, "requires": { - "estraverse": "^5.0.0" + "estraverse": "^5.1.0" }, "dependencies": { "estraverse": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.0.0.tgz", - "integrity": "sha512-j3acdrMzqrxmJTNj5dbr1YbjacrYgAxVMeF0gK16E3j494mOe7xygM/ZLIguEQ0ETwAg2hlJCtHRGav+y0Ny5A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", + "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", "dev": true } } @@ -4195,9 +4393,9 @@ } }, "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, "flush-write-stream": { @@ -4253,9 +4451,9 @@ }, "dependencies": { "cross-spawn": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", - "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -4327,9 +4525,9 @@ } }, "fromentries": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", - "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.1.tgz", + "integrity": "sha512-Xu2Qh8yqYuDhQGOhD5iJGninErSfI9A3FrriD3tjUgV5VbJFeH8vfgZ9HnC6jWN80QDVNQK5vmxRAmEAp7Mevw==", "dev": true }, "fs-extra": { @@ -4936,6 +5134,12 @@ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, "get-stream": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", @@ -5110,12 +5314,6 @@ "type-fest": "^0.8.0" }, "dependencies": { - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -5283,26 +5481,26 @@ }, "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", "dev": true }, "inquirer": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", - "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", "dev": true, "requires": { "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", + "chalk": "^4.1.0", "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", + "cli-width": "^3.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", - "lodash": "^4.17.15", + "lodash": "^4.17.19", "mute-stream": "0.0.8", "run-async": "^2.4.0", - "rxjs": "^6.5.3", + "rxjs": "^6.6.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6" @@ -5334,9 +5532,9 @@ } }, "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -5394,21 +5592,12 @@ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true }, - "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, "restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -5419,6 +5608,15 @@ "signal-exit": "^3.0.2" } }, + "rxjs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.0.tgz", + "integrity": "sha512-3HMA8z/Oz61DUHe+SdOiQyzIf4tOx5oQHmMir7IZEu6TMqCLHT4LRcmNaUS0NwOz8VLvmmBduMsoaUvMaIiqzg==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, "string-width": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", @@ -5491,6 +5689,12 @@ } } }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", + "dev": true + }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -5507,9 +5711,9 @@ "dev": true }, "is-callable": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", "dev": true }, "is-data-descriptor": { @@ -5590,6 +5794,12 @@ "is-extglob": "^2.1.1" } }, + "is-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", + "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==", + "dev": true + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -5641,20 +5851,32 @@ "dev": true }, "is-regex": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", - "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", + "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", "dev": true, "requires": { - "has": "^1.0.3" + "has-symbols": "^1.0.1" } }, + "is-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", + "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==", + "dev": true + }, "is-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", @@ -5716,15 +5938,12 @@ } }, "istanbul-lib-instrument": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz", - "integrity": "sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, "requires": { "@babel/core": "^7.7.5", - "@babel/parser": "^7.7.5", - "@babel/template": "^7.7.4", - "@babel/traverse": "^7.7.4", "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.0.0", "semver": "^6.3.0" @@ -5754,9 +5973,9 @@ }, "dependencies": { "cross-spawn": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", - "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { "path-key": "^3.1.0", @@ -5765,9 +5984,9 @@ } }, "make-dir": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", - "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "requires": { "semver": "^6.0.0" @@ -5818,12 +6037,6 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5853,9 +6066,9 @@ "dev": true }, "make-dir": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", - "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "requires": { "semver": "^6.0.0" @@ -5907,6 +6120,22 @@ "istanbul-lib-report": "^3.0.0" } }, + "iterate-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.1.tgz", + "integrity": "sha512-3Q6tudGN05kbkDQDI4CqjaBf4qf85w6W6GnuZDtUVYwKgtC1q8yxYX7CZed7N+tLzQqS6roujWvszf13T+n9aw==", + "dev": true + }, + "iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "dev": true, + "requires": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + } + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6021,13 +6250,13 @@ } }, "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" } }, "listr": { @@ -6190,9 +6419,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg=", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true }, "lodash._reinterpolate": { @@ -6239,37 +6468,6 @@ "dev": true, "requires": { "chalk": "^2.4.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } } }, "log-update": { @@ -6353,6 +6551,12 @@ "semver": "^5.6.0" } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -6552,32 +6756,33 @@ } }, "mocha": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.1.tgz", - "integrity": "sha512-3qQsu3ijNS3GkWcccT5Zw0hf/rWvu1fTN9sPvEd81hlwsr30GX2GcDSSoBxo24IR8FelmrAydGC6/1J5QQP4WA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.0.1.tgz", + "integrity": "sha512-vefaXfdYI8+Yo8nPZQQi0QO2o+5q9UIMX1jZ1XMmK3+4+CQjc7+B0hPdUeglXiTlr8IHMVRo63IhO9Mzt6fxOg==", "dev": true, "requires": { - "ansi-colors": "3.2.3", + "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.3.0", + "chokidar": "3.3.1", "debug": "3.2.6", - "diff": "3.5.0", + "diff": "4.0.2", "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", + "find-up": "4.1.0", + "glob": "7.1.6", "growl": "1.10.5", "he": "1.2.0", "js-yaml": "3.13.1", "log-symbols": "3.0.0", "minimatch": "3.0.4", - "mkdirp": "0.5.3", - "ms": "2.1.1", - "node-environment-flags": "1.0.6", + "ms": "2.1.2", "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", + "promise.allsettled": "1.0.2", + "serialize-javascript": "3.0.0", + "strip-json-comments": "3.0.1", + "supports-color": "7.1.0", + "which": "2.0.2", "wide-align": "1.1.3", + "workerpool": "6.0.0", "yargs": "13.3.2", "yargs-parser": "13.1.2", "yargs-unparser": "1.6.0" @@ -6594,9 +6799,9 @@ } }, "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, "braces": { @@ -6609,19 +6814,19 @@ } }, "chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", + "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", "dev": true, "requires": { "anymatch": "~3.1.1", "braces": "~3.0.2", - "fsevents": "~2.1.1", + "fsevents": "~2.1.2", "glob-parent": "~5.1.0", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" + "readdirp": "~3.3.0" } }, "debug": { @@ -6633,12 +6838,6 @@ "ms": "^2.1.1" } }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -6648,27 +6847,23 @@ "to-regex-range": "^5.0.1" } }, - "fsevents": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", - "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", - "dev": true, - "optional": true - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, "glob-parent": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", @@ -6678,6 +6873,12 @@ "is-glob": "^4.0.1" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -6693,49 +6894,64 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, - "mkdirp": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", - "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "minimist": "^1.2.5" + "p-locate": "^4.1.0" } }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, "readdirp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", - "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", + "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", "dev": true, "requires": { - "picomatch": "^2.0.4" + "picomatch": "^2.0.7" } }, + "serialize-javascript": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.0.0.tgz", + "integrity": "sha512-skZcHYw2vEX4bw90nAr2iTTsz6x2SrHEnfxgKYmZlvJYBEZrvbKtobJWlQ20zczKb3bsHHXXTYt48zBA7ni9cw==", + "dev": true + }, "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", "dev": true }, "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } }, "to-regex-range": { @@ -6746,6 +6962,15 @@ "requires": { "is-number": "^7.0.0" } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -6886,24 +7111,6 @@ "lower-case": "^1.1.1" } }, - "node-environment-flags": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", - "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, "node-fetch": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", @@ -6959,9 +7166,9 @@ } }, "node-releases": { - "version": "1.1.53", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.53.tgz", - "integrity": "sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==", + "version": "1.1.60", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", + "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", "dev": true }, "normalize-path": { @@ -6997,9 +7204,9 @@ "dev": true }, "nyc": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.0.1.tgz", - "integrity": "sha512-n0MBXYBYRqa67IVt62qW1r/d9UH/Qtr7SF1w/nQLJ9KxvWF6b2xCHImRAixHN9tnMMYHC2P14uo6KddNGwMgGg==", + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, "requires": { "@istanbuljs/load-nyc-config": "^1.0.0", @@ -7010,6 +7217,7 @@ "find-cache-dir": "^3.2.0", "find-up": "^4.1.0", "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", "glob": "^7.1.6", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-hook": "^3.0.0", @@ -7121,9 +7329,9 @@ } }, "make-dir": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", - "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "requires": { "semver": "^6.0.0" @@ -7215,9 +7423,9 @@ } }, "yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { "cliui": "^6.0.0", @@ -7230,13 +7438,13 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" + "yargs-parser": "^18.1.2" } }, "yargs-parser": { - "version": "18.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.2.tgz", - "integrity": "sha512-hlIPNR3IzC1YuL1c2UwwDKpXlNFBqD1Fswwh1khz5+d8Cq/8yc/Mn0i+rQXduu8hcrFKvO7Eryk+09NecTQAAQ==", + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -7289,9 +7497,9 @@ "dev": true }, "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", "dev": true }, "object-keys": { @@ -7321,16 +7529,6 @@ "object-keys": "^1.0.11" } }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, "object.pick": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", @@ -7368,17 +7566,17 @@ } }, "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" } }, "os-browserify": { @@ -7436,9 +7634,9 @@ }, "dependencies": { "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true } } @@ -7601,60 +7799,6 @@ "find-up": "^3.0.0" } }, - "pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", - "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", - "dev": true, - "requires": { - "find-up": "^2.1.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - } - } - }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -7662,15 +7806,9 @@ "dev": true }, "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, "process": { @@ -7706,6 +7844,19 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "promise.allsettled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", + "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", + "dev": true, + "requires": { + "array.prototype.map": "^1.0.1", + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "iterate-value": "^1.0.0" + } + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -7888,9 +8039,9 @@ } }, "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", + "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", "dev": true }, "regenerate-unicode-properties": { @@ -7909,13 +8060,12 @@ "dev": true }, "regenerator-transform": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.4.tgz", - "integrity": "sha512-EaJaKPBI9GvKpvUz2mz4fhx7WPgvwRLY9v3hlNHWmAuJHI13T4nwKnNvm5RWJzEdnI5g5UwtOww+S8IdoUC2bw==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", "dev": true, "requires": { - "@babel/runtime": "^7.8.4", - "private": "^0.1.8" + "@babel/runtime": "^7.8.4" } }, "regex-not": { @@ -7929,9 +8079,9 @@ } }, "regexpp": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", - "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", "dev": true }, "regexpu-core": { @@ -7949,9 +8099,9 @@ } }, "regjsgen": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", - "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", "dev": true }, "regjsparser": { @@ -8077,6 +8227,158 @@ "dev": true, "requires": { "eslint": "^6.8.0" + }, + "dependencies": { + "eslint": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz", + "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.3", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.2", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^7.0.0", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.3", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-scope": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "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" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } } }, "rimraf": { @@ -8099,13 +8401,10 @@ } }, "run-async": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.0.tgz", - "integrity": "sha512-xJTbh/d7Lm7SBhc1tNvTpeCHaEzoyxPrqNlvSdMfBTYwaY++UJFyXUOxAtsRUXjlqOfj8luNaR9vjCh4KeV+pg==", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true }, "run-queue": { "version": "1.0.3", @@ -8395,7 +8694,7 @@ }, "should-util": { "version": "1.0.0", - "resolved": false, + "resolved": "", "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=", "dev": true }, @@ -8455,17 +8754,6 @@ "ansi-styles": "^3.2.0", "astral-regex": "^1.0.0", "is-fullwidth-code-point": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - } } }, "snapdragon": { @@ -8654,9 +8942,9 @@ }, "dependencies": { "make-dir": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.2.tgz", - "integrity": "sha512-rYKABKutXa6vXTXhoV18cBE7PaewPXHe/Bdq4v+ZLMhxbWApkFFplT0LcbMW+6BbjnQXzZ/sAvSE/JdguApG5w==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "requires": { "semver": "^6.0.0" @@ -8870,24 +9158,24 @@ } } }, - "string.prototype.trimleft": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", - "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5" } }, - "string.prototype.trimright": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", - "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5" } }, "string_decoder": { @@ -8921,9 +9209,9 @@ "dev": true }, "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "stubs": { @@ -8977,12 +9265,6 @@ "string-width": "^3.0.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -8993,15 +9275,6 @@ "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^5.1.0" } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } } } }, @@ -9230,12 +9503,34 @@ "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==", "dev": true }, + "ts-node": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", + "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, "tslib": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", "integrity": "sha1-w8GflZc/sKYpc/sJ2Q2WHuQ+XIo=", "dev": true }, + "tsutils": { + "version": "3.17.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", + "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -9249,12 +9544,12 @@ "dev": true }, "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "^1.2.1" } }, "type-detect": { @@ -9294,6 +9589,12 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "dev": true + }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -9489,15 +9790,15 @@ "dev": true }, "uuid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "dev": true }, "v8-compile-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", "dev": true }, "vary": { @@ -9650,6 +9951,12 @@ "errno": "~0.1.7" } }, + "workerpool": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", + "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", + "dev": true + }, "wrap-ansi": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", @@ -9661,21 +9968,6 @@ "strip-ansi": "^5.0.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, "string-width": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", @@ -9686,15 +9978,6 @@ "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^5.1.0" } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } } } }, @@ -9726,9 +10009,9 @@ } }, "ws": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz", - "integrity": "sha512-C34cIU4+DB2vMyAbmEKossWq2ZQDr6QEyuuCzWrM9zfw1sGc0mYiJ0UnG9zzNykt49C2Fi34hvr2vssFQRS6EA==" + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==" }, "xregexp": { "version": "4.3.0", @@ -9795,12 +10078,6 @@ "yargs-parser": "^13.1.2" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -9817,15 +10094,6 @@ "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^5.1.0" } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } } } }, @@ -9849,6 +10117,12 @@ "lodash": "^4.17.15", "yargs": "^13.3.0" } + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true } } } diff --git a/package.json b/package.json index d6e21b661..9f0aea951 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "kuzzle-sdk", - "version": "7.2.0", + "version": "7.3.0", "description": "Official Javascript SDK for Kuzzle", "author": "The Kuzzle Team ", "repository": { @@ -19,11 +19,14 @@ ], "scripts": { "prepublishOnly": "npm run build", - "test": "npm run --silent lint && npm run unit-testing && npm run functional-testing", - "unit-testing": "nyc --reporter=text-summary --reporter=lcov mocha", - "functional-testing": "cucumber-js --exit --fail-fast", - "lint": "eslint --max-warnings=0 ./src ./test ./features", - "build": "node build.js", + "test": "npm run test:lint && npm run test:unit && npm run test:functional", + "test:unit": "nyc --reporter=text-summary --reporter=lcov mocha", + "test:functional": "cucumber-js --exit --fail-fast", + "test:lint": "npm run test:lint:js && npm run test:lint:ts", + "test:lint:js": "eslint --max-warnings=0 ./src ./test ./features", + "test:lint:ts": "eslint ./src --ext .ts --config .eslintc-ts.json", + "build": "npm run build-ts && node build.js", + "build-ts": "tsc --build tsconfig.json", "doc": "docker-compose -f doc/docker-compose.yml up", "doc-testing": "bash .ci/test-docs.sh", "doc-prepare": "kuzdoc framework:install", @@ -39,36 +42,43 @@ "license": "Apache-2.0", "dependencies": { "min-req-promise": "^1.0.1", - "ws": "^7.2.5" + "ws": "^7.3.1" }, "devDependencies": { - "@babel/core": "^7.9.0", - "@babel/preset-env": "^7.9.5", + "@babel/core": "^7.10.5", + "@babel/preset-env": "^7.10.4", + "@types/node": "^14.0.24", + "@typescript-eslint/eslint-plugin": "^3.7.0", + "@typescript-eslint/parser": "^3.7.0", "babel-loader": "^8.1.0", - "codecov": "^3.6.5", + "codecov": "^3.7.2", "cucumber": "^6.0.5", - "eslint": "^6.8.0", + "eslint": "^7.5.0", "eslint-friendly-formatter": "^4.0.1", "eslint-loader": "^4.0.2", "kuzdoc": "^1.2.2", "lolex": "^6.0.0", - "mocha": "7.1.1", + "mocha": "8.0.1", "mock-require": "^3.0.3", - "nyc": "^15.0.1", + "nyc": "^15.1.0", "proxyquire": "^2.1.3", "retry": "^0.12.0", "rewire": "^5.0.0", "should": "13.2.3", "should-sinon": "0.0.6", "sinon": "^9.0.2", + "ts-node": "^8.10.2", + "typescript": "^3.9.7", "webpack": "^4.43.0" }, "engines": { "node": ">= 10.13.0" }, "files": [ - "src/**/*", + "dist/**/*", "index.js", - "dist/**/*" + "index.d.ts", + "src/**/*.js", + "src/**/*.d.ts" ] } diff --git a/src/Kuzzle.js b/src/Kuzzle.ts similarity index 84% rename from src/Kuzzle.js rename to src/Kuzzle.ts index 24e0b2b8b..98a27138e 100644 --- a/src/Kuzzle.js +++ b/src/Kuzzle.ts @@ -1,37 +1,91 @@ -const KuzzleEventEmitter = require('./core/KuzzleEventEmitter'); -const AuthController = require('./controllers/Auth'); -const BulkController = require('./controllers/Bulk'); -const CollectionController = require('./controllers/Collection'); -const DocumentController = require('./controllers/Document'); -const IndexController = require('./controllers/Index'); -const RealtimeController = require('./controllers/Realtime'); -const ServerController = require('./controllers/Server'); -const SecurityController = require('./controllers/Security'); -const MemoryStorageController = require('./controllers/MemoryStorage'); -const uuidv4 = require('./utils/uuidv4'); -const proxify = require('./utils/proxify'); - -const - events = [ - 'connected', - 'discarded', - 'disconnected', - 'loginAttempt', - 'networkError', - 'offlineQueuePush', - 'offlineQueuePop', - 'queryError', - 'reconnected', - 'tokenExpired' - ]; - -class Kuzzle extends KuzzleEventEmitter { +import { KuzzleEventEmitter } from './core/KuzzleEventEmitter'; + +import { AuthController } from './controllers/Auth'; +import { BulkController } from './controllers/Bulk'; +import { CollectionController } from './controllers/Collection'; +import { DocumentController } from './controllers/Document'; +import { IndexController } from './controllers/Index'; +import { RealtimeController } from './controllers/Realtime'; +import { ServerController } from './controllers/Server'; +import { SecurityController } from './controllers/Security'; +import { MemoryStorageController } from './controllers/MemoryStorage'; + +import { uuidv4 } from './utils/uuidv4'; +import { proxify } from './utils/proxify'; +import { JSONObject, KuzzleRequest } from './utils/interfaces'; + +// Defined by webpack plugin +declare const SDKVERSION: any; + +const events = [ + 'connected', + 'discarded', + 'disconnected', + 'loginAttempt', + 'networkError', + 'offlineQueuePush', + 'offlineQueuePop', + 'queryError', + 'reconnected', + 'tokenExpired' +]; + +export class Kuzzle extends KuzzleEventEmitter { + /** + * Protocol used by the SDK to communicate with Kuzzle. + */ + public protocol: any; + /** + * If true, automatically renews all subscriptions on a reconnected event. + */ + public autoResubscribe: boolean; + /** + * Timeout before sending again a similar event. + */ + public eventTimeout: number; + /** + * SDK version. + */ + public sdkVersion: string; + /** + * SDK name (e.g: js@7.4.2). + */ + public sdkName: string; + /** + * Common volatile data that will be sent to all future requests. + */ + public volatile: JSONObject; + + public auth: AuthController; + public bulk: any; + public collection: any; + public document: DocumentController; + public index: any; + public ms: any; + public realtime: any; + public security: any; + public server: any; + + private _protectedEvents: any; + private _offlineQueue: any; + private _autoQueue: any; + private _autoReplay: any; + private _offlineQueueLoader: any; + private _queuing: boolean; + private _queueFilter: any; + private _queueMaxSize: any; + private _queueTTL: any; + private _replayInterval: any; + private _tokenExpiredInterval: any; + private _lastTokenExpired: any; + + private __proxy__: any; /** * @param protocol - the protocol to use * @param [options] - Kuzzle options */ - constructor(protocol, options = {}) { + constructor(protocol: any, options: any = {}) { super(); if (protocol === undefined || protocol === null) { @@ -64,6 +118,7 @@ class Kuzzle extends KuzzleEventEmitter { : 200; this.sdkVersion = typeof SDKVERSION === 'undefined' + // eslint-disable-next-line @typescript-eslint/no-var-requires ? require('../package').version : SDKVERSION; @@ -115,7 +170,7 @@ class Kuzzle extends KuzzleEventEmitter { this._autoQueue = true; this._autoReplay = true; } - this.queuing = false; + this._queuing = false; this._lastTokenExpired = null; @@ -123,7 +178,7 @@ class Kuzzle extends KuzzleEventEmitter { seal: true, name: 'kuzzle', exposeApi: true - }); + }) as Kuzzle; } get authenticated () { @@ -259,21 +314,25 @@ class Kuzzle extends KuzzleEventEmitter { if (protectedEvent) { if ( protectedEvent.lastEmitted - && protectedEvent.lastEmitted > now - this.eventTimeout) - { + && protectedEvent.lastEmitted > now - this.eventTimeout + ) { return false; } protectedEvent.lastEmitted = now; } - super.emit(eventName, ...payload); + return this._superEmit(eventName, ...payload); + } + + _superEmit (eventName, ...payload) { + return super.emit(eventName, ...payload); } /** * Connects to a Kuzzle instance using the provided host name * @returns {Promise} */ - connect () { + connect (): Promise { if (this.protocol.isReady()) { return Promise.resolve(); } @@ -359,6 +418,10 @@ class Kuzzle extends KuzzleEventEmitter { throw new Error(`[${event}] is not a known event. Known events: ${events.toString()}`); } + return this._superAddListener(event, listener); + } + + _superAddListener (event, listener) { return super.addListener(event, listener); } @@ -392,7 +455,7 @@ class Kuzzle extends KuzzleEventEmitter { * @param {object} [options] - Optional arguments * @returns {Promise} */ - query (request = {}, options = {}) { + query (request: KuzzleRequest = {}, options: JSONObject = {}): Promise { if (typeof request !== 'object' || Array.isArray(request)) { throw new Error(`Kuzzle.query: Invalid request: ${JSON.stringify(request)}`); } @@ -438,7 +501,7 @@ class Kuzzle extends KuzzleEventEmitter { queuable = queuable && this.queueFilter(request); } - if (this.queuing) { + if (this._queuing) { if (queuable) { this._cleanQueue(); this.emit('offlineQueuePush', {request}); @@ -464,7 +527,7 @@ Discarded request: ${JSON.stringify(request)}`)); * Starts the requests queuing. */ startQueuing () { - this.queuing = true; + this._queuing = true; return this; } @@ -472,7 +535,7 @@ Discarded request: ${JSON.stringify(request)}`)); * Stops the requests queuing. */ stopQueuing () { - this.queuing = false; + this._queuing = false; return this; } @@ -633,4 +696,4 @@ Discarded request: ${JSON.stringify(request)}`)); } -module.exports = Kuzzle; +module.exports = { Kuzzle }; diff --git a/src/controllers/Auth.js b/src/controllers/Auth.js deleted file mode 100644 index 0dcb9a0e5..000000000 --- a/src/controllers/Auth.js +++ /dev/null @@ -1,358 +0,0 @@ -const Jwt = require('../core/Jwt'); -const BaseController = require('./Base'); -const User = require('../core/security/User'); - -/** - * Auth controller - * - * @param kuzzle - * @constructor - */ -class AuthController extends BaseController { - - /** - * constructor - * @param kuzzle - */ - constructor (kuzzle) { - super(kuzzle, 'auth'); - - this._authenticationToken = null; - - this.kuzzle.on('tokenExpired', () => { - this._authenticationToken = null; - }); - } - - get authenticationToken () { - return this._authenticationToken; - } - - set authenticationToken (encodedJwt) { - if (encodedJwt === undefined || encodedJwt === null) { - this._authenticationToken = null; - } - else if (typeof encodedJwt === 'string') { - this._authenticationToken = new Jwt(encodedJwt); - } - else { - throw new Error(`Invalid token argument: ${encodedJwt}`); - } - } - - /** - * Do not add the token for the checkToken route, to avoid getting a token error when - * a developer simply wish to verify his token - * - * @param {object} request - */ - authenticateRequest (request) { - if ( !this.authenticationToken - || (request.controller === 'auth' - && (request.action === 'checkToken' || request.action === 'login')) - ) { - return; - } - - request.jwt = this.authenticationToken.encodedJwt; - } - - /** - * Creates a new API key for the currently loggued user. - * - * @param {String} description - API key description - * @param {Object} [options] - { _id, expiresIn, refresh } - * - * @returns {Promise.} ApiKey { _id, _source } - */ - createApiKey(description, options = {}) { - const request = { - action: 'createApiKey', - _id: options._id, - expiresIn: options.expiresIn, - refresh: options.refresh, - body: { - description - } - }; - - return this.query(request) - .then(response => response.result); - } - - /** - * Deletes an API key for the currently loggued user. - * - * @param {String} id - API key ID - * @param {Object} [options] - { refresh } - * - * @returns {Promise} - */ - deleteApiKey(id, options = {}) { - const request = { - action: 'deleteApiKey', - _id: id, - refresh: options.refresh - }; - - return this.query(request) - .then(() => {}); - } - - /** - * Searches API keys for the currently loggued user. - * - * @param {Object} [query] - Search query - * @param {Object} [options] - { from, size } - * - * @returns {Promise.} - { hits, total } - */ - searchApiKeys(query = {}, options = {}) { - const request = { - action: 'searchApiKeys', - from: options.from, - size: options.size, - body: query - }; - - return this.query(request) - .then(response => response.result); - } - - /** - * Checks whether a given jwt token still represents a valid session in Kuzzle. - * - * @param {string} token The jwt token to check - * @return {Promise|*|PromiseLike|Promise} - */ - checkToken (token) { - if (token === undefined && this.authenticationToken) { - token = this.authenticationToken.encodedJwt; - } - - return this.query({ - action: 'checkToken', - body: { token } - }, { queuable: false }) - .then(response => response.result); - } - - /** - * Create credentials of the specified for the current user. - * - * @param credentials - * @param strategy - * @param options - * @returns {Promise|*|PromiseLike|Promise} - */ - createMyCredentials (strategy, credentials, options = {}) { - return this.query({ - strategy, - action: 'createMyCredentials', - body: credentials - }, options) - .then(response => response.result); - } - - /** - * Check the existence of the specified 's credentials for the current user. - * - * @param strategy - * @returns {Promise|*|PromiseLike|Promise} - */ - credentialsExist (strategy, options = {}) { - return this.query({ - strategy, - action: 'credentialsExist' - }, options) - .then(response => response.result); - } - - /** - * Delete credentials of the specified for the current user. - * - * @param strategy - * @param options - * @returns {Promise|*|PromiseLike|Promise} - */ - deleteMyCredentials (strategy, options = {}) { - return this.query({ - strategy, - action: 'deleteMyCredentials' - }, options) - .then(response => response.result.acknowledged); - } - - /** - * Fetches the current user. - * - * @returns {Promise|*|PromiseLike|Promise} - */ - getCurrentUser (options = {}) { - return this.query({ - action: 'getCurrentUser' - }, options) - .then(response => new User(this.kuzzle, response.result._id, response.result._source)); - } - - /** - * Get credential information of the specified for the current user. - * - * @param strategy - * @returns {Promise|*|PromiseLike|Promise} - */ - getMyCredentials(strategy, options = {}) { - return this.query({ - strategy, - action: 'getMyCredentials' - }, options) - .then(response => response.result); - } - - /** - * Gets the rights array of the currently logged user. - * - * @param {object} [options] - Optional parameters - * @returns {Promise|*|PromiseLike|Promise} - */ - getMyRights (options = {}) { - return this.query({ - action: 'getMyRights' - }, options) - .then(response => response.result.hits); - } - - /** - * Get all the strategies registered in Kuzzle by all auth plugins - * - * @param {object} [options] - Optional parameters - * @returns {Promise|*|PromiseLike|Promise} - */ - getStrategies (options = {}) { - return this.query({ - action: 'getStrategies' - }, options) - .then(response => response.result); - } - - /** - * Send login request to kuzzle with credentials - * If login success, store the jwt into kuzzle object - * - * @param strategy - * @param credentials - * @param expiresIn - * @returns {Promise|*|PromiseLike|Promise} - */ - login (strategy, credentials = {}, expiresIn = null) { - const request = { - strategy, - expiresIn, - body: credentials, - action: 'login' - }; - - return this.query(request, {queuable: false, verb: 'POST'}) - .then(response => { - try { - this._authenticationToken = new Jwt(response.result.jwt); - - this.kuzzle.emit('loginAttempt', {success: true}); - } - catch (err) { - return Promise.reject(err); - } - - return response.result.jwt; - }) - .catch(err => { - this.kuzzle.emit('loginAttempt', {success: false, error: err.message}); - throw err; - }); - } - - /** - * Send logout request to kuzzle with jwt. - * - * @returns {Promise|*|PromiseLike|Promise} - */ - logout () { - return this.query({ - action: 'logout' - }, {queuable: false}) - .then(() => { - this._authenticationToken = null; - }); - } - - /** - * Update credentials of the specified for the current user. - * - * @param strategy - * @param credentals - * @param options - * @returns {Promise|*|PromiseLike|Promise} - */ - updateMyCredentials (strategy, credentials, options = {}) { - return this.query({ - strategy, - body: credentials, - action: 'updateMyCredentials' - }, options) - .then(response => response.result); - } - - /** - * Update current user in Kuzzle. - * - * @param {object} body - a plain javascript object representing the user's modification - * @param {object} [options] - (optional) arguments - * @returns {Promise|*|PromiseLike|Promise} - */ - updateSelf (body, options = {}) { - return this.query({ - body, - action: 'updateSelf' - }, options) - .then(response => new User(this.kuzzle, response.result._id, response.result._source)); - } - - /** - * Validate credentials of the specified for the current user. - * - * @param strategy - * @param credentials - * @param options - * @returns {Promise|*|PromiseLike|Promise} - */ - validateMyCredentials (strategy, credentials, options = {}) { - return this.query({ - strategy, - body: credentials, - action: 'validateMyCredentials' - }, options) - .then(response => response.result); - } - - /** - * Refresh an authentication token - * - * @param {Object} options - * @returns {Promise.} - */ - refreshToken(options = {}) { - const query = { - action: 'refreshToken', - expiresIn: options.expiresIn - }; - - return this.query(query, options) - .then(response => { - this._authenticationToken = new Jwt(response.result.jwt); - - return response.result; - }); - } -} - -module.exports = AuthController; diff --git a/src/controllers/Auth.ts b/src/controllers/Auth.ts new file mode 100644 index 000000000..2d8ef3ce6 --- /dev/null +++ b/src/controllers/Auth.ts @@ -0,0 +1,524 @@ +import { Jwt } from '../core/Jwt'; +import { BaseController } from './Base'; +import { User } from '../core/security/User'; +import { JSONObject, ApiKey } from '../utils/interfaces'; + +/** + * Auth controller + * + * @param kuzzle + * @constructor + */ +export class AuthController extends BaseController { + private _authenticationToken: any | null; + + /** + * constructor + * @param kuzzle + */ + constructor (kuzzle) { + super(kuzzle, 'auth'); + + this._authenticationToken = null; + + this.kuzzle.on('tokenExpired', () => { + this._authenticationToken = null; + }); + } + + /** + * Authentication token in use + */ + get authenticationToken (): any | null { + return this._authenticationToken; + } + + set authenticationToken (encodedJwt: any) { + if (encodedJwt === undefined || encodedJwt === null) { + this._authenticationToken = null; + } + else if (typeof encodedJwt === 'string') { + this._authenticationToken = new Jwt(encodedJwt); + } + else { + throw new Error(`Invalid token argument: ${encodedJwt}`); + } + } + + /** + * Do not add the token for the checkToken route, to avoid getting a token error when + * a developer simply wishes to verify their token + */ + authenticateRequest (request: any) { + if ( !this.authenticationToken + || (request.controller === 'auth' + && (request.action === 'checkToken' || request.action === 'login')) + ) { + return; + } + + request.jwt = this.authenticationToken.encodedJwt; + } + + /** + * Creates a new API key for the currently loggued user. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/create-api-key + * + * @param description API key description + * @param options Additional options + * - `_id` API key unique ID + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * - `expiresIn` Expiration duration + * + * @returns The created API key + */ + createApiKey( + description: string, + options: { _id?: string, expiresIn?: number, refresh?: string } = {} + ): Promise { + const request = { + action: 'createApiKey', + _id: options._id, + expiresIn: options.expiresIn, + refresh: options.refresh, + body: { + description + } + }; + + return this.query(request) + .then(response => response.result); + } + + /** + * Deletes an API key for the currently loggued user. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/delete-api-key + * + * @param id API key ID + * @param options Additional options + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + */ + deleteApiKey(id: string, options: { refresh?: string } = {}): Promise { + const request = { + action: 'deleteApiKey', + _id: id, + refresh: options.refresh + }; + + return this.query(request) + .then(() => null); + } + + /** + * Searches API keys for the currently loggued user. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/search-api-keys + * + * @param query Search query + * @param options Additional options + * - `from` Offset of the first document to fetch + * - `size` Maximum number of documents to retrieve per page + * + * @returns A search result object + */ + searchApiKeys( + query: JSONObject = {}, + options: { from?: number, size?: number } = {} + ): Promise<{ + /** + * Array of found ApiKeys + */ + hits: Array, + /** + * Total number of API keys found + */ + total: number + }> { + const request = { + action: 'searchApiKeys', + from: options.from, + size: options.size, + body: query + }; + + return this.query(request) + .then(response => response.result); + } + + /** + * Checks whether a given jwt token still represents a valid session in Kuzzle. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/check-token + * + * @param token The jwt token to check (default to current SDK token) + * + * @returns A token validity object + */ + checkToken (token?: string): Promise<{ + /** + * Tell if the token is valid or not + */ + valid: boolean, + /** + * Explain why the token is invalid + */ + state: string, + /** + * Token expiration timestamp + */ + expiresAt: number + }> { + if (token === undefined && this.authenticationToken) { + token = this.authenticationToken.encodedJwt; + } + + return this.query({ + action: 'checkToken', + body: { token } + }, { queuable: false }) + .then(response => response.result); + } + + /** + * Create credentials of the specified strategy for the current user. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/create-my-credentials + * + * @param strategy New credentials + * @param credentials Name of the strategy to use + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * + * @returns An object representing the new credentials. + * The content depends on the authentication strategy + */ + createMyCredentials ( + strategy: string, + credentials: JSONObject, + options: { queuable?: boolean } = {} + ): Promise { + return this.query({ + strategy, + action: 'createMyCredentials', + body: credentials + }, options) + .then(response => response.result); + } + + /** + * Check the existence of the specified strategy's credentials for the current user. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/credentials-exist + * + * @param strategy Name of the strategy to use + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * + * @returns A boolean indicating if the credentials exists + */ + credentialsExist ( + strategy: string, + options: { queuable?: boolean } = {} + ): Promise { + return this.query({ + strategy, + action: 'credentialsExist' + }, options) + .then(response => response.result); + } + + /** + * Delete credentials of the specified strategy for the current user. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/delete-my-credentials + * + * @param strategy Name of the strategy to use + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + */ + deleteMyCredentials ( + strategy: string, + options: { queuable?: boolean } = {} + ): Promise { + return this.query({ + strategy, + action: 'deleteMyCredentials' + }, options) + .then(response => response.result.acknowledged); + } + + /** + * Fetches the current user. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/get-current-user + * + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * + * @returns Currently loggued User + */ + getCurrentUser (options: { queuable?: boolean } = {}): Promise { + return this.query({ + action: 'getCurrentUser' + }, options) + .then(response => new User( + this.kuzzle, + response.result._id, + response.result._source)); + } + + /** + * Get credential information of the specified strategy for the current user. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/get-my-credentials + * + * @param strategy Name of the strategy to use + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * + * @returns An object representing the credentials for the provided authentication strategy. + * Its content depends on the authentication strategy. + */ + getMyCredentials( + strategy: string, + options: { queuable?: boolean } = {} + ): Promise { + return this.query({ + strategy, + action: 'getMyCredentials' + }, options) + .then(response => response.result); + } + + /** + * Gets the rights array of the currently logged user. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/get-my-rights + * + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * + * @returns An array containing user rights objects + */ + getMyRights ( + options: { queuable?: boolean } = {} + ): Promise> { + return this.query({ + action: 'getMyRights' + }, options) + .then(response => response.result.hits); + } + + /** + * Get all the strategies registered in Kuzzle by all auth plugins + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/get-strategies + * + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * + * @returns An array of available strategies names + */ + getStrategies (options: { queuable?: boolean } = {}): Promise> { + return this.query({ + action: 'getStrategies' + }, options) + .then(response => response.result); + } + + /** + * Send login request to kuzzle with credentials + * If login success, store the jwt into kuzzle object + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/login + * + * @param strategy Name of the strategy to use + * @param credentials Credentials object for the strategy + * @param expiresIn Expiration time in ms library format. (e.g. "2h") + * + * @returns The encrypted JSON Web Token + */ + login ( + strategy: string, + credentials: JSONObject, + expiresIn?: string|number + ): Promise { + const request = { + strategy, + expiresIn, + body: credentials, + action: 'login' + }; + + return this.query(request, {queuable: false, verb: 'POST'}) + .then(response => { + this._authenticationToken = new Jwt(response.result.jwt); + + this.kuzzle.emit('loginAttempt', {success: true}); + + return response.result.jwt; + }) + .catch(err => { + this.kuzzle.emit('loginAttempt', {success: false, error: err.message}); + throw err; + }); + } + + /** + * Send logout request to kuzzle with jwt. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/logout + */ + logout (): Promise { + return this.query({ + action: 'logout' + }, { queuable: false }) + .then(() => { + this._authenticationToken = null; + }); + } + + /** + * Update credentials of the specified strategy for the current user. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/update-my-credentials + * + * @param strategy Name of the strategy to use + * @param credentials Updated credentials + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * + * @returns An object representing the updated credentials. + * The content depends on the authentication strategy + */ + updateMyCredentials ( + strategy: string, + credentials: JSONObject, + options: { queuable?: boolean } = {} + ): Promise { + return this.query({ + strategy, + body: credentials, + action: 'updateMyCredentials' + }, options) + .then(response => response.result); + } + + /** + * Update current user in Kuzzle. + * This route cannot update the list of associated security profiles. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/update-self + * + * @param {object} content - User custom information + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * + * @returns Currently loggued User + */ + updateSelf ( + content: JSONObject, + options: { queuable?: boolean } = {} + ): Promise { + return this.query({ + body: content, + action: 'updateSelf' + }, options) + .then(response => new User( + this.kuzzle, + response.result._id, + response.result._source)); + } + + /** + * Validate credentials of the specified strategy for the current user. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/validate-my-credentials + * + * @param strategy Name of the strategy to use + * @param credentials Credentials to validate + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + */ + validateMyCredentials ( + strategy: string, + credentials: JSONObject, + options: { queuable?: boolean } = {} + ): Promise { + return this.query({ + strategy, + body: credentials, + action: 'validateMyCredentials' + }, options) + .then(response => response.result); + } + + /** + * Refresh the SDK current authentication token + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/auth/refresh-token + * + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `expiresIn` Expiration duration + * + * @returns The refreshed token + */ + refreshToken( + options: { queuable?: boolean, expiresIn?: number|string } = {} + ): Promise<{ + /** + * Token unique ID + */ + _id: string; + /** + * Expiration date in UNIX micro-timestamp format (-1 if the token never expires) + */ + expiresAt: number; + /** + * Authentication token associated with this API key + */ + jwt: string; + /** + * Original TTL in ms + */ + ttl: number; + }> { + const query = { + action: 'refreshToken', + expiresIn: options.expiresIn + }; + + return this.query(query, options) + .then(response => { + this._authenticationToken = new Jwt(response.result.jwt); + + return response.result; + }); + } +} + +module.exports = { AuthController }; diff --git a/src/controllers/Base.js b/src/controllers/Base.js deleted file mode 100644 index 33ca42450..000000000 --- a/src/controllers/Base.js +++ /dev/null @@ -1,32 +0,0 @@ -class BaseController { - - /** - * @param {Kuzzle} kuzzle - Kuzzle SDK object. - * @param {string} name - Controller full name for API request. - */ - constructor (kuzzle, name) { - this._kuzzle = kuzzle; - this._name = name; - } - - get kuzzle () { - return this._kuzzle; - } - - get name () { - return this._name; - } - - /** - * @param {object} request - * @param {object} [options] - Optional arguments - * @returns {Promise} - */ - query (request = {}, options = {}) { - request.controller = request.controller || this.name; - - return this._kuzzle.query(request, options); - } -} - -module.exports = BaseController; diff --git a/src/controllers/Base.ts b/src/controllers/Base.ts new file mode 100644 index 000000000..b67d63f58 --- /dev/null +++ b/src/controllers/Base.ts @@ -0,0 +1,44 @@ +import { KuzzleRequest, JSONObject } from '../utils/interfaces'; + +export class BaseController { + private _name: string; + private _kuzzle: any; + + /** + * @param {Kuzzle} kuzzle - Kuzzle SDK object. + * @param {string} name - Controller full name for API request. + */ + constructor (kuzzle: any, name: string) { + Reflect.defineProperty(this, '_kuzzle', { + value: kuzzle + }); + + this._name = name; + } + + protected get kuzzle () { + return this._kuzzle; + } + + /** + * Controller name + */ + get name () { + return this._name; + } + + /** + * Sends a query to Kuzzle. + * If not set, the "controller" property of the request will be the controller name. + * + * @param request + * @param options + */ + query (request: KuzzleRequest = {}, options: any = {}): Promise { + request.controller = request.controller || this.name; + + return this._kuzzle.query(request, options); + } +} + +module.exports = { BaseController }; diff --git a/src/controllers/Bulk.js b/src/controllers/Bulk.js index c11e36f4d..d46a6fdc0 100644 --- a/src/controllers/Bulk.js +++ b/src/controllers/Bulk.js @@ -1,10 +1,34 @@ -const BaseController = require('./Base'); +const { BaseController } = require('./Base'); class BulkController extends BaseController { constructor (kuzzle) { super(kuzzle, 'bulk'); } + /** + * Directly deletes every documents matching the search query without: + * - applying max documents write limit + * - fetching deleted documents + * - triggering realtime notifications + * {@link https://docs.kuzzle.io/core/2/api/controllers/bulk/delete-by-query/|Official documentation} + * @param {String} index - Index name + * @param {String} collection - Collection name + * @param {Object[]} query - Query matching documents to delete + * @param {Object} [options] - Additional options + * @returns {Promise} + */ + deleteByQuery(index, collection, query = {}, options = {}) { + const request = { + index, + collection, + body: query, + action: 'deleteByQuery' + }; + + return this.query(request, options) + .then(response => response.result.deleted); + } + /** * Creates, updates or deletes large amounts of documents as fast as possible. * {@link https://docs.kuzzle.io/core/2/api/controllers/bulk/import/|Official documentation} @@ -71,4 +95,4 @@ class BulkController extends BaseController { } -module.exports = BulkController; +module.exports = { BulkController }; diff --git a/src/controllers/Collection.js b/src/controllers/Collection.js index 42ec86320..97727ab6b 100644 --- a/src/controllers/Collection.js +++ b/src/controllers/Collection.js @@ -1,5 +1,5 @@ -const BaseController = require('./Base'); -const SpecificationsSearchResult = require('../core/searchResult/Specifications'); +const { BaseController } = require('./Base'); +const { SpecificationsSearchResult } = require('../core/searchResult/Specifications'); class CollectionController extends BaseController { @@ -106,6 +106,17 @@ class CollectionController extends BaseController { .then(response => response.result); } + update(index, collection, body) { + return this.query({ + index, + collection, + body, + action: 'update' + }) + .then(response => response.result); + } + + // @deprecated updateMapping (index, collection, body, options = {}) { return this.query({ index, @@ -137,4 +148,4 @@ class CollectionController extends BaseController { } } -module.exports = CollectionController; +module.exports = { CollectionController }; diff --git a/src/controllers/Document.js b/src/controllers/Document.js deleted file mode 100644 index bf62cacd0..000000000 --- a/src/controllers/Document.js +++ /dev/null @@ -1,234 +0,0 @@ -const BaseController = require('./Base'); -const DocumentSearchResult = require('../core/searchResult/Document'); - -class DocumentController extends BaseController { - - /** - * @param {Kuzzle} kuzzle - */ - constructor (kuzzle) { - super(kuzzle, 'document'); - } - - count (index, collection, body, options = {}) { - const request = { - index, - collection, - body, - action: 'count' - }; - - return this.query(request, options) - .then(response => response.result.count); - } - - create (index, collection, document, _id = null, options = {}) { - const request = { - index, - collection, - _id, - body: document, - action: 'create' - }; - return this.query(request, options) - .then(response => response.result); - } - - createOrReplace (index, collection, _id, body, options = {}) { - const request = { - index, - collection, - _id, - body, - action: 'createOrReplace' - }; - - return this.query(request, options) - .then(response => response.result); - } - - delete (index, collection, _id, options = {}) { - const request = { - index, - collection, - _id, - action: 'delete' - }; - - return this.query(request, options) - .then(response => response.result._id); - } - - deleteByQuery(index, collection, body = {}, options = {}) { - const request = { - index, - collection, - body, - action: 'deleteByQuery' - }; - - return this.query(request, options) - .then(response => response.result.ids); - } - - exists (index, collection, _id, options = {}) { - const request = { - index, - collection, - _id, - action: 'exists' - }; - - return this.query(request, options) - .then(response => response.result); - } - - get (index, collection, _id, options = {}) { - const request = { - index, - collection, - _id, - action: 'get' - }; - - return this.query(request, options) - .then(response => response.result); - } - - mCreate (index, collection, documents, options = {}) { - const request = { - index, - collection, - body: {documents}, - action: 'mCreate' - }; - - return this.query(request, options) - .then(response => response.result); - } - - mCreateOrReplace (index, collection, documents, options = {}) { - const request = { - index, - collection, - body: {documents}, - action: 'mCreateOrReplace' - }; - - return this.query(request, options) - .then(response => response.result); - } - - mDelete (index, collection, ids, options = {}) { - const request = { - index, - collection, - body: {ids}, - action: 'mDelete' - }; - - return this.query(request, options) - .then(response => response.result); - } - - mGet (index, collection, ids, options = {}) { - const request = { - index, - collection, - action: 'mGet', - body: {ids} - }; - - return this.query(request, options) - .then(response => response.result); - } - - mReplace (index, collection, documents, options = {}) { - const request = { - index, - collection, - body: {documents}, - action: 'mReplace' - }; - - return this.query(request, options) - .then(response => response.result); - } - - mUpdate (index, collection, documents, options = {}) { - const request = { - index, - collection, - body: {documents}, - action: 'mUpdate' - }; - - return this.query(request, options) - .then(response => response.result); - } - - replace (index, collection, _id, body, options = {}) { - const request = { - index, - collection, - _id, - body, - action: 'replace' - }; - - return this.query(request, options) - .then(response => response.result); - } - - search (index, collection, body = {}, options = {}) { - return this._search(index, collection, body, options) - .then(({ response, request, opts }) => ( - new DocumentSearchResult(this.kuzzle, request, opts, response.result) - )); - } - - _search (index, collection, body = {}, options = {}) { - const request = { - index, - collection, - body, - action: 'search', - }; - - for (const opt of ['from', 'size', 'scroll']) { - request[opt] = options[opt]; - } - - const opts = { verb: 'POST', ...options }; - - return this.query(request, opts) - .then(response => ({ response, request, opts })); - } - - update (index, collection, _id, body, options = {}) { - const request = { - index, - collection, - _id, - body, - action: 'update', - retryOnConflict: options.retryOnConflict, - source: options.source - }; - - return this.query(request, options) - .then(response => response.result); - } - - validate (index, collection, body, options = {}) { - return this.query({ - index, - collection, - body, - action: 'validate' - }, options) - .then(response => response.result); - } -} - -module.exports = DocumentController; diff --git a/src/controllers/Document.ts b/src/controllers/Document.ts new file mode 100644 index 000000000..34141a911 --- /dev/null +++ b/src/controllers/Document.ts @@ -0,0 +1,805 @@ +import { BaseController } from './Base'; +import { SearchResult } from '../core/searchResult/SearchResultBase'; +import { DocumentSearchResult } from '../core/searchResult/Document'; +import { JSONObject, Document, DocumentHit } from '../utils/interfaces'; + +export class DocumentController extends BaseController { + constructor (kuzzle) { + super(kuzzle, 'document'); + } + + /** + * Counts documents in a collection. + * + * A query can be provided to alter the count result, + * otherwise returns the total number of documents in the collection. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/count/ + * + * @param index Index name + * @param collection Collection name + * @param query Query to match + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * + * @returns The number of matching documents + */ + count ( + index: string, + collection: string, + body: JSONObject = null, + options: { queuable?: boolean } = {} + ): Promise { + const request = { + index, + collection, + body, + action: 'count' + }; + + return this.query(request, options) + .then(response => response.result.count); + } + + /** + * Creates a new document in the persistent data storage. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/create/ + * + * @param index Index name + * @param collection Collection name + * @param content Document content + * @param _id Optional document ID + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * + * @returns The created document + */ + create ( + index: string, + collection: string, + content: JSONObject, + _id: string = null, + options: { queuable?: boolean, refresh?: string } = {} + ): Promise { + const request = { + index, + collection, + _id, + body: content, + action: 'create' + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Creates a new document in the persistent data storage, + * or replaces its content if it already exists. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/create-or-replace/ + * + * @param index Index name + * @param collection Collection name + * @param id Document ID + * @param content Document content + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * + * @returns The created or replaced document + */ + createOrReplace ( + index: string, + collection: string, + _id: string, + content: JSONObject, + options: { queuable?: boolean, refresh?: string } = {} + ): Promise { + const request = { + index, + collection, + _id, + body: content, + action: 'createOrReplace' + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Deletes a document. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/delete/ + * + * @param index Index name + * @param collection Collection name + * @param _id Document ID + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * + * @returns The document ID + */ + delete ( + index: string, + collection: string, + _id: string, + options: { queuable?: boolean, refresh?: string } = {} + ): Promise { + const request = { + index, + collection, + _id, + action: 'delete' + }; + + return this.query(request, options) + .then(response => response.result._id); + } + + /** + * Deletes documents matching the provided search query. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/delete-by-query/ + * + * @param index Index name + * @param collection Collection name + * @param query Query to match + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * + * @returns The deleted documents IDs + */ + deleteByQuery( + index: string, + collection: string, + query: JSONObject = {}, + options: { queuable?: boolean, refresh?: string } = {} + ): Promise> { + const request = { + index, + collection, + body: query, + action: 'deleteByQuery' + }; + + return this.query(request, options) + .then(response => response.result.ids); + } + + /** + * Checks if the given document exists. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/exists/ + * + * @param index Index name + * @param collection Collection name + * @param _id Document ID + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * + * @returns True if the document exists + */ + exists ( + index: string, + collection: string, + _id: string, + options: { queuable?: boolean, refresh?: string } = {} + ): Promise { + const request = { + index, + collection, + _id, + action: 'exists' + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Gets a document. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/get/ + * + * @param index Index name + * @param collection Collection name + * @param _id Document ID + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * + * @returns The document + */ + get ( + index: string, + collection: string, + _id: string, + options: { queuable?: boolean, refresh?: string } = {} + ): Promise { + const request = { + index, + collection, + _id, + action: 'get' + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Creates multiple documents. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/m-create/ + * + * @param index Index name + * @param collection Collection name + * @param documents Documents to create + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * + * @returns An object containing 2 arrays: "successes" and "errors" + */ + mCreate ( + index: string, + collection: string, + documents: Array<{ + /** + * Optional document ID + */ + _id?: string; + /** + * Document content + */ + body: JSONObject; + }>, + options: { queuable?: boolean, refresh?: string } = {} + ): Promise<{ + /** + * Array of successfully created documents + */ + successes: Array; + /** + * Array of failed creation + */ + errors: Array<{ + /** + * Document that cause the error + */ + document: Document; + /** + * HTTP error status + */ + status: number; + /** + * Human readable reason + */ + reason: string; + }>; + }> { + const request = { + index, + collection, + body: { documents }, + action: 'mCreate' + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Creates or replaces multiple documents. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/m-create-or-replace/ + * + * @param index Index name + * @param collection Collection name + * @param documents Documents to create + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * + * @returns An object containing 2 arrays: "successes" and "errors" + */ + mCreateOrReplace ( + index: string, + collection: string, + documents: Array<{ + /** + * Document ID + */ + _id: string; + /** + * Document content + */ + body: JSONObject; + }>, + options: { queuable?: boolean, refresh?: string } = {} + ): Promise<{ + /** + * Array of successfully created documents + */ + successes: Array; + /** + * Array of failed creation + */ + errors: Array<{ + /** + * Document that cause the error + */ + document: Document; + /** + * HTTP error status + */ + status: number; + /** + * Human readable reason + */ + reason: string; + }>; + }> { + const request = { + index, + collection, + body: { documents }, + action: 'mCreateOrReplace' + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Deletes multiple documents. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/m-delete/ + * + * @param index Index name + * @param collection Collection name + * @param ids Document IDs + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * + * @returns An object containing 2 arrays: "successes" and "errors" + */ + mDelete ( + index: string, + collection: string, + ids: Array, + options: { queuable?: boolean, refresh?: string } = {} + ): Promise<{ + /** + * Array of successfully deleted documents IDS + */ + successes: Array; + /** + * Array of failed deletion + */ + errors: Array<{ + /** + * Document ID + */ + id: string; + /** + * Human readable reason + */ + reason: string; + }>; + }> { + const request = { + index, + collection, + body: {ids}, + action: 'mDelete' + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Gets multiple documents. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/m-get/ + * + * @param index Index name + * @param collection Collection name + * @param ids Document IDs + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `verb` (HTTP only) Forces the verb of the route + * + * @returns An object containing 2 arrays: "successes" and "errors" + */ + mGet ( + index: string, + collection: string, + ids: Array, + options: { queuable?: boolean, verb?: string } = {} + ): Promise<{ + /** + * Array of successfully retrieved documents + */ + successes: Array; + /** + * Array of the IDs of not found documents. + */ + errors: Array; + }> { + const request = { + index, + collection, + action: 'mGet', + body: { ids } + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Replaces multiple documents. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/m-replace/ + * + * @param index Index name + * @param collection Collection name + * @param documents Documents to create + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * + * @returns An object containing 2 arrays: "successes" and "errors" + */ + mReplace ( + index: string, + collection: string, + documents: Array<{ + /** + * Document ID + */ + _id: string; + /** + * Document content + */ + body: JSONObject; + }>, + options: { queuable?: boolean, refresh?: string } = {} + ): Promise<{ + /** + * Array of successfully replaced documents + */ + successes: Array; + /** + * Array of failed creation + */ + errors: Array<{ + /** + * Document that cause the error + */ + document: Document; + /** + * HTTP error status + */ + status: number; + /** + * Human readable reason + */ + reason: string; + }>; + }> { + const request = { + index, + collection, + body: { documents }, + action: 'mReplace' + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Updates multiple documents. + * + * Conflicts may occur if the same document gets updated multiple times + * within a short timespan in a database cluster. (See `retryOnConflict`) + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/m-update/ + * + * @param index Index name + * @param collection Collection name + * @param documents Documents to create + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * - `retryOnConflict` Number of times the database layer should retry in case of version conflict + * + * @returns An object containing 2 arrays: "successes" and "errors" + */ + mUpdate ( + index: string, + collection: string, + documents: Array<{ + /** + * Document ID + */ + _id: string; + /** + * Document content + */ + body: JSONObject; + }>, + options: { queuable?: boolean, refresh?: string, retryOnConflict?: number } = {} + ): Promise<{ + /** + * Array of successfully updated documents + */ + successes: Array; + /** + * Array of failed creation + */ + errors: Array<{ + /** + * Document that cause the error + */ + document: Document; + /** + * HTTP error status + */ + status: number; + /** + * Human readable reason + */ + reason: string; + }>; + }> { + const request = { + index, + collection, + body: {documents}, + action: 'mUpdate' + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Replaces the content of an existing document. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/replace/ + * + * @param index Index name + * @param collection Collection name + * @param id Document ID + * @param content Document content + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * + * @returns The replaced document + */ + replace ( + index: string, + collection: string, + _id: string, + content: JSONObject, + options: { queuable?: boolean, refresh?: string } = {} + ): Promise { + const request = { + index, + collection, + _id, + body: content, + action: 'replace' + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Searches documents. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/search/ + * + * @param index Index name + * @param collection Collection name + * @param query Search query + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `from` Offset of the first document to fetch + * - `size` Maximum number of documents to retrieve per page + * - `scroll` When set, gets a forward-only cursor having its ttl set to the given value (e.g. `30s`) + * - `verb` (HTTP only) Forces the verb of the route + * + * @returns A SearchResult + */ + search ( + index: string, + collection: string, + query: JSONObject = {}, + options: { + queuable?: boolean; + from?: number; + size?: number; + scroll?: string; + verb?: string; + } = {} + ): Promise> { + return this._search(index, collection, query, options) + .then(({ response, request, opts }) => ( + new DocumentSearchResult(this.kuzzle, request, opts, response.result) + )); + } + + private _search ( + index: string, + collection: string, + body: JSONObject = {}, + options: JSONObject = {} + ) { + const request: any = { + index, + collection, + body: null, + action: 'search', + }; + if ( this.kuzzle.protocol.name === 'http' + && options.verb + && options.verb.toLowerCase() === 'get' + ) { + request.searchBody = body; + } + else { + request.body = body; + } + for (const opt of ['from', 'size', 'scroll']) { + request[opt] = options[opt]; + } + + const opts = { verb: options.verb || 'POST', ...options }; + return this.query(request, opts) + .then(response => ({ response, request, opts })); + } + + /** + * Updates the content of an existing document. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/update/ + * + * @param index Index name + * @param collection Collection name + * @param id Document ID + * @param content Document content + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * - `retryOnConflict` Number of times the database layer should retry in case of version conflict + * - `source` If true, returns the updated document inside the response + * + * @returns The replaced document + */ + update ( + index: string, + collection: string, + _id: string, + content: JSONObject, + options: { + queuable?: boolean, + refresh?: string, + retryOnConflict?: number, + source?: boolean + } = {} + ): Promise { + const request = { + index, + collection, + _id, + body: content, + action: 'update', + retryOnConflict: options.retryOnConflict, + source: options.source + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Updates documents matching the provided search query. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/update-by-query/ + * + * @param index Index name + * @param collection Collection name + * @param query Query to match + * @param changes Partial changes to apply to the documents + * @param options Additional options + * - `refresh` If set to `wait_for`, Kuzzle will not respond until the API key is indexed + * - `source` If true, returns the updated document inside the response + * + * @returns An object containing 2 arrays: "successes" and "errors" + */ + updateByQuery( + index: string, + collection: string, + query: JSONObject, + changes: JSONObject, + options: { refresh?: string, source?: boolean } = {} + ): Promise<{ + /** + * Array of successfully updated documents + */ + successes: Array; + /** + * Array of failed creation + */ + errors: Array<{ + /** + * Document that cause the error + */ + document: Document; + /** + * HTTP error status + */ + status: number; + /** + * Human readable reason + */ + reason: string; + }>; + }> { + const request = { + index, + collection, + body: { query, changes }, + action: 'updateByQuery', + source: options.source + }; + + return this.query(request, options) + .then(response => response.result); + } + + /** + * Validates a document against existing validation rules. + * + * @see https://docs.kuzzle.io/sdk/js/7/controllers/document/validate/ + * + * @param index Index name + * @param collection Collection name + * @param content Document content + * @param options Additional options + * - `queuable` If true, queues the request during downtime, until connected to Kuzzle again + * + * @returns True if the document is valid + */ + validate ( + index: string, + collection: string, + content: JSONObject, + options: { queuable?: boolean } = {} + ): Promise { + return this.query({ + index, + collection, + body: content, + action: 'validate' + }, options) + .then(response => response.result); + } +} + +module.exports = { DocumentController }; diff --git a/src/controllers/Index.js b/src/controllers/Index.js index b073d03ea..626d8c949 100644 --- a/src/controllers/Index.js +++ b/src/controllers/Index.js @@ -1,4 +1,4 @@ -const BaseController = require('./Base'); +const { BaseController } = require('./Base'); class IndexController extends BaseController { @@ -55,4 +55,4 @@ class IndexController extends BaseController { } } -module.exports = IndexController; +module.exports = { IndexController }; diff --git a/src/controllers/MemoryStorage.js b/src/controllers/MemoryStorage.js index 73713be11..4ddf0ee1d 100644 --- a/src/controllers/MemoryStorage.js +++ b/src/controllers/MemoryStorage.js @@ -1,168 +1,167 @@ -const BaseControler = require('./Base'); +const { BaseController } = require('./Base'); // Parameter mutualization -const - getId = {getter: true, required: ['_id']}, - getIdField = {getter: true, required: ['_id', 'field']}, - getKeys = {getter: true, required: ['keys']}, - getMember = {getter: true, required: ['_id', 'member']}, - getxScan = { +const getId = {getter: true, required: ['_id']}; +const getIdField = {getter: true, required: ['_id', 'field']}; +const getKeys = {getter: true, required: ['keys']}; +const getMember = {getter: true, required: ['_id', 'member']}; +const getxScan = { + getter: true, + required: ['_id', 'cursor'], + opts: ['match', 'count'], + mapResults: mapScanResults +}; +const getZrange = { + getter: true, + required: ['_id', 'start', 'stop'], + opts: assignZrangeOptions, + mapResults: mapZrangeResults +}; +const getZrangeBy = { + getter: true, + required: ['_id', 'min', 'max'], + opts: assignZrangeOptions, + mapResults: mapZrangeResults +}; +const setId = {required: ['_id']}; +const setIdValue = {required: ['_id', 'value']}; + +// Redis commands +const commands = { + append: setIdValue, + bitcount: {getter: true, required: ['_id'], opts: ['start', 'end']}, + bitop: {required: ['_id', 'operation', 'keys']}, + bitpos: {getter: true, required: ['_id', 'bit'], opts: ['start', 'end']}, + dbsize: {getter: true}, + decr: setId, + decrby: setIdValue, + del: {required: ['keys']}, + exists: getKeys, + expire: {required: ['_id', 'seconds'], mapResults: Boolean}, + expireat: {required: ['_id', 'timestamp'], mapResults: Boolean}, + flushdb: {mapResults: mapNoResult}, + geoadd: {required: ['_id', 'points']}, + geodist: { getter: true, - required: ['_id', 'cursor'], - opts: ['match', 'count'], - mapResults: mapScanResults + required: ['_id', 'member1', 'member2'], + opts: ['unit'], + mapResults: parseFloat }, - getZrange = { + geohash: {getter: true, required: ['_id', 'members']}, + geopos: {getter: true, required: ['_id', 'members'], mapResults: mapGeoposResults}, + georadius: { getter: true, - required: ['_id', 'start', 'stop'], - opts: assignZrangeOptions, - mapResults: mapZrangeResults + required: ['_id', 'lon', 'lat', 'distance', 'unit'], + opts: assignGeoRadiusOptions, + mapResults: mapGeoRadiusResults }, - getZrangeBy = { + georadiusbymember: { getter: true, - required: ['_id', 'min', 'max'], - opts: assignZrangeOptions, - mapResults: mapZrangeResults + required: ['_id', 'member', 'distance', 'unit'], + opts: assignGeoRadiusOptions, + mapResults: mapGeoRadiusResults }, - setId = {required: ['_id']}, - setIdValue = {required: ['_id', 'value']}; - -// Redis commands -const - commands = { - append: setIdValue, - bitcount: {getter: true, required: ['_id'], opts: ['start', 'end']}, - bitop: {required: ['_id', 'operation', 'keys']}, - bitpos: {getter: true, required: ['_id', 'bit'], opts: ['start', 'end']}, - dbsize: {getter: true}, - decr: setId, - decrby: setIdValue, - del: {required: ['keys']}, - exists: getKeys, - expire: {required: ['_id', 'seconds'], mapResults: Boolean}, - expireat: {required: ['_id', 'timestamp'], mapResults: Boolean}, - flushdb: {mapResults: mapNoResult}, - geoadd: {required: ['_id', 'points']}, - geodist: { - getter: true, - required: ['_id', 'member1', 'member2'], - opts: ['unit'], - mapResults: parseFloat - }, - geohash: {getter: true, required: ['_id', 'members']}, - geopos: {getter: true, required: ['_id', 'members'], mapResults: mapGeoposResults}, - georadius: { - getter: true, - required: ['_id', 'lon', 'lat', 'distance', 'unit'], - opts: assignGeoRadiusOptions, - mapResults: mapGeoRadiusResults - }, - georadiusbymember: { - getter: true, - required: ['_id', 'member', 'distance', 'unit'], - opts: assignGeoRadiusOptions, - mapResults: mapGeoRadiusResults - }, - get: getId, - getbit: {getter: true, required: ['_id', 'offset']}, - getrange: {getter: true, required: ['_id', 'start', 'end']}, - getset: setIdValue, - hdel: {required: ['_id', 'fields']}, - hexists: {getter: true, required: ['_id', 'field'], mapResults: Boolean}, - hget: getIdField, - hgetall: {getter: true, required: ['_id']}, - hincrby: {required: ['_id', 'field', 'value']}, - hincrbyfloat: {required: ['_id', 'field', 'value'], mapResults: parseFloat}, - hkeys: getId, - hlen: getId, - hmget: {getter: true, required: ['_id', 'fields']}, - hmset: {required: ['_id', 'entries'], mapResults: mapNoResult}, - hscan: getxScan, - hset: {required: ['_id', 'field', 'value'], mapResults: Boolean}, - hsetnx: {required: ['_id', 'field', 'value'], mapResults: Boolean}, - hstrlen: getIdField, - hvals: getId, - incr: setId, - incrby: setIdValue, - incrbyfloat: {required: ['_id', 'value'], mapResults: parseFloat}, - keys: {getter: true, required: ['pattern']}, - lindex: {getter: true, required: ['_id', 'idx']}, - linsert: {required: ['_id', 'position', 'pivot', 'value']}, - llen: getId, - lpop: setId, - lpush: {required: ['_id', 'values']}, - lpushx: setIdValue, - lrange: {getter: true, required: ['_id', 'start', 'stop']}, - lrem: {required: ['_id', 'count', 'value']}, - lset: {required: ['_id', 'index', 'value'], mapResults: mapNoResult}, - ltrim: {required: ['_id', 'start', 'stop'], mapResults: mapNoResult}, - mget: getKeys, - mset: {required: ['entries'], mapResults: mapNoResult}, - msetnx: {required: ['entries'], mapResults: Boolean}, - object: {getter: true, required: ['_id', 'subcommand']}, - persist: {required: ['_id'], mapResults: Boolean}, - pexpire: {required: ['_id', 'milliseconds'], mapResults: Boolean}, - pexpireat: {required: ['_id', 'timestamp'], mapResults: Boolean}, - pfadd: {required: ['_id', 'elements'], mapResults: Boolean}, - pfcount: getKeys, - pfmerge: {required: ['_id', 'sources'], mapResults: mapNoResult}, - ping: {getter: true}, - psetex: {required: ['_id', 'value', 'milliseconds'], mapResults: mapNoResult}, - pttl: getId, - randomkey: {getter: true}, - rename: {required: ['_id', 'newkey'], mapResults: mapNoResult}, - renamenx: {required: ['_id', 'newkey'], mapResults: Boolean}, - rpop: setId, - rpoplpush: {required: ['source', 'destination']}, - rpush: {required: ['_id', 'values']}, - rpushx: setIdValue, - sadd: {required: ['_id', 'members']}, - scan: {getter: true, required: ['cursor'], opts: ['match', 'count'], mapResults: mapScanResults}, - scard: getId, - sdiff: {getter: true, required: ['_id', 'keys']}, - sdiffstore: {required: ['_id', 'keys', 'destination']}, - set: {required: ['_id', 'value'], opts: ['ex', 'px', 'nx', 'xx'], mapResults: mapNoResult}, - setex: {required: ['_id', 'value', 'seconds'], mapResults: mapNoResult}, - setnx: {required: ['_id', 'value'], mapResults: Boolean}, - sinter: getKeys, - sinterstore: {required: ['destination', 'keys']}, - sismember: {getter: true, required: ['_id', 'member'], mapResults: Boolean}, - smembers: getId, - smove: {required: ['_id', 'destination', 'member'], mapResults: Boolean}, - sort: {required: ['_id'], opts: ['alpha', 'by', 'direction', 'get', 'limit']}, - spop: {required: ['_id'], opts: ['count'], mapResults: mapStringToArray }, - srandmember: {getter: true, required: ['_id'], opts: ['count'], mapResults: mapStringToArray}, - srem: {required: ['_id', 'members']}, - sscan: getxScan, - strlen: getId, - sunion: getKeys, - sunionstore: {required: ['destination', 'keys']}, - time: {getter: true, mapResults: mapArrayStringToArrayInt}, - touch: {required: ['keys']}, - ttl: getId, - type: getId, - zadd: {required: ['_id', 'elements'], opts: ['nx', 'xx', 'ch', 'incr']}, - zcard: getId, - zcount: {getter: true, required: ['_id', 'min', 'max']}, - zincrby: {required: ['_id', 'member', 'value']}, - zinterstore: {required: ['_id', 'keys'], opts: ['weights', 'aggregate']}, - zlexcount: {getter: true, required: ['_id', 'min', 'max']}, - zrange: getZrange, - zrangebylex: {getter: true, required: ['_id', 'min', 'max'], opts: ['limit']}, - zrevrangebylex: {getter: true, required: ['_id', 'min', 'max'], opts: ['limit']}, - zrangebyscore: getZrangeBy, - zrank: getMember, - zrem: {required: ['_id', 'members']}, - zremrangebylex: {required: ['_id', 'min', 'max']}, - zremrangebyrank: {required: ['_id', 'start', 'stop']}, - zremrangebyscore: {required: ['_id', 'min', 'max']}, - zrevrange: getZrange, - zrevrangebyscore: getZrangeBy, - zrevrank: getMember, - zscan: getxScan, - zscore: {getter: true, required: ['_id', 'member'], mapResults: parseFloat}, - zunionstore: {required: ['_id', 'keys'], opts: ['weights', 'aggregate']} - }; + get: getId, + getbit: {getter: true, required: ['_id', 'offset']}, + getrange: {getter: true, required: ['_id', 'start', 'end']}, + getset: setIdValue, + hdel: {required: ['_id', 'fields']}, + hexists: {getter: true, required: ['_id', 'field'], mapResults: Boolean}, + hget: getIdField, + hgetall: {getter: true, required: ['_id']}, + hincrby: {required: ['_id', 'field', 'value']}, + hincrbyfloat: {required: ['_id', 'field', 'value'], mapResults: parseFloat}, + hkeys: getId, + hlen: getId, + hmget: {getter: true, required: ['_id', 'fields']}, + hmset: {required: ['_id', 'entries'], mapResults: mapNoResult}, + hscan: getxScan, + hset: {required: ['_id', 'field', 'value'], mapResults: Boolean}, + hsetnx: {required: ['_id', 'field', 'value'], mapResults: Boolean}, + hstrlen: getIdField, + hvals: getId, + incr: setId, + incrby: setIdValue, + incrbyfloat: {required: ['_id', 'value'], mapResults: parseFloat}, + keys: {getter: true, required: ['pattern']}, + lindex: {getter: true, required: ['_id', 'idx']}, + linsert: {required: ['_id', 'position', 'pivot', 'value']}, + llen: getId, + lpop: setId, + lpush: {required: ['_id', 'values']}, + lpushx: setIdValue, + lrange: {getter: true, required: ['_id', 'start', 'stop']}, + lrem: {required: ['_id', 'count', 'value']}, + lset: {required: ['_id', 'index', 'value'], mapResults: mapNoResult}, + ltrim: {required: ['_id', 'start', 'stop'], mapResults: mapNoResult}, + mexecute: {required: ['actions']}, + mget: getKeys, + mset: {required: ['entries'], mapResults: mapNoResult}, + msetnx: {required: ['entries'], mapResults: Boolean}, + object: {getter: true, required: ['_id', 'subcommand']}, + persist: {required: ['_id'], mapResults: Boolean}, + pexpire: {required: ['_id', 'milliseconds'], mapResults: Boolean}, + pexpireat: {required: ['_id', 'timestamp'], mapResults: Boolean}, + pfadd: {required: ['_id', 'elements'], mapResults: Boolean}, + pfcount: getKeys, + pfmerge: {required: ['_id', 'sources'], mapResults: mapNoResult}, + ping: {getter: true}, + psetex: {required: ['_id', 'value', 'milliseconds'], mapResults: mapNoResult}, + pttl: getId, + randomkey: {getter: true}, + rename: {required: ['_id', 'newkey'], mapResults: mapNoResult}, + renamenx: {required: ['_id', 'newkey'], mapResults: Boolean}, + rpop: setId, + rpoplpush: {required: ['source', 'destination']}, + rpush: {required: ['_id', 'values']}, + rpushx: setIdValue, + sadd: {required: ['_id', 'members']}, + scan: {getter: true, required: ['cursor'], opts: ['match', 'count'], mapResults: mapScanResults}, + scard: getId, + sdiff: {getter: true, required: ['_id', 'keys']}, + sdiffstore: {required: ['_id', 'keys', 'destination']}, + set: {required: ['_id', 'value'], opts: ['ex', 'px', 'nx', 'xx'], mapResults: mapNoResult}, + setex: {required: ['_id', 'value', 'seconds'], mapResults: mapNoResult}, + setnx: {required: ['_id', 'value'], mapResults: Boolean}, + sinter: getKeys, + sinterstore: {required: ['destination', 'keys']}, + sismember: {getter: true, required: ['_id', 'member'], mapResults: Boolean}, + smembers: getId, + smove: {required: ['_id', 'destination', 'member'], mapResults: Boolean}, + sort: {required: ['_id'], opts: ['alpha', 'by', 'direction', 'get', 'limit']}, + spop: {required: ['_id'], opts: ['count'], mapResults: mapStringToArray }, + srandmember: {getter: true, required: ['_id'], opts: ['count'], mapResults: mapStringToArray}, + srem: {required: ['_id', 'members']}, + sscan: getxScan, + strlen: getId, + sunion: getKeys, + sunionstore: {required: ['destination', 'keys']}, + time: {getter: true, mapResults: mapArrayStringToArrayInt}, + touch: {required: ['keys']}, + ttl: getId, + type: getId, + zadd: {required: ['_id', 'elements'], opts: ['nx', 'xx', 'ch', 'incr']}, + zcard: getId, + zcount: {getter: true, required: ['_id', 'min', 'max']}, + zincrby: {required: ['_id', 'member', 'value']}, + zinterstore: {required: ['_id', 'keys'], opts: ['weights', 'aggregate']}, + zlexcount: {getter: true, required: ['_id', 'min', 'max']}, + zrange: getZrange, + zrangebylex: {getter: true, required: ['_id', 'min', 'max'], opts: ['limit']}, + zrevrangebylex: {getter: true, required: ['_id', 'min', 'max'], opts: ['limit']}, + zrangebyscore: getZrangeBy, + zrank: getMember, + zrem: {required: ['_id', 'members']}, + zremrangebylex: {required: ['_id', 'min', 'max']}, + zremrangebyrank: {required: ['_id', 'start', 'stop']}, + zremrangebyscore: {required: ['_id', 'min', 'max']}, + zrevrange: getZrange, + zrevrangebyscore: getZrangeBy, + zrevrank: getMember, + zscan: getxScan, + zscore: {getter: true, required: ['_id', 'member'], mapResults: parseFloat}, + zunionstore: {required: ['_id', 'keys'], opts: ['weights', 'aggregate']} +}; /** * This is a global callback pattern, called by all asynchronous functions of the Kuzzle object. @@ -189,7 +188,7 @@ const * @param {object} kuzzle - Kuzzle instance to inherit from * @constructor */ -class MemoryStorageController extends BaseControler { +class MemoryStorageController extends BaseController { constructor (kuzzle) { super(kuzzle, 'ms'); @@ -201,12 +200,11 @@ class MemoryStorageController extends BaseControler { for (const action of Object.keys(commands)) { // eslint-disable-next-line no-loop-func MemoryStorageController.prototype[action] = function (...args) { - const - command = commands[action], - request = { - action - }, - options = {}; + const command = commands[action]; + const request = { + action + }; + const options = {}; if (!command.getter) { request.body = {}; @@ -237,7 +235,6 @@ for (const action of Object.keys(commands)) { for (const opt of command.opts) { if (options[opt] !== null && options[opt] !== undefined) { assignParameter(request, command.getter, opt, options[opt]); - delete options[opt]; } } } @@ -296,7 +293,6 @@ function assignGeoRadiusOptions(data, options) { .forEach(function (opt) { if (opt === 'withcoord' || opt === 'withdist') { parsed.push(opt); - delete options[opt]; } else if (opt === 'count' || opt === 'sort') { if (opt === 'count') { @@ -305,8 +301,6 @@ function assignGeoRadiusOptions(data, options) { parsed.push(options[opt]); } - - delete options[opt]; }); if (parsed.length > 0) { @@ -327,7 +321,6 @@ function assignZrangeOptions (data, options) { if (options.limit) { data.limit = options.limit; - delete options.limit; } } @@ -472,4 +465,4 @@ function mapScanResults (results) { }; } -module.exports = MemoryStorageController; +module.exports = { MemoryStorageController }; diff --git a/src/controllers/Realtime.js b/src/controllers/Realtime.js index aca778320..e68478ba2 100644 --- a/src/controllers/Realtime.js +++ b/src/controllers/Realtime.js @@ -1,16 +1,16 @@ -const BaseController = require('./Base'); +const { BaseController } = require('./Base'); const Room = require('../core/Room'); -class RealTimeController extends BaseController { +class RealtimeController extends BaseController { /** * @param {Kuzzle} kuzzle */ constructor (kuzzle) { super(kuzzle, 'realtime'); - this.subscriptions = {}; - this.subscriptionsOff = {}; + this.subscriptions = new Map(); + this.subscriptionsOff = new Map(); this.kuzzle.on('tokenExpired', () => this.tokenExpired()); } @@ -28,7 +28,8 @@ class RealTimeController extends BaseController { index, collection, body: message, - action: 'publish' + action: 'publish', + _id: options._id }; return this.query(request, options) @@ -40,50 +41,51 @@ class RealTimeController extends BaseController { return room.subscribe() .then(() => { - if (!this.subscriptions[room.id]) { - this.subscriptions[room.id] = []; + if (!this.subscriptions.has(room.id)) { + this.subscriptions.set(room.id, []); } - this.subscriptions[room.id].push(room); + this.subscriptions.get(room.id).push(room); return room.id; }); } unsubscribe (roomId, options = {}) { - const rooms = this.subscriptions[roomId]; + const request = { + action: 'unsubscribe', + body: { roomId } + }; - if (!rooms) { - return Promise.reject(new Error(`not subscribed to ${roomId}`)); - } + return this.query(request, options) + .then(response => { + const rooms = this.subscriptions.get(roomId); - for (const room of rooms) { - room.removeListeners(); - } - delete this.subscriptions[roomId]; + if (rooms) { + for (const room of rooms) { + room.removeListeners(); + } + + this.subscriptions.delete(roomId); + } - return this.query({ - action: 'unsubscribe', - body: {roomId} - }, options) - .then(response => { return response.result; }); } // called on network error or disconnection disconnected () { - for (const roomId of Object.keys(this.subscriptions)) { - for (const room of this.subscriptions[roomId]) { + for (const roomId of this.subscriptions.keys()) { + for (const room of this.subscriptions.get(roomId)) { room.removeListeners(); if (room.autoResubscribe) { - if (!this.subscriptionsOff[roomId]) { - this.subscriptionsOff[roomId] = []; + if (!this.subscriptionsOff.has(roomId)) { + this.subscriptionsOff.set(roomId, []); } - this.subscriptionsOff[roomId].push(room); + this.subscriptionsOff.get(roomId).push(room); } } - delete this.subscriptions[roomId]; + this.subscriptions.delete(roomId); } } @@ -92,18 +94,18 @@ class RealTimeController extends BaseController { * Resubscribe to eligible disabled rooms. */ reconnected () { - for (const roomId of Object.keys(this.subscriptionsOff)) { - for (const room of this.subscriptionsOff[roomId]) { - if (!this.subscriptions[roomId]) { - this.subscriptions[roomId] = []; + for (const roomId of this.subscriptionsOff.keys()) { + for (const room of this.subscriptionsOff.get(roomId)) { + if (!this.subscriptions.has(roomId)) { + this.subscriptions.set(roomId, []); } - this.subscriptions[roomId].push(room); + this.subscriptions.get(roomId).push(room); room.subscribe() .catch(() => this.kuzzle.emit('discarded', {request: room.request})); } - delete this.subscriptionsOff[roomId]; + this.subscriptionsOff.delete(roomId); } } @@ -111,14 +113,16 @@ class RealTimeController extends BaseController { * Removes all subscriptions. */ tokenExpired() { - for (const roomId of Object.keys(this.subscriptions)) { - this.subscriptions[roomId].forEach(room => room.removeListeners()); + for (const roomId of this.subscriptions.keys()) { + for (const room of this.subscriptions.get(roomId)) { + room.removeListeners(); + } } - this.subscriptions = {}; - this.subscriptionsOff = {}; + this.subscriptions = new Map(); + this.subscriptionsOff = new Map(); } } -module.exports = RealTimeController; +module.exports = { RealtimeController }; diff --git a/src/controllers/Security.js b/src/controllers/Security.js index f4f959a7d..26e5b24aa 100644 --- a/src/controllers/Security.js +++ b/src/controllers/Security.js @@ -1,10 +1,10 @@ -const BaseController = require('./Base'); -const Role = require('../core/security/Role'); -const RoleSearchResult = require('../core/searchResult/Role'); -const Profile = require('../core/security/Profile'); -const ProfileSearchResult = require('../core/searchResult/Profile'); -const User = require('../core/security/User'); -const UserSearchResult = require('../core/searchResult/User'); +const { BaseController } = require('./Base'); +const { Role } = require('../core/security/Role'); +const { RoleSearchResult } = require('../core/searchResult/Role'); +const { Profile } = require('../core/security/Profile'); +const { ProfileSearchResult } = require('../core/searchResult/Profile'); +const { User } = require('../core/security/User'); +const { UserSearchResult } = require('../core/searchResult/User'); class SecurityController extends BaseController { /** @@ -99,7 +99,6 @@ class SecurityController extends BaseController { action: 'createFirstAdmin', reset: options.reset }; - delete options.reset; return this.query(request, options) .then(response => new User(this.kuzzle, response.result._id, response.result._source)); @@ -513,4 +512,4 @@ class SecurityController extends BaseController { } } -module.exports = SecurityController; +module.exports = { SecurityController }; diff --git a/src/controllers/Server.js b/src/controllers/Server.js index ece80e71e..6f5eb6b5d 100644 --- a/src/controllers/Server.js +++ b/src/controllers/Server.js @@ -1,10 +1,10 @@ -const BaseControler = require('./Base'); +const { BaseController } = require('./Base'); /** * @class ServerController * @property {Kuzzle} kuzzle - The Kuzzle SDK Instance */ -class ServerController extends BaseControler { +class ServerController extends BaseController { /** * @param {Kuzzle} kuzzle - The Kuzzle SDK Instance @@ -110,4 +110,4 @@ class ServerController extends BaseControler { } } -module.exports = ServerController; +module.exports = { ServerController }; diff --git a/src/core/Jwt.js b/src/core/Jwt.js index 9899323cf..5cdde4321 100644 --- a/src/core/Jwt.js +++ b/src/core/Jwt.js @@ -71,4 +71,4 @@ class Jwt { } } -module.exports = Jwt; +module.exports = { Jwt }; diff --git a/src/core/KuzzleEventEmitter.js b/src/core/KuzzleEventEmitter.js index 981d26f86..e88ee825c 100644 --- a/src/core/KuzzleEventEmitter.js +++ b/src/core/KuzzleEventEmitter.js @@ -7,7 +7,7 @@ class Listener { class KuzzleEventEmitter { constructor() { - this._events = {}; + this._events = new Map(); } _exists (listeners, fn) { @@ -15,11 +15,11 @@ class KuzzleEventEmitter { } listeners (eventName) { - if (this._events[eventName] === undefined) { + if (! this._events.has(eventName)) { return []; } - return this._events[eventName].map(listener => listener.fn); + return this._events.get(eventName).map(listener => listener.fn); } addListener (eventName, listener, once = false) { @@ -33,12 +33,12 @@ class KuzzleEventEmitter { throw new Error(`Invalid listener type: expected a function, got a ${listenerType}`); } - if (this._events[eventName] === undefined) { - this._events[eventName] = []; + if (! this._events.has(eventName)) { + this._events.set(eventName, []); } - if (!this._exists(this._events[eventName], listener)) { - this._events[eventName].push(new Listener(listener, once)); + if (! this._exists(this._events.get(eventName), listener)) { + this._events.get(eventName).push(new Listener(listener, once)); } return this; @@ -53,12 +53,14 @@ class KuzzleEventEmitter { return this; } - if (this._events[eventName] === undefined) { - this._events[eventName] = []; + if (! this._events.has(eventName)) { + this._events.set(eventName, []); } - if (!this._exists(this._events[eventName], listener)) { - this._events[eventName] = [new Listener(listener, once)].concat(this._events[eventName]); + if (!this._exists(this._events.get(eventName), listener)) { + const listeners = [new Listener(listener, once)].concat(this._events.get(eventName)); + + this._events.set(eventName, listeners); } return this; @@ -77,7 +79,7 @@ class KuzzleEventEmitter { } removeListener (eventName, listener) { - const listeners = this._events[eventName]; + const listeners = this._events.get(eventName); if (!listeners || !listeners.length) { return this; @@ -90,7 +92,7 @@ class KuzzleEventEmitter { } if (listeners.length === 0) { - delete this._events[eventName]; + this._events.delete(eventName); } return this; @@ -98,16 +100,17 @@ class KuzzleEventEmitter { removeAllListeners (eventName) { if (eventName) { - delete this._events[eventName]; - } else { - this._events = {}; + this._events.delete(eventName); + } + else { + this._events = new Map(); } return this; } emit (eventName, ...payload) { - const listeners = this._events[eventName]; + const listeners = this._events.get(eventName); if (listeners === undefined) { return false; @@ -131,12 +134,12 @@ class KuzzleEventEmitter { } eventNames () { - return Object.keys(this._events); + return Array.from(this._events.keys()); } listenerCount (eventName) { - return this._events[eventName] && this._events[eventName].length || 0; + return this._events.has(eventName) && this._events.get(eventName).length || 0; } } -module.exports = KuzzleEventEmitter; +module.exports = { KuzzleEventEmitter }; diff --git a/src/core/Room.js b/src/core/Room.js index 3cfaf90f4..ddf0c4af4 100644 --- a/src/core/Room.js +++ b/src/core/Room.js @@ -1,7 +1,7 @@ class Room { /** - * @param {RealTimeController} controller + * @param {RealtimeController} controller * @param {string} index * @param {string} collection * @param {object} body @@ -9,8 +9,10 @@ class Room { * @param {object} options */ constructor (controller, index, collection, body, callback, options = {}) { + Reflect.defineProperty(this, '_kuzzle', { + value: controller.kuzzle + }); this.controller = controller; - this.kuzzle = controller.kuzzle; this.index = index; this.collection = collection; this.callback = callback; @@ -25,12 +27,12 @@ class Room { collection, body, controller: 'realtime', - action: 'subscribe' + action: 'subscribe', + state: this.options.state, + scope: this.options.scope, + users: this.options.users, + volatile: this.options.volatile }; - for (const opt of ['state', 'scope', 'users', 'volatile']) { - this.request[opt] = this.options[opt]; - delete this.options[opt]; - } this.autoResubscribe = typeof options.autoResubscribe === 'boolean' ? options.autoResubscribe @@ -39,14 +41,14 @@ class Room { ? options.subscribeToSelf : true; - for (const opt of ['autoResubscribe', 'subscribeToSelf']) { - delete this.options[opt]; - } - // force bind for further event listener calls this._channelListener = this._channelListener.bind(this); } + get kuzzle () { + return this._kuzzle; + } + subscribe () { return this.kuzzle.query(this.request, this.options) .then(response => { diff --git a/src/core/searchResult/Document.js b/src/core/searchResult/Document.ts similarity index 57% rename from src/core/searchResult/Document.js rename to src/core/searchResult/Document.ts index 8a175be77..de992df3d 100644 --- a/src/core/searchResult/Document.js +++ b/src/core/searchResult/Document.ts @@ -1,7 +1,7 @@ -const SearchResultBase = require('./SearchResultBase'); - -class DocumentsSearchResult extends SearchResultBase { +import { SearchResultBase } from './SearchResultBase'; +import { DocumentHit } from '../../utils/interfaces'; +export class DocumentSearchResult extends SearchResultBase { /** * @param {Kuzzle} kuzzle * @param {object} query @@ -16,4 +16,4 @@ class DocumentsSearchResult extends SearchResultBase { } } -module.exports = DocumentsSearchResult; +module.exports = { DocumentSearchResult }; diff --git a/src/core/searchResult/Profile.js b/src/core/searchResult/Profile.js index be27cd96d..ac7de860b 100644 --- a/src/core/searchResult/Profile.js +++ b/src/core/searchResult/Profile.js @@ -1,5 +1,5 @@ -const Profile = require('../security/Profile'); -const SearchResultBase = require('./SearchResultBase'); +const { Profile } = require('../security/Profile'); +const { SearchResultBase } = require('./SearchResultBase'); class ProfileSearchResult extends SearchResultBase { constructor (kuzzle, request, options, response) { @@ -26,4 +26,4 @@ class ProfileSearchResult extends SearchResultBase { } } -module.exports = ProfileSearchResult; +module.exports = { ProfileSearchResult }; diff --git a/src/core/searchResult/Role.js b/src/core/searchResult/Role.js index d03574051..241e310da 100644 --- a/src/core/searchResult/Role.js +++ b/src/core/searchResult/Role.js @@ -1,5 +1,5 @@ -const Role = require('../security/Role'); -const SearchResultBase = require('./SearchResultBase'); +const { Role } = require('../security/Role'); +const { SearchResultBase } = require('./SearchResultBase'); class RoleSearchResult extends SearchResultBase { @@ -32,4 +32,4 @@ class RoleSearchResult extends SearchResultBase { } } -module.exports = RoleSearchResult; +module.exports = { RoleSearchResult }; diff --git a/src/core/searchResult/SearchResultBase.js b/src/core/searchResult/SearchResultBase.ts similarity index 63% rename from src/core/searchResult/SearchResultBase.js rename to src/core/searchResult/SearchResultBase.ts index 0949a76ec..a6c2da445 100644 --- a/src/core/searchResult/SearchResultBase.js +++ b/src/core/searchResult/SearchResultBase.ts @@ -1,4 +1,59 @@ -class SearchResultBase { +import { JSONObject, KuzzleRequest } from '../../utils/interfaces'; +import { Kuzzle } from '../../Kuzzle'; + +export interface SearchResult { + /** + * Search aggregations + */ + aggregations?: JSONObject; + + /** + * Page results + */ + hits: Array; + + /** + * Total number of items that can be retrieved + */ + total: number; + + /** + * Number of retrieved items so far + */ + fetched: number; + + /** + * Advances through the search results and returns the next page of items. + * + * @see https://docs.kuzzle.io/sdk/js/7/core-classes/search-result/next/ + * + * @example + * while (result) { + * // process result.hits here + * result = await result.next(); + * } + * + * @returns A SearchResult or null if no more pages + */ + next (): Promise | null>; +} + +export class SearchResultBase implements SearchResult { + protected _searchAction: string; + protected _scrollAction: string; + protected _controller: string; + protected _request: KuzzleRequest; + protected _kuzzle: Kuzzle; + protected _options: JSONObject; + protected _response: JSONObject; + + public aggregations?: JSONObject; + + public hits: Array; + + public total: number; + + public fetched: number; /** * @@ -7,11 +62,24 @@ class SearchResultBase { * @param {object} options * @param {object} response */ - constructor (kuzzle, request = {}, options = {}, response = {}) { - this._kuzzle = kuzzle; - this._request = request; - this._response = response; - this._options = options; + constructor ( + kuzzle: Kuzzle, + request: KuzzleRequest = {}, + options: any = {}, + response: any = {} + ) { + Reflect.defineProperty(this, '_kuzzle', { + value: kuzzle + }); + Reflect.defineProperty(this, '_request', { + value: request + }); + Reflect.defineProperty(this, '_options', { + value: options + }); + Reflect.defineProperty(this, '_response', { + value: response + }); this._controller = request.controller; this._searchAction = 'search'; @@ -23,7 +91,7 @@ class SearchResultBase { this.total = response.total || 0; } - next () { + next (): Promise | null> { if (this.fetched >= this.total) { return Promise.resolve(null); } @@ -112,7 +180,9 @@ class SearchResultBase { } _buildNextSearchResult (response) { - const nextSearchResult = new this.constructor(this._kuzzle, this._request, this._options, response.result); + const Constructor: any = this.constructor; + + const nextSearchResult = new Constructor(this._kuzzle, this._request, this._options, response.result); nextSearchResult.fetched += this.fetched; return nextSearchResult; @@ -121,4 +191,4 @@ class SearchResultBase { } -module.exports = SearchResultBase; +module.exports = { SearchResultBase }; diff --git a/src/core/searchResult/Specifications.js b/src/core/searchResult/Specifications.js index c0c167d28..15d2d2410 100644 --- a/src/core/searchResult/Specifications.js +++ b/src/core/searchResult/Specifications.js @@ -1,4 +1,4 @@ -const SearchResultBase = require('./SearchResultBase'); +const { SearchResultBase } = require('./SearchResultBase'); class SpecificationsSearchResult extends SearchResultBase { @@ -11,4 +11,4 @@ class SpecificationsSearchResult extends SearchResultBase { } } -module.exports = SpecificationsSearchResult; +module.exports = { SpecificationsSearchResult }; diff --git a/src/core/searchResult/User.js b/src/core/searchResult/User.js index 58e6a28b6..20ec93dcb 100644 --- a/src/core/searchResult/User.js +++ b/src/core/searchResult/User.js @@ -1,5 +1,5 @@ -const SearchResultBase = require('./SearchResultBase'); -const User = require('../security/User'); +const { SearchResultBase } = require('./SearchResultBase'); +const { User } = require('../security/User'); class UserSearchResult extends SearchResultBase { @@ -24,4 +24,4 @@ class UserSearchResult extends SearchResultBase { } } -module.exports = UserSearchResult; +module.exports = { UserSearchResult }; diff --git a/src/core/security/Profile.js b/src/core/security/Profile.js deleted file mode 100644 index ca68a6d38..000000000 --- a/src/core/security/Profile.js +++ /dev/null @@ -1,33 +0,0 @@ -class Profile { - /** - * - * @param {Kuzzle} kuzzle - * @param {Object} data - */ - constructor (kuzzle, _id = null, content = null) { - this._kuzzle = kuzzle; - this._id = _id; - this.rateLimit = content && content.rateLimit ? content.rateLimit : 0; - this.policies = content && content.policies ? content.policies : []; - } - - get kuzzle () { - return this._kuzzle; - } - - /** - * @returns {Promise<[Role]>} - */ - getRoles (options = {}) { - if (!this.policies || this.policies.length === 0) { - return Promise.resolve([]); - } - - return this.kuzzle.security.mGetRoles( - this.policies.map(policy => policy.roleId), - options); - } -} - -module.exports = Profile; - diff --git a/src/core/security/Profile.ts b/src/core/security/Profile.ts new file mode 100644 index 000000000..12e18010a --- /dev/null +++ b/src/core/security/Profile.ts @@ -0,0 +1,57 @@ +import { Role } from './Role'; +import { ProfilePolicy } from '../../utils/interfaces'; + +export class Profile { + /** + * Profile unique ID + */ + public _id: string; + + /** + * Maximum number of requests per second and per node with this profile + */ + public rateLimit: number; + + /** + * Array of policies + */ + public policies: Array; + + + private _kuzzle: any; + + /** + * + * @param {Kuzzle} kuzzle + * @param {Object} data + */ + constructor (kuzzle, _id = null, content = null) { + Reflect.defineProperty(this, '_kuzzle', { + value: kuzzle + }); + + this._id = _id; + this.rateLimit = content && content.rateLimit ? content.rateLimit : 0; + this.policies = content && content.policies ? content.policies : []; + } + + protected get kuzzle () { + return this._kuzzle; + } + + /** + * Gets the associated roles definitions from the API. + */ + getRoles (options = {}): Promise> { + if (!this.policies || this.policies.length === 0) { + return Promise.resolve([]); + } + + return this.kuzzle.security.mGetRoles( + this.policies.map(policy => policy.roleId), + options); + } +} + +module.exports = { Profile }; + diff --git a/src/core/security/Role.js b/src/core/security/Role.js deleted file mode 100644 index 640d5bfde..000000000 --- a/src/core/security/Role.js +++ /dev/null @@ -1,19 +0,0 @@ -class Role { - - /** - * @param {Kuzzle} kuzzle - * @param {Object} data - */ - constructor (kuzzle, _id = null, controllers = {}) { - this._kuzzle = kuzzle; - this._id = _id; - this.controllers = controllers; - } - - get kuzzle () { - return this._kuzzle; - } -} - -module.exports = Role; - diff --git a/src/core/security/Role.ts b/src/core/security/Role.ts new file mode 100644 index 000000000..5e2d4bbca --- /dev/null +++ b/src/core/security/Role.ts @@ -0,0 +1,34 @@ +import { RoleRightsDefinition } from '../../utils/interfaces'; + +export class Role { + /** + * Role unique ID + */ + public _id: string; + /** + * List of rights on controllers/actions + */ + public controllers: RoleRightsDefinition; + + private _kuzzle: any; + + /** + * @param {Kuzzle} kuzzle + * @param {Object} data + */ + constructor (kuzzle, _id = null, controllers = {}) { + Reflect.defineProperty(this, '_kuzzle', { + value: kuzzle + }); + + this._id = _id; + this.controllers = controllers; + } + + protected get kuzzle () { + return this._kuzzle; + } +} + +module.exports = { Role }; + diff --git a/src/core/security/User.js b/src/core/security/User.js deleted file mode 100644 index eb9cdc191..000000000 --- a/src/core/security/User.js +++ /dev/null @@ -1,34 +0,0 @@ -class User { - /** - * - * @param {Kuzzle} kuzzle - * @param {Object} data - */ - constructor (kuzzle, _id = null, content = {}) { - this._kuzzle = kuzzle; - this._id = _id; - this.content = content; - } - - get kuzzle () { - return this._kuzzle; - } - - get profileIds () { - return this.content.profileIds || []; - } - - /** - * @returns {Promise<[Profile]>} - */ - getProfiles () { - if (!this.profileIds || this.profileIds.length === 0) { - return Promise.resolve([]); - } - return this.kuzzle.security.mGetProfiles(this.profileIds); - } - -} - -module.exports = User; - diff --git a/src/core/security/User.ts b/src/core/security/User.ts new file mode 100644 index 000000000..1e54da94c --- /dev/null +++ b/src/core/security/User.ts @@ -0,0 +1,55 @@ +import { JSONObject } from '../../utils/interfaces'; +import { Profile } from './Profile'; + +export class User { + /** + * Kuid (Kuzzle unique ID) + */ + public _id: string; + /** + * Custom content + */ + public content: JSONObject; + + private _kuzzle: any; + + /** + * + * @param {Kuzzle} kuzzle + * @param {Object} data + */ + constructor (kuzzle, _id = null, content = {}) { + Reflect.defineProperty(this, '_kuzzle', { + value: kuzzle + }); + + this._id = _id; + this.content = content; + } + + private get kuzzle () { + return this._kuzzle; + } + + /** + * Array of profile IDs + */ + get profileIds (): Array { + return this.content.profileIds || []; + } + + /** + * Gets user profile definitions from the API + */ + getProfiles (): Promise> { + if (!this.profileIds || this.profileIds.length === 0) { + return Promise.resolve([]); + } + + return this.kuzzle.security.mGetProfiles(this.profileIds); + } + +} + +module.exports = { User }; + diff --git a/src/protocols/Http.js b/src/protocols/Http.js index b3b40e85a..e7f1d86fe 100644 --- a/src/protocols/Http.js +++ b/src/protocols/Http.js @@ -1,11 +1,11 @@ 'use strict'; const staticHttpRoutes = require('./routes.json'); -const BaseProtocol = require('./abstract/Base'); +const { KuzzleAbstractProtocol } = require('./abstract/Base'); -class HttpProtocol extends BaseProtocol { +class HttpProtocol extends KuzzleAbstractProtocol { constructor(host, options = {}) { - super(host, options); + super(host, options, 'http'); if (typeof host !== 'string' || host === '') { throw new Error('host is required'); @@ -201,7 +201,7 @@ class HttpProtocol extends BaseProtocol { return; } - url = url.replace(regex, '/' + data[ matches[1] ]); + url = url.replace(regex, `/${encodeURIComponent(data[matches[1]])}`); delete(queryArgs[ matches[1] ]); @@ -210,11 +210,13 @@ class HttpProtocol extends BaseProtocol { // inject queryString arguments: const queryString = []; + for (const key of Object.keys(queryArgs)) { - const value = queryArgs[key]; + let value = queryArgs[key]; + const encodedKey = encodeURIComponent(key); if (Array.isArray(value)) { - queryString.push(`${key}=${value.join()}`); + queryString.push(`${encodedKey}=${encodeURIComponent(value.join())}`); } else if (typeof value === 'boolean') { // In Kuzzle, an optional boolean option is set to true if present in @@ -222,11 +224,12 @@ class HttpProtocol extends BaseProtocol { // As there is no boolean type in querystrings, encoding a boolean // option "foo=false" in it will make Kuzzle consider it as truthy. if (value === true) { - queryString.push(key); + queryString.push(encodedKey); } } else { - queryString.push(`${key}=${value}`); + value = typeof value === 'object' ? JSON.stringify(value) : value; + queryString.push(`${encodedKey}=${encodeURIComponent(value)}`); } } diff --git a/src/protocols/WebSocket.js b/src/protocols/WebSocket.js index 2f53e3aca..f2d05e1fb 100644 --- a/src/protocols/WebSocket.js +++ b/src/protocols/WebSocket.js @@ -6,7 +6,7 @@ const BaseProtocolRealtime = require('./abstract/Realtime'); class WebSocketProtocol extends BaseProtocolRealtime { constructor(host, options = {}) { - super(host, options); + super(host, options, 'ws'); if (typeof host !== 'string' || host === '') { throw new Error('host is required'); diff --git a/src/protocols/abstract/Base.js b/src/protocols/abstract/Base.js index 81d6a752d..258c6082e 100644 --- a/src/protocols/abstract/Base.js +++ b/src/protocols/abstract/Base.js @@ -1,16 +1,17 @@ 'use strict'; const KuzzleError = require('../../KuzzleError'); -const uuidv4 = require('../../utils/uuidv4'); -const KuzzleEventEmitter = require('../../core/KuzzleEventEmitter'); +const { uuidv4 } = require('../../utils/uuidv4'); +const { KuzzleEventEmitter } = require('../../core/KuzzleEventEmitter'); const PendingRequest = require('./PendingRequest'); class KuzzleAbstractProtocol extends KuzzleEventEmitter { - constructor (host, options = {}) { + constructor (host, options = {}, name = undefined) { super(); this._pendingRequests = new Map(); this._host = host; + this._name = name; const port = parseInt(options.port, 10); this._port = isNaN(port) ? 7512 : port; this._ssl = typeof options.sslConnection === 'boolean' ? options.sslConnection : false; @@ -31,6 +32,10 @@ class KuzzleAbstractProtocol extends KuzzleEventEmitter { return this._host; } + get name () { + return this._name; + } + get port () { return this._port; } @@ -134,4 +139,4 @@ Discarded request: ${JSON.stringify(request)}`)); } -module.exports = KuzzleAbstractProtocol; +module.exports = { KuzzleAbstractProtocol }; diff --git a/src/protocols/abstract/Realtime.js b/src/protocols/abstract/Realtime.js index 53ee5e311..0dab94019 100644 --- a/src/protocols/abstract/Realtime.js +++ b/src/protocols/abstract/Realtime.js @@ -1,6 +1,6 @@ 'use strict'; -const KuzzleAbstractProtocol = require('./Base'); +const { KuzzleAbstractProtocol } = require('./Base'); class BaseProtocolRealtime extends KuzzleAbstractProtocol { constructor (host, options = {}) { diff --git a/src/protocols/routes.json b/src/protocols/routes.json index 1a6836f0d..f07f9d939 100644 --- a/src/protocols/routes.json +++ b/src/protocols/routes.json @@ -58,6 +58,10 @@ } }, "bulk": { + "deleteByQuery": { + "url": "/:index/:collection/_bulk/_query", + "verb": "DELETE" + }, "import": { "verb": "POST", "url": "/:index/:collection/_bulk" @@ -76,10 +80,6 @@ "verb": "POST", "url": "/:index/:collection/_create" }, - "search": { - "url": "/:index/:collection", - "verb": "GET" - }, "scroll": { "url": "/_scroll/:scrollId", "verb": "GET" @@ -116,6 +116,10 @@ "url": "/:index/:collection/:_id/_update", "verb": "PUT" }, + "updateByQuery": { + "url": "/:index/:collection/_query", + "verb": "PUT" + }, "mUpdate": { "url": "/:index/:collection/_mUpdate", "verb": "PUT" @@ -143,6 +147,10 @@ "validate": { "url": "/:index/:collection/_validate", "verb": "POST" + }, + "search": { + "url": "/:index/:collection/_search", + "verb": "GET" } }, "security": { @@ -324,6 +332,10 @@ } }, "collection": { + "update": { + "url": "/:index/:collection/", + "verb": "POST" + }, "updateMapping": { "url": "/:index/:collection/_mapping", "verb": "PUT" @@ -540,6 +552,10 @@ "url": "/ms/_ltrim/:_id", "verb": "POST" }, + "mexecute": { + "url": "/ms/_mexecute", + "verb": "POST" + }, "mget": { "url": "/ms/_mget", "verb": "GET" diff --git a/src/utils/interfaces.ts b/src/utils/interfaces.ts new file mode 100644 index 000000000..6062231a3 --- /dev/null +++ b/src/utils/interfaces.ts @@ -0,0 +1,187 @@ +'use strict'; + +/** + * An interface representing an object with string key and any value + */ +export interface JSONObject { + [key: string]: JSONObject | any +} + +/** + * Kuzzle API request + * + * @see https://docs.kuzzle.io/core/2/api/essentials/query-syntax/#other-protocols + */ +export interface KuzzleRequest extends JSONObject { + controller?: string; + action?: string; + index?: string; + collection?: string; + _id?: string; + jwt?: string; + volatile?: JSONObject; + body?: JSONObject; +} + +/** + * A profile policy is composed of a roleId to define API rights + * and an optional array of restrictions on index and collections + * + * @example + * { + * "roleId": "editor", + * "restrictedTo": { + * "index": "blog", + * "collections": [ + * "articles" + * ] + * } + * } + * + * @see https://docs.kuzzle.io/core/2/guides/essentials/security/#defining-profiles + */ +export interface ProfilePolicy { + /** + * Role unique ID used by this policy + */ + roleId: string; + + /** + * Optional array of restrictions on which the rights are gonne be applied + */ + restrictedTo?: { + /** + * Index name. + * Rights will only be applied on this index. + */ + index: string; + + /** + * Collection names. + * Rights will only be applied on those collections. + */ + collections?: Array; + } +} + +/** + * Role list of rights definition for controllers and actions. + * + * @example + * + * { + * auth: { + * actions: { + * getCurrentUser: true, + * getMyCredentials: true, + * getMyRights: true, + * logout: true + * } + * }, + * realtime: { + * actions: { + * "*": true + * } + * } + * } + * + * @see https://docs.kuzzle.io/core/2/guides/essentials/security#defining-roles + */ +export interface RoleRightsDefinition { + [key: string]: { + actions: { + [key: string]: boolean + } + } +} + +/** + * ApiKey + */ +export interface ApiKey { + /** + * ApiKey unique ID + */ + _id: string; + /** + * ApiKey content + */ + _source: { + /** + * User kuid + */ + userId: string; + /** + * Expiration date in UNIX micro-timestamp format (-1 if the token never expires) + */ + expiresAt: number; + /** + * Original TTL in ms + */ + ttl: number; + /** + * API key description + */ + description: string; + /** + * Authentication token associated with this API key + */ + token: string; + } +} + +/** + * Kuzzle document + * + * @property _id + * @property _version + * @property _source + */ +export interface Document { + /** + * Document unique ID + */ + _id?: string; + /** + * Document Version (generated by Elasticsearch) + */ + _version?: number; + /** + * Document Content + */ + _source?: { + [key: string]: JSONObject | any, + /** + * Kuzzle metadata + * @see https://docs.kuzzle.io/core/2/guides/essentials/document-metadata/ + */ + _kuzzle_info?: { + /** + * Kuid of the user who created the document + */ + author: string, + /** + * Creation date in micro-timestamp + */ + createdAt: number, + /** + * Kuid of the user who last updated the document + */ + updater: string | null, + /** + * Update date in micro-timestamp + */ + updatedAt: number | null + } + }; +} + +/** + * Document retrieved from a search + */ +export interface DocumentHit extends Document { + /** + * Relevance score + */ + _score: number; +} diff --git a/src/utils/proxify.js b/src/utils/proxify.js index 1dd3768da..58fbf4cb0 100644 --- a/src/utils/proxify.js +++ b/src/utils/proxify.js @@ -132,4 +132,4 @@ const proxify = (obj, opts = {}) => { return new Proxy(obj, handler); }; -module.exports = proxify; +module.exports = { proxify }; diff --git a/src/utils/uuidv4.js b/src/utils/uuidv4.js index deb629b21..d4eb8b83f 100644 --- a/src/utils/uuidv4.js +++ b/src/utils/uuidv4.js @@ -3,7 +3,7 @@ // // cf amazing https://gist.github.com/jed/982883 -const b = (a) => a +const uuidv4 = a => a ? ( a ^ Math.random() @@ -18,7 +18,7 @@ const b = (a) => a -1e11 ).replace( /[018]/g, - b + uuidv4 ); -module.exports = b; +module.exports = { uuidv4 }; diff --git a/test/controllers/auth.test.js b/test/controllers/auth.test.js index a3e774792..f58b8c331 100644 --- a/test/controllers/auth.test.js +++ b/test/controllers/auth.test.js @@ -1,10 +1,10 @@ const sinon = require('sinon'); const should = require('should'); -const KuzzleEventEmitter = require('../../src/core/KuzzleEventEmitter'); -const Jwt = require('../../src/core/Jwt'); -const AuthController = require('../../src/controllers/Auth'); -const User = require('../../src/core/security/User'); +const { KuzzleEventEmitter } = require('../../src/core/KuzzleEventEmitter'); +const { Jwt } = require('../../src/core/Jwt'); +const { AuthController } = require('../../src/controllers/Auth'); +const { User } = require('../../src/core/security/User'); const generateJwt = require('../mocks/generateJwt.mock'); describe('Auth Controller', () => { diff --git a/test/controllers/bulk.test.js b/test/controllers/bulk.test.js index 8df3e1e3f..cc41dc0ec 100644 --- a/test/controllers/bulk.test.js +++ b/test/controllers/bulk.test.js @@ -1,5 +1,5 @@ const - BulkController = require('../../src/controllers/Bulk'), + { BulkController } = require('../../src/controllers/Bulk'), sinon = require('sinon'), should = require('should'); @@ -20,6 +20,27 @@ describe('Bulk Controller', () => { kuzzle.bulk = new BulkController(kuzzle); }); + describe('deleteByQuery', () => { + it('should call document/deleteByQuery query and return a Promise which resolves the list of deleted document ids', () => { + kuzzle.query.resolves({ result: { deleted: 3 } }); + const options = {refresh: 'wait_for'}; + return kuzzle.bulk.deleteByQuery('index', 'collection', { query: { match: { foo: 'bar' } } }, options) + .then(res => { + should(kuzzle.query) + .be.calledOnce() + .be.calledWith({ + controller: 'bulk', + action: 'deleteByQuery', + index: 'index', + collection: 'collection', + body: {query: {match: {foo: 'bar' }}} + }, options); + + should(res).be.an.Number(); + should(res).be.equal(3); + }); + }); + }); describe('import', () => { it('should call bulk/import query with the bulk data and return a Promise which resolves json object', () => { diff --git a/test/controllers/collection.test.js b/test/controllers/collection.test.js index 957de1e7e..03e83489f 100644 --- a/test/controllers/collection.test.js +++ b/test/controllers/collection.test.js @@ -1,6 +1,6 @@ const - CollectionController = require('../../src/controllers/Collection'), - SpecificationsSearchResult = require('../../src/core/searchResult/Specifications'), + { CollectionController } = require('../../src/controllers/Collection'), + { SpecificationsSearchResult } = require('../../src/core/searchResult/Specifications'), sinon = require('sinon'), should = require('should'); @@ -328,6 +328,28 @@ describe('Collection Controller', () => { }); }); + describe('update', () => { + it('should call collection/update query with the new mapping and return a Promise which resolves a json object', () => { + kuzzle.query.resolves({ result: { foo: 'bar' } }); + + const body = { foo: 'bar' }; + return kuzzle.collection.update('index', 'collection', body) + .then(res => { + should(kuzzle.query) + .be.calledOnce() + .be.calledWith({ + body, + controller: 'collection', + action: 'update', + index: 'index', + collection: 'collection' + }); + + should(res).match({ foo: 'bar' }); + }); + }); + }); + describe('updateSpecifications', () => { it('should call collection/updateSpecifications query with the new specifications and return a Promise which resolves a json object', () => { kuzzle.query.resolves({ result: { foo: 'bar' } }); diff --git a/test/controllers/document.test.js b/test/controllers/document.test.js index 5ab034ef9..ec1ddda64 100644 --- a/test/controllers/document.test.js +++ b/test/controllers/document.test.js @@ -1,8 +1,8 @@ -const - DocumentController = require('../../src/controllers/Document'), - DocumentSearchResult = require('../../src/core/searchResult/Document'), - sinon = require('sinon'), - should = require('should'); +const sinon = require('sinon'); +const should = require('should'); + +const { DocumentController } = require('../../src/controllers/Document'); +const { DocumentSearchResult } = require('../../src/core/searchResult/Document'); describe('Document Controller', () => { const options = {opt: 'in'}; @@ -377,7 +377,8 @@ describe('Document Controller', () => { total: 3 }; kuzzle.query.resolves({result}); - + kuzzle.protocol = {}; + kuzzle.protocol.name = 'http'; return kuzzle.document.search('index', 'collection', {foo: 'bar'}, options) .then(res => { should(kuzzle.query) @@ -402,17 +403,57 @@ describe('Document Controller', () => { }); }); - it('should inject the "from", "size", "scroll" options into the request', () => { + it('should call document/search query and return a Promise which resolves a DocumentSearchResult instance', () => { const result = { scrollId: 'scroll-id', hits: [ + {_id: 'document1', _score: 0.9876, _source: {foo: 'bar'}}, {_id: 'document2', _score: 0.6789, _source: {foo: 'barbar'}}, {_id: 'document3', _score: 0.6543, _source: {foo: 'barbaz'}} ], total: 3 }; kuzzle.query.resolves({result}); + kuzzle.protocol = {}; + kuzzle.protocol.name = 'http'; + options.verb = 'GET'; + return kuzzle.document.search('index', 'collection', {foo: 'bar'}, options) + .then(res => { + should(kuzzle.query) + .be.calledOnce() + .be.calledWithMatch({ + controller: 'document', + action: 'search', + index: 'index', + collection: 'collection', + searchBody: {foo: 'bar'}, + body: null, + from: undefined, + size: undefined, + scroll: undefined + }, options); + should(res).be.an.instanceOf(DocumentSearchResult); + should(res._options).match(options); + should(res._options.verb).be.eql('GET'); + should(res._response).be.equal(result); + should(res.fetched).be.equal(3); + should(res.total).be.equal(3); + }); + }); + + it('should inject the "from", "size", "scroll" options into the request', () => { + const result = { + scrollId: 'scroll-id', + hits: [ + {_id: 'document2', _score: 0.6789, _source: {foo: 'barbar'}}, + {_id: 'document3', _score: 0.6543, _source: {foo: 'barbaz'}} + ], + total: 3 + }; + kuzzle.query.resolves({result}); + kuzzle.protocol = {}; + kuzzle.protocol.name = 'http'; return kuzzle.document.search('index', 'collection', {foo: 'bar'}, {from: 1, size: 2, scroll: '10s'}) .then(res => { should(kuzzle.query) @@ -442,7 +483,8 @@ describe('Document Controller', () => { total: 0 }; kuzzle.document.query = sinon.stub().resolves({result}); - + kuzzle.protocol = {}; + kuzzle.protocol.name = 'http'; return kuzzle.document.search('index', 'collection', {}, { size: 0 }) .then(() => { should(kuzzle.document.query).be.calledOnce(); @@ -458,7 +500,8 @@ describe('Document Controller', () => { total: 0 }; kuzzle.document.query = sinon.stub().resolves({result}); - + kuzzle.protocol = {}; + kuzzle.protocol.name = 'http'; return kuzzle.document.search('index', 'collection', {}, { scroll: '42s' }) .then(() => { should(kuzzle.document.query).be.calledOnce(); @@ -556,7 +599,86 @@ describe('Document Controller', () => { body: { foo: 'bar' }, retryOnConflict: undefined, source: true - }, { source: true }); + }); + + should(res).be.equal(result); + }); + }); + }); + + describe('updateByQuery', () => { + it('should call document/update query and return a Promise which resolves the updated document', () => { + const result = { + _id: 'document-id', + _version: 1, + _source: { foo: 'bar' }, + created: false + }; + kuzzle.query.resolves({ result }); + const searchQuery = { + match: { foo: 'bar' } + }; + const changes = { + bar: 'foo' + }; + return kuzzle.document.updateByQuery('index', 'collection', searchQuery, changes, options) + .then(res => { + should(kuzzle.query) + .be.calledOnce() + .be.calledWith({ + controller: 'document', + action: 'updateByQuery', + index: 'index', + collection: 'collection', + body: { + query: { + match: {foo: 'bar'} + }, + changes: { + bar: 'foo' + } + }, + source: undefined + }, options); + + should(res).be.equal(result); + }); + }); + + it('should inject the "source" option into the request', () => { + const result = { + _id: 'document-id', + _version: 1, + _source: { foo: 'bar' }, + created: false + }; + kuzzle.query.resolves({ result }); + const searchQuery = { + match: { foo: 'bar' } + }; + const changes = { + bar: 'foo' + }; + + return kuzzle.document.updateByQuery('index', 'collection', searchQuery, changes, { source: true }) + .then(res => { + should(kuzzle.query) + .be.calledOnce() + .be.calledWith({ + controller: 'document', + action: 'updateByQuery', + index: 'index', + collection: 'collection', + body: { + query: { + match: { foo: 'bar' } + }, + changes: { + bar: 'foo' + } + }, + source: true + }); should(res).be.equal(result); }); diff --git a/test/controllers/index.test.js b/test/controllers/index.test.js index 09eba3bd1..409a9ed13 100644 --- a/test/controllers/index.test.js +++ b/test/controllers/index.test.js @@ -1,5 +1,5 @@ const - IndexController = require('../../src/controllers/Index'), + { IndexController } = require('../../src/controllers/Index'), sinon = require('sinon'), should = require('should'); diff --git a/test/controllers/memoryStorage.test.js b/test/controllers/memoryStorage.test.js index b14d8047d..913cd0529 100644 --- a/test/controllers/memoryStorage.test.js +++ b/test/controllers/memoryStorage.test.js @@ -1,5 +1,5 @@ const - MemoryStorageController = require('../../src/controllers/MemoryStorage'), + { MemoryStorageController } = require('../../src/controllers/MemoryStorage'), should = require('should'), sinon = require('sinon'); @@ -695,6 +695,24 @@ describe('MemoryStorage Controller', function () { ); }); + it('#mexecute', function () { + const actions = [ + { 'action': 'set', 'args': { '_id': 'list:a', 'body': { 'value': 1, 'ex': 100, 'nx': true } } }, + { 'action': 'get', 'args': { '_id': 'list:a' } }, + { 'action': 'del', 'args': { 'body': { 'keys': ['list:a'] } } } + ]; + + return testReadCommand( + 'mexecute', + [actions], + {}, + {body: {actions: actions}}, + {}, + [[null, 'OK'], [null, '1'], [null, 1]], + [[null, 'OK'], [null, '1'], [null, 1]], + ); + }); + it('#mget', function () { return testReadCommand( 'mget', diff --git a/test/controllers/realtime.test.js b/test/controllers/realtime.test.js index 5aa4ebcb8..c264a24cb 100644 --- a/test/controllers/realtime.test.js +++ b/test/controllers/realtime.test.js @@ -2,11 +2,11 @@ const mockrequire = require('mock-require'); const sinon = require('sinon'); const should = require('should'); -const KuzzleEventEmitter = require('../../src/core/KuzzleEventEmitter'); -const AuthController = require('../../src/controllers/Auth'); -const RealtimeController = require('../../src/controllers/Realtime'); +const { KuzzleEventEmitter } = require('../../src/core/KuzzleEventEmitter'); +const { AuthController } = require('../../src/controllers/Auth'); +const { RealtimeController } = require('../../src/controllers/Realtime'); const generateJwt = require('../mocks/generateJwt.mock'); -const uuidv4 = require('../../src/utils/uuidv4'); +const { uuidv4 } = require('../../src/utils/uuidv4'); describe('Realtime Controller', () => { const options = {opt: 'in'}; @@ -60,6 +60,7 @@ describe('Realtime Controller', () => { describe('#publish', () => { it('should call realtime/publish query with the index, collection and body and return a Promise which resolves an acknowledgement', () => { kuzzle.query.resolves({result: {published: true}}); + options._id = 'doc-id'; return kuzzle.realtime.publish('index', 'collection', {foo: 'bar'}, options) .then(published => { @@ -70,7 +71,8 @@ describe('Realtime Controller', () => { action: 'publish', index: 'index', collection: 'collection', - body: {foo: 'bar'} + body: {foo: 'bar'}, + _id: 'doc-id' }, options); should(published).be.a.Boolean().and.be.true(); @@ -108,8 +110,9 @@ describe('Realtime Controller', () => { return room; }); - const MockRealtimeController = - mockrequire.reRequire('../../src/controllers/Realtime'); + const reRequire = mockrequire.reRequire('../../src/controllers/Realtime'); + const MockRealtimeController = reRequire.RealtimeController; + kuzzle.realtime = new MockRealtimeController(kuzzle); }); @@ -131,22 +134,22 @@ describe('Realtime Controller', () => { }); }); - it('should store the room subsciption locally', () => { + it('should store the room subscription locally', () => { const body = {foo: 'bar'}, cb = sinon.stub(); - kuzzle.realtime.subscriptions = {}; + kuzzle.realtime.subscriptions = new Map(); return kuzzle.realtime.subscribe('index', 'collection', body, cb, options) .then(() => { - const subscriptions = kuzzle.realtime.subscriptions[roomId]; + const subscriptions = kuzzle.realtime.subscriptions.get(roomId); should(subscriptions).be.an.Array(); should(subscriptions.length).be.exactly(1); should(subscriptions[0]).be.exactly(room); return kuzzle.realtime.subscribe('index', 'collection', body, cb, options); }).then(() => { - const subscriptions = kuzzle.realtime.subscriptions[roomId]; + const subscriptions = kuzzle.realtime.subscriptions.get(roomId); should(subscriptions).be.an.Array(); should(subscriptions.length).be.exactly(2); @@ -172,22 +175,12 @@ describe('Realtime Controller', () => { room1.removeListeners.reset(); room2.removeListeners.reset(); - kuzzle.realtime.subscriptions[roomId] = [room1, room2]; - kuzzle.realtime.subscriptions.foo = [room3]; + kuzzle.realtime.subscriptions.set(roomId, [room1, room2]); + kuzzle.realtime.subscriptions.set('foo', [room3]); kuzzle.query.resolves({result: roomId}); }); - it('should reject the promise if the room is not found', () => { - return kuzzle.realtime.unsubscribe('bar') - .then(() => { - throw new Error('Expected Function unsubscribe() to reject'); - }) - .catch(err => { - should(err.message).be.equal('not subscribed to bar'); - }); - }); - it('should call removeListeners for each room', () => { return kuzzle.realtime.unsubscribe(roomId) .then(() => { @@ -200,12 +193,12 @@ describe('Realtime Controller', () => { it('should delete rooms from local storage', () => { return kuzzle.realtime.unsubscribe(roomId) .then(() => { - should(kuzzle.realtime.subscriptions[roomId]).be.undefined(); + should(kuzzle.realtime.subscriptions.get(roomId)).be.undefined(); // Check we do not remove other registered rooms: - should(kuzzle.realtime.subscriptions.foo).be.an.Array(); - should(kuzzle.realtime.subscriptions.foo.length).be.equal(1); - should(kuzzle.realtime.subscriptions.foo[0]).be.equal(room3); + should(kuzzle.realtime.subscriptions.get('foo')).be.an.Array(); + should(kuzzle.realtime.subscriptions.get('foo').length).be.equal(1); + should(kuzzle.realtime.subscriptions.get('foo')[0]).be.equal(room3); }); }); @@ -240,17 +233,17 @@ describe('Realtime Controller', () => { removeListeners: sinon.stub() }; - kuzzle.realtime.subscriptions = { - foo: [roomA, roomB], - bar: [roomC] - }; + kuzzle.realtime.subscriptions = new Map([ + ['foo', [roomA, roomB]], + ['bar', [roomC]] + ]); kuzzle.realtime.disconnected(); should(kuzzle.realtime.subscriptions).be.empty(); - should(kuzzle.realtime.subscriptionsOff).eql({ - foo: [roomA] - }); + should(kuzzle.realtime.subscriptionsOff).eql(new Map([ + ['foo', [roomA]] + ])); for (const room of [roomA, roomB, roomC]) { should(room.removeListeners).be.calledOnce(); } @@ -263,18 +256,18 @@ describe('Realtime Controller', () => { const roomB = { subscribe: sinon.stub().resolves() }; const roomC = { subscribe: sinon.stub().resolves() }; - kuzzle.realtime.subscriptionsOff = { - foo: [roomA, roomB], - bar: [roomC] - }; + kuzzle.realtime.subscriptionsOff = new Map([ + ['foo', [roomA, roomB]], + ['bar', [roomC]] + ]); kuzzle.realtime.reconnected(); should(kuzzle.realtime.subscriptionsOff).be.empty(); - should(kuzzle.realtime.subscriptions).eql({ - foo: [roomA, roomB], - bar: [roomC] - }); + should(kuzzle.realtime.subscriptions).eql(new Map([ + ['foo', [roomA, roomB]], + ['bar', [roomC]] + ])); for (const room of [roomA, roomB, roomC]) { should(room.subscribe).be.calledOnce(); @@ -290,7 +283,7 @@ describe('Realtime Controller', () => { kuzzle.jwt = 'foobar'; for (let i = 0; i < 10; i++) { - kuzzle.realtime.subscriptions[uuidv4()] = [{removeListeners: stub}]; + kuzzle.realtime.subscriptions.set(uuidv4(), [{removeListeners: stub}]); } kuzzle.realtime.tokenExpired(); diff --git a/test/controllers/security.test.js b/test/controllers/security.test.js index dd497d8d6..f42316844 100644 --- a/test/controllers/security.test.js +++ b/test/controllers/security.test.js @@ -1,10 +1,10 @@ -const SecurityController = require('../../src/controllers/Security'); -const Profile = require('../../src/core/security/Profile'); -const Role = require('../../src/core/security/Role'); -const User = require('../../src/core/security/User'); -const ProfileSearchResult = require('../../src/core/searchResult/Profile'); -const RoleSearchResult = require('../../src/core/searchResult/Role'); -const UserSearchResult = require('../../src/core/searchResult/User'); +const { SecurityController } = require('../../src/controllers/Security'); +const { Profile } = require('../../src/core/security/Profile'); +const { Role } = require('../../src/core/security/Role'); +const { User } = require('../../src/core/security/User'); +const { ProfileSearchResult } = require('../../src/core/searchResult/Profile'); +const { RoleSearchResult } = require('../../src/core/searchResult/Role'); +const { UserSearchResult } = require('../../src/core/searchResult/User'); const sinon = require('sinon'); const should = require('should'); @@ -165,7 +165,7 @@ describe('Security Controller', () => { controller: 'security', action: 'createFirstAdmin', reset: true - }, {}); + }, {reset: true}); should(user).be.an.instanceOf(User); should(user._id).be.eql('id'); diff --git a/test/controllers/server.test.js b/test/controllers/server.test.js index 243eb9467..193a13ff7 100644 --- a/test/controllers/server.test.js +++ b/test/controllers/server.test.js @@ -1,5 +1,5 @@ const - ServerController = require('../../src/controllers/Server'), + { ServerController } = require('../../src/controllers/Server'), sinon = require('sinon'), should = require('should'); diff --git a/test/core/Jwt.test.js b/test/core/Jwt.test.js index 699c27599..371f9f72b 100644 --- a/test/core/Jwt.test.js +++ b/test/core/Jwt.test.js @@ -9,7 +9,7 @@ describe('Jwt', () => { authenticationToken; beforeEach(() => { - Jwt = rewire('../../src/core/Jwt'); + ({ Jwt } = rewire('../../src/core/Jwt')); }); describe('#constructor', () => { diff --git a/test/core/room.test.js b/test/core/room.test.js index 2cddfe977..6e7172269 100644 --- a/test/core/room.test.js +++ b/test/core/room.test.js @@ -1,6 +1,6 @@ const Room = require('../../src/core/Room'), - KuzzleEventEmitter = require('../../src/core/KuzzleEventEmitter'), + { KuzzleEventEmitter } = require('../../src/core/KuzzleEventEmitter'), sinon = require('sinon'), should = require('should'); @@ -67,20 +67,17 @@ describe('Room', () => { }); it('should handle scope/state/users/volatile options', () => { - const - opts = { - scope: 'scope', - state: 'state', - users: 'users', - volatile: 'volatile' - }, - body = {foo: 'bar'}, - cb = sinon.stub(); + const opts = { + scope: 'scope', + state: 'state', + users: 'users', + volatile: 'volatile' + }; + const body = {foo: 'bar'}; + const cb = sinon.stub(); const room = new Room(controller, 'index', 'collection', body, cb, opts); - should(room.options).be.empty(); - should(room.request.scope).be.equal('scope'); should(room.request.state).be.equal('state'); should(room.request.users).be.equal('users'); @@ -104,10 +101,6 @@ describe('Room', () => { controller, 'index', 'collection', body, cb, {autoResubscribe: 'foobar'}); - should(room1.options).be.empty(); - should(room2.options).be.empty(); - should(room3.options).be.empty(); - should(room1.autoResubscribe).be.a.Boolean().and.be.True(); should(room2.autoResubscribe).be.a.Boolean().and.be.False(); should(room3.autoResubscribe).be.equal('default'); @@ -128,10 +121,6 @@ describe('Room', () => { controller, 'index', 'collection', body, cb, {subscribeToSelf: 'foobar'}); - should(room1.options).be.empty(); - should(room2.options).be.empty(); - should(room3.options).be.empty(); - should(room1.subscribeToSelf).be.a.Boolean().and.be.True(); should(room2.subscribeToSelf).be.a.Boolean().and.be.False(); should(room3.subscribeToSelf).be.a.Boolean().and.be.True(); @@ -177,7 +166,7 @@ describe('Room', () => { state: 'done', users: 'all', volatile: {bar: 'foo'} - }, options); + }, opts); should(res).be.equal(response); }); diff --git a/test/core/searchResult/document.test.js b/test/core/searchResult/document.test.js index eade0043f..20b8214d3 100644 --- a/test/core/searchResult/document.test.js +++ b/test/core/searchResult/document.test.js @@ -1,7 +1,7 @@ -const - DocumentSearchResult = require('../../../src/core/searchResult/Document'), - sinon = require('sinon'), - should = require('should'); +const sinon = require('sinon'); +const should = require('should'); + +const { DocumentSearchResult } = require('../../../src/core/searchResult/Document'); describe('DocumentSearchResult', () => { const options = {opt: 'in'}; diff --git a/test/core/searchResult/profile.test.js b/test/core/searchResult/profile.test.js index 8df5c0803..8e10e26dd 100644 --- a/test/core/searchResult/profile.test.js +++ b/test/core/searchResult/profile.test.js @@ -1,6 +1,6 @@ const - ProfileSearchResult = require('../../../src/core/searchResult/Profile'), - Profile = require('../../../src/core/security/Profile'), + { ProfileSearchResult } = require('../../../src/core/searchResult/Profile'), + { Profile } = require('../../../src/core/security/Profile'), sinon = require('sinon'), should = require('should'); diff --git a/test/core/searchResult/role.test.js b/test/core/searchResult/role.test.js index 554199b49..5f92d858a 100644 --- a/test/core/searchResult/role.test.js +++ b/test/core/searchResult/role.test.js @@ -1,6 +1,6 @@ const - RoleSearchResult = require('../../../src/core/searchResult/Role'), - Role = require('../../../src/core/security/Role'), + { RoleSearchResult } = require('../../../src/core/searchResult/Role'), + { Role } = require('../../../src/core/security/Role'), sinon = require('sinon'), should = require('should'); diff --git a/test/core/searchResult/specifications.test.js b/test/core/searchResult/specifications.test.js index 156a9e69f..c524409d1 100644 --- a/test/core/searchResult/specifications.test.js +++ b/test/core/searchResult/specifications.test.js @@ -1,5 +1,5 @@ const - SpecificationsSearchResult = require('../../../src/core/searchResult/Specifications'), + { SpecificationsSearchResult } = require('../../../src/core/searchResult/Specifications'), sinon = require('sinon'), should = require('should'); diff --git a/test/core/searchResult/user.test.js b/test/core/searchResult/user.test.js index c696db429..e0d6583de 100644 --- a/test/core/searchResult/user.test.js +++ b/test/core/searchResult/user.test.js @@ -1,6 +1,6 @@ const - UserSearchResult = require('../../../src/core/searchResult/User'), - User = require('../../../src/core/security/User'), + { UserSearchResult } = require('../../../src/core/searchResult/User'), + { User } = require('../../../src/core/security/User'), sinon = require('sinon'), should = require('should'); diff --git a/test/core/security/profile.test.js b/test/core/security/profile.test.js index 90dea92ae..175f143b0 100644 --- a/test/core/security/profile.test.js +++ b/test/core/security/profile.test.js @@ -1,4 +1,4 @@ -const Profile = require('../../../src/core/security/Profile'); +const { Profile } = require('../../../src/core/security/Profile'); const sinon = require('sinon'); const should = require('should'); diff --git a/test/core/security/user.test.js b/test/core/security/user.test.js index 9d36dbc8d..57054e5b5 100644 --- a/test/core/security/user.test.js +++ b/test/core/security/user.test.js @@ -1,5 +1,5 @@ const - User = require('../../../src/core/security/User'), + { User } = require('../../../src/core/security/User'), sinon = require('sinon'), should = require('should'); diff --git a/test/kuzzle/connect.test.js b/test/kuzzle/connect.test.js index c3a191ff3..63c784b55 100644 --- a/test/kuzzle/connect.test.js +++ b/test/kuzzle/connect.test.js @@ -3,7 +3,7 @@ const sinon = require('sinon'), ProtocolMock = require('../mocks/protocol.mock'), generateJwt = require('../mocks/generateJwt.mock'), - Kuzzle = require('../../src/Kuzzle'); + { Kuzzle } = require('../../src/Kuzzle'); describe('Kuzzle connect', () => { @@ -98,7 +98,7 @@ describe('Kuzzle connect', () => { it('should keep a valid JWT at reconnection', () => { const - jwt = generateJwt(), + jwt = generateJwt(), kuzzle = new Kuzzle(protocols.somewhereagain); kuzzle.auth.checkToken = sinon.stub().resolves({ @@ -116,7 +116,7 @@ describe('Kuzzle connect', () => { it('should empty the JWT at reconnection if it has expired', () => { const - jwt = generateJwt(), + jwt = generateJwt(), kuzzle = new Kuzzle(protocols.somewhereagain); kuzzle.auth.checkToken = sinon.stub().resolves({ diff --git a/test/kuzzle/constructor.test.js b/test/kuzzle/constructor.test.js index 46aaa219d..f18316898 100644 --- a/test/kuzzle/constructor.test.js +++ b/test/kuzzle/constructor.test.js @@ -1,16 +1,16 @@ const should = require('should'), sinon = require('sinon'), - Kuzzle = require('../../src/Kuzzle'), - AuthController = require('../../src/controllers/Auth'), - BulkController = require('../../src/controllers/Bulk'), - CollectionController = require('../../src/controllers/Collection'), - DocumentController = require('../../src/controllers/Document'), - IndexController = require('../../src/controllers/Index'), - MemoryStorageController = require('../../src/controllers/MemoryStorage'), - SecurityController = require('../../src/controllers/Security'), - ServerController = require('../../src/controllers/Server'), - RealTimeController = require('../../src/controllers/Realtime'), + { Kuzzle } = require('../../src/Kuzzle'), + { AuthController } = require('../../src/controllers/Auth'), + { BulkController } = require('../../src/controllers/Bulk'), + { CollectionController } = require('../../src/controllers/Collection'), + { DocumentController } = require('../../src/controllers/Document'), + { IndexController } = require('../../src/controllers/Index'), + { MemoryStorageController } = require('../../src/controllers/MemoryStorage'), + { SecurityController } = require('../../src/controllers/Security'), + { ServerController } = require('../../src/controllers/Server'), + { RealtimeController } = require('../../src/controllers/Realtime'), { WebSocket, // eslint-disable-line no-redeclare Http @@ -65,7 +65,7 @@ describe('Kuzzle constructor', () => { should(kuzzle.ms).be.an.instanceof(MemoryStorageController); should(kuzzle.security).be.an.instanceof(SecurityController); should(kuzzle.server).be.an.instanceof(ServerController); - should(kuzzle.realtime).be.an.instanceof(RealTimeController); + should(kuzzle.realtime).be.an.instanceof(RealtimeController); }); it('should expose the documented properties with their default values', () => { @@ -123,7 +123,7 @@ describe('Kuzzle constructor', () => { should(kuzzle.ms).be.an.instanceof(MemoryStorageController); should(kuzzle.security).be.an.instanceof(SecurityController); should(kuzzle.server).be.an.instanceof(ServerController); - should(kuzzle.realtime).be.an.instanceof(RealTimeController); + should(kuzzle.realtime).be.an.instanceof(RealtimeController); should(kuzzle.protocol).be.an.instanceof(ProtocolMock); should(kuzzle.sdkVersion).be.a.String().and.be.equal(version); should(kuzzle.jwt).be.null(); diff --git a/test/kuzzle/eventEmitter.test.js b/test/kuzzle/eventEmitter.test.js index 819a100dd..bcdf7e752 100644 --- a/test/kuzzle/eventEmitter.test.js +++ b/test/kuzzle/eventEmitter.test.js @@ -1,7 +1,7 @@ const should = require('should'), sinon = require('sinon'), - KuzzleEventEmitter = require('../../src/core/KuzzleEventEmitter'); + { KuzzleEventEmitter } = require('../../src/core/KuzzleEventEmitter'); describe('Event emitter', () => { const diff --git a/test/kuzzle/getters.test.js b/test/kuzzle/getters.test.js index 258a50a34..13cdad2fe 100644 --- a/test/kuzzle/getters.test.js +++ b/test/kuzzle/getters.test.js @@ -2,11 +2,11 @@ const should = require('should'), ProtocolMock = require('../mocks/protocol.mock'), generateJwt = require('../mocks/generateJwt.mock'), - Kuzzle = require('../../src/Kuzzle'); + { Kuzzle } = require('../../src/Kuzzle'); describe('Kuzzle getters', () => { let - jwt, + jwt, kuzzle; beforeEach(() => { diff --git a/test/kuzzle/listenersManagement.test.js b/test/kuzzle/listenersManagement.test.js index 06025882a..0bd0599dc 100644 --- a/test/kuzzle/listenersManagement.test.js +++ b/test/kuzzle/listenersManagement.test.js @@ -1,35 +1,22 @@ -const - should = require('should'), - sinon = require('sinon'), - proxyquire = require('proxyquire'), - ProtocolMock = require('../mocks/protocol.mock'); +const should = require('should'); +const sinon = require('sinon'); -describe('Kuzzle listeners management', () => { - const - addListenerStub = sinon.stub(), - emitStub = sinon.stub(); - - let - Kuzzle, - kuzzle; - - before(() => { - const KuzzleEventEmitterMock = function() {}; - - KuzzleEventEmitterMock.prototype.addListener = addListenerStub; - KuzzleEventEmitterMock.prototype.emit = emitStub; - - Kuzzle = proxyquire('../../src/Kuzzle', { - './core/KuzzleEventEmitter': KuzzleEventEmitterMock - }); - }); +const { Kuzzle } = require('../../src/Kuzzle'); +const { KuzzleEventEmitter } =require('../../src/core/KuzzleEventEmitter'); +const ProtocolMock = require('../mocks/protocol.mock'); +describe('Kuzzle listeners management', () => { + let kuzzle; beforeEach(() => { const protocol = new ProtocolMock(); kuzzle = new Kuzzle(protocol, {eventTimeout: 20}); - addListenerStub.reset(); - emitStub.reset(); + sinon.stub(KuzzleEventEmitter.prototype, 'addListener').resolves(); + sinon.stub(KuzzleEventEmitter.prototype, 'emit').resolves(); + }); + + afterEach(() => { + sinon.restore(); }); it('should only listen to allowed events', () => { @@ -46,16 +33,19 @@ describe('Kuzzle listeners management', () => { 'tokenExpired' ]; - should(function() {kuzzle.addListener('foo', sinon.stub());}).throw('[foo] is not a known event. Known events: ' + knownEvents.toString()); + should(function() { + kuzzle.addListener('foo', sinon.stub()); + }).throw('[foo] is not a known event. Known events: ' + knownEvents.toString()); let i; for (i = 0; i < knownEvents.length; i++) { kuzzle.addListener(knownEvents[i], sinon.stub()); } - should(addListenerStub.callCount).be.exactly(10); + should(KuzzleEventEmitter.prototype.addListener).have.called(10); + for (i = 0; i < knownEvents.length; i++) { - should(addListenerStub.getCall(i)).be.calledWith(knownEvents[i]); + should(KuzzleEventEmitter.prototype.addListener.getCall(i)).be.calledWith(knownEvents[i]); } }); @@ -68,18 +58,18 @@ describe('Kuzzle listeners management', () => { kuzzle.emit('offlineQueuePush', 'bar'); setTimeout(function () { - should(emitStub).be.calledTwice(); - should(emitStub.firstCall).be.calledWith('connected', 'foo'); - should(emitStub.secondCall).be.calledWith('offlineQueuePush', 'bar'); + should(KuzzleEventEmitter.prototype.emit).be.calledTwice(); + should(KuzzleEventEmitter.prototype.emit.firstCall).be.calledWith('connected', 'foo'); + should(KuzzleEventEmitter.prototype.emit.secondCall).be.calledWith('offlineQueuePush', 'bar'); - emitStub.reset(); + KuzzleEventEmitter.prototype.emit.reset(); setTimeout(function () { kuzzle.emit('connected', 'bar'); kuzzle.emit('connected', 'bar'); setTimeout(function () { - should(emitStub).be.calledOnce(); - should(emitStub).be.calledWith('connected', 'bar'); + should(KuzzleEventEmitter.prototype.emit).be.calledOnce(); + should(KuzzleEventEmitter.prototype.emit).be.calledWith('connected', 'bar'); done(); }, 0); }, 30); diff --git a/test/kuzzle/protocol.test.js b/test/kuzzle/protocol.test.js index 1f702e185..234e17e69 100644 --- a/test/kuzzle/protocol.test.js +++ b/test/kuzzle/protocol.test.js @@ -3,7 +3,7 @@ const sinon = require('sinon'), ProtocolMock = require('../mocks/protocol.mock'), generateJwt = require('../mocks/generateJwt.mock'), - Kuzzle = require('../../src/Kuzzle'); + { Kuzzle } = require('../../src/Kuzzle'); describe('Kuzzle protocol methods', () => { let kuzzle; diff --git a/test/kuzzle/proxy.test.js b/test/kuzzle/proxy.test.js index 4f9b57387..6449e9481 100644 --- a/test/kuzzle/proxy.test.js +++ b/test/kuzzle/proxy.test.js @@ -1,6 +1,6 @@ const should = require('should'), - Kuzzle = require('../../src/Kuzzle'), + { Kuzzle } = require('../../src/Kuzzle'), ProtocolMock = require('../mocks/protocol.mock'); describe('Kuzzle proxy', () => { @@ -10,7 +10,7 @@ describe('Kuzzle proxy', () => { const kuzzle = new Kuzzle(protocolMock); should(() => { kuzzle.jvt = 'foobar'; - }).throwError('Cannot set a value to the undefined \'jvt\' property in \'kuzzle\''); + }).throwError('Cannot set a value to the undefined \'jvt\' property in \'kuzzle\''); }); }); diff --git a/test/kuzzle/query.test.js b/test/kuzzle/query.test.js index 75d439fdb..fbba9e7b9 100644 --- a/test/kuzzle/query.test.js +++ b/test/kuzzle/query.test.js @@ -3,7 +3,7 @@ const sinon = require('sinon'), ProtocolMock = require('../mocks/protocol.mock'), generateJwt = require('../mocks/generateJwt.mock'), - Kuzzle = require('../../src/Kuzzle'); + { Kuzzle } = require('../../src/Kuzzle'); describe('Kuzzle query management', () => { describe('#query', () => { @@ -179,7 +179,7 @@ describe('Kuzzle query management', () => { }); it('should queue the request if queing and queuable', () => { - kuzzle.queuing = true; + kuzzle._queuing = true; const eventStub = sinon.stub(); kuzzle.addListener('offlineQueuePush', eventStub); @@ -197,7 +197,7 @@ describe('Kuzzle query management', () => { }); it('should not queue if the request is not queuable', () => { - kuzzle.queuing = true; + kuzzle._queuing = true; const eventStub = sinon.stub(); kuzzle.addListener('discarded', eventStub); @@ -222,7 +222,7 @@ describe('Kuzzle query management', () => { }); it('should not queue if queueFilter is set and says so', () => { - kuzzle.queuing = true; + kuzzle._queuing = true; kuzzle.queueFilter = () => false; return kuzzle.query({controller: 'foo', action: 'bar'}, {queuable: true}) diff --git a/test/kuzzle/queue.test.js b/test/kuzzle/queue.test.js index 9d99a183f..e34657dbc 100644 --- a/test/kuzzle/queue.test.js +++ b/test/kuzzle/queue.test.js @@ -2,7 +2,7 @@ const should = require('should'), sinon = require('sinon'), ProtocolMock = require('../mocks/protocol.mock'), - Kuzzle = require('../../src/Kuzzle'); + { Kuzzle } = require('../../src/Kuzzle'); describe('Kuzzle queue', () => { let kuzzle; diff --git a/test/kuzzle/setters.test.js b/test/kuzzle/setters.test.js index 2aa4e45a1..de19dd92b 100644 --- a/test/kuzzle/setters.test.js +++ b/test/kuzzle/setters.test.js @@ -3,8 +3,8 @@ const sinon = require('sinon'), ProtocolMock = require('../mocks/protocol.mock'), generateJwt = require('../mocks/generateJwt.mock'), - Jwt = require('../../src/core/Jwt'), - Kuzzle = require('../../src/Kuzzle'); + { Jwt } = require('../../src/core/Jwt'), + { Kuzzle } = require('../../src/Kuzzle'); describe('Kuzzle setters', () => { let kuzzle; diff --git a/test/kuzzle/useController.test.js b/test/kuzzle/useController.test.js index 2afd1fb58..8cb79634d 100644 --- a/test/kuzzle/useController.test.js +++ b/test/kuzzle/useController.test.js @@ -2,8 +2,8 @@ const should = require('should'), sinon = require('sinon'), ProtocolMock = require('../mocks/protocol.mock'), - BaseController = require('../../src/controllers/Base'), - Kuzzle = require('../../src/Kuzzle'); + { BaseController } = require('../../src/controllers/Base'), + { Kuzzle } = require('../../src/Kuzzle'); class CustomController extends BaseController { constructor (kuzzle) { diff --git a/test/mocks/protocol.mock.js b/test/mocks/protocol.mock.js index e01fab468..d6a414b0e 100644 --- a/test/mocks/protocol.mock.js +++ b/test/mocks/protocol.mock.js @@ -1,6 +1,6 @@ const sinon = require('sinon'), - KuzzleEventEmitter = require('../../src/core/KuzzleEventEmitter'); + { KuzzleEventEmitter } = require('../../src/core/KuzzleEventEmitter'); class ProtocolMock extends KuzzleEventEmitter { diff --git a/test/mocks/window.mock.js b/test/mocks/window.mock.js index 45b26940c..b813731fb 100644 --- a/test/mocks/window.mock.js +++ b/test/mocks/window.mock.js @@ -1,6 +1,6 @@ const sinon = require('sinon'), - KuzzleEventEmitter = require('../../src/core/KuzzleEventEmitter'); + { KuzzleEventEmitter } = require('../../src/core/KuzzleEventEmitter'); // A class to mock the global window object class WindowMock extends KuzzleEventEmitter { diff --git a/test/protocol/Base.test.js b/test/protocol/Base.test.js index 524aa786b..bd2652459 100644 --- a/test/protocol/Base.test.js +++ b/test/protocol/Base.test.js @@ -2,7 +2,7 @@ const should = require('should'), sinon = require('sinon'), KuzzleError = require('../../src/KuzzleError'), - AbstractWrapper = require('../../src/protocols/abstract/Base'), + { KuzzleAbstractProtocol } = require('../../src/protocols/abstract/Base'), PendingRequest = require('../../src/protocols/abstract/PendingRequest'); describe('Common Protocol', () => { @@ -11,7 +11,7 @@ describe('Common Protocol', () => { protocol; beforeEach(function () { - protocol = new AbstractWrapper('somewhere'); + protocol = new KuzzleAbstractProtocol('somewhere'); protocol.send = function(request) { protocol.emit(request.requestId, request.response); }; @@ -20,23 +20,23 @@ describe('Common Protocol', () => { describe('#constructor', () => { it('should accept string as port', () => { - protocol = new AbstractWrapper('somewhere', { port: '443' }); + protocol = new KuzzleAbstractProtocol('somewhere', { port: '443' }); should(protocol.port).be.eql(443); }); it('should use 7512 when no port is given or when port is not a parseable number', () => { - protocol = new AbstractWrapper('somewhere', { port: 'foobar' }); + protocol = new KuzzleAbstractProtocol('somewhere', { port: 'foobar' }); should(protocol.port).be.eql(7512); - protocol = new AbstractWrapper('somewhere'); + protocol = new KuzzleAbstractProtocol('somewhere'); should(protocol.port).be.eql(7512); }); it('should accept number as port', () => { - protocol = new AbstractWrapper('somewhere', { port: 443 }); + protocol = new KuzzleAbstractProtocol('somewhere', { port: 443 }); should(protocol.port).be.eql(443); }); diff --git a/test/protocol/Http.test.js b/test/protocol/Http.test.js index 067a6e8b7..d435a1b1b 100644 --- a/test/protocol/Http.test.js +++ b/test/protocol/Http.test.js @@ -1,9 +1,9 @@ -const - proxyquire = require('proxyquire'), - should = require('should'), - sinon = require('sinon'), - staticHttpRoutes = require('../../src/protocols/routes.json'), - Http = require('../../src/protocols/Http'); +const proxyquire = require('proxyquire'); +const should = require('should'); +const sinon = require('sinon'); + +const staticHttpRoutes = require('../../src/protocols/routes.json'); +const Http = require('../../src/protocols/Http'); describe('HTTP networking module', () => { let protocol; @@ -216,24 +216,29 @@ describe('HTTP networking module', () => { }; protocol.on('requestId', () => { - should(protocol._sendHttpRequest).be.calledOnce(); + try { + should(protocol._sendHttpRequest).be.calledOnce(); - should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('VERB'); - should(protocol._sendHttpRequest.firstCall.args[1]).be.equal('/foo/bar'); - should(protocol._sendHttpRequest.firstCall.args[2]).match({ - requestId: 'requestId', - headers: { - 'Content-Type': 'application/json' - }, - controller: 'foo', - action: 'bar', - index: 'index', - collection: 'collection', - meta: 'meta', - body: JSON.stringify({foo: 'bar'}) - }); + should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('VERB'); + should(protocol._sendHttpRequest.firstCall.args[1]).be.equal('/foo/bar'); + should(protocol._sendHttpRequest.firstCall.args[2]).match({ + requestId: 'requestId', + headers: { + 'Content-Type': 'application/json' + }, + controller: 'foo', + action: 'bar', + index: 'index', + collection: 'collection', + meta: 'meta', + body: JSON.stringify({foo: 'bar'}) + }); - done(); + done(); + } + catch (e) { + done(e); + } }); protocol.send(data); @@ -248,20 +253,25 @@ describe('HTTP networking module', () => { }; protocol.on('requestId', () => { - should(protocol._sendHttpRequest).be.calledOnce(); + try { + should(protocol._sendHttpRequest).be.calledOnce(); - should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('VERB'); - should(protocol._sendHttpRequest.firstCall.args[1]).be.equal('/foo/bar'); - should(protocol._sendHttpRequest.firstCall.args[2]).match({ - requestId: 'requestId', - headers: { - authorization: 'Bearer fake-jwt' - }, - controller: 'foo', - action: 'bar' - }); + should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('VERB'); + should(protocol._sendHttpRequest.firstCall.args[1]).be.equal('/foo/bar'); + should(protocol._sendHttpRequest.firstCall.args[2]).match({ + requestId: 'requestId', + headers: { + authorization: 'Bearer fake-jwt' + }, + controller: 'foo', + action: 'bar' + }); - done(); + done(); + } + catch (e) { + done(e); + } }); protocol.send(data); @@ -278,20 +288,25 @@ describe('HTTP networking module', () => { }; protocol.on('requestId', () => { - should(protocol._sendHttpRequest).be.calledOnce(); + try { + should(protocol._sendHttpRequest).be.calledOnce(); - should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('VERB'); - should(protocol._sendHttpRequest.firstCall.args[1]).be.equal('/foo/bar'); - should(protocol._sendHttpRequest.firstCall.args[2]).match({ - requestId: 'requestId', - headers: { - 'x-kuzzle-volatile': '{"some":"volatile-data"}' - }, - controller: 'foo', - action: 'bar' - }); + should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('VERB'); + should(protocol._sendHttpRequest.firstCall.args[1]).be.equal('/foo/bar'); + should(protocol._sendHttpRequest.firstCall.args[2]).match({ + requestId: 'requestId', + headers: { + 'x-kuzzle-volatile': '{"some":"volatile-data"}' + }, + controller: 'foo', + action: 'bar' + }); - done(); + done(); + } + catch (e) { + done(e); + } }); protocol.send(data); @@ -310,7 +325,31 @@ describe('HTTP networking module', () => { should(protocol._sendHttpRequest).be.calledOnce(); should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('GET'); should(protocol._sendHttpRequest.firstCall.args[1]) - .be.equal('/foo?foo=bar&baz=oh,an,array'); + .be.equal(`/foo?foo=bar&baz=${encodeURIComponent('oh,an,array')}`); + done(); + } + catch (error) { + done(error); + } + }); + + protocol.send(data); + }); + + it('should inject the nested body object as querystring on a GET request', done => { + const data = { + requestId: 'requestId', + action: 'action', + controller: 'getreq', + body: { foo: { foofoo: { barbar: 'bar' } }, '&baz': ['oh', 'an', 'array'] } + }; + + protocol.on('requestId', () => { + try { + should(protocol._sendHttpRequest).be.calledOnce(); + should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('GET'); + should(protocol._sendHttpRequest.firstCall.args[1]) + .be.equal(`/foo?foo=${encodeURIComponent('{"foofoo":{"barbar":"bar"}}')}&${encodeURIComponent('&baz')}=${encodeURIComponent('oh,an,array')}`); done(); } catch (error) { @@ -326,14 +365,15 @@ describe('HTTP networking module', () => { requestId: 'requestId', action: 'bar', controller: 'foo', - foo: 'bar' + 'foo?lol': 'bar&baz' }; protocol.on('requestId', () => { should(protocol._sendHttpRequest).be.calledOnce(); should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('VERB'); - should(protocol._sendHttpRequest.firstCall.args[1]).be.equal('/foo/bar?foo=bar'); + should(protocol._sendHttpRequest.firstCall.args[1]) + .be.equal(`/foo/bar?${encodeURIComponent('foo?lol')}=${encodeURIComponent('bar&baz')}`); done(); }); @@ -346,7 +386,7 @@ describe('HTTP networking module', () => { requestId: 'requestId', controller: 'foo', action: 'bar', - foo: 'baz' + foo: 'baz&qux' }; protocol._routes = { foo: {bar: {verb: 'VERB', url: '/foo/bar/:foo'}} @@ -356,7 +396,8 @@ describe('HTTP networking module', () => { should(protocol._sendHttpRequest).be.calledOnce(); should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('VERB'); - should(protocol._sendHttpRequest.firstCall.args[1]).be.equal('/foo/bar/baz'); + should(protocol._sendHttpRequest.firstCall.args[1]) + .be.equal(`/foo/bar/${encodeURIComponent('baz&qux')}`); done(); }); @@ -446,7 +487,7 @@ describe('HTTP networking module', () => { should(protocol._sendHttpRequest).be.calledOnce(); should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('VERB'); should(protocol._sendHttpRequest.firstCall.args[1]) - .be.equal('/foo/bar?foo=bar,baz,qux&qux=123'); + .be.equal(`/foo/bar?foo=${encodeURIComponent('bar,baz,qux')}&qux=123`); } catch (error) { return done(error); @@ -464,7 +505,7 @@ describe('HTTP networking module', () => { action: 'bar', controller: 'foo', foo: false, - bar: true, + '?bar': true, qux: 123 }; @@ -473,7 +514,7 @@ describe('HTTP networking module', () => { should(protocol._sendHttpRequest).be.calledOnce(); should(protocol._sendHttpRequest.firstCall.args[0]).be.equal('VERB'); should(protocol._sendHttpRequest.firstCall.args[1]) - .be.equal('/foo/bar?bar&qux=123'); + .be.equal(`/foo/bar?${encodeURIComponent('?bar')}&qux=123`); } catch (error) { return done(error); diff --git a/test/utils/proxify.test.js b/test/utils/proxify.test.js index 70916f0d6..7ac5f8629 100644 --- a/test/utils/proxify.test.js +++ b/test/utils/proxify.test.js @@ -1,7 +1,7 @@ const should = require('should'), sinon = require('sinon'), - proxify = require('../../src/utils/proxify'); + { proxify } = require('../../src/utils/proxify'); describe('proxify', () => { let diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..1ea049850 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "declaration": true, + "listEmittedFiles": true, + "module": "commonjs", + "target": "es2020", + "moduleResolution": "node", + "sourceMap": true, + "baseUrl": ".", + "resolveJsonModule": true + }, + "rootDir": "src/", + "include": [ + "index.ts", + "src/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index ddca56227..6c4e33c46 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -27,11 +27,6 @@ module.exports = { use: { loader: 'babel-loader' } - }, - { - test: /\.?js$/, - exclude: /node_modules/, - loader: 'eslint-loader' } ] },