From 43a89ec4f242b26b8ba4864d580518df1eca38b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wieland=20Sch=C3=B6bl?= Date: Fri, 3 Sep 2021 15:17:15 +0000 Subject: [PATCH] refactor: use core supplied mappings --- README.md | 38 +- config/elasticsearch-b-tu.ts | 2 +- config/elasticsearch.ts | 2 +- integration-test.yml | 3 +- package-lock.json | 1760 ++++++++++------- package.json | 33 +- src/routes/route.ts | 2 +- src/storage/elasticsearch/aggregations.ts | 31 +- src/storage/elasticsearch/elasticsearch.ts | 52 +- src/storage/elasticsearch/query.ts | 2 +- .../elasticsearch/templates/.gitignore | 2 - src/storage/elasticsearch/templating.ts | 84 +- .../{common.ts => types/elasticsearch.ts} | 58 +- src/storage/elasticsearch/types/guards.ts | 64 + test/routes/bulk-route.spec.ts | 2 +- test/routes/thing-update-route.spec.ts | 2 +- .../elasticsearch/aggregations.spec.ts | 123 +- test/storage/elasticsearch/common.spec.ts | 14 +- .../elasticsearch/elasticsearch.spec.ts | 889 +++++---- test/storage/elasticsearch/monitoring.spec.ts | 2 - test/storage/elasticsearch/query.spec.ts | 18 +- test/storage/elasticsearch/templating.spec.ts | 201 -- 22 files changed, 1622 insertions(+), 1762 deletions(-) delete mode 100644 src/storage/elasticsearch/templates/.gitignore rename src/storage/elasticsearch/{common.ts => types/elasticsearch.ts} (86%) create mode 100644 src/storage/elasticsearch/types/guards.ts delete mode 100644 test/storage/elasticsearch/templating.spec.ts diff --git a/README.md b/README.md index c5a2c120..7eb06383 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,10 @@ This project is a reference implementation for a StApps backend. It provides an perform full text search, sorts and filters. It also delivers the configuration needed by the app. The API is specified within the [@openstapps/core](https://gitlab.com/openstapps/core). -If you want to perform requests, index data or search within JavaScript or TypeScript you should consider using -[@openstapps/api](https://gitlab.com/openstapps/api) +If you want to perform requests, index data or search within JavaScript or TypeScript you should consider using our client +[@openstapps/api](https://gitlab.com/openstapps/api). + +Or generate your own client using the openapi/swagger definitions you can get form the [API documentation](https://openstapps.gitlab.io/backend). # Usage This backend is not a standalone software. It needs a database like Elasticsearch to work. @@ -16,38 +18,15 @@ you with everything you need to run this backend. # Local usage for development purposes ## Requirements -* Elasticsearch (5.5) -* Node.js (~10) / NPM +* Elasticsearch (5.6) +* Node.js (~14) / NPM * Docker -## Generating Elasticsearch Mapping -The mappings will be generated automatically on the first start. If there are any errors, the backend will inform you and stop -the execution, however it will do its best to complete the mappings. You can then either resolve these errors in the `core-tools` or the `core`, depending on where it originated. -If you need a quick solution, you can also take the generated output file and manually correct the errors, then rename it to `[coreVersion]_template_[type].json` (replace any spaces with a `_`) -and restart the backend (make sure that you don't have `ES_FORCE_MAPPING_UPDATE` set to `true`). This time it will take your file. *The filenames and the path will also be displayed in the log of the backend.* - -### Manually Resolving Errors -There are multiple types of errors the backend can run into. Manual error resolving requires you to be familiar with Elasticsearch -mappings. -An error will be represented in the output through an Elasticsearch type written in CAPS. Refer to either the console output -or the `[coreVersion]_error_report.txt` for more info. If you feel lucky you can try to replace every error (`"type": "MISSING_PREMAP"`, -`"type": "PARSE_ERROR"`, `"type": "TYPE_CONFLICT"`) with -```json -"dynamic": true, -"properties": {} -``` -This should ONLY be used as a temporary workaround and might compromise other features. - ### Startup Behaviour + *This might be important if you work on the Core* -The backend is using the `core-tools` to automatically generate Elasticsearch Mappings and Aggregations from the current `core` version. - -By default, the backend creates a local copy of the generated mappings and aggregations in `src/storage/elasticsearch/templates/[coreVersion]_template_[type].json` and `src/storage/elasticsearch/templates/[coreVersion]_aggregations.json`. -On each start, it first checks if the aggregation file exists, this is because it does not know which of the types actually exist for the current core version. If the file does exist, it will just use the existing files and *not* generate a new mapping to cut down the time -it takes to start the backend. When you are working on the Core, you might not want to have this behaviour, you can then either delete -the generated file at each start or run the backend with the environment variable `ES_FORCE_MAPPING_UPDATE=true`. This will cause it to generate the mapping -each time starts regardless of whether there are already files there. +The backend is using Elasticsearch Mappings and Aggregations from its currently used `core` dependency. ## Start Database (Elasticsearch) Elasticsearch needs some configuration and plugins to be able to work @@ -95,7 +74,6 @@ The list of environment variables includes: * `NODE_ENV` when set to `production`, there will be a reduced amount of output from the logger * `PORT` when this is not set, the backend will default to port 3000 * `ES_ADDR` the Elasticsearch address, if not set it will default the Elasticsearch address to `http://localhost:9200` -* `ES_FORCE_MAPPING_UPDATE` when this variable is set to `true`, the backend will always generate a new Elasticsearch mapping from the core regardless of whether there is already a version present. This should only really be used when you are working on the core. * `ALLOW_NO_TRANSPORT` if set to true, the backend will allow starting without an Email configured that receives critical errors. * `ES_DEBUG` setting this to `true` will result in Elasticsearch logging to be **VERY** extensive, in almost all situation this should no be enabled. * `PROMETHEUS_MIDDLEWARE` if set to `true` will enable metrics collection with [Express Prometheus Middleware](https://www.npmjs.com/package/express-prometheus-middleware) diff --git a/config/elasticsearch-b-tu.ts b/config/elasticsearch-b-tu.ts index c356c27d..eb30ad3b 100644 --- a/config/elasticsearch-b-tu.ts +++ b/config/elasticsearch-b-tu.ts @@ -1,7 +1,7 @@ // tslint:disable:no-default-export // tslint:disable:no-magic-numbers import {RecursivePartial} from '@openstapps/logger/lib/common'; -import {ElasticsearchConfigFile} from '../src/storage/elasticsearch/common'; +import {ElasticsearchConfigFile} from '../src/storage/elasticsearch/types/elasticsearch'; /** * This is the database configuration for the technical university of berlin diff --git a/config/elasticsearch.ts b/config/elasticsearch.ts index 27d0d6d5..cd07f20c 100644 --- a/config/elasticsearch.ts +++ b/config/elasticsearch.ts @@ -1,6 +1,6 @@ // tslint:disable:no-default-export // tslint:disable:no-magic-numbers -import {ElasticsearchConfigFile} from '../src/storage/elasticsearch/common'; +import {ElasticsearchConfigFile} from '../src/storage/elasticsearch/types/elasticsearch'; /** * This is the default configuration for elasticsearch (a database) diff --git a/integration-test.yml b/integration-test.yml index 1821e5a3..7c2a6930 100644 --- a/integration-test.yml +++ b/integration-test.yml @@ -10,7 +10,6 @@ services: NODE_CONFIG_ENV: "elasticsearch" NODE_ENV: "integration-test" ALLOW_NO_TRANSPORT: "true" - ES_FORCE_MAPPING_UPDATE: "true" ES_ADDR: "http://elasticsearch:9200" elasticsearch: @@ -25,4 +24,4 @@ services: STAPPS_EXIT_LEVEL: "8" volumes: - ./node_modules/@openstapps/core/test/resources:/@openstapps/core/test/resources:ro - command: e2e http://backend:3000 --waiton tcp:backend:3000 --samples /@openstapps/core/test/resources + command: e2e http://backend:3000 --waiton tcp:backend:3000 --samples /@openstapps/core/test/resources/indexable diff --git a/package-lock.json b/package-lock.json index 614a70f0..18bf6866 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,26 +13,26 @@ } }, "@babel/compat-data": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.9.tgz", - "integrity": "sha512-p3QjZmMGHDGdpcwEYYWu7i7oJShJvtgMjJeb0W95PPhSm++3lm8YXYOh45Y6iCN9PkZLTZ7CIX5nFrp7pw7TXw==", + "version": "7.15.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", + "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", "dev": true }, "@babel/core": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.8.tgz", - "integrity": "sha512-/AtaeEhT6ErpDhInbXmjHcUQXH0L0TEgscfcxk1qbOvLuKCa5aZT0SOOtDKFY96/CLROwbLSKyFor6idgNaU4Q==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.4.tgz", + "integrity": "sha512-Lkcv9I4a8bgUI8LJOLM6IKv6hnz1KOju6KM1lceqVMKlKKqNRopYd2Pc9MgIurqvMJ6BooemrnJz8jlIiQIpsA==", "dev": true, "requires": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.14.8", - "@babel/helper-compilation-targets": "^7.14.5", - "@babel/helper-module-transforms": "^7.14.8", - "@babel/helpers": "^7.14.8", - "@babel/parser": "^7.14.8", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8", + "@babel/generator": "^7.15.4", + "@babel/helper-compilation-targets": "^7.15.4", + "@babel/helper-module-transforms": "^7.15.4", + "@babel/helpers": "^7.15.4", + "@babel/parser": "^7.15.4", + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -56,12 +56,12 @@ } }, "@babel/generator": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.9.tgz", - "integrity": "sha512-4yoHbhDYzFa0GLfCzLp5GxH7vPPMAHdZjyE7M/OajM9037zhx0rf+iNsJwp4PT0MSFpwjG7BsHEbPkBQpZ6cYA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.4.tgz", + "integrity": "sha512-d3itta0tu+UayjEORPNz6e1T3FtvWlP5N4V5M+lhp/CxT4oAA7/NcScnpRyspUMLK6tu9MNHmQHxRykuN2R7hw==", "dev": true, "requires": { - "@babel/types": "^7.14.9", + "@babel/types": "^7.15.4", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -75,12 +75,12 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", - "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", + "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", "dev": true, "requires": { - "@babel/compat-data": "^7.14.5", + "@babel/compat-data": "^7.15.0", "@babel/helper-validator-option": "^7.14.5", "browserslist": "^4.16.6", "semver": "^6.3.0" @@ -95,105 +95,105 @@ } }, "@babel/helper-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", - "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", + "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.14.5", - "@babel/template": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/helper-get-function-arity": "^7.15.4", + "@babel/template": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/helper-get-function-arity": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", - "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", + "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-hoist-variables": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", - "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", + "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.14.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz", - "integrity": "sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", + "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-module-imports": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", - "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", + "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-module-transforms": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.8.tgz", - "integrity": "sha512-RyE+NFOjXn5A9YU1dkpeBaduagTlZ0+fccnIcAGbv1KGUlReBj7utF7oEth8IdIBQPcux0DDgW5MFBH2xu9KcA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.4.tgz", + "integrity": "sha512-9fHHSGE9zTC++KuXLZcB5FKgvlV83Ox+NLUmQTawovwlJ85+QMhk1CnVk406CQVj97LaWod6KVjl2Sfgw9Aktw==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.14.5", - "@babel/helper-simple-access": "^7.14.8", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.8", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8" + "@babel/helper-module-imports": "^7.15.4", + "@babel/helper-replace-supers": "^7.15.4", + "@babel/helper-simple-access": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/helper-validator-identifier": "^7.14.9", + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/helper-optimise-call-expression": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", - "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", + "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-replace-supers": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", - "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", + "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.14.5", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/traverse": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/helper-member-expression-to-functions": "^7.15.4", + "@babel/helper-optimise-call-expression": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/helper-simple-access": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz", - "integrity": "sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", + "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", "dev": true, "requires": { - "@babel/types": "^7.14.8" + "@babel/types": "^7.15.4" } }, "@babel/helper-split-export-declaration": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", - "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", + "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", "dev": true, "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.15.4" } }, "@babel/helper-validator-identifier": { @@ -208,14 +208,14 @@ "dev": true }, "@babel/helpers": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.8.tgz", - "integrity": "sha512-ZRDmI56pnV+p1dH6d+UN6GINGz7Krps3+270qqI9UJ4wxYThfAIcI5i7j5vXC4FJ3Wap+S9qcebxeYiqn87DZw==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", + "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", "dev": true, "requires": { - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8" + "@babel/template": "^7.15.4", + "@babel/traverse": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/highlight": { @@ -275,57 +275,78 @@ } }, "@babel/parser": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.9.tgz", - "integrity": "sha512-RdUTOseXJ8POjjOeEBEvNMIZU/nm4yu2rufRkcibzkkg7DmQvXU8v3M4Xk9G7uuI86CDGkKcuDWgioqZm+mScQ==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.4.tgz", + "integrity": "sha512-xmzz+7fRpjrvDUj+GV7zfz/R3gSK2cOxGlazaXooxspCr539cbTXJKvBJzSVI2pPhcRGquoOtaIkKCsHQUiO3w==", "dev": true }, "@babel/runtime": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.8.tgz", - "integrity": "sha512-twj3L8Og5SaCRCErB4x4ajbvBIVV77CGeFglHpeg5WC5FF8TZzBWXtTJ4MqaD9QszLYTtr+IsaAL2rEUevb+eg==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz", + "integrity": "sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==", "requires": { "regenerator-runtime": "^0.13.4" } }, "@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", + "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", "dev": true, "requires": { "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4" } }, "@babel/traverse": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.9.tgz", - "integrity": "sha512-bldh6dtB49L8q9bUyB7bC20UKgU+EFDwKJylwl234Kv+ySZeMD31Xeht6URyueQ6LrRRpF2tmkfcZooZR9/e8g==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", + "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", "dev": true, "requires": { "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.14.9", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-hoist-variables": "^7.14.5", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.14.9", - "@babel/types": "^7.14.9", + "@babel/generator": "^7.15.4", + "@babel/helper-function-name": "^7.15.4", + "@babel/helper-hoist-variables": "^7.15.4", + "@babel/helper-split-export-declaration": "^7.15.4", + "@babel/parser": "^7.15.4", + "@babel/types": "^7.15.4", "debug": "^4.1.0", "globals": "^11.1.0" + }, + "dependencies": { + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } } }, "@babel/types": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.9.tgz", - "integrity": "sha512-u0bLTnv3DFHeaQLYzb7oRJ1JHr1sv/SYDM7JSqHFFLwXG1wTZRughxFI5NCP8qBEo1rVVsn7Yg2Lvw49nne/Ow==", + "version": "7.15.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.4.tgz", + "integrity": "sha512-0f1HJFuGmmbrKTCZtbm3cU+b/AqdEYk5toj5iQur58xkVMlS0JWaKxTBSmCXd47uiN7vbcozAupm6Mvs80GNhw==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.9", "to-fast-properties": "^2.0.0" } }, + "@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==" + }, + "@cspotcode/source-map-support": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz", + "integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==", + "requires": { + "@cspotcode/source-map-consumer": "0.8.0" + } + }, "@elastic/elasticsearch": { "version": "5.6.22", "resolved": "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-5.6.22.tgz", @@ -340,6 +361,44 @@ "secure-json-parse": "^2.1.0" } }, + "@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + } + } + }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==" + }, "@hutson/parse-repository-url": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", @@ -357,6 +416,14 @@ "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + } } }, "@istanbuljs/schema": { @@ -365,11 +432,6 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, - "@krlwlfrt/async-pool": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@krlwlfrt/async-pool/-/async-pool-0.5.0.tgz", - "integrity": "sha512-ZwdRzVEQ89zKVsXFyM6mPwJ5NwaPwvGB5rN5VyJ7SFKBPtjZhzY2VBHLszdKC7f1lFvCXISDace6SE+O/M+4eg==" - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -416,24 +478,43 @@ "integrity": "sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw==", "dev": true }, + "chalk": { + "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", + "supports-color": "^7.1.0" + } + }, "commander": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", "dev": true + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } } } }, "@openstapps/core": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@openstapps/core/-/core-0.48.0.tgz", - "integrity": "sha512-HJVRPSDwk1Enw4pQ03jvzK5xotsdyrJstXWo8L3Q8qSeH5vkEjzZ56ohuG5Axa7kZsQkWcLkRNBdRGYzKt0/ew==", + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@openstapps/core/-/core-0.50.0.tgz", + "integrity": "sha512-0g2YQF6j9j9Mhqsc6HkD+EbkGvjoXI9Q3+1U+B3FdSxE23ubA6Fp/DM17uN5/OvXrygjNXnU6oehwW80iKXVJw==", "requires": { - "@openstapps/core-tools": "0.21.0", + "@openstapps/core-tools": "0.25.0", "@types/geojson": "1.0.6", "@types/json-patch": "0.0.30", - "@types/json-schema": "7.0.7", - "@types/node": "14.17.4", + "@types/json-schema": "7.0.9", + "@types/node": "14.17.9", "fast-clone": "1.5.13", "fast-deep-equal": "3.1.3", "http-status-codes": "2.1.4", @@ -442,190 +523,92 @@ "ts-optchain": "0.1.8" }, "dependencies": { - "@openstapps/core-tools": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@openstapps/core-tools/-/core-tools-0.21.0.tgz", - "integrity": "sha512-8zJfuGImeAjqUddYVxRD1mgqpVsmn8k5ZiEeDX0JW1q590OCbAZsoTiaLPtfHjUK4bu2hoNkaPs5cyYTAxD8Ew==", - "requires": { - "@krlwlfrt/async-pool": "0.5.0", - "@openstapps/logger": "0.6.0", - "@types/glob": "7.1.3", - "@types/json-schema": "7.0.7", - "@types/mustache": "4.1.1", - "@types/node": "14.14.41", - "ajv": "6.12.6", - "better-ajv-errors": "0.7.0", - "chai": "4.3.4", - "commander": "7.2.0", - "deepmerge": "4.2.2", - "del": "6.0.0", - "flatted": "3.1.1", - "glob": "7.1.6", - "got": "11.8.2", - "humanize-string": "2.1.0", - "json-schema": "0.3.0", - "mustache": "4.2.0", - "plantuml-encoder": "1.4.0", - "toposort": "2.0.2", - "ts-json-schema-generator": "0.70.2", - "ts-node": "9.1.1", - "typedoc": "0.18.0", - "typescript": "3.8.3" - }, - "dependencies": { - "@types/node": { - "version": "14.14.41", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.41.tgz", - "integrity": "sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g==" - } - } - }, - "@openstapps/logger": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@openstapps/logger/-/logger-0.6.0.tgz", - "integrity": "sha512-l/ILWPOSxhawcdDxn9vkdzib4xlRTnFmG4YygX8l8z0m9cocitMMZGw/DquZ0x6zGt2suOwSVRckYiSlk/6Erw==", - "requires": { - "@types/node": "14.14.37", - "@types/nodemailer": "6.4.1", - "chalk": "4.1.0", - "flatted": "3.1.1", - "moment": "2.29.1", - "nodemailer": "6.5.0" - }, - "dependencies": { - "@types/node": { - "version": "14.14.37", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.37.tgz", - "integrity": "sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw==" - } - } - }, "@types/node": { - "version": "14.17.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz", - "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==" - }, - "@types/nodemailer": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.1.tgz", - "integrity": "sha512-8081UY/0XTTDpuGqCnDc8IY+Q3DSg604wB3dBH0CaZlj4nZWHWuxtZ3NRZ9c9WUrz1Vfm6wioAUnqL3bsh49uQ==", - "requires": { - "@types/node": "*" - } - }, - "nodemailer": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.5.0.tgz", - "integrity": "sha512-Tm4RPrrIZbnqDKAvX+/4M+zovEReiKlEXWDzG4iwtpL9X34MJY+D5LnQPH/+eghe8DLlAVshHAJZAZWBGhkguw==" + "version": "14.17.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.9.tgz", + "integrity": "sha512-CMjgRNsks27IDwI785YMY0KLt3co/c0cQ5foxHYv/shC2w8oOnVwz5Ubq1QG5KzrcW+AXk6gzdnxIkDnTvzu3g==" } } }, "@openstapps/core-tools": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/@openstapps/core-tools/-/core-tools-0.23.2.tgz", - "integrity": "sha512-h/J+i22FsTxnOYndYntRYKHpprX63dub/7gFDAQokC06rH6oKJSqhReXM8xxNQa6DFhbNEq79U+GaqlQcWW98w==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@openstapps/core-tools/-/core-tools-0.25.0.tgz", + "integrity": "sha512-tluVrUnoKScpCszs9WQXioG6zLmkkFQRoeNgWDmKDIU+vIZDoxOYedHrzpxk0a0x+GBWetgnqEX69HIz9ZOzkA==", "requires": { - "@krlwlfrt/async-pool": "0.6.0", "@openstapps/logger": "0.7.0", - "@types/fs-extra": "9.0.12", - "@types/glob": "7.1.4", - "@types/json-schema": "7.0.8", - "@types/mustache": "4.1.2", - "@types/node": "14.17.5", "ajv": "6.12.6", "better-ajv-errors": "0.7.0", "chai": "4.3.4", - "commander": "7.2.0", + "commander": "8.1.0", "deepmerge": "4.2.2", "del": "6.0.0", - "flatted": "3.2.1", + "eslint": "7.32.0", + "flatted": "3.2.2", "fs-extra": "10.0.0", "glob": "7.1.7", "got": "11.8.2", "humanize-string": "2.1.0", "json-schema": "0.3.0", + "lodash": "4.17.21", "mustache": "4.2.0", - "openapi-types": "9.1.0", + "openapi-types": "9.2.0", "plantuml-encoder": "1.4.0", "toposort": "2.0.2", - "ts-json-schema-generator": "0.70.2", - "ts-node": "10.1.0", + "ts-json-schema-generator": "0.95.0", + "ts-node": "10.2.1", + "typescript": "4.4.2" + }, + "dependencies": { + "typescript": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.2.tgz", + "integrity": "sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ==" + } + } + }, + "@openstapps/es-mapping-generator": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@openstapps/es-mapping-generator/-/es-mapping-generator-0.0.3.tgz", + "integrity": "sha512-zs30bGv00GtXvYeYgOxOyaIe43pHeb568qw/vE8wpJMS6Vqvf4e1DjwCMgHcxkFfBWhkh35+Chi9JvsZslG3jA==", + "dev": true, + "requires": { + "@openstapps/logger": "0.7.0", + "commander": "8.1.0", + "deepmerge": "4.2.2", + "flatted": "3.2.2", + "got": "11.8.2", "typedoc": "0.18.0", "typescript": "3.8.3" }, "dependencies": { - "@krlwlfrt/async-pool": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@krlwlfrt/async-pool/-/async-pool-0.6.0.tgz", - "integrity": "sha512-xP4sfGMDUU+sb+m6swwO7Wr8MGRzJyd7IuUFQpC/Qqq30IoMeP7YtHmC/C235kIWZhQVtrcmuVgDY9pXuKueEw==" - }, - "@types/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==", - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/json-schema": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz", - "integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==" - }, - "@types/mustache": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@types/mustache/-/mustache-4.1.2.tgz", - "integrity": "sha512-c4OVMMcyodKQ9dpwBwh3ofK9P6U9ZktKU9S+p33UqwMNN1vlv2P0zJZUScTshnx7OEoIIRcCFNQ904sYxZz8kg==" - }, - "@types/node": { - "version": "14.17.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.5.tgz", - "integrity": "sha512-bjqH2cX/O33jXT/UmReo2pM7DIJREPMnarixbQ57DOOzzFaI6D2+IcwaJQaJpv0M1E9TIhPCYVxrkcityLjlqA==" - }, - "flatted": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.1.tgz", - "integrity": "sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg==" - }, "fs-extra": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", - "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, "requires": { + "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "typedoc": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.18.0.tgz", + "integrity": "sha512-UgDQwapCGQCCdYhEQzQ+kGutmcedklilgUGf62Vw6RdI29u6FcfAXFQfRTiJEbf16aK3YnkB20ctQK1JusCRbA==", + "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" - } - }, - "ts-node": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.1.0.tgz", - "integrity": "sha512-6szn3+J9WyG2hE+5W8e0ruZrzyk1uFLYye6IGMBadnOzDh8aP7t8CbFpsfCiEx2+wMixAhjFt7lOZC4+l+WbEA==", - "requires": { - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" + "fs-extra": "^9.0.1", + "handlebars": "^4.7.6", + "highlight.js": "^10.0.0", + "lodash": "^4.17.15", + "lunr": "^2.3.8", + "marked": "^1.1.1", + "minimatch": "^3.0.0", + "progress": "^2.0.3", + "shelljs": "^0.8.4", + "typedoc-default-themes": "^0.10.2" } } } @@ -656,14 +639,10 @@ "@types/node": "*" } }, - "chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } + "flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==" }, "nodemailer": { "version": "6.6.0", @@ -696,9 +675,9 @@ } }, "@sinonjs/samsam": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", - "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-6.0.2.tgz", + "integrity": "sha512-jxPRPp9n93ci7b8hMfJOFDPRLFYadN6FSpeROFTR4UNF4i5b+EK6m4QXPO46BDhFgRy1JuS87zAnFOzCUwMJcQ==", "dev": true, "requires": { "@sinonjs/commons": "^1.6.0", @@ -851,28 +830,11 @@ "@types/range-parser": "*" } }, - "@types/fs-extra": { - "version": "9.0.12", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.12.tgz", - "integrity": "sha512-I+bsBr67CurCGnSenZZ7v94gd3tc3+Aj2taxMT4yu4ABLuOgOjeFxX3dokG24ztSRg5tnT00sL8BszO7gSMoIw==", - "requires": { - "@types/node": "*" - } - }, "@types/geojson": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-1.0.6.tgz", "integrity": "sha512-Xqg/lIZMrUd0VRmSRbCAewtwGZiAk3mEUDvV4op1tGl+LvyPcb/MIOSxTl9z+9+J+R4/vpjiCAT4xeKzH9ji1w==" }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, "@types/http-cache-semantics": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", @@ -884,9 +846,9 @@ "integrity": "sha512-MhCUjojzDhVLnZnxwPwa+rETFRDQ0ffjxYdrqOP6TBO2O0/Z64PV5tNeYApo4bc4y4frbWOrRwv/eEkXlI13Rw==" }, "@types/json-schema": { - "version": "7.0.7", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", - "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==" + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==" }, "@types/keyv": { "version": "3.1.2", @@ -901,11 +863,6 @@ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, - "@types/minimatch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", - "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==" - }, "@types/minimist": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", @@ -913,9 +870,9 @@ "dev": true }, "@types/mocha": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz", - "integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.0.0.tgz", + "integrity": "sha512-scN0hAWyLVAvLR9AyW7HoFF5sJZglyBsbPuHO4fv7JRvfmPBMfp1ozWqOf/e4wwPNxezBZXRfWzMb6iFLgEVRA==", "dev": true }, "@types/morgan": { @@ -927,15 +884,10 @@ "@types/node": "*" } }, - "@types/mustache": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@types/mustache/-/mustache-4.1.1.tgz", - "integrity": "sha512-Sm0NWeLhS2QL7NNGsXvO+Fgp7e3JLHCO6RS3RCnfjAnkw6Y1bsji/AGfISdQZDIR/AeOyzkrxRk9jBkl55zdJw==" - }, "@types/node": { - "version": "14.17.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.7.tgz", - "integrity": "sha512-SYTdMaW47se8499q8m0fYKZZRlmq0RaRv6oYmlVm6DUm31l0fhOl1D03X8hGxohCKTI2Bg6w7W0TiYB51aJzag==" + "version": "14.17.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.12.tgz", + "integrity": "sha512-vhUqgjJR1qxwTWV5Ps5txuy2XMdf7Fw+OrdChRboy8BmWUPkckOhphaohzFG6b8DW7CrxaBMdrdJ47SYFq1okw==" }, "@types/node-cron": { "version": "2.0.4", @@ -1084,6 +1036,21 @@ "negotiator": "0.6.2" } }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==" + }, + "acorn-walk": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz", + "integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==" + }, "add-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", @@ -1113,14 +1080,12 @@ "ansi-colors": { "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 + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" }, "ansi-styles": { "version": "4.3.0", @@ -1164,7 +1129,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -1196,6 +1160,11 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1205,7 +1174,8 @@ "at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true }, "balanced-match": { "version": "1.0.2", @@ -1347,23 +1317,18 @@ "dev": true }, "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "4.16.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz", + "integrity": "sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001251", + "colorette": "^1.3.0", + "electron-to-chromium": "^1.3.811", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^1.1.75" } }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", @@ -1416,6 +1381,11 @@ "get-intrinsic": "^1.0.2" } }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -1442,9 +1412,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001248", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001248.tgz", - "integrity": "sha512-NwlQbJkxUFJ8nMErnGtT0QTM2TJ33xgz4KXJSMIrjXIbDVdaYueGyjOrLKRtJC+rTiWfi6j5cnZN1NBiSBJGNw==", + "version": "1.0.30001252", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001252.tgz", + "integrity": "sha512-I56jhWDGMtdILQORdusxBOH+Nl/KgQSdDmpJezYddnAkVOmnoU8zwjTV9xAjMIYxr0iPreEAVylCGcmHCjfaOw==", "dev": true }, "chai": { @@ -1470,9 +1440,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -1490,19 +1460,19 @@ "dev": true }, "chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", "dev": true, "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.3.1", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" } }, "clean-stack": { @@ -1519,40 +1489,6 @@ "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" - }, - "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 - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "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": "^5.0.0" - } - } } }, "clone": { @@ -1594,9 +1530,9 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", + "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", "dev": true }, "combined-stream": { @@ -1609,9 +1545,9 @@ } }, "commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==" + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.1.0.tgz", + "integrity": "sha512-mf45ldcuHSYShkplHHGKWb4TrmwQadxOn7v4WuhDJy0ZVoY5JFajaRDKD0PNe5qXzBX0rhovjTnP6Kz9LETcuA==" }, "commondir": { "version": "1.0.1", @@ -1882,14 +1818,14 @@ "dev": true }, "core-js": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.16.0.tgz", - "integrity": "sha512-5+5VxRFmSf97nM8Jr2wzOwLqRo6zphH2aX+7KsAUONObyzakDNq2G/bgbhinxB4PoV9L3aXQYhiDKyIKWd2c8g==" + "version": "3.17.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.17.2.tgz", + "integrity": "sha512-XkbXqhcXeMHPRk2ItS+zQYliAMilea2euoMsnpRRdDad6b2VY6CQQcwz1K8AnWesfw4p165RzY0bTnr3UrbYiA==" }, "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "cors": { "version": "2.8.5", @@ -1909,7 +1845,6 @@ "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", "shebang-command": "^2.0.0", @@ -1991,6 +1926,11 @@ "type-detect": "^4.0.0" } }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + }, "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", @@ -2063,21 +2003,11 @@ } }, "doctrine": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", - "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", - "dev": true, + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "requires": { - "esutils": "^1.1.6", - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } + "esutils": "^2.0.2" } }, "dot-prop": { @@ -2095,16 +2025,15 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.3.793", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.793.tgz", - "integrity": "sha512-l9NrGV6Mr4ov5mayYPvIWcwklNw5ROmy6rllzz9dCACw9nKE5y+s5uQk+CBJMetxrWZ6QJFsvEfG6WDcH2IGUg==", + "version": "1.3.828", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.828.tgz", + "integrity": "sha512-2kx537tLqIVfUpx7LRknZce5PcCyxyBB1YUVOhxlkrDoCqFITGJGYfBAvSxGOdqlp+R9pHeU9Ai/dsHgsqjrvQ==", "dev": true }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "encodeurl": { "version": "1.0.2", @@ -2119,6 +2048,14 @@ "once": "^1.4.0" } }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "requires": { + "ansi-colors": "^4.1.1" + } + }, "error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -2150,17 +2087,163 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "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==" + } + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "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==" + } + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==" }, "esutils": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", - "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", - "dev": true + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" }, "etag": { "version": "1.8.1", @@ -2266,6 +2349,11 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + }, "fast-safe-stringify": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.8.tgz", @@ -2273,13 +2361,21 @@ "dev": true }, "fastq": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.1.tgz", - "integrity": "sha512-HOnr8Mc60eNYl1gzwp6r5RoUyAn5/glBolUzP/Ez6IFVPMPirxn/9phgL6zhOtaTy7ISwPvQ+wT+hfcRZh/bzw==", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", + "integrity": "sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==", "requires": { "reusify": "^1.0.4" } }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "requires": { + "flat-cache": "^3.0.4" + } + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -2318,9 +2414,9 @@ } }, "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "requires": { "commondir": "^1.0.1", @@ -2344,10 +2440,19 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, "flatted": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", - "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==" + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==" }, "foreground-child": { "version": "2.0.0", @@ -2402,11 +2507,10 @@ "dev": true }, "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", "requires": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" @@ -2427,7 +2531,13 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "gc-stats": { "version": "1.4.0", @@ -3139,9 +3249,9 @@ } }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3160,10 +3270,12 @@ } }, "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", + "requires": { + "type-fest": "^0.20.2" + } }, "globby": { "version": "11.0.4", @@ -3212,9 +3324,9 @@ } }, "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==" + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, "grapheme-splitter": { "version": "1.0.4", @@ -3231,6 +3343,7 @@ "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, "requires": { "minimist": "^1.2.5", "neo-async": "^2.6.0", @@ -3249,6 +3362,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -3291,7 +3405,8 @@ "highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", - "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==" + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "dev": true }, "hosted-git-info": { "version": "4.0.2", @@ -3367,11 +3482,19 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==" }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "4.0.0", @@ -3401,7 +3524,8 @@ "interpret": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true }, "into-stream": { "version": "5.1.1", @@ -3433,9 +3557,10 @@ } }, "is-core-module": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", - "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", + "dev": true, "requires": { "has": "^1.0.3" } @@ -3446,10 +3571,9 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "is-glob": { "version": "4.0.1", @@ -3512,6 +3636,12 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", @@ -3526,8 +3656,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "istanbul-lib-coverage": { "version": "3.0.0", @@ -3637,7 +3766,6 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -3689,6 +3817,11 @@ "jsonify": "~0.0.0" } }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -3767,6 +3900,15 @@ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -3817,6 +3959,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, "lodash.flattendeep": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", @@ -3834,18 +3981,29 @@ "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, "lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=" + }, "log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, "requires": { - "chalk": "^4.0.0" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" } }, "lowercase-keys": { @@ -3857,7 +4015,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -3865,7 +4022,8 @@ "lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true }, "make-dir": { "version": "3.1.0", @@ -3898,7 +4056,8 @@ "marked": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.9.tgz", - "integrity": "sha512-H8lIX2SvyitGX+TRdtS06m1jHMijKN/XjfH6Ooii9fvxMlh8QdqBfBDkGUpMWH2kQNrtixjzYUa3SH8ROTgRRw==" + "integrity": "sha512-H8lIX2SvyitGX+TRdtS06m1jHMijKN/XjfH6Ooii9fvxMlh8QdqBfBDkGUpMWH2kQNrtixjzYUa3SH8ROTgRRw==", + "dev": true }, "media-typer": { "version": "0.3.0", @@ -3986,6 +4145,12 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true + }, + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true } } }, @@ -4076,33 +4241,33 @@ } }, "mocha": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", - "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.1.1.tgz", + "integrity": "sha512-0wE74YMgOkCgBUj8VyIDwmLUjTsS13WV1Pg7l0SHea2qzZzlq7MDnfbPsHKcELBRk3+izEVkRofjmClpycudCA==", "dev": true, "requires": { "@ungap/promise-all-settled": "1.1.2", "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.5.1", + "chokidar": "3.5.2", "debug": "4.3.1", "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.1.6", + "glob": "7.1.7", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", + "nanoid": "3.1.23", + "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", "which": "2.0.2", "wide-align": "1.1.3", - "workerpool": "6.1.0", + "workerpool": "6.1.5", "yargs": "16.2.0", "yargs-parser": "20.2.4", "yargs-unparser": "2.0.0" @@ -4154,9 +4319,9 @@ } }, "js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "requires": { "argparse": "^2.0.1" @@ -4280,17 +4445,22 @@ "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==" }, "nan": { - "version": "2.14.2", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", - "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", "optional": true }, "nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", "dev": true }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -4299,30 +4469,22 @@ "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true }, "nise": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", - "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.0.tgz", + "integrity": "sha512-W5WlHu+wvo3PaKLsJJkgPup2LrsXCcm7AWwyNZkUnn5rwPkuPBi3Iwk5SQtN0mv+K65k7nKKjwNQ30wg3wLAQQ==", "dev": true, "requires": { "@sinonjs/commons": "^1.7.0", - "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/fake-timers": "^7.0.4", "@sinonjs/text-encoding": "^0.7.1", "just-extend": "^4.0.2", "path-to-regexp": "^1.7.0" }, "dependencies": { - "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -4341,9 +4503,9 @@ } }, "nock": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.1.1.tgz", - "integrity": "sha512-YKTR9MjfK3kS9/l4nuTxyYm30cgOExRHzkLNhL8nhEUyU4f8Za/dRxOqjhVT1vGs0svWo3dDnJTUX1qxYeWy5w==", + "version": "13.1.3", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.1.3.tgz", + "integrity": "sha512-YKj0rKQWMGiiIO+Y65Ut8OEgYM3PplLU2+GAhnPmqZdBd6z5IskgdBqWmjzA6lH3RF0S2a3wiAlrMOF5Iv2Jeg==", "requires": { "debug": "^4.1.0", "json-stringify-safe": "^5.0.1", @@ -4377,9 +4539,9 @@ } }, "node-releases": { - "version": "1.1.73", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", - "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "version": "1.1.75", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", + "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", "dev": true }, "nodemailer": { @@ -4388,13 +4550,13 @@ "integrity": "sha512-faZFufgTMrphYoDjvyVpbpJcYzwyFnbAMmQtj1lVBYAUSm3SOy2fIdd9+Mr4UxPosBa0JRw9bJoIwQn+nswiew==" }, "normalize-package-data": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.2.tgz", - "integrity": "sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", "dev": true, "requires": { "hosted-git-info": "^4.0.1", - "resolve": "^1.20.0", + "is-core-module": "^2.5.0", "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" } @@ -4445,12 +4607,6 @@ "yargs": "^15.0.2" }, "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 - }, "cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -4468,12 +4624,6 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, "p-map": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", @@ -4483,25 +4633,11 @@ "aggregate-error": "^3.0.0" } }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "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": "^5.0.0" - } + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true }, "wrap-ansi": { "version": "6.2.0", @@ -4583,10 +4719,36 @@ "wrappy": "1" } }, + "onigasm": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/onigasm/-/onigasm-2.2.5.tgz", + "integrity": "sha512-F+th54mPc0l1lp1ZcFMyL/jTs2Tlq4SqIHKIXGZOR/VkHkF9A7Fr5rRr5+ZG/lWeRsyrClLYRq7s/yFQ/XhWCA==", + "dev": true, + "requires": { + "lru-cache": "^5.1.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, "openapi-types": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-9.1.0.tgz", - "integrity": "sha512-mhXh8QN8sbErlxfxBeZ/pzgvmDn443p8CXlxwGSi2bWANZAFvjLPI0PoGjqHW+JdBbXg6uvmvM81WXaweh/SVA==" + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-9.2.0.tgz", + "integrity": "sha512-3x0gg8DxhpZ5MVki7AK6jmMdVIZASmVGo9CoUtD+nksLdkqz7EzWKdfS9Oxxq1J7idnZV0b3LjqcvizfKFySpQ==" }, "optional": { "version": "0.1.4", @@ -4594,6 +4756,19 @@ "integrity": "sha512-gtvrrCfkE08wKcgXaVwQVgwEQ8vel2dc5DDBn9RLQZ3YtmtkBss6A2HY6BnJH4N/4Ku97Ri/SF8sNWE2225WJw==", "optional": true }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "requires": { + "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-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -4654,6 +4829,14 @@ "release-zalgo": "^1.0.0" } }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "requires": { + "callsites": "^3.0.0" + } + }, "parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -4685,13 +4868,13 @@ "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 + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true }, "path-to-regexp": { "version": "0.1.7", @@ -4733,6 +4916,11 @@ "resolved": "https://registry.npmjs.org/plantuml-encoder/-/plantuml-encoder-1.4.0.tgz", "integrity": "sha512-sxMwpDw/ySY1WB2CE3+IdMuEcWibJ72DDOsXLkSmEaSzwEUaYBT6DWgOfBiHGCux4q433X6+OEFWjlVqp7gL6g==" }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + }, "prepend-file": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/prepend-file/-/prepend-file-1.3.1.tgz", @@ -4772,9 +4960,9 @@ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, "prom-client": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-12.0.0.tgz", - "integrity": "sha512-JbzzHnw0VDwCvoqf8y1WDtq4wSBAbthMB1pcVI/0lzdqHGJI3KBJDXle70XK+c7Iv93Gihqo0a5LlOn+g8+DrQ==", + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/prom-client/-/prom-client-13.2.0.tgz", + "integrity": "sha512-wGr5mlNNdRNzEhRYXgboUU2LxHWIojxscJKmtG3R8f4/KiWqyYgXTLHs0+Ted7tG3zFT7pgHJbtomzZ1L0ARaQ==", "requires": { "tdigest": "^0.1.1" } @@ -5002,9 +5190,9 @@ } }, "readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, "requires": { "picomatch": "^2.2.1" @@ -5014,6 +5202,7 @@ "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, "requires": { "resolve": "^1.1.6" } @@ -5029,9 +5218,9 @@ } }, "redoc-cli": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/redoc-cli/-/redoc-cli-0.12.2.tgz", - "integrity": "sha512-GyOCEr1g+U/Js7lgHj+0vH9L2uCwbc0m9CJrlb099qp6jzmxnJQ6sC85BiN9DOwr4/fsQfVhoNpWQSkkpFBo5Q==", + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/redoc-cli/-/redoc-cli-0.12.3.tgz", + "integrity": "sha512-qTBaEfwVqCvqLbuloZ9sMBQA49WfMOQrLVBGiVyT7pNMAjosQCpMyFESqQL8WqVxDzV2olPCZ1L2rG9cuDGOsA==", "dev": true, "requires": { "chokidar": "^3.5.1", @@ -5042,7 +5231,7 @@ "node-libs-browser": "^2.2.1", "react": "^17.0.1", "react-dom": "^17.0.1", - "redoc": "2.0.0-rc.55", + "redoc": "2.0.0-rc.56", "styled-components": "^5.3.0", "yargs": "^17.0.1" }, @@ -6658,9 +6847,9 @@ } }, "redoc": { - "version": "2.0.0-rc.55", - "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.55.tgz", - "integrity": "sha512-32sUHhc33m8zQKz2V7xREwlf05S52dDOkn7K0WMquu2GDl6ZquxmrQfqnlj0IPoVCWQPR+XosmmIJj4rZbqjeA==", + "version": "2.0.0-rc.56", + "resolved": "https://registry.npmjs.org/redoc/-/redoc-2.0.0-rc.56.tgz", + "integrity": "sha512-ir2TtQ2d/1FqZWIoLmUZ3qvAAnO6jg8dt0SV75TanmfCXpEABcElXWH3mtUf6qKlvgDVt40diDCVuSvyPPxkAw==", "dev": true, "requires": { "@babel/runtime": "^7.14.0", @@ -6681,7 +6870,7 @@ "path-browserify": "^1.0.1", "perfect-scrollbar": "^1.5.1", "polished": "^4.1.3", - "prismjs": "^1.24.0", + "prismjs": "^1.24.1", "prop-types": "^15.7.2", "react-tabs": "^3.2.2", "slugify": "~1.4.7", @@ -7150,6 +7339,11 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==" + }, "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -7165,6 +7359,11 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", @@ -7175,21 +7374,21 @@ "version": "1.20.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, "requires": { "is-core-module": "^2.2.0", "path-parse": "^1.0.6" } }, "resolve-alpn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.0.tgz", - "integrity": "sha512-e4FNQs+9cINYMO5NMFc6kOUCdohjqFPSgMuwuZAOUWqrfWsen+Yjy5qZFkV5K7VO7tFSLKcUL97olkED7sCBHA==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" }, "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, "response-time": { "version": "2.3.2", @@ -7239,24 +7438,15 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "sanitize-filename": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", - "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", - "requires": { - "truncate-utf8-bytes": "^1.0.0" - } - }, "secure-json-parse": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.4.0.tgz", "integrity": "sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg==" }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", - "dev": true, + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "requires": { "lru-cache": "^6.0.0" } @@ -7304,9 +7494,9 @@ } }, "serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -7338,7 +7528,6 @@ "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" } @@ -7346,19 +7535,30 @@ "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 + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "shelljs": { "version": "0.8.4", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.4.tgz", "integrity": "sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==", + "dev": true, "requires": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" } }, + "shiki": { + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.9.10.tgz", + "integrity": "sha512-xeM7Oc6hY+6iW5O/T5hor8ul7mEprzyl5y4r5zthEHToQNw7MIhREMgU3r2gKDB0NaMLNrkcEQagudCdzE13Lg==", + "dev": true, + "requires": { + "json5": "^2.2.0", + "onigasm": "^2.2.5", + "vscode-textmate": "5.2.0" + } + }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -7377,27 +7577,24 @@ "dev": true }, "sinon": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-10.0.0.tgz", - "integrity": "sha512-XAn5DxtGVJBlBWYrcYKEhWCz7FLwZGdyvANRyK06419hyEpdT0dMc5A8Vcxg5SCGHc40CsqoKsc1bt1CbJPfNw==", + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-11.1.2.tgz", + "integrity": "sha512-59237HChms4kg7/sXhiRcUzdSkKuydDeTiamT/jesUVHshBgL8XAmhgFo0GfK6RruMDM/iRSij1EybmMog9cJw==", "dev": true, "requires": { - "@sinonjs/commons": "^1.8.1", - "@sinonjs/fake-timers": "^6.0.1", - "@sinonjs/samsam": "^5.3.1", - "diff": "^4.0.2", - "nise": "^4.1.0", - "supports-color": "^7.1.0" + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^7.1.2", + "@sinonjs/samsam": "^6.0.2", + "diff": "^5.0.0", + "nise": "^5.1.0", + "supports-color": "^7.2.0" }, "dependencies": { - "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } + "diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true } } }, @@ -7412,19 +7609,21 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true }, "spawn-wrap": { "version": "2.0.0", @@ -7467,9 +7666,9 @@ } }, "spdx-license-ids": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", - "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", "dev": true }, "split": { @@ -7506,8 +7705,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "statuses": { "version": "1.5.0", @@ -7515,13 +7713,13 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, "string_decoder": { @@ -7533,12 +7731,11 @@ } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^5.0.0" } }, "strip-bom": { @@ -7559,8 +7756,7 @@ "strip-json-comments": { "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 + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, "superagent": { "version": "6.1.0", @@ -7610,9 +7806,9 @@ } }, "supertest": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.1.4.tgz", - "integrity": "sha512-giC9Zm+Bf1CZP09ciPdUyl+XlMAu6rbch79KYiYKOGcbK2R1wH8h+APul1i/3wN6RF1XfWOIF+8X1ga+7SBrug==", + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.1.6.tgz", + "integrity": "sha512-0hACYGNJ8OHRg8CRITeZOdbjur7NLuNs0mBjVhdpxi7hP6t3QIbOzLON5RTUmZcy2I9riuII3+Pr2C7yztrIIg==", "dev": true, "requires": { "methods": "^1.1.2", @@ -7627,6 +7823,37 @@ "has-flag": "^4.0.0" } }, + "table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "requires": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.6.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", + "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + } + } + }, "tdigest": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/tdigest/-/tdigest-0.1.1.tgz", @@ -7676,6 +7903,11 @@ "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", "dev": true }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", @@ -7749,49 +7981,51 @@ "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", "dev": true }, - "truncate-utf8-bytes": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", - "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", - "requires": { - "utf8-byte-length": "^1.0.1" - } - }, "ts-json-schema-generator": { - "version": "0.70.2", - "resolved": "https://registry.npmjs.org/ts-json-schema-generator/-/ts-json-schema-generator-0.70.2.tgz", - "integrity": "sha512-4miuxRyxYvwzCGGzxGvN39fwlY7HDlj1KRpZq8Hi3IegeAnguc9q4gDvcqMaDKoRiNNnV5fwplRWZFhRrtvr4Q==", + "version": "0.95.0", + "resolved": "https://registry.npmjs.org/ts-json-schema-generator/-/ts-json-schema-generator-0.95.0.tgz", + "integrity": "sha512-qyArLCOmy0UnnGeCewpZgaGglPMmawAhsuYDRDa1BeZiyE+M/I2dH+dSMtFj8kVbWSEayfVmQIF9UBINBfeKSg==", "requires": { - "@types/json-schema": "^7.0.5", - "commander": "~5.1.0", - "glob": "~7.1.6", + "@types/json-schema": "^7.0.7", + "commander": "^8.0.0", + "fast-json-stable-stringify": "^2.1.0", + "glob": "^7.1.7", "json-stable-stringify": "^1.0.1", - "typescript": "~3.9.5" + "json5": "^2.2.0", + "typescript": "~4.3.4" }, "dependencies": { - "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" - }, "typescript": { - "version": "3.9.10", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", - "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==" + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==" } } }, "ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.1.tgz", + "integrity": "sha512-hCnyOyuGmD5wHleOQX6NIjJtYVIO8bPP8F2acWkB4W06wdlkgyvJtubO/I9NkI88hCFECbsEgoLc0VNkYmcSfw==", "requires": { + "@cspotcode/source-map-support": "0.6.1", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.17", "yn": "3.1.1" + }, + "dependencies": { + "acorn": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", + "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==" + } } }, "ts-optchain": { @@ -7901,6 +8135,28 @@ "tsutils": "^3.0.0" }, "dependencies": { + "doctrine": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-0.7.2.tgz", + "integrity": "sha1-fLhgNZujvpDgQLJrcpzkv6ZUxSM=", + "dev": true, + "requires": { + "esutils": "^1.1.6", + "isarray": "0.0.1" + } + }, + "esutils": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-1.1.6.tgz", + "integrity": "sha1-wBzKqa5LiXxtDD4hCuUvPHqEQ3U=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, "tslib": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.0.tgz", @@ -7927,16 +8183,23 @@ "tslib": "^1.8.1" } }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" }, "type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" }, "type-is": { "version": "1.6.18", @@ -7957,26 +8220,40 @@ } }, "typedoc": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.18.0.tgz", - "integrity": "sha512-UgDQwapCGQCCdYhEQzQ+kGutmcedklilgUGf62Vw6RdI29u6FcfAXFQfRTiJEbf16aK3YnkB20ctQK1JusCRbA==", + "version": "0.21.9", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.21.9.tgz", + "integrity": "sha512-VRo7aII4bnYaBBM1lhw4bQFmUcDQV8m8tqgjtc7oXl87jc1Slbhfw2X5MccfcR2YnEClHDWgsiQGgNB8KJXocA==", + "dev": true, "requires": { - "fs-extra": "^9.0.1", - "handlebars": "^4.7.6", - "highlight.js": "^10.0.0", - "lodash": "^4.17.15", - "lunr": "^2.3.8", - "marked": "^1.1.1", + "glob": "^7.1.7", + "handlebars": "^4.7.7", + "lunr": "^2.3.9", + "marked": "^3.0.2", "minimatch": "^3.0.0", "progress": "^2.0.3", - "shelljs": "^0.8.4", - "typedoc-default-themes": "^0.10.2" + "shiki": "^0.9.8", + "typedoc-default-themes": "^0.12.10" + }, + "dependencies": { + "marked": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-3.0.2.tgz", + "integrity": "sha512-TMJQQ79Z0e3rJYazY0tIoMsFzteUGw9fB3FD+gzuIT3zLuG9L9ckIvUfF51apdJkcqc208jJN2KbtPbOvXtbjA==", + "dev": true + }, + "typedoc-default-themes": { + "version": "0.12.10", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.12.10.tgz", + "integrity": "sha512-fIS001cAYHkyQPidWXmHuhs8usjP5XVJjWB8oZGqkTowZaz3v7g3KDZeeqE82FBrmkAnIBOY3jgy7lnPnqATbA==", + "dev": true + } } }, "typedoc-default-themes": { "version": "0.10.2", "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.10.2.tgz", "integrity": "sha512-zo09yRj+xwLFE3hyhJeVHWRSPuKEIAsFK5r2u47KL/HBKqpwdUSanoaz5L34IKiSATFrjG5ywmIu98hPVMfxZg==", + "dev": true, "requires": { "lunr": "^2.3.8" } @@ -7984,12 +8261,14 @@ "typescript": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", - "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==" + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", + "dev": true }, "uglify-js": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.1.tgz", "integrity": "sha512-JhS3hmcVaXlp/xSo3PKY5R0JqKs5M3IV+exdLHW99qKvKivPO4Z8qbej6mte17SOPqAOVMjt/XGgWacnFSzM3g==", + "dev": true, "optional": true }, "universalify": { @@ -8015,11 +8294,6 @@ "resolved": "https://registry.npmjs.org/url-value-parser/-/url-value-parser-2.0.3.tgz", "integrity": "sha512-FjIX+Q9lYmDM9uYIGdMYfQW0uLbWVwN2NrL2ayAI7BTOvEwzH+VoDdNquwB9h4dFAx+u6mb0ONLa3sHD5DvyvA==" }, - "utf8-byte-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", - "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=" - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -8035,6 +8309,11 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -8050,11 +8329,16 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, + "vscode-textmate": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", + "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", + "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" } @@ -8072,17 +8356,56 @@ "dev": true, "requires": { "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true }, "workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.5.tgz", + "integrity": "sha512-XdKkCK0Zqc6w3iTxLckiuJ81tiD/o5rBE/m+nXpRCB+/Sq4DqkfXZ/x0jW02DG1tGsfUGXbTJyZDP+eu67haSw==", "dev": true }, "wrap-ansi": { @@ -8094,40 +8417,6 @@ "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" - }, - "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 - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "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": "^5.0.0" - } - } } }, "wrappy": { @@ -8167,8 +8456,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "yaml": { "version": "1.10.0", @@ -8189,40 +8477,6 @@ "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" - }, - "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 - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "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": "^5.0.0" - } - } } }, "yargs-parser": { diff --git a/package.json b/package.json index a12629c6..2d532165 100644 --- a/package.json +++ b/package.json @@ -25,41 +25,39 @@ "preversion": "npm run prepublishOnly", "push": "git push && git push origin \"v$npm_package_version\"", "start": "NODE_CONFIG_ENV=elasticsearch ALLOW_NO_TRANSPORT=true node ./lib/cli.js", - "start-debug": "STAPPS_LOG_LEVEL=31 NODE_CONFIG_ENV=elasticsearch ALLOW_NO_TRANSPORT=true ES_FORCE_MAPPING_UPDATE=true node ./lib/cli.js --require ts-node/register", + "start-debug": "STAPPS_LOG_LEVEL=31 NODE_CONFIG_ENV=elasticsearch ALLOW_NO_TRANSPORT=true node ./lib/cli.js --require ts-node/register", "test": "npm run test-unit && npm run test-integration", - "test-unit": "env NODE_CONFIG_ENV=elasticsearch ALLOW_NO_TRANSPORT=true ES_FORCE_MAPPING_UPDATE=true STAPPS_LOG_LEVEL=0 nyc mocha --require ts-node/register --exit 'test/**/*.spec.ts'", + "test-unit": "env NODE_CONFIG_ENV=elasticsearch ALLOW_NO_TRANSPORT=true STAPPS_LOG_LEVEL=0 nyc mocha --require ts-node/register --exit 'test/**/*.spec.ts'", "test-integration": "sudo docker-compose -f integration-test.yml pull && sudo docker-compose -f integration-test.yml up --build --abort-on-container-exit --exit-code-from apicli", "tslint": "tslint -p tsconfig.json -c tslint.json 'src/**/*.ts'" }, "dependencies": { "@elastic/elasticsearch": "5.6.22", - "@openstapps/core": "0.48.0", - "@openstapps/core-tools": "0.23.2", + "@openstapps/core": "0.50.0", + "@openstapps/core-tools": "0.25.0", "@openstapps/logger": "0.7.0", "@types/express-prometheus-middleware": "1.2.1", - "@types/node": "14.17.7", - "commander": "7.2.0", + "@types/node": "14.17.12", "config": "3.3.6", "cors": "2.8.5", "express": "4.17.1", "express-prometheus-middleware": "1.2.0", "express-promise-router": "4.1.0", - "fs-extra": "9.1.0", "got": "11.8.2", "moment": "2.29.1", "morgan": "1.10.0", - "nock": "13.1.1", + "nock": "13.1.3", "node-cache": "5.1.2", "node-cron": "3.0.0", "nodemailer": "6.6.3", - "prom-client": "12.0.0", + "prom-client": "13.2.0", "promise-queue": "2.2.5", - "sanitize-filename": "1.6.3", - "ts-node": "9.1.1", + "ts-node": "10.2.1", "uuid": "8.3.2" }, "devDependencies": { "@openstapps/configuration": "0.27.0", + "@openstapps/es-mapping-generator": "0.0.3", "@testdeck/mocha": "0.1.2", "@types/chai": "4.2.21", "@types/chai-as-promised": "7.1.4", @@ -67,9 +65,8 @@ "@types/cors": "2.8.12", "@types/elasticsearch": "5.0.38", "@types/express": "4.17.13", - "@types/fs-extra": "9.0.12", "@types/geojson": "1.0.6", - "@types/mocha": "8.2.3", + "@types/mocha": "9.0.0", "@types/morgan": "1.9.3", "@types/node-cron": "2.0.4", "@types/nodemailer": "6.4.4", @@ -81,17 +78,17 @@ "chai-as-promised": "7.1.1", "conventional-changelog-cli": "2.1.1", "get-port": "5.1.1", - "mocha": "8.4.0", + "mocha": "9.1.1", "mocked-env": "1.3.5", "nyc": "15.1.0", "prepend-file-cli": "1.0.6", - "redoc-cli": "0.12.2", + "redoc-cli": "0.12.3", "rimraf": "3.0.2", - "sinon": "10.0.0", + "sinon": "11.1.2", "sinon-express-mock": "2.2.1", - "supertest": "6.1.4", + "supertest": "6.1.6", "tslint": "6.1.3", - "typedoc": "0.18.0", + "typedoc": "0.21.9", "typescript": "3.8.3" }, "nyc": { diff --git a/src/routes/route.ts b/src/routes/route.ts index 3de475a3..515ffdab 100644 --- a/src/routes/route.ts +++ b/src/routes/route.ts @@ -19,7 +19,7 @@ import { SCRoute, SCValidationErrorResponse, } from '@openstapps/core'; -import {ValidationError} from '@openstapps/core-tools/lib/common'; +import {ValidationError} from '@openstapps/core-tools/src/types/validator'; import {Logger} from '@openstapps/logger'; import {Application, Router} from 'express'; import PromiseRouter from 'express-promise-router'; diff --git a/src/storage/elasticsearch/aggregations.ts b/src/storage/elasticsearch/aggregations.ts index d7bdcadb..fe847178 100644 --- a/src/storage/elasticsearch/aggregations.ts +++ b/src/storage/elasticsearch/aggregations.ts @@ -14,44 +14,31 @@ * along with this program. If not, see . */ import {SCFacet, SCThingType} from '@openstapps/core'; -import {readFileSync} from 'fs'; +import {aggregations} from './templating'; +import {AggregationResponse} from './types/elasticsearch'; import { - AggregationResponse, - AggregationSchema, isBucketAggregation, isESAggMatchAllFilter, isESNestedAggregation, isESTermsFilter, isNestedAggregation, -} from './common'; -import {aggregationsPath} from './templating'; - -/** - * Builds the aggregation - * @returns a schema to tell elasticsearch which aggregations to collect - */ -export function buildAggregations(): AggregationSchema { - return JSON.parse((readFileSync(aggregationsPath, 'utf8')).toString()); -} +} from './types/guards'; /** * Parses elasticsearch aggregations (response from es) to facets for the app - * @param aggregationSchema - aggregation-schema for elasticsearch - * @param aggregations - aggregations response from elasticsearch + * @param aggregationResponse - aggregations response from elasticsearch */ -export function parseAggregations( - aggregationSchema: AggregationSchema, - aggregations: AggregationResponse): SCFacet[] { +export function parseAggregations(aggregationResponse: AggregationResponse): SCFacet[] { const facets: SCFacet[] = []; // get all names of the types an aggregation is on - for (const typeName in aggregationSchema) { - if (aggregationSchema.hasOwnProperty(typeName) && aggregations.hasOwnProperty(typeName)) { + for (const typeName in aggregations) { + if (aggregations.hasOwnProperty(typeName) && aggregationResponse.hasOwnProperty(typeName)) { // the type object from the schema - const type = aggregationSchema[typeName]; + const type = aggregations[typeName]; // the "real" type object from the response - const realType = aggregations[typeName]; + const realType = aggregationResponse[typeName]; // both conditions must apply, else we have an error somewhere if (isESNestedAggregation(type) && isNestedAggregation(realType)) { diff --git a/src/storage/elasticsearch/elasticsearch.ts b/src/storage/elasticsearch/elasticsearch.ts index 50c882c3..7bb773ef 100644 --- a/src/storage/elasticsearch/elasticsearch.ts +++ b/src/storage/elasticsearch/elasticsearch.ts @@ -33,17 +33,16 @@ import moment from 'moment'; import {MailQueue} from '../../notification/mail-queue'; import {Bulk} from '../bulk-storage'; import {Database} from '../database'; -import {buildAggregations, parseAggregations} from './aggregations'; +import {parseAggregations} from './aggregations'; +import * as Monitoring from './monitoring'; +import {buildQuery, buildSort} from './query'; +import {aggregations, putTemplate} from './templating'; import { AggregationResponse, - AggregationSchema, ElasticsearchConfig, ElasticsearchObject, ElasticsearchQueryDisMaxConfig, ElasticsearchQueryQueryStringConfig, -} from './common'; -import * as Monitoring from './monitoring'; -import {buildQuery, buildSort} from './query'; -import {checkESTemplate, putTemplate} from './templating'; +} from './types/elasticsearch'; /** * Matches index names such as stapps___ @@ -60,11 +59,6 @@ export class Elasticsearch implements Database { */ static readonly INDEX_UID_LENGTH = 8; - /** - * Holds aggregations - */ - aggregationsSchema: AggregationSchema; - /** * Holds a map of all elasticsearch indices that are available to search */ @@ -207,11 +201,6 @@ export class Elasticsearch implements Database { this.aliasMap = {}; this.ready = false; - checkESTemplate(typeof process.env.ES_FORCE_MAPPING_UPDATE !== 'undefined' ? - process.env.ES_FORCE_MAPPING_UPDATE === 'true' : false); - - this.aggregationsSchema = buildAggregations(); - this.mailQueue = mailQueue; } @@ -221,6 +210,8 @@ export class Elasticsearch implements Database { private async getAliasMap() { // delay after which alias map will be fetched again const RETRY_INTERVAL = 5000; + // maximum number of retries + const RETRY_COUNT = 3; // create a list of old indices that are not in use const oldIndicesToDelete: string[] = []; @@ -233,17 +224,24 @@ export class Elasticsearch implements Database { [K in SCThingType]: unknown }; }; - }; + } | undefined; - try { - aliases = (await this.client.indices.getAlias({})).body; - } catch (error) { - await Logger.error('Failed getting alias map:', error); - setTimeout(async () => { - return this.getAliasMap(); - }, RETRY_INTERVAL); // retry after a delay + for(const retry of [...Array(RETRY_COUNT)].map((_, i) => i+1)) { + if (typeof aliases !== 'undefined') { + break; + } + try { + const aliasResponse = await this.client.indices.getAlias({}); + aliases = aliasResponse.body; + } catch (error) { + Logger.warn('Failed getting alias map:', error); + Logger.warn(`Retrying in ${RETRY_INTERVAL} milliseconds. (${retry} of ${RETRY_COUNT})`); + await new Promise(resolve => setTimeout(resolve, RETRY_INTERVAL)); + } + } - return; + if (typeof aliases === 'undefined') { + throw Error(`Failed to retrieve alias map after ${RETRY_COUNT} attempts!`); } for (const index in aliases) { @@ -566,7 +564,7 @@ export class Elasticsearch implements Database { const searchRequest: RequestParams.Search = { body: { - aggs: this.aggregationsSchema, // use cached version of aggregations (they only change if config changes) + aggs: aggregations, query: buildQuery(params, this.config, esConfig), }, from: params.from, @@ -603,7 +601,7 @@ export class Elasticsearch implements Database { // read the aggregations from elasticsearch and parse them to facets by our configuration if (typeof response.body.aggregations !== 'undefined') { - facets = parseAggregations(this.aggregationsSchema, response.body.aggregations as AggregationResponse); + facets = parseAggregations(response.body.aggregations as AggregationResponse); } return { diff --git a/src/storage/elasticsearch/query.ts b/src/storage/elasticsearch/query.ts index 52958501..5803b385 100644 --- a/src/storage/elasticsearch/query.ts +++ b/src/storage/elasticsearch/query.ts @@ -45,7 +45,7 @@ import { ESTermFilter, ESTypeFilter, ScriptSort, -} from './common'; +} from './types/elasticsearch'; /** * Escapes any reserved character that would otherwise not be accepted by Elasticsearch diff --git a/src/storage/elasticsearch/templates/.gitignore b/src/storage/elasticsearch/templates/.gitignore deleted file mode 100644 index 35340fb5..00000000 --- a/src/storage/elasticsearch/templates/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.json -*.txt diff --git a/src/storage/elasticsearch/templating.ts b/src/storage/elasticsearch/templating.ts index 49ac71a3..f9509088 100644 --- a/src/storage/elasticsearch/templating.ts +++ b/src/storage/elasticsearch/templating.ts @@ -15,77 +15,18 @@ */ import {Client} from '@elastic/elasticsearch'; import {SCThingType} from '@openstapps/core'; -import {getProjectReflection} from '@openstapps/core-tools/lib/common'; -import {generateTemplate} from '@openstapps/core-tools/lib/mapping'; -import {Logger} from '@openstapps/logger'; -import {existsSync, writeFileSync} from 'fs'; -import {readFile} from 'fs-extra'; +// tslint:disable-next-line:no-implicit-dependencies +import {AggregationSchema} from '@openstapps/es-mapping-generator/src/types/aggregation'; +// tslint:disable-next-line:no-implicit-dependencies +import {ElasticsearchTemplateCollection} from '@openstapps/es-mapping-generator/src/types/mapping'; +import {readFileSync} from 'fs'; import {resolve} from 'path'; -import sanitize = require('sanitize-filename'); -import {configFile, coreVersion} from '../../common'; -const dirPath = resolve('src', 'storage', 'elasticsearch', 'templates'); -export const aggregationsPath = resolve(dirPath, sanitize(`${coreVersion}-aggregations.json`, {replacement: '-'})); -const templateErrorPath = resolve(dirPath, sanitize(`${coreVersion}-template-[type].error.json`, {replacement: '-'})); -const aggregationsErrorPath = resolve(dirPath, sanitize(`${coreVersion}-aggregations.error.json`, {replacement: '-'})); -const errorReportPath = resolve(dirPath, sanitize(`${coreVersion}-error-report.txt`, {replacement: '-'})); +const mappingsPath = resolve('node_modules', '@openstapps', 'core', 'lib','mappings'); -/** - * Check if the correct template exists - */ -export function checkESTemplate(forceUpdate: boolean) { - // as the forced mapping update is only meant for development, print a warning if it is enabled - if (forceUpdate) { - Logger.warn('CAUTION: Force update of the mapping files is enabled. This causes the backend to ignore' + - ' existing mapping files on start.'); - } - // we don't exactly know which files are there, so we just check if the aggregations exist - // for the current core version - if (forceUpdate || !existsSync(aggregationsPath)) { - Logger.info(`No mapping for Core version ${coreVersion} found, starting automatic mapping generation. ` + - `This may take a while.`); - const map = generateTemplate(getProjectReflection(resolve('node_modules', '@openstapps', 'core', 'src')), - configFile.backend.mappingIgnoredTags, false); +export const mappings = JSON.parse(readFileSync(resolve(mappingsPath, 'mappings.json'), 'utf-8')) as ElasticsearchTemplateCollection; +export const aggregations = JSON.parse(readFileSync(resolve(mappingsPath, 'aggregations.json'), 'utf-8')) as AggregationSchema; - if (map.errors.length > 0) { - for (const type of Object.keys(map.mappings)) { - writeFileSync(getTemplatePath(Object.keys(map.mappings[type].mappings)[0] as SCThingType, true), - // tslint:disable-next-line:no-magic-numbers - JSON.stringify(map.mappings[type], null, 2)); - } - // tslint:disable-next-line:no-magic-numbers - writeFileSync(aggregationsErrorPath, JSON.stringify(map.aggregations, null, 2)); - - writeFileSync(errorReportPath, `ERROR REPORT FOR CORE VERSION ${coreVersion}\n${map.errors.join('\n')}`); - - void Logger.error(`There were errors while generating the template, and the backend cannot continue. A list of ` + - `all errors can be found at ${errorReportPath}. To resolve this` + - ` issue by hand you can go to "${templateErrorPath}" and "${aggregationsErrorPath}", then correct the issues` + - ` manually and move the files to the template paths and "${aggregationsPath}" respectively.`); - process.exit(1); - } else { - Logger.ok('Mapping files were generated successfully.'); - for (const type of Object.keys(map.mappings)) { - writeFileSync(getTemplatePath(Object.keys(map.mappings[type].mappings)[0] as SCThingType, false), - // tslint:disable-next-line:no-magic-numbers - JSON.stringify(map.mappings[type], null, 2)); - } - writeFileSync(aggregationsPath, JSON.stringify(map.aggregations)); - } - } else { - Logger.info(`Using existing mappings for core version ${coreVersion}`); - } -} - -/** - * Generates the path to the template of an SCThingType - * - * @param type the type for the path - * @param error whether an error occurred in the file - */ -function getTemplatePath(type: SCThingType, error = false): string { - return resolve(dirPath, sanitize(`${coreVersion}-template-${type}${error ? '.error' : ''}.json`, {replacement: '-'})); -} /** * Re-applies all interfaces for every type @@ -107,13 +48,10 @@ export async function refreshAllTemplates(client: Client) { * @param client An elasticsearch client to use */ export async function putTemplate(client: Client, type: SCThingType) { - let out = type.toLowerCase(); - while (out.includes(' ')) { - out = out.replace(' ', '_'); - } + const sanitizedType = `template_${type.replace(/\s/g, '_')}`; return client.indices.putTemplate({ - body: JSON.parse((await readFile(getTemplatePath(type), 'utf8')).toString()), - name: `template_${out}`, + body: mappings[sanitizedType], + name: sanitizedType, }); } diff --git a/src/storage/elasticsearch/common.ts b/src/storage/elasticsearch/types/elasticsearch.ts similarity index 86% rename from src/storage/elasticsearch/common.ts rename to src/storage/elasticsearch/types/elasticsearch.ts index f2f0ecf7..9566f11f 100644 --- a/src/storage/elasticsearch/common.ts +++ b/src/storage/elasticsearch/types/elasticsearch.ts @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019 StApps + * Copyright (C) 2019-2021 StApps * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the @@ -13,15 +13,8 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import {SCThingType} from '@openstapps/core'; -import {SCThing} from '@openstapps/core'; -import { - ESAggMatchAllFilter, - ESAggTypeFilter, ESNestedAggregation, - ESTermsFilter, -} from '@openstapps/core-tools/lib/mappings/aggregation-definitions'; +import {SCThing, SCThingType} from '@openstapps/core'; // we only have the @types package because some things type definitions are still missing from the official -// @elastic/elasticsearch package // tslint:disable-next-line:no-implicit-dependencies import {NameList} from 'elasticsearch'; // tslint:disable-next-line:no-implicit-dependencies @@ -67,14 +60,6 @@ export interface BucketAggregation { doc_count?: number; } -/** - * Checks if the type is a BucketAggregation - * @param agg the type to check - */ -export function isBucketAggregation(agg: BucketAggregation | number): agg is BucketAggregation { - return typeof agg !== 'number'; -} - /** * An aggregation that contains more aggregations nested inside */ @@ -90,21 +75,6 @@ export interface NestedAggregation { [name: string]: BucketAggregation | number; } -/** - * Checks if the type is a NestedAggregation - * @param agg the type to check - */ -export function isNestedAggregation(agg: BucketAggregation | NestedAggregation): agg is NestedAggregation { - return typeof (agg as BucketAggregation).buckets === 'undefined'; -} - -/** - * An elasticsearch bucket aggregation - * @see https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-aggregations-bucket.html - */ -export interface AggregationSchema { - [aggregationName: string]: ESTermsFilter | ESNestedAggregation; -} /** * A configuration for using the Dis Max Query @@ -348,30 +318,6 @@ export type ESNumericRangeFilter = ESGenericRangeFilter; export type ESRangeFilter = ESNumericRangeFilter | ESDateRangeFilter; -/** - * Checks if the parameter is of type ESTermsFilter - * @param agg the value to check - */ -export function isESTermsFilter(agg: ESTermsFilter | ESNestedAggregation): agg is ESTermsFilter { - return typeof (agg as ESTermsFilter).terms !== 'undefined'; -} - -/** - * Checks if the parameter is of type ESTermsFilter - * @param agg the value to check - */ -export function isESNestedAggregation(agg: ESTermsFilter | ESNestedAggregation): agg is ESNestedAggregation { - return typeof (agg as ESNestedAggregation).aggs !== 'undefined'; -} - -/** - * Checks if the parameter is of type - * - * @param filter the filter to narrow the type of - */ -export function isESAggMatchAllFilter(filter: ESAggTypeFilter | ESAggMatchAllFilter): filter is ESAggMatchAllFilter { - return filter.hasOwnProperty('match_all'); -} /** * An elasticsearch type filter diff --git a/src/storage/elasticsearch/types/guards.ts b/src/storage/elasticsearch/types/guards.ts new file mode 100644 index 00000000..637b21be --- /dev/null +++ b/src/storage/elasticsearch/types/guards.ts @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2019-2021 StApps + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +import { + ESAggMatchAllFilter, + ESAggTypeFilter, + ESNestedAggregation, + ESTermsFilter, +// tslint:disable-next-line:no-implicit-dependencies we're just using the types here +} from '@openstapps/es-mapping-generator/src/types/aggregation'; +import {BucketAggregation, NestedAggregation} from './elasticsearch'; + +/** + * Checks if the type is a BucketAggregation + * @param agg the type to check + */ +export function isBucketAggregation(agg: BucketAggregation | number): agg is BucketAggregation { + return typeof agg !== 'number'; +} + +/** + * Checks if the type is a NestedAggregation + * @param agg the type to check + */ +export function isNestedAggregation(agg: BucketAggregation | NestedAggregation): agg is NestedAggregation { + return typeof (agg as BucketAggregation).buckets === 'undefined'; +} + +/** + * Checks if the parameter is of type ESTermsFilter + * @param agg the value to check + */ +export function isESTermsFilter(agg: ESTermsFilter | ESNestedAggregation): agg is ESTermsFilter { + return typeof (agg as ESTermsFilter).terms !== 'undefined'; +} + +/** + * Checks if the parameter is of type ESTermsFilter + * @param agg the value to check + */ +export function isESNestedAggregation(agg: ESTermsFilter | ESNestedAggregation): agg is ESNestedAggregation { + return typeof (agg as ESNestedAggregation).aggs !== 'undefined'; +} + +/** + * Checks if the parameter is of type + * + * @param filter the filter to narrow the type of + */ +export function isESAggMatchAllFilter(filter: ESAggTypeFilter | ESAggMatchAllFilter): filter is ESAggMatchAllFilter { + return filter.hasOwnProperty('match_all'); +} diff --git a/test/routes/bulk-route.spec.ts b/test/routes/bulk-route.spec.ts index f739511c..89e6924d 100644 --- a/test/routes/bulk-route.spec.ts +++ b/test/routes/bulk-route.spec.ts @@ -21,7 +21,7 @@ import { SCNotFoundErrorResponse, } from '@openstapps/core'; import {expect} from 'chai'; -import {instance as book} from '@openstapps/core/test/resources/Book.1.json'; +import {instance as book} from '@openstapps/core/test/resources/indexable/Book.1.json'; import {bulk, DEFAULT_TEST_TIMEOUT} from '../common'; import {testApp} from '../tests-setup'; diff --git a/test/routes/thing-update-route.spec.ts b/test/routes/thing-update-route.spec.ts index 646f9160..82bd15f7 100644 --- a/test/routes/thing-update-route.spec.ts +++ b/test/routes/thing-update-route.spec.ts @@ -17,7 +17,7 @@ import {SCThingUpdateRoute} from '@openstapps/core'; import chaiAsPromised from 'chai-as-promised'; import {bulkStorageMock, DEFAULT_TEST_TIMEOUT} from '../common'; import {expect, use} from 'chai'; -import {instance as book} from '@openstapps/core/test/resources/Book.1.json'; +import {instance as book} from '@openstapps/core/test/resources/indexable/Book.1.json'; import {testApp} from '../tests-setup'; use(chaiAsPromised); diff --git a/test/storage/elasticsearch/aggregations.spec.ts b/test/storage/elasticsearch/aggregations.spec.ts index ed09c177..8f6d928b 100644 --- a/test/storage/elasticsearch/aggregations.spec.ts +++ b/test/storage/elasticsearch/aggregations.spec.ts @@ -16,118 +16,9 @@ import {SCFacet, SCThingType} from '@openstapps/core'; import {expect} from 'chai'; import {parseAggregations} from '../../../src/storage/elasticsearch/aggregations'; -import {AggregationResponse, AggregationSchema} from '../../../src/storage/elasticsearch/common'; +import {AggregationResponse} from '../../../src/storage/elasticsearch/types/elasticsearch'; describe('Aggregations', function () { - const schema: AggregationSchema = { - '@all': { - aggs: { - type: { - terms: { - field: 'type.raw', - size: 1000 - } - } - }, - filter: { - match_all: {} - } - }, - 'academic event': { - aggs: { - 'academicTerms.acronym': { - terms: { - field: 'academicTerms.acronym.raw', - size: 1000 - } - }, - 'catalogs.categories': { - terms: { - field: 'catalogs.categories.raw', - size: 1000 - } - }, - categories: { - terms: { - field: 'categories.raw', - size: 1000 - } - }, - 'creativeWorks.keywords': { - terms: { - field: 'creativeWorks.keywords.raw', - size: 1000 - } - }, - majors: { - terms: { - field: 'majors.raw', - size: 1000 - } - } - }, - filter: { - type: { - value: 'academic event' - } - } - }, - catalog: { - aggs: { - 'academicTerm.acronym': { - terms: { - field: 'academicTerm.acronym.raw', - size: 1000 - } - }, - categories: { - terms: { - field: 'categories.raw', - size: 1000 - } - }, - 'superCatalog.categories': { - terms: { - field: 'superCatalog.categories.raw', - size: 1000 - } - }, - 'superCatalogs.categories': { - terms: { - field: 'superCatalogs.categories.raw', - size: 1000 - } - } - }, - filter: { - type: { - value: 'catalog' - } - } - }, - person: { - aggs: { - 'homeLocations.categories': { - terms: { - field: 'homeLocations.categories.raw', - size: 1000 - } - } - }, - filter: { - type: { - value: 'person' - } - } - }, - fooType: { - terms: { - field: 'foo', - size: 123, - } - } - }; - const aggregations: AggregationResponse = { catalog: { doc_count: 4, @@ -262,19 +153,11 @@ describe('Aggregations', function () { field: 'categories', onlyOnType: SCThingType.Catalog, }, - { - buckets: [ - { - count: 321, - key: 'foo' - } - ], - field: 'fooType' - } + // no fooType as it doesn't appear in the aggregation schema ]; it('should parse the aggregations providing the appropriate facets', function () { - const facets = parseAggregations(schema, aggregations); + const facets = parseAggregations(aggregations); expect(facets).to.be.eql(expectedFacets); }); diff --git a/test/storage/elasticsearch/common.spec.ts b/test/storage/elasticsearch/common.spec.ts index 82ead6fc..3e102970 100644 --- a/test/storage/elasticsearch/common.spec.ts +++ b/test/storage/elasticsearch/common.spec.ts @@ -18,14 +18,16 @@ import { ESAggTypeFilter, ESNestedAggregation, ESTermsFilter -} from '@openstapps/core-tools/lib/mappings/aggregation-definitions'; -import { expect } from "chai"; +} from '@openstapps/es-mapping-generator/src/types/aggregation'; +import {expect} from "chai"; import { - BucketAggregation, - isBucketAggregation, isESAggMatchAllFilter, isESNestedAggregation, isESTermsFilter, isNestedAggregation, - NestedAggregation -} from '../../../src/storage/elasticsearch/common'; + isBucketAggregation, + isESTermsFilter, + isESAggMatchAllFilter, + isESNestedAggregation +} from '../../../lib/storage/elasticsearch/types/guards'; +import {BucketAggregation, NestedAggregation} from '../../../src/storage/elasticsearch/types/elasticsearch'; describe('Common', function () { const bucketAggregation: BucketAggregation = {buckets: []}; diff --git a/test/storage/elasticsearch/elasticsearch.spec.ts b/test/storage/elasticsearch/elasticsearch.spec.ts index d77e9455..25463b85 100644 --- a/test/storage/elasticsearch/elasticsearch.spec.ts +++ b/test/storage/elasticsearch/elasticsearch.spec.ts @@ -15,8 +15,8 @@ */ import {ApiResponse, Client} from '@elastic/elasticsearch'; import {SCBook, SCBulkResponse, SCConfigFile, SCMessage, SCSearchQuery, SCThings, SCThingType} from '@openstapps/core'; -import {instance as book} from '@openstapps/core/test/resources/Book.1.json'; -import {instance as message} from '@openstapps/core/test/resources/Message.1.json'; +import {instance as book} from '@openstapps/core/test/resources/indexable/Book.1.json'; +import {instance as message} from '@openstapps/core/test/resources/indexable/Message.1.json'; import {Logger} from '@openstapps/logger'; import {SMTP} from '@openstapps/logger/lib/smtp'; import {expect, use} from 'chai'; @@ -26,8 +26,8 @@ import mockedEnv from 'mocked-env'; import sinon from 'sinon'; import {configFile} from '../../../src/common'; import {MailQueue} from '../../../src/notification/mail-queue'; -import * as aggregations from '../../../src/storage/elasticsearch/aggregations'; -import {ElasticsearchObject} from '../../../src/storage/elasticsearch/common'; +import {aggregations} from '../../../src/storage/elasticsearch/templating'; +import {ElasticsearchObject} from '../../../src/storage/elasticsearch/types/elasticsearch'; import {Elasticsearch} from '../../../src/storage/elasticsearch/elasticsearch'; import * as Monitoring from '../../../src/storage/elasticsearch/monitoring'; import * as query from '../../../src/storage/elasticsearch/query'; @@ -41,7 +41,6 @@ describe('Elasticsearch', function () { // increase timeout for the suite this.timeout(DEFAULT_TEST_TIMEOUT); const sandbox = sinon.createSandbox(); - let checkESTemplateStub: sinon.SinonStub = sandbox.stub(templating, 'checkESTemplate'); before(function () { console.log('before'); @@ -195,465 +194,481 @@ describe('Elasticsearch', function () { restore(); }); - it('should force mapping update if related process env variable is not set', async function () { - const restore = mockedEnv({ - 'ES_FORCE_MAPPING_UPDATE': undefined, - }); - - new Elasticsearch(configFile); - - expect(checkESTemplateStub.calledWith(false)).to.be.true; - // restore env variables - restore(); - }); - - it('should force mapping update if related process env variable is set', async function () { - const restore = mockedEnv({ - 'ES_FORCE_MAPPING_UPDATE': 'true', - }); - - new Elasticsearch(configFile); - - expect(checkESTemplateStub.calledWith(true)).to.be.true; - // restore env variables - restore(); - }); - }); - - describe('init', async function () { - const sandbox = sinon.createSandbox(); - after(function () { - sandbox.restore(); - }); - - it('should complain (throw an error) if monitoring is set but mail queue is undefined', async function () { - const config: SCConfigFile = { - ...configFile, - internal: { - ...configFile.internal, - monitoring: { - actions: [], - watchers: [], - } - } - }; - - const es = new Elasticsearch(config); - - return expect(es.init()).to.be.rejected; - }); - - it('should setup the monitoring if there is monitoring is set and mail queue is defined', function () { - const config: SCConfigFile = { - ...configFile, - internal: { - ...configFile.internal, - monitoring: { - actions: [], - watchers: [], - } - } - }; - const monitoringSetUpStub = sandbox.stub(Monitoring, 'setUp'); - - const es = new Elasticsearch(config, new MailQueue(getTransport(false) as unknown as SMTP)); - - es.init(); - - expect(monitoringSetUpStub.called).to.be.true; - }); - }); - - describe('Operations with bundle/index', async function () { - const sandbox = sinon.createSandbox(); - let es: Elasticsearch; - const oldIndex = 'stapps_footype_foosource_oldindex'; - - beforeEach(function () { - es = new Elasticsearch(configFile); - // @ts-ignore - es.client.indices = { - // @ts-ignore - getAlias: () => Promise.resolve({body: [{[oldIndex]: {aliases: {[SCThingType.Book]: {}}}}]}), - // @ts-ignore - putTemplate: () => Promise.resolve({}), - // @ts-ignore - create: () => Promise.resolve({}), - // @ts-ignore - delete: () => Promise.resolve({}), - // @ts-ignore - exists: () => Promise.resolve({}), - // @ts-ignore - refresh: () => Promise.resolve({}), - // @ts-ignore - updateAliases: () => Promise.resolve({}) - }; - }); - - afterEach(function () { - sandbox.restore(); - }); - - describe('bulkCreated', async function () { - it('should reject (throw an error) if the connection to elasticsearch is not established', async function () { - return expect(es.bulkCreated(bulk)).to.be.rejectedWith('elasticsearch'); - }); - - it('should reject (throw an error) if the index name is not valid', async function () { - sandbox.stub(Elasticsearch, 'getIndex').returns(`invalid_${getIndex}`); - sandbox.createStubInstance(Client, {}); - await es.init(); - - return expect(es.bulkCreated(bulk)).to.be.rejectedWith('Index'); - }); - - it('should create a new index', async function () { - const index = getIndex(); - sandbox.stub(Elasticsearch, 'getIndex').returns(index); - const putTemplateStub = sandbox.stub(templating, 'putTemplate'); - const createStub = sandbox.stub(es.client.indices, 'create'); - await es.init(); - - await es.bulkCreated(bulk); - - expect(putTemplateStub.called).to.be.true; - expect(createStub.calledWith({index})).to.be.true; - }); - }); - - describe('bulkExpired', async function () { + describe('init', async function () { const sandbox = sinon.createSandbox(); + after(function () { + sandbox.restore(); + }); + + it('should complain (throw an error) if monitoring is set but mail queue is undefined', async function () { + const config: SCConfigFile = { + ...configFile, + internal: { + ...configFile.internal, + monitoring: { + actions: [], + watchers: [], + } + } + }; + + const es = new Elasticsearch(config); + + return expect(es.init()).to.be.rejected; + }); + + it('should setup the monitoring if there is monitoring is set and mail queue is defined', function () { + const config: SCConfigFile = { + ...configFile, + internal: { + ...configFile.internal, + monitoring: { + actions: [], + watchers: [], + } + } + }; + const monitoringSetUpStub = sandbox.stub(Monitoring, 'setUp'); + + const es = new Elasticsearch(config, new MailQueue(getTransport(false) as unknown as SMTP)); + + es.init(); + + expect(monitoringSetUpStub.called).to.be.true; + }); + }); + + describe('Operations with bundle/index', async function () { + const sandbox = sinon.createSandbox(); + let es: Elasticsearch; + const oldIndex = 'stapps_footype_foosource_oldindex'; + + beforeEach(function () { + es = new Elasticsearch(configFile); + // @ts-ignore + es.client.indices = { + // @ts-ignore + getAlias: () => Promise.resolve({body: [{[oldIndex]: {aliases: {[SCThingType.Book]: {}}}}]}), + // @ts-ignore + putTemplate: () => Promise.resolve({}), + // @ts-ignore + create: () => Promise.resolve({}), + // @ts-ignore + delete: () => Promise.resolve({}), + // @ts-ignore + exists: () => Promise.resolve({}), + // @ts-ignore + refresh: () => Promise.resolve({}), + // @ts-ignore + updateAliases: () => Promise.resolve({}) + }; + }); + afterEach(function () { sandbox.restore(); }); - it('should cleanup index in case of the expired bulk for bulk whose index is not in use', async function () { - sandbox.stub(Elasticsearch, 'getIndex').returns(getIndex()); - const clientDeleteStub = sandbox.stub(es.client.indices, 'delete'); - await es.bulkExpired({...bulk, state: 'in progress'}); + describe('bulkCreated', async function () { + it('should reject (throw an error) if the connection to elasticsearch is not established', async function () { + return expect(es.bulkCreated(bulk)).to.be.rejectedWith('elasticsearch'); + }); - expect(clientDeleteStub.called).to.be.true; + it('should reject (throw an error) if the index name is not valid', async function () { + sandbox.stub(Elasticsearch, 'getIndex').returns(`invalid_${getIndex}`); + sandbox.createStubInstance(Client, {}); + await es.init(); + + return expect(es.bulkCreated(bulk)).to.be.rejectedWith('Index'); + }); + + it('should create a new index', async function () { + const index = getIndex(); + sandbox.stub(Elasticsearch, 'getIndex').returns(index); + const putTemplateStub = sandbox.stub(templating, 'putTemplate'); + const createStub = sandbox.stub(es.client.indices, 'create'); + await es.init(); + + await es.bulkCreated(bulk); + + expect(putTemplateStub.called).to.be.true; + expect(createStub.calledWith({index})).to.be.true; + }); }); - it('should not cleanup index in case of the expired bulk for bulk whose index is in use', async function () { - sandbox.stub(Elasticsearch, 'getIndex').returns(getIndex()); - const clientDeleteStub = sandbox.stub(es.client.indices, 'delete'); + describe('bulkExpired', async function () { + const sandbox = sinon.createSandbox(); + afterEach(function () { + sandbox.restore(); + }); + it('should cleanup index in case of the expired bulk for bulk whose index is not in use', async function () { + sandbox.stub(Elasticsearch, 'getIndex').returns(getIndex()); + const clientDeleteStub = sandbox.stub(es.client.indices, 'delete'); - await es.bulkExpired({...bulk, state: 'done'}); + await es.bulkExpired({...bulk, state: 'in progress'}); - expect(clientDeleteStub.called).to.be.false; + expect(clientDeleteStub.called).to.be.true; + }); + + it('should not cleanup index in case of the expired bulk for bulk whose index is in use', async function () { + sandbox.stub(Elasticsearch, 'getIndex').returns(getIndex()); + const clientDeleteStub = sandbox.stub(es.client.indices, 'delete'); + + await es.bulkExpired({...bulk, state: 'done'}); + + expect(clientDeleteStub.called).to.be.false; + }); + }); + + describe('bulkUpdated', function () { + it('should reject if the connection to elasticsearch is not established', async function () { + return expect(es.bulkUpdated(bulk)).to.be.rejectedWith('elasticsearch'); + }); + + it('should reject if the index name is not valid', async function () { + sandbox.stub(Elasticsearch, 'getIndex').returns(`invalid_${getIndex()}`); + sandbox.createStubInstance(Client, {}); + await es.init(); + + return expect(es.bulkUpdated(bulk)).to.be.rejectedWith('Index'); + }); + + it('should create a new index', async function () { + const index = getIndex(); + const expectedRefreshActions = [ + { + add: {index: index, alias: SCThingType.Book}, + }, + { + remove: {index: oldIndex, alias: SCThingType.Book}, + } + ]; + sandbox.stub(Elasticsearch, 'getIndex').returns(index); + sandbox.stub(es, 'aliasMap').value({ + [SCThingType.Book]: { + [bulk.source]: oldIndex, + } + }); + const refreshStub = sandbox.stub(es.client.indices, 'refresh'); + const updateAliasesStub = sandbox.stub(es.client.indices, 'updateAliases'); + const deleteStub = sandbox.stub(es.client.indices, 'delete'); + sandbox.stub(templating, 'putTemplate'); + await es.init(); + + await es.bulkUpdated(bulk); + + expect(refreshStub.calledWith({index})).to.be.true; + expect(updateAliasesStub.calledWith({ + body: { + actions: expectedRefreshActions + } + }) + ).to.be.true; + expect(deleteStub.called).to.be.true; + }); }); }); - describe('bulkUpdated', function () { - it('should reject if the connection to elasticsearch is not established', async function () { - return expect(es.bulkUpdated(bulk)).to.be.rejectedWith('elasticsearch'); + describe('get', async function () { + let es: Elasticsearch; + const sandbox = sinon.createSandbox(); + + before(function () { + es = new Elasticsearch(configFile); }); - it('should reject if the index name is not valid', async function () { - sandbox.stub(Elasticsearch, 'getIndex').returns(`invalid_${getIndex()}`); - sandbox.createStubInstance(Client, {}); - await es.init(); - - return expect(es.bulkUpdated(bulk)).to.be.rejectedWith('Index'); + afterEach(function () { + sandbox.restore(); }); - it('should create a new index', async function () { + it('should reject if object is not found', async function () { + sandbox.stub(es.client, 'search').resolves({body: {hits: {hits: []}}}); + + return expect(es.get('123')).to.rejectedWith('found'); + }); + + it('should provide the thing if object is found', async function () { + const foundObject: ElasticsearchObject = { + _id: '', + _index: '', + _score: 0, + _type: '', + _source: message as SCMessage + }; + sandbox.stub(es.client, 'search').resolves({body: {hits: {hits: [foundObject]}}}); + + return expect(await es.get('123')).to.be.eql(message); + }); + }); + + describe('post', async function () { + let es: Elasticsearch; + const sandbox = sinon.createSandbox(); + + before(function () { + es = new Elasticsearch(configFile); + }); + + afterEach(function () { + sandbox.restore(); + }); + + it('should not post if the object already exists in an index which will not be rolled over', async function () { const index = getIndex(); - const expectedRefreshActions = [ - { - add: {index: index, alias: SCThingType.Book}, + const oldIndex = index.replace('foosource', 'barsource'); + const object: ElasticsearchObject = { + _id: '', + _index: oldIndex, + _score: 0, + _type: '', + _source: message as SCMessage + }; + sandbox.stub(es.client, 'search').resolves({body: {hits: {hits: [object]}}}); + sandbox.stub(Elasticsearch, 'getIndex').returns(index); + + return expect(es.post(object._source, bulk)).to.rejectedWith('exist'); + }); + + it('should not reject if the object already exists but in an index which will be rolled over', async function () { + const object: ElasticsearchObject = { + _id: '', + _index: getIndex(), + _score: 0, + _type: '', + _source: message as SCMessage + }; + sandbox.stub(es.client, 'search').resolves({body: {hits: {hits: [object]}}}); + // return index name with different generated UID (see getIndex method) + sandbox.stub(Elasticsearch, 'getIndex').returns(getIndex()); + + return expect(es.post(object._source, bulk)).to.not.rejectedWith('exist'); + }); + + it('should reject if there is an object creation error on the elasticsearch side', async function () { + sandbox.stub(es.client, 'search').resolves({body: {hits: {hits: []}}}); + sandbox.stub(es.client, 'create').resolves({body: {created: false}}); + + return expect(es.post(message as SCMessage, bulk)).to.rejectedWith('creation'); + }); + + it('should create a new object', async function () { + let caughtParam: any; + sandbox.stub(es.client, 'search').resolves({body: {hits: {hits: []}}}); + // @ts-ignore + let createStub = sandbox.stub(es.client, 'create').callsFake((param) => { + caughtParam = param; + return Promise.resolve({body: {created: true}}); + }); + + await es.post(message as SCMessage, bulk); + + expect(createStub.called).to.be.true; + expect(caughtParam.body).to.be.eql({...message, creation_date: caughtParam.body.creation_date}); + }); + }); + + describe('put', async function () { + let es: Elasticsearch; + const sandbox = sinon.createSandbox(); + + before(function () { + es = new Elasticsearch(configFile); + }); + afterEach(function () { + sandbox.restore(); + }); + it('should reject to put if the object does not already exist', async function () { + const object: ElasticsearchObject = { + _id: '', + _index: getIndex(), + _score: 0, + _type: '', + _source: message as SCMessage + }; + sandbox.stub(es.client, 'search').resolves({body: {hits: {hits: []}}}); + + return expect(es.put(object._source)).to.rejectedWith('exist'); + }); + + it('should update the object if it already exists', async function () { + let caughtParam: any; + const object: ElasticsearchObject = { + _id: '', + _index: getIndex(), + _score: 0, + _type: '', + _source: message as SCMessage + }; + sandbox.stub(es.client, 'search').resolves({body: {hits: {hits: [object]}}}); + // @ts-ignore + const stubUpdate = sandbox.stub(es.client, 'update').callsFake((params) => { + caughtParam = params; + return Promise.resolve({body: {created: true}}); + }); + + await es.put(object._source); + + expect(caughtParam.body.doc).to.be.eql(object._source); + }); + }); + + describe('search', async function () { + let es: Elasticsearch; + const sandbox = sinon.createSandbox(); + const objectMessage: ElasticsearchObject = { + _id: '123', + _index: getIndex(), + _score: 0, + _type: '', + _source: message as SCMessage + }; + const objectBook: ElasticsearchObject = { + _id: '321', + _index: getIndex(), + _score: 0, + _type: '', + _source: book as SCBook + }; + const fakeEsAggregations = { + '@all': { + doc_count: 17, + type: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [ + { + key: 'person', + doc_count: 13 + }, + { + key: 'catalog', + doc_count: 4 + } + ] + } + } + }; + const fakeSearchResponse: Partial>> = { + // @ts-ignore + body: { + took: 12, + timed_out: false, + // @ts-ignore + _shards: {}, + // @ts-ignore + hits: { + hits: [ + objectMessage, + objectBook, + ], + total: 123 }, + aggregations: fakeEsAggregations + }, + headers: {}, + // @ts-ignore + meta: {}, + // @ts-ignore + statusCode: {}, + // @ts-ignore + warnings: {} + }; + let searchStub: sinon.SinonStub; + before(function () { + es = new Elasticsearch(configFile); + }); + beforeEach(function () { + searchStub = sandbox.stub(es.client, 'search').resolves(fakeSearchResponse); + }); + afterEach(function () { + sandbox.restore(); + }); + + it('should provide appropriate data and facets', async function () { + const fakeFacets = [ { - remove: {index: oldIndex, alias: SCThingType.Book}, + buckets: [ + { + count: 13, + key: 'person', + }, + { + count: 4, + key: 'catalog' + } + ], + field: 'type', } ]; - sandbox.stub(Elasticsearch, 'getIndex').returns(index); - sandbox.stub(es, 'aliasMap').value({ - [SCThingType.Book]: { - [bulk.source]: oldIndex, - } + + const {data, facets} = await es.search({}); + + expect(data).to.be.eql([objectMessage._source, objectBook._source]); + expect(facets).to.be.eql(fakeFacets); + }); + + it('should provide pagination from params', async function () { + const from = 30; + const {pagination} = await es.search({from}); + + expect(pagination).to.be.eql({ + count: fakeSearchResponse.body!.hits.hits.length, + offset: from, + total: fakeSearchResponse.body!.hits.total }); - const refreshStub = sandbox.stub(es.client.indices, 'refresh'); - const updateAliasesStub = sandbox.stub(es.client.indices, 'updateAliases'); - const deleteStub = sandbox.stub(es.client.indices, 'delete'); - sandbox.stub(templating, 'putTemplate'); - await es.init(); + }); - await es.bulkUpdated(bulk); + it('should have fallback to zero if from is not given through params', async function () { + const {pagination} = await es.search({}); - expect(refreshStub.calledWith({index})).to.be.true; - expect(updateAliasesStub.calledWith({ - body: { - actions: expectedRefreshActions + expect(pagination.offset).to.be.equal(0); + }); + + it('should build the search request properly', async function () { + const params: SCSearchQuery = { + query: 'mathematics', + from: 30, + size: 5, + sort: [ + { + type: 'ducet', + order: 'desc', + arguments: + { + field: 'name' + } + } + ], + filter: { + type: 'value', + arguments: { + field: 'type', + value: SCThingType.AcademicEvent + } } - }) - ).to.be.true; - expect(deleteStub.called).to.be.true; - }); - }); - }); - - describe('get', async function () { - let es: Elasticsearch; - const sandbox = sinon.createSandbox(); - - before(function () { - es = new Elasticsearch(configFile); - }); - - afterEach(function () { - sandbox.restore(); - }); - - it('should reject if object is not found', async function () { - sandbox.stub(es.client, 'search').resolves({body:{hits: { hits: []}}}); - - return expect(es.get('123')).to.rejectedWith('found'); - }); - - it('should provide the thing if object is found', async function () { - const foundObject: ElasticsearchObject = {_id: '', _index: '', _score: 0, _type: '', _source: message as SCMessage}; - sandbox.stub(es.client, 'search').resolves({body:{hits: { hits: [foundObject]}}}); - - return expect(await es.get('123')).to.be.eql(message); - }); - }); - - describe('post', async function () { - let es: Elasticsearch; - const sandbox = sinon.createSandbox(); - - before(function () { - es = new Elasticsearch(configFile); - }); - - afterEach(function () { - sandbox.restore(); - }); - - it('should not post if the object already exists in an index which will not be rolled over', async function () { - const index = getIndex(); - const oldIndex = index.replace('foosource', 'barsource'); - const object: ElasticsearchObject = {_id: '', _index: oldIndex, _score: 0, _type: '', _source: message as SCMessage}; - sandbox.stub(es.client, 'search').resolves({body:{hits: { hits: [object]}}}); - sandbox.stub(Elasticsearch, 'getIndex').returns(index); - - return expect(es.post(object._source, bulk)).to.rejectedWith('exist'); - }); - - it('should not reject if the object already exists but in an index which will be rolled over', async function () { - const object: ElasticsearchObject = {_id: '', _index: getIndex(), _score: 0, _type: '', _source: message as SCMessage}; - sandbox.stub(es.client, 'search').resolves({body:{hits: { hits: [object]}}}); - // return index name with different generated UID (see getIndex method) - sandbox.stub(Elasticsearch, 'getIndex').returns(getIndex()); - - return expect(es.post(object._source, bulk)).to.not.rejectedWith('exist'); - }); - - it('should reject if there is an object creation error on the elasticsearch side', async function () { - sandbox.stub(es.client, 'search').resolves({body:{hits: { hits: []}}}); - sandbox.stub(es.client, 'create').resolves({body: {created: false}}); - - return expect(es.post(message as SCMessage, bulk)).to.rejectedWith('creation'); - }); - - it('should create a new object', async function () { - let caughtParam: any; - sandbox.stub(es.client, 'search').resolves({body:{hits: { hits: []}}}); - // @ts-ignore - let createStub = sandbox.stub(es.client, 'create').callsFake((param) => { - caughtParam = param; - return Promise.resolve({body: { created: true }}); - }); - - await es.post(message as SCMessage, bulk); - - expect(createStub.called).to.be.true; - expect(caughtParam.body).to.be.eql({...message, creation_date: caughtParam.body.creation_date}); - }); - }); - - describe('put', async function () { - let es: Elasticsearch; - const sandbox = sinon.createSandbox(); - - before(function () { - es = new Elasticsearch(configFile); - }); - afterEach(function () { - sandbox.restore(); - }); - it('should reject to put if the object does not already exist', async function () { - const object: ElasticsearchObject = {_id: '', _index: getIndex(), _score: 0, _type: '', _source: message as SCMessage}; - sandbox.stub(es.client, 'search').resolves({body:{hits: { hits: []}}}); - - return expect(es.put(object._source)).to.rejectedWith('exist'); - }); - - it('should update the object if it already exists', async function () { - let caughtParam: any; - const object: ElasticsearchObject = {_id: '', _index: getIndex(), _score: 0, _type: '', _source: message as SCMessage}; - sandbox.stub(es.client, 'search').resolves({body:{hits: { hits: [object]}}}); - // @ts-ignore - const stubUpdate = sandbox.stub(es.client, 'update').callsFake((params) => { - caughtParam = params; - return Promise.resolve({body: { created: true }}); - }); - - await es.put(object._source); - - expect(caughtParam.body.doc).to.be.eql(object._source); - }); - }); - - describe('search', async function () { - let es: Elasticsearch; - const sandbox = sinon.createSandbox(); - const objectMessage: ElasticsearchObject = {_id: '123', _index: getIndex(), _score: 0, _type: '', _source: message as SCMessage}; - const objectBook: ElasticsearchObject = {_id: '321', _index: getIndex(), _score: 0, _type: '', _source: book as SCBook}; - const fakeEsAggregations = { - '@all': { - doc_count: 17, - type: { - doc_count_error_upper_bound: 0, - sum_other_doc_count: 0, - buckets: [ - { - key: 'person', - doc_count: 13 - }, - { - key: 'catalog', - doc_count: 4 - } - ] - } - } - }; - const fakeSearchResponse: Partial>> = { - // @ts-ignore - body: { - took: 12, - timed_out: false, + }; + const fakeResponse = {foo: 'bar'}; + const fakeBuildSortResponse = [fakeResponse]; // @ts-ignore - _shards: {}, - // @ts-ignore - hits: { - hits: [ - objectMessage, - objectBook, - ], - total: 123 - }, - aggregations: fakeEsAggregations - }, - headers: {}, - // @ts-ignore - meta: {}, - // @ts-ignore - statusCode: {}, - // @ts-ignore - warnings: {} - }; - let searchStub: sinon.SinonStub; - before(function () { - es = new Elasticsearch(configFile); + sandbox.stub(query, 'buildQuery').returns(fakeResponse); + // @ts-ignore + sandbox.stub(query, 'buildSort').returns(fakeBuildSortResponse); + + await es.search(params); + + sandbox.assert + .calledWithMatch(searchStub, + { + body: { + aggs: aggregations, + query: fakeResponse, + sort: fakeBuildSortResponse + }, + from: params.from, + index: Elasticsearch.getListOfAllIndices(), + size: params.size, + } + ); + }); }); - beforeEach(function () { - searchStub = sandbox.stub(es.client, 'search').resolves(fakeSearchResponse); - }); - afterEach(function () { - sandbox.restore(); - }); - - it('should provide appropriate data and facets', async function () { - const fakeFacets = [ - { - buckets: [ - { - count: 1, - 'key': 'foo' - }, - { - count: 1, - key: 'bar' - } - ], - field: 'type', - } - ]; - const parseAggregationsStub = sandbox.stub(aggregations, 'parseAggregations').returns(fakeFacets); - - const {data, facets} = await es.search({}); - - expect(data).to.be.eql([objectMessage._source, objectBook._source]); - expect(facets).to.be.eql(fakeFacets); - expect(parseAggregationsStub.calledWith(sinon.match.any, fakeEsAggregations)).to.be.true; - }); - - it('should provide pagination from params', async function () { - const from = 30; - const {pagination} = await es.search({from}); - - expect(pagination).to.be.eql({ - count: fakeSearchResponse.body!.hits.hits.length, - offset: from, - total: fakeSearchResponse.body!.hits.total - }); - }); - - it('should have fallback to zero if from is not given through params', async function () { - const {pagination} = await es.search({}); - - expect(pagination.offset).to.be.equal(0); - }); - - it('should build the search request properly', async function () { - const params: SCSearchQuery = { - query: 'mathematics', - from: 30, - size: 5, - sort: [ - { - type: 'ducet', - order: 'desc', - arguments: - { - field: 'name' - } - } - ], - filter: { - type: 'value', - arguments: { - field: 'type', - value: SCThingType.AcademicEvent - } - } - }; - const fakeResponse = {foo: 'bar'}; - const fakeBuildSortResponse = [fakeResponse]; - // @ts-ignore - sandbox.stub(query, 'buildQuery').returns(fakeResponse); - // @ts-ignore - sandbox.stub(query, 'buildSort').returns(fakeBuildSortResponse); - - await es.search(params); - - sandbox.assert - .calledWithMatch(searchStub, - { - body: { - aggs: es.aggregationsSchema, - query: fakeResponse, - sort: fakeBuildSortResponse - }, - from: params.from, - index: Elasticsearch.getListOfAllIndices(), - size: params.size, - } - ); - }); }); }); diff --git a/test/storage/elasticsearch/monitoring.spec.ts b/test/storage/elasticsearch/monitoring.spec.ts index 9cc3aef0..29ad6734 100644 --- a/test/storage/elasticsearch/monitoring.spec.ts +++ b/test/storage/elasticsearch/monitoring.spec.ts @@ -29,7 +29,6 @@ import {getTransport} from '../../common'; import { expect } from 'chai'; import sinon from 'sinon'; import cron from 'node-cron'; -import * as templating from '../../../src/storage/elasticsearch/templating'; describe('Monitoring', async function () { const sandbox = sinon.createSandbox(); @@ -51,7 +50,6 @@ describe('Monitoring', async function () { transport = getTransport(true); mailQueue = new MailQueue(transport); cronScheduleStub = sandbox.stub(cron, 'schedule'); - sandbox.stub(templating, 'checkESTemplate'); }); afterEach(async function () { sandbox.restore(); diff --git a/test/storage/elasticsearch/query.spec.ts b/test/storage/elasticsearch/query.spec.ts index e9edb591..ad8921a2 100644 --- a/test/storage/elasticsearch/query.spec.ts +++ b/test/storage/elasticsearch/query.spec.ts @@ -22,15 +22,19 @@ import { SCThingType } from '@openstapps/core'; import {expect} from 'chai'; -import {ESDateRangeFilter, ESRangeFilter} from '../../../src/storage/elasticsearch/common'; -import {ESNumericRangeFilter} from '../../../src/storage/elasticsearch/common'; -import {configFile} from '../../../src/common'; import { - ElasticsearchConfig, ESBooleanFilter, ESGenericSort, ESGeoDistanceFilter, + ESDateRangeFilter, + ESRangeFilter, + ESNumericRangeFilter, + ElasticsearchConfig, + ESBooleanFilter, + ESGenericSort, + ESGeoDistanceFilter, ESGeoDistanceSort, ESTermFilter, ScriptSort -} from '../../../src/storage/elasticsearch/common'; +} from '../../../src/storage/elasticsearch/types/elasticsearch'; +import {configFile} from '../../../src/common'; import {buildBooleanFilter, buildFilter, buildQuery, buildSort} from '../../../src/storage/elasticsearch/query'; describe('Query', function () { @@ -366,7 +370,7 @@ describe('Query', function () { } }); - it('should default to second scope', function() { + it('should default to second scope', function () { const filter = buildFilter({ type: 'availability', arguments: { @@ -384,7 +388,7 @@ describe('Query', function () { }, }; expect(filter).to.be.eql(expectedFilter); - }) + }); it('should add || to dates', function () { const filter = buildFilter({ diff --git a/test/storage/elasticsearch/templating.spec.ts b/test/storage/elasticsearch/templating.spec.ts deleted file mode 100644 index 74140098..00000000 --- a/test/storage/elasticsearch/templating.spec.ts +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2020 StApps - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -import {SCThingType} from '@openstapps/core'; -import * as mapping from '@openstapps/core-tools/lib/mapping'; -import {ElasticsearchTemplateCollection} from '@openstapps/core-tools/lib/mappings/mapping-definitions'; -import {Logger} from '@openstapps/logger'; -import {AggregationSchema} from '../../../src/storage/elasticsearch/common'; -import {checkESTemplate, refreshAllTemplates} from '../../../src/storage/elasticsearch/templating'; -import sinon from "sinon"; -import * as path from 'path'; -import * as common from '@openstapps/core-tools/lib/common'; -import {expect} from 'chai'; -import fs from 'fs'; -import fsExtra from 'fs-extra'; -import {Client} from '@elastic/elasticsearch'; - -describe('templating', function () { - describe('checkESTemplate', function () { - const sandbox = sinon.createSandbox(); - let fakeMap: { aggregations: AggregationSchema, errors: string[], mappings: ElasticsearchTemplateCollection }; - beforeEach(function () { - fakeMap = { - aggregations: { - '@all': { - aggs: { - type: { - terms: { - field: 'type.raw', - size: 1000 - } - } - }, - filter: { - match_all: {} - } - }, - }, - errors: [], - mappings: { - 'template_dish': { - mappings: { - dish: { - // @ts-ignore just mock the mapping - foo: 'mapping' - } - }, - settings: { - analysis: { - ducet_sort: { - filter: [ - 'german_phonebook' - ], - tokenizer: 'keyword', - type: 'custom' - }, - search_german: { - filter: [ - 'lowercase', - 'german_stop', - 'german_stemmer' - ], - tokenizer: 'stapps_ngram', - type: 'custom' - } - }, - max_result_window: 30000, - }, - template: 'stapps_dish*' - }, - 'template_book': { - mappings: { - book: { - // @ts-ignore just mock the mapping - foo: 'mapping' - } - }, - settings: { - analysis: { - ducet_sort: { - filter: [ - 'german_phonebook' - ], - tokenizer: 'keyword', - type: 'custom' - }, - search_german: { - filter: [ - 'lowercase', - 'german_stop', - 'german_stemmer' - ], - tokenizer: 'stapps_ngram', - type: 'custom' - } - }, - max_result_window: 30000, - }, - template: 'stapps_book*' - } - } - } - }); - afterEach(function () { - sandbox.restore(); - }); - - it('should write new templates when "force update" is true', async function () { - sandbox.stub(Logger, 'error').resolves(); - sandbox.stub(fs, 'existsSync').returns(true); - sandbox.stub(common, 'getProjectReflection'); - let caughtData: any = []; - const writeFileSyncStub = sandbox.stub(fs, 'writeFileSync'); - sandbox.stub(path, 'resolve').returns('/foo/bar'); - sandbox.stub(mapping, 'generateTemplate').returns(fakeMap); - - checkESTemplate(true); - - expect(writeFileSyncStub.callCount).to.be.gt(0); - for (let i = 0; i < writeFileSyncStub.callCount; i++) { - caughtData.push(writeFileSyncStub.getCall(i).args[1]); - } - - expect(caughtData).to.be.eql([ - JSON.stringify(fakeMap.mappings['template_dish'], null, 2), - JSON.stringify(fakeMap.mappings['template_book'], null, 2), - JSON.stringify(fakeMap.aggregations), - ]); - }); - - it('should not write new templates when "force update" is false', async function () { - sandbox.stub(Logger, 'error').resolves(); - sandbox.stub(fs, 'existsSync').returns(true); - sandbox.stub(common, 'getProjectReflection'); - const writeFileSyncStub = sandbox.stub(fs, 'writeFileSync'); - sandbox.stub(path, 'resolve').returns('/foo/bar'); - sandbox.stub(mapping, 'generateTemplate').returns(fakeMap); - - checkESTemplate(false); - - expect(writeFileSyncStub.called).to.be.false; - }); - - it('should terminate if there are errors in the map', async function () { - const processExitStub = sandbox.stub(process, 'exit'); - const fakeMapWithErrors = { - ...fakeMap, - errors: ['Foo Error'] - }; - sandbox.stub(Logger, 'error').resolves(); - sandbox.stub(fs, 'existsSync').returns(true); - sandbox.stub(common, 'getProjectReflection'); - sandbox.stub(fs, 'writeFileSync'); - sandbox.stub(path, 'resolve').returns('/foo/bar'); - sandbox.stub(mapping, 'generateTemplate').returns(fakeMapWithErrors); - - checkESTemplate(true); - - expect(processExitStub.called).to.be.true; - }); - }); - - describe('refreshAllTemplates', async function () { - const sandbox = sinon.createSandbox(); - const client = { - indices: { - putTemplate: (_template: any) => { - } - } - } - - after(function () { - sandbox.restore(); - }); - - it('should put templates for all types', async function () { - const clientPutTemplateStub = sandbox.stub(client.indices, 'putTemplate'); - sandbox.stub(fsExtra, 'readFile').resolves(Buffer.from('{"foo": "file content"}', 'utf8')); - await refreshAllTemplates(client as Client); - - for (const type of Object.values(SCThingType)) { - sinon.assert.calledWith(clientPutTemplateStub, { - body: {foo: 'file content'}, - name: `template_${type.split(' ').join('_')}` - }) - } - }); - }); -});