Page MenuHomeSealhub

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/common_lib/response/responses.ts b/common_lib/response/responses.ts
index b9ef943d..a0866530 100644
--- a/common_lib/response/responses.ts
+++ b/common_lib/response/responses.ts
@@ -1,26 +1,26 @@
-import CollectionItem from "../../src/chip-types/collection-item";
+import type CollectionItem from "../../src/chip-types/collection-item";
export class NewSession {
status: string;
message: string;
data: any;
metadata: any;
constructor(session_id: string) {
this.status = "success";
this.message = "Logged in!";
Object.defineProperty(this, "metadata", {
value: { session_id: session_id },
});
this.data = {};
}
}
export class ResourceCreated {
[field: string]: any;
constructor(item: CollectionItem) {
for (const field in item.collection.fields) {
this[field] = item.get(field);
}
this.id = item.id;
}
}
diff --git a/package-lock.json b/package-lock.json
index 071cc978..da78b36a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6030 +1,14168 @@
{
"name": "sealious",
"version": "0.14.10",
- "lockfileVersion": 1,
+ "lockfileVersion": 2,
"requires": true,
+ "packages": {
+ "": {
+ "name": "sealious",
+ "version": "0.14.10",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "@babel/polyfill": "^7.0.0",
+ "@koa/router": "^10.0.0",
+ "@sealcode/ts-predicates": "^0.2.5",
+ "@types/bluebird": "^3.5.30",
+ "@types/boom": "^7.3.0",
+ "@types/clone": "^0.1.30",
+ "@types/color": "^3.0.1",
+ "@types/color-hash": "^1.0.0",
+ "@types/escape-html": "^1.0.0",
+ "@types/koa": "^2.11.6",
+ "@types/koa__router": "*",
+ "@types/koa-mount": "^4.0.0",
+ "@types/koa-qs": "^2.0.0",
+ "@types/koa-send": "^4.1.2",
+ "@types/koa-static": "^4.0.1",
+ "@types/mime": "^2.0.2",
+ "@types/mjml": "^4.0.4",
+ "@types/mocha": "^7.0.2",
+ "@types/mongodb": "^3.5.20",
+ "@types/node": "^13.13.4",
+ "@types/nodemailer": "^6.4.0",
+ "@types/object-hash": "^1.3.3",
+ "@types/shortid": "0.0.29",
+ "@types/uuid": "^8.3.0",
+ "axios": "^0.18.1",
+ "bluebird": "^3.4.6",
+ "boom": "^7.3.0",
+ "chalk": "^4.1.0",
+ "clone": "^1.0.2",
+ "color": "latest",
+ "color-hash": "^1.0.3",
+ "deepmerge": "^4.2.2",
+ "dot-prop": "^5.2.0",
+ "emittery": "github:sindresorhus/emittery#7db46441",
+ "escape-html": "^1.0.3",
+ "get-port": "^5.1.1",
+ "koa": "^2.13.0",
+ "koa-body": "^4.2.0",
+ "koa-mount": "^4.0.0",
+ "koa-qs": "^3.0.0",
+ "koa-send": "^5.0.1",
+ "koa-static": "^5.0.0",
+ "locreq": "^2.0.2",
+ "mime": "^2.4.6",
+ "mjml": "^4.2.0",
+ "mongodb": "^3.6.2",
+ "nodemailer": "^6.4.6",
+ "object-hash": "^2.0.3",
+ "pretty-ms": "^7.0.0",
+ "qs": "^6.5.1",
+ "sanitize-html": "^1.13.0",
+ "shortid": "^2.2.6",
+ "typedoc": "^0.17.8",
+ "uuid": "^8.3.2"
+ },
+ "devDependencies": {
+ "@babel/cli": "^7.0.0",
+ "@babel/core": "^7.0.0",
+ "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
+ "@babel/preset-env": "^7.0.0",
+ "@babel/preset-react": "^7.0.0",
+ "@typescript-eslint/eslint-plugin": "^3.6.0",
+ "@typescript-eslint/parser": "^3.6.0",
+ "eslint": "^7.4.0",
+ "eslint-config-prettier": "^7.1.0",
+ "eslint-plugin-jsdoc": "^29.1.3",
+ "eslint-plugin-node": "^11.1.0",
+ "eslint-plugin-prettier": "^3.3.0",
+ "mocha": "^8.2.1",
+ "mri": "^1.1.6",
+ "nyc": "^15.1.0",
+ "prettier": "^2.2.1",
+ "source-map-support": "^0.5.19",
+ "typescript": "^4.1.3"
+ }
+ },
+ "node_modules/@babel/cli": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.16.8.tgz",
+ "integrity": "sha512-FTKBbxyk5TclXOGmwYyqelqP5IF6hMxaeJskd85jbR5jBfYlwqgwAbJwnixi1ZBbTqKfFuAA95mdmUFeSRwyJA==",
+ "dev": true,
+ "dependencies": {
+ "commander": "^4.0.1",
+ "convert-source-map": "^1.1.0",
+ "fs-readdir-recursive": "^1.1.0",
+ "glob": "^7.0.0",
+ "make-dir": "^2.1.0",
+ "slash": "^2.0.0",
+ "source-map": "^0.5.0"
+ },
+ "bin": {
+ "babel": "bin/babel.js",
+ "babel-external-helpers": "bin/babel-external-helpers.js"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "optionalDependencies": {
+ "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3",
+ "chokidar": "^3.4.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
+ "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.8.tgz",
+ "integrity": "sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.16.12",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz",
+ "integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.16.7",
+ "@babel/generator": "^7.16.8",
+ "@babel/helper-compilation-targets": "^7.16.7",
+ "@babel/helper-module-transforms": "^7.16.7",
+ "@babel/helpers": "^7.16.7",
+ "@babel/parser": "^7.16.12",
+ "@babel/template": "^7.16.7",
+ "@babel/traverse": "^7.16.10",
+ "@babel/types": "^7.16.8",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.1.2",
+ "semver": "^6.3.0",
+ "source-map": "^0.5.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz",
+ "integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.8",
+ "jsesc": "^2.5.1",
+ "source-map": "^0.5.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz",
+ "integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz",
+ "integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-explode-assignable-expression": "^7.16.7",
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz",
+ "integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.16.4",
+ "@babel/helper-validator-option": "^7.16.7",
+ "browserslist": "^4.17.5",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.16.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.10.tgz",
+ "integrity": "sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.16.7",
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-function-name": "^7.16.7",
+ "@babel/helper-member-expression-to-functions": "^7.16.7",
+ "@babel/helper-optimise-call-expression": "^7.16.7",
+ "@babel/helper-replace-supers": "^7.16.7",
+ "@babel/helper-split-export-declaration": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-regexp-features-plugin": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz",
+ "integrity": "sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.16.7",
+ "regexpu-core": "^4.7.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz",
+ "integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.13.0",
+ "@babel/helper-module-imports": "^7.12.13",
+ "@babel/helper-plugin-utils": "^7.13.0",
+ "@babel/traverse": "^7.13.0",
+ "debug": "^4.1.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.14.2",
+ "semver": "^6.1.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0-0"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
+ "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-explode-assignable-expression": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz",
+ "integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz",
+ "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-get-function-arity": "^7.16.7",
+ "@babel/template": "^7.16.7",
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-get-function-arity": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz",
+ "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
+ "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz",
+ "integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
+ "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz",
+ "integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/helper-simple-access": "^7.16.7",
+ "@babel/helper-split-export-declaration": "^7.16.7",
+ "@babel/helper-validator-identifier": "^7.16.7",
+ "@babel/template": "^7.16.7",
+ "@babel/traverse": "^7.16.7",
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz",
+ "integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz",
+ "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-remap-async-to-generator": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz",
+ "integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.16.7",
+ "@babel/helper-wrap-function": "^7.16.8",
+ "@babel/types": "^7.16.8"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz",
+ "integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-member-expression-to-functions": "^7.16.7",
+ "@babel/helper-optimise-call-expression": "^7.16.7",
+ "@babel/traverse": "^7.16.7",
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz",
+ "integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz",
+ "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
+ "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
+ "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz",
+ "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-wrap-function": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz",
+ "integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-function-name": "^7.16.7",
+ "@babel/template": "^7.16.7",
+ "@babel/traverse": "^7.16.8",
+ "@babel/types": "^7.16.8"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz",
+ "integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.16.7",
+ "@babel/traverse": "^7.16.7",
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.16.10",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz",
+ "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.16.7",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.16.12",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz",
+ "integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==",
+ "dev": true,
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz",
+ "integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz",
+ "integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
+ "@babel/plugin-proposal-optional-chaining": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.13.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz",
+ "integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-remap-async-to-generator": "^7.16.8",
+ "@babel/plugin-syntax-async-generators": "^7.8.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-class-properties": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz",
+ "integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-class-static-block": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz",
+ "integrity": "sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.12.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-dynamic-import": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz",
+ "integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-export-namespace-from": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz",
+ "integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-json-strings": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz",
+ "integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-json-strings": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-logical-assignment-operators": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz",
+ "integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz",
+ "integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-numeric-separator": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz",
+ "integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz",
+ "integrity": "sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.16.4",
+ "@babel/helper-compilation-targets": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-transform-parameters": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz",
+ "integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-optional-chaining": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz",
+ "integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-private-methods": {
+ "version": "7.16.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz",
+ "integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.16.10",
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-private-property-in-object": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz",
+ "integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.16.7",
+ "@babel/helper-create-class-features-plugin": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz",
+ "integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-export-namespace-from": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz",
+ "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-arrow-functions": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz",
+ "integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-to-generator": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz",
+ "integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-remap-async-to-generator": "^7.16.8"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz",
+ "integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoping": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz",
+ "integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-classes": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz",
+ "integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.16.7",
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-function-name": "^7.16.7",
+ "@babel/helper-optimise-call-expression": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-replace-supers": "^7.16.7",
+ "@babel/helper-split-export-declaration": "^7.16.7",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-computed-properties": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz",
+ "integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-destructuring": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz",
+ "integrity": "sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-dotall-regex": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz",
+ "integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-duplicate-keys": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz",
+ "integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz",
+ "integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-for-of": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz",
+ "integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-function-name": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz",
+ "integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.16.7",
+ "@babel/helper-function-name": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-literals": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz",
+ "integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-member-expression-literals": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz",
+ "integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-amd": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz",
+ "integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz",
+ "integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-simple-access": "^7.16.7",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-systemjs": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz",
+ "integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-hoist-variables": "^7.16.7",
+ "@babel/helper-module-transforms": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-validator-identifier": "^7.16.7",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-umd": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz",
+ "integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz",
+ "integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-new-target": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz",
+ "integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-super": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz",
+ "integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-replace-supers": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-parameters": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz",
+ "integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-property-literals": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz",
+ "integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-display-name": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz",
+ "integrity": "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.7.tgz",
+ "integrity": "sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.16.7",
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/plugin-syntax-jsx": "^7.16.7",
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-development": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz",
+ "integrity": "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/plugin-transform-react-jsx": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-pure-annotations": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz",
+ "integrity": "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-regenerator": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz",
+ "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==",
+ "dev": true,
+ "dependencies": {
+ "regenerator-transform": "^0.14.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-reserved-words": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz",
+ "integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-shorthand-properties": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz",
+ "integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-spread": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz",
+ "integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-sticky-regex": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz",
+ "integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-template-literals": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz",
+ "integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typeof-symbol": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz",
+ "integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-escapes": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz",
+ "integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-regex": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz",
+ "integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/polyfill": {
+ "version": "7.12.1",
+ "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz",
+ "integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==",
+ "deprecated": "🚨 This package has been deprecated in favor of separate inclusion of a polyfill and regenerator-runtime (when needed). See the @babel/polyfill docs (https://babeljs.io/docs/en/babel-polyfill) for more information.",
+ "dependencies": {
+ "core-js": "^2.6.5",
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "node_modules/@babel/preset-env": {
+ "version": "7.16.11",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz",
+ "integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.16.8",
+ "@babel/helper-compilation-targets": "^7.16.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-validator-option": "^7.16.7",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7",
+ "@babel/plugin-proposal-async-generator-functions": "^7.16.8",
+ "@babel/plugin-proposal-class-properties": "^7.16.7",
+ "@babel/plugin-proposal-class-static-block": "^7.16.7",
+ "@babel/plugin-proposal-dynamic-import": "^7.16.7",
+ "@babel/plugin-proposal-export-namespace-from": "^7.16.7",
+ "@babel/plugin-proposal-json-strings": "^7.16.7",
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.16.7",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7",
+ "@babel/plugin-proposal-numeric-separator": "^7.16.7",
+ "@babel/plugin-proposal-object-rest-spread": "^7.16.7",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.16.7",
+ "@babel/plugin-proposal-optional-chaining": "^7.16.7",
+ "@babel/plugin-proposal-private-methods": "^7.16.11",
+ "@babel/plugin-proposal-private-property-in-object": "^7.16.7",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.16.7",
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5",
+ "@babel/plugin-transform-arrow-functions": "^7.16.7",
+ "@babel/plugin-transform-async-to-generator": "^7.16.8",
+ "@babel/plugin-transform-block-scoped-functions": "^7.16.7",
+ "@babel/plugin-transform-block-scoping": "^7.16.7",
+ "@babel/plugin-transform-classes": "^7.16.7",
+ "@babel/plugin-transform-computed-properties": "^7.16.7",
+ "@babel/plugin-transform-destructuring": "^7.16.7",
+ "@babel/plugin-transform-dotall-regex": "^7.16.7",
+ "@babel/plugin-transform-duplicate-keys": "^7.16.7",
+ "@babel/plugin-transform-exponentiation-operator": "^7.16.7",
+ "@babel/plugin-transform-for-of": "^7.16.7",
+ "@babel/plugin-transform-function-name": "^7.16.7",
+ "@babel/plugin-transform-literals": "^7.16.7",
+ "@babel/plugin-transform-member-expression-literals": "^7.16.7",
+ "@babel/plugin-transform-modules-amd": "^7.16.7",
+ "@babel/plugin-transform-modules-commonjs": "^7.16.8",
+ "@babel/plugin-transform-modules-systemjs": "^7.16.7",
+ "@babel/plugin-transform-modules-umd": "^7.16.7",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8",
+ "@babel/plugin-transform-new-target": "^7.16.7",
+ "@babel/plugin-transform-object-super": "^7.16.7",
+ "@babel/plugin-transform-parameters": "^7.16.7",
+ "@babel/plugin-transform-property-literals": "^7.16.7",
+ "@babel/plugin-transform-regenerator": "^7.16.7",
+ "@babel/plugin-transform-reserved-words": "^7.16.7",
+ "@babel/plugin-transform-shorthand-properties": "^7.16.7",
+ "@babel/plugin-transform-spread": "^7.16.7",
+ "@babel/plugin-transform-sticky-regex": "^7.16.7",
+ "@babel/plugin-transform-template-literals": "^7.16.7",
+ "@babel/plugin-transform-typeof-symbol": "^7.16.7",
+ "@babel/plugin-transform-unicode-escapes": "^7.16.7",
+ "@babel/plugin-transform-unicode-regex": "^7.16.7",
+ "@babel/preset-modules": "^0.1.5",
+ "@babel/types": "^7.16.8",
+ "babel-plugin-polyfill-corejs2": "^0.3.0",
+ "babel-plugin-polyfill-corejs3": "^0.5.0",
+ "babel-plugin-polyfill-regenerator": "^0.3.0",
+ "core-js-compat": "^3.20.2",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-modules": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz",
+ "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+ "@babel/plugin-transform-dotall-regex": "^7.4.4",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-react": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz",
+ "integrity": "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "@babel/helper-validator-option": "^7.16.7",
+ "@babel/plugin-transform-react-display-name": "^7.16.7",
+ "@babel/plugin-transform-react-jsx": "^7.16.7",
+ "@babel/plugin-transform-react-jsx-development": "^7.16.7",
+ "@babel/plugin-transform-react-pure-annotations": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz",
+ "integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==",
+ "dependencies": {
+ "regenerator-runtime": "^0.13.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.16.7",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
+ "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.16.7",
+ "@babel/parser": "^7.16.7",
+ "@babel/types": "^7.16.7"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.16.10",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.10.tgz",
+ "integrity": "sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.16.7",
+ "@babel/generator": "^7.16.8",
+ "@babel/helper-environment-visitor": "^7.16.7",
+ "@babel/helper-function-name": "^7.16.7",
+ "@babel/helper-hoist-variables": "^7.16.7",
+ "@babel/helper-split-export-declaration": "^7.16.7",
+ "@babel/parser": "^7.16.10",
+ "@babel/types": "^7.16.8",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.16.8",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz",
+ "integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.16.7",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
+ "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==",
+ "dev": true,
+ "dependencies": {
+ "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"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "13.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
+ "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@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==",
+ "dev": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^1.2.0",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@koa/router": {
+ "version": "10.1.1",
+ "resolved": "https://registry.npmjs.org/@koa/router/-/router-10.1.1.tgz",
+ "integrity": "sha512-ORNjq5z4EmQPriKbR0ER3k4Gh7YGNhWDL7JBW+8wXDrHLbWYKYSJaOJ9aN06npF5tbTxe2JBOsurpJDAvjiXKw==",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "http-errors": "^1.7.3",
+ "koa-compose": "^4.1.0",
+ "methods": "^1.1.2",
+ "path-to-regexp": "^6.1.0"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/@nicolo-ribaudo/chokidar-2": {
+ "version": "2.1.8-no-fsevents.3",
+ "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz",
+ "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/@sealcode/ts-predicates": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.2.5.tgz",
+ "integrity": "sha512-mALqlRBsjLkroDb3B/m6aYIB4/7kIh6s3R9diCR4EdrUzKyAHtXdgV5SdZyj6llxPOzJt3VYokXvOQbZazw5kg=="
+ },
+ "node_modules/@types/accepts": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz",
+ "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/bluebird": {
+ "version": "3.5.36",
+ "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz",
+ "integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q=="
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.2",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
+ "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/boom": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/@types/boom/-/boom-7.3.1.tgz",
+ "integrity": "sha512-9952U+NySPQ35Xr8CU0lHrC3vBuqjh2xmK87l06uW8PN4ePHOqhtjrJV5+e7lqgb4UtzwUHELkbxEXxnPXLlTA=="
+ },
+ "node_modules/@types/bson": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.2.0.tgz",
+ "integrity": "sha512-ELCPqAdroMdcuxqwMgUpifQyRoTpyYCNr1V9xKyF40VsBobsj+BbWNRvwGchMgBPGqkw655ypkjj2MEF5ywVwg==",
+ "deprecated": "This is a stub types definition. bson provides its own type definitions, so you do not need this installed.",
+ "dependencies": {
+ "bson": "*"
+ }
+ },
+ "node_modules/@types/clone": {
+ "version": "0.1.30",
+ "resolved": "https://registry.npmjs.org/@types/clone/-/clone-0.1.30.tgz",
+ "integrity": "sha1-5zZWSMG0ITalnH1QQGN7O1yDthQ="
+ },
+ "node_modules/@types/color": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.2.tgz",
+ "integrity": "sha512-INiJl6sfNn8iyC5paxVzqiVUEj2boIlFki02uRTAkKwAj++7aAF+ZfEv/XrIeBa0XI/fTZuDHW8rEEcEVnON+Q==",
+ "dependencies": {
+ "@types/color-convert": "*"
+ }
+ },
+ "node_modules/@types/color-convert": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.0.tgz",
+ "integrity": "sha512-m7GG7IKKGuJUXvkZ1qqG3ChccdIM/qBBo913z+Xft0nKCX4hAU/IxKwZBU4cpRZ7GS5kV4vOblUkILtSShCPXQ==",
+ "dependencies": {
+ "@types/color-name": "*"
+ }
+ },
+ "node_modules/@types/color-hash": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@types/color-hash/-/color-hash-1.0.2.tgz",
+ "integrity": "sha512-QJCVXSVRse+mMvzWQ8vH6AcKxtqCgHPHf5abAdGn86DEeQdUpSJnKAeCa1+hZuohaUF3l4RhigC9akRx82Bwig=="
+ },
+ "node_modules/@types/color-name": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.35",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
+ "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-0mPF08jn9zYI0n0Q/Pnz7C4kThdSt+6LD4amsrYDDpgBfrVWa3TcCOxKX1zkGgYniGagRv8heN2cbh+CAn+uuQ=="
+ },
+ "node_modules/@types/cookies": {
+ "version": "0.7.7",
+ "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz",
+ "integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/express": "*",
+ "@types/keygrip": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/escape-html": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@types/escape-html/-/escape-html-1.0.1.tgz",
+ "integrity": "sha512-4mI1FuUUZiuT95fSVqvZxp/ssQK9zsa86S43h9x3zPOSU9BBJ+BfDkXwuaU7BfsD+e7U0/cUUfJFk3iW2M4okA=="
+ },
+ "node_modules/@types/eslint-visitor-keys": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+ "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
+ "dev": true
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.13",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz",
+ "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==",
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.18",
+ "@types/qs": "*",
+ "@types/serve-static": "*"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "4.17.28",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz",
+ "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*"
+ }
+ },
+ "node_modules/@types/formidable": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.2.5.tgz",
+ "integrity": "sha512-zu3mQJa4hDNubEMViSj937602XdDGzK7Q5pJ5QmLUbNxclbo9tZGt5jtwM352ssZ+pqo5V4H14TBvT/ALqQQcA==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/http-assert": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.3.tgz",
+ "integrity": "sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA=="
+ },
+ "node_modules/@types/http-errors": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.2.tgz",
+ "integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w=="
+ },
+ "node_modules/@types/json-schema": {
+ "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==",
+ "dev": true
+ },
+ "node_modules/@types/keygrip": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz",
+ "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw=="
+ },
+ "node_modules/@types/koa": {
+ "version": "2.13.4",
+ "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.4.tgz",
+ "integrity": "sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==",
+ "dependencies": {
+ "@types/accepts": "*",
+ "@types/content-disposition": "*",
+ "@types/cookies": "*",
+ "@types/http-assert": "*",
+ "@types/http-errors": "*",
+ "@types/keygrip": "*",
+ "@types/koa-compose": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/koa__router": {
+ "version": "8.0.11",
+ "resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-8.0.11.tgz",
+ "integrity": "sha512-WXgKWpBsbS14kzmzD9LeFapOIa678h7zvUHxDwXwSx4ETKXhXLVUAToX6jZ/U7EihM7qwyD9W/BZvB0MRu7MTQ==",
+ "dependencies": {
+ "@types/koa": "*"
+ }
+ },
+ "node_modules/@types/koa-compose": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz",
+ "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==",
+ "dependencies": {
+ "@types/koa": "*"
+ }
+ },
+ "node_modules/@types/koa-mount": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@types/koa-mount/-/koa-mount-4.0.1.tgz",
+ "integrity": "sha512-HNeg80CVS9Dfq8dGYqCZZCAUm7g6jPCNJ1ydqVLEJxLrjmeburpvq+lOZkE4rxBZ6O38dr3tj9IA3IfbdoI05w==",
+ "dependencies": {
+ "@types/koa": "*"
+ }
+ },
+ "node_modules/@types/koa-qs": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/koa-qs/-/koa-qs-2.0.0.tgz",
+ "integrity": "sha512-cBfbUvW70JsU2FCgUCFOoretdvayGzRJ2vEyNQbnZ7vb2pZ/QA+gcNzE6nVxxCcrcnRtGB7tXIRHqHPXS51utA==",
+ "dependencies": {
+ "@types/koa": "*"
+ }
+ },
+ "node_modules/@types/koa-send": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/@types/koa-send/-/koa-send-4.1.3.tgz",
+ "integrity": "sha512-daaTqPZlgjIJycSTNjKpHYuKhXYP30atFc1pBcy6HHqB9+vcymDgYTguPdx9tO4HMOqNyz6bz/zqpxt5eLR+VA==",
+ "dependencies": {
+ "@types/koa": "*"
+ }
+ },
+ "node_modules/@types/koa-static": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/koa-static/-/koa-static-4.0.2.tgz",
+ "integrity": "sha512-ns/zHg+K6XVPMuohjpOlpkR1WLa4VJ9czgUP9bxkCDn0JZBtUWbD/wKDZzPGDclkQK1bpAEScufCHOy8cbfL0w==",
+ "dependencies": {
+ "@types/koa": "*",
+ "@types/koa-send": "*"
+ }
+ },
+ "node_modules/@types/mime": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz",
+ "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q=="
+ },
+ "node_modules/@types/mjml": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/@types/mjml/-/mjml-4.7.0.tgz",
+ "integrity": "sha512-aWWu8Lxq2SexXGs+lBPRUpN3kFf0sDRo3Y4jz7BQ15cQvMfyZOadgFJsNlHmDqI6D2Qjx0PIK+1f9IMXgq9vTA==",
+ "dependencies": {
+ "@types/mjml-core": "*"
+ }
+ },
+ "node_modules/@types/mjml-core": {
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/@types/mjml-core/-/mjml-core-4.7.1.tgz",
+ "integrity": "sha512-k5IRafi93tyZBGF+0BTrcBDvG47OueI+Q7TC4V4UjGQn0AMVvL3Y+S26QF/UHMmMJW5r1hxLyv3StX2/+FatFg=="
+ },
+ "node_modules/@types/mocha": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
+ "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w=="
+ },
+ "node_modules/@types/mongodb": {
+ "version": "3.6.20",
+ "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.20.tgz",
+ "integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==",
+ "dependencies": {
+ "@types/bson": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "13.13.52",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.52.tgz",
+ "integrity": "sha512-s3nugnZumCC//n4moGGe6tkNMyYEdaDBitVjwPxXmR5lnMG5dHePinH2EdxkG3Rh1ghFHHixAG4NJhpJW1rthQ=="
+ },
+ "node_modules/@types/nodemailer": {
+ "version": "6.4.4",
+ "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.4.tgz",
+ "integrity": "sha512-Ksw4t7iliXeYGvIQcSIgWQ5BLuC/mljIEbjf615svhZL10PE9t+ei8O9gDaD3FPCasUJn9KTLwz2JFJyiiyuqw==",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/object-hash": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@types/object-hash/-/object-hash-1.3.4.tgz",
+ "integrity": "sha512-xFdpkAkikBgqBdG9vIlsqffDV8GpvnPEzs0IUtr1v3BEB97ijsFQ4RXVbUZwjFThhB4MDSTUfvmxUD5PGx0wXA=="
+ },
+ "node_modules/@types/qs": {
+ "version": "6.9.7",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
+ "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
+ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.13.10",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz",
+ "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==",
+ "dependencies": {
+ "@types/mime": "^1",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-static/node_modules/@types/mime": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
+ "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
+ },
+ "node_modules/@types/shortid": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/shortid/-/shortid-0.0.29.tgz",
+ "integrity": "sha1-gJPuBBam4r8qpjOBCRFLP7/6Dps="
+ },
+ "node_modules/@types/uuid": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
+ "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz",
+ "integrity": "sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/experimental-utils": "3.10.1",
+ "debug": "^4.1.1",
+ "functional-red-black-tree": "^1.0.1",
+ "regexpp": "^3.0.0",
+ "semver": "^7.3.2",
+ "tsutils": "^3.17.1"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^3.0.0",
+ "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": {
+ "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,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/experimental-utils": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz",
+ "integrity": "sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.3",
+ "@typescript-eslint/types": "3.10.1",
+ "@typescript-eslint/typescript-estree": "3.10.1",
+ "eslint-scope": "^5.0.0",
+ "eslint-utils": "^2.0.0"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz",
+ "integrity": "sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==",
+ "dev": true,
+ "dependencies": {
+ "@types/eslint-visitor-keys": "^1.0.0",
+ "@typescript-eslint/experimental-utils": "3.10.1",
+ "@typescript-eslint/types": "3.10.1",
+ "@typescript-eslint/typescript-estree": "3.10.1",
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz",
+ "integrity": "sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==",
+ "dev": true,
+ "engines": {
+ "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz",
+ "integrity": "sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "3.10.1",
+ "@typescript-eslint/visitor-keys": "3.10.1",
+ "debug": "^4.1.1",
+ "glob": "^7.1.6",
+ "is-glob": "^4.0.1",
+ "lodash": "^4.17.15",
+ "semver": "^7.3.2",
+ "tsutils": "^3.17.1"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": {
+ "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,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz",
+ "integrity": "sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "engines": {
+ "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ungap/promise-all-settled": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
+ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
+ "dev": true
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
+ },
+ "node_modules/accepts": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
+ "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "dependencies": {
+ "mime-types": "~2.1.24",
+ "negotiator": "0.6.2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/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==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/append-transform": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz",
+ "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==",
+ "dev": true,
+ "dependencies": {
+ "default-require-extensions": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/archy": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
+ "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=",
+ "dev": true
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/axios": {
+ "version": "0.18.1",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz",
+ "integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==",
+ "deprecated": "Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410",
+ "dependencies": {
+ "follow-redirects": "1.5.10",
+ "is-buffer": "^2.0.2"
+ }
+ },
+ "node_modules/babel-plugin-dynamic-import-node": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+ "dev": true,
+ "dependencies": {
+ "object.assign": "^4.1.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz",
+ "integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.13.11",
+ "@babel/helper-define-polyfill-provider": "^0.3.1",
+ "semver": "^6.1.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs3": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.1.tgz",
+ "integrity": "sha512-TihqEe4sQcb/QcPJvxe94/9RZuLQuF1+To4WqQcRvc+3J3gLCPIPgDKzGLG6zmQLfH3nn25heRuDNkS2KR4I8A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.3.1",
+ "core-js-compat": "^3.20.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-regenerator": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz",
+ "integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.3.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/bl": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
+ "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
+ "dependencies": {
+ "readable-stream": "^2.3.5",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node_modules/bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
+ },
+ "node_modules/boom": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz",
+ "integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==",
+ "deprecated": "This module has moved and is now available at @hapi/boom. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.",
+ "dependencies": {
+ "hoek": "6.x.x"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "node_modules/browserslist": {
+ "version": "4.19.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz",
+ "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==",
+ "dev": true,
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001286",
+ "electron-to-chromium": "^1.4.17",
+ "escalade": "^3.1.1",
+ "node-releases": "^2.0.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ }
+ },
+ "node_modules/bson": {
+ "version": "4.6.1",
+ "resolved": "https://registry.npmjs.org/bson/-/bson-4.6.1.tgz",
+ "integrity": "sha512-I1LQ7Hz5zgwR4QquilLNZwbhPw0Apx7i7X9kGMBTsqPdml/03Q9NBtD9nt/19ahjlphktQImrnderxqpzeVDjw==",
+ "dependencies": {
+ "buffer": "^5.6.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/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==",
+ "dev": true
+ },
+ "node_modules/bytes": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz",
+ "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/cache-content-type": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz",
+ "integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==",
+ "dependencies": {
+ "mime-types": "^2.1.18",
+ "ylru": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/caching-transform": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz",
+ "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==",
+ "dev": true,
+ "dependencies": {
+ "hasha": "^5.0.0",
+ "make-dir": "^3.0.0",
+ "package-hash": "^4.0.0",
+ "write-file-atomic": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/caching-transform/node_modules/make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camel-case": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
+ "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
+ "dependencies": {
+ "no-case": "^2.2.0",
+ "upper-case": "^1.1.1"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001301",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001301.tgz",
+ "integrity": "sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA==",
+ "dev": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/cheerio": {
+ "version": "1.0.0-rc.10",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
+ "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
+ "dependencies": {
+ "cheerio-select": "^1.5.0",
+ "dom-serializer": "^1.3.2",
+ "domhandler": "^4.2.0",
+ "htmlparser2": "^6.1.0",
+ "parse5": "^6.0.1",
+ "parse5-htmlparser2-tree-adapter": "^6.0.1",
+ "tslib": "^2.2.0"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz",
+ "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==",
+ "dependencies": {
+ "css-select": "^4.1.3",
+ "css-what": "^5.0.1",
+ "domelementtype": "^2.2.0",
+ "domhandler": "^4.2.0",
+ "domutils": "^2.7.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/clean-css": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
+ "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==",
+ "dependencies": {
+ "source-map": "~0.6.0"
+ },
+ "engines": {
+ "node": ">= 4.0"
+ }
+ },
+ "node_modules/clean-css/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/co-body": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/co-body/-/co-body-5.2.0.tgz",
+ "integrity": "sha512-sX/LQ7LqUhgyaxzbe7IqwPeTr2yfpfUIQ/dgpKo6ZI4y4lpQA0YxAomWIY+7I7rHWcG02PG+OuPREzMW/5tszQ==",
+ "dependencies": {
+ "inflation": "^2.0.0",
+ "qs": "^6.4.0",
+ "raw-body": "^2.2.0",
+ "type-is": "^1.6.14"
+ }
+ },
+ "node_modules/color": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.1.tgz",
+ "integrity": "sha512-MFJr0uY4RvTQUKvPq7dh9grVOTYSFeXja2mBXioCGjnjJoXrAp9jJ1NQTDR73c9nwBSAQiNKloKl5zq9WB9UPw==",
+ "dependencies": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=12.5.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-hash": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/color-hash/-/color-hash-1.1.1.tgz",
+ "integrity": "sha512-OOZ2pKPuon1H7/77G0+xzSRDgITsik/kYzfJxmCBEI4ozM6UFhZ1aaZ6OhASbDwolHUq5PTRnhDle9FR72tqbw=="
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/color-string": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz",
+ "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==",
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/comment-parser": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.7.6.tgz",
+ "integrity": "sha512-GKNxVA7/iuTnAqGADlTWX4tkhzxZKXp5fLJqKTlQLHkE65XDUKutZ3BHaJC5IGcper2tT3QRD1xr4o3jNpgXXg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
+ "dev": true
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "node_modules/config-chain": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
+ "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
+ "dependencies": {
+ "ini": "^1.3.4",
+ "proto-list": "~1.2.1"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-disposition/node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/content-type": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
+ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
+ "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "node_modules/cookies": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz",
+ "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "keygrip": "~1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/cookies/node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/core-js": {
+ "version": "2.6.12",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
+ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
+ "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
+ "hasInstallScript": true
+ },
+ "node_modules/core-js-compat": {
+ "version": "3.20.3",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.20.3.tgz",
+ "integrity": "sha512-c8M5h0IkNZ+I92QhIpuSijOxGAcj3lgpsWdkCqmUTZNwidujF4r3pi6x1DCN+Vcs5qTS2XWWMfWSuCqyupX8gw==",
+ "dev": true,
+ "dependencies": {
+ "browserslist": "^4.19.1",
+ "semver": "7.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/core-js-compat/node_modules/semver": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
+ "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz",
+ "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^5.1.0",
+ "domhandler": "^4.3.0",
+ "domutils": "^2.8.0",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
+ "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+ "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/deep-equal": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
+ "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/deepmerge": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
+ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/default-require-extensions": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz",
+ "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==",
+ "dev": true,
+ "dependencies": {
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
+ "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "dev": true,
+ "dependencies": {
+ "object-keys": "^1.0.12"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+ },
+ "node_modules/denque": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz",
+ "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
+ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
+ },
+ "node_modules/detect-node": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
+ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw=="
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
+ "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "domhandler": "^4.2.0",
+ "entities": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
+ "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ]
+ },
+ "node_modules/domhandler": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
+ "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
+ "dependencies": {
+ "domelementtype": "^2.2.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
+ "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
+ "dependencies": {
+ "dom-serializer": "^1.0.1",
+ "domelementtype": "^2.2.0",
+ "domhandler": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dot-prop": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
+ "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
+ "dependencies": {
+ "is-obj": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/editorconfig": {
+ "version": "0.15.3",
+ "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz",
+ "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==",
+ "dependencies": {
+ "commander": "^2.19.0",
+ "lru-cache": "^4.1.5",
+ "semver": "^5.6.0",
+ "sigmund": "^1.0.1"
+ },
+ "bin": {
+ "editorconfig": "bin/editorconfig"
+ }
+ },
+ "node_modules/editorconfig/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ },
+ "node_modules/editorconfig/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.51",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.51.tgz",
+ "integrity": "sha512-JNEmcYl3mk1tGQmy0EvL5eik/CKSBuzAyGP0QFdG6LIgxQe3II0BL1m2zKc2MZMf3uGqHWE1TFddJML0RpjSHQ==",
+ "dev": true
+ },
+ "node_modules/emittery": {
+ "version": "0.7.2",
+ "resolved": "git+ssh://git@github.com/sindresorhus/emittery.git#7db4644126c66f062062c0ea103f95a4f7235c35",
+ "integrity": "sha512-1Jz5UUmi3kHrZFNAKogCa8P9TN2HFVq72fTDCc8mm/7vRc5z55qCBy14SZjC6qHG53IZ2xxxkvMBE95BRdApiQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/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=="
+ },
+ "node_modules/encodeurl": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
+ "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/es6-error": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
+ "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
+ "dev": true
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-goat": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz",
+ "integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
+ },
+ "node_modules/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==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "dependencies": {
+ "@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"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz",
+ "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==",
+ "dev": true,
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-es": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz",
+ "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==",
+ "dev": true,
+ "dependencies": {
+ "eslint-utils": "^2.0.0",
+ "regexpp": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=4.19.1"
+ }
+ },
+ "node_modules/eslint-plugin-jsdoc": {
+ "version": "29.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-29.2.0.tgz",
+ "integrity": "sha512-B1a8LWPkkxyxIp4y3pnRQR18j03Wp+V9gDE7IjQG/MvWAzp5gqXM0q71gXRAZMvWUjujAsNg8B9v1csl+/zkvw==",
+ "dev": true,
+ "dependencies": {
+ "comment-parser": "^0.7.5",
+ "debug": "^4.1.1",
+ "jsdoctypeparser": "^8.0.0",
+ "lodash": "^4.17.15",
+ "regextras": "^0.7.1",
+ "semver": "^7.3.2",
+ "spdx-expression-parse": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-jsdoc/node_modules/lru-cache": {
+ "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,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-plugin-jsdoc/node_modules/semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-plugin-jsdoc/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/eslint-plugin-node": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz",
+ "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==",
+ "dev": true,
+ "dependencies": {
+ "eslint-plugin-es": "^3.0.0",
+ "eslint-utils": "^2.0.0",
+ "ignore": "^5.1.1",
+ "minimatch": "^3.0.4",
+ "resolve": "^1.10.1",
+ "semver": "^6.1.0"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=5.16.0"
+ }
+ },
+ "node_modules/eslint-plugin-node/node_modules/ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz",
+ "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==",
+ "dev": true,
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=5.0.0",
+ "prettier": ">=1.13.0"
+ },
+ "peerDependenciesMeta": {
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
+ "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/eslint/node_modules/@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==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.10.4"
+ }
+ },
+ "node_modules/eslint/node_modules/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==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint/node_modules/globals": {
+ "version": "13.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
+ "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/lru-cache": {
+ "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,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint/node_modules/semver": {
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
+ "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint/node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/espree": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
+ "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^7.4.0",
+ "acorn-jsx": "^5.3.1",
+ "eslint-visitor-keys": "^1.3.0"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/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,
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-diff": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
+ "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
+ "dev": true
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
+ "dev": true
+ },
+ "node_modules/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==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-cache-dir": {
+ "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,
+ "dependencies": {
+ "commondir": "^1.0.1",
+ "make-dir": "^3.0.2",
+ "pkg-dir": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
+ }
+ },
+ "node_modules/find-cache-dir/node_modules/make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true,
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz",
+ "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
+ "dev": true
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
+ "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
+ "dependencies": {
+ "debug": "=3.1.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/follow-redirects/node_modules/debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/follow-redirects/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ },
+ "node_modules/foreground-child": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
+ "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/formidable": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz",
+ "integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==",
+ "deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau",
+ "funding": {
+ "url": "https://ko-fi.com/tunnckoCore/commissions"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fromentries": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
+ "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/fs-extra": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
+ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/fs-readdir-recursive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
+ "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
+ "dev": true
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
+ "node_modules/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=",
+ "dev": true
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
+ "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-port": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz",
+ "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dependencies": {
+ "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"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.9",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
+ "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
+ },
+ "node_modules/growl": {
+ "version": "1.10.5",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.x"
+ }
+ },
+ "node_modules/handlebars": {
+ "version": "4.7.7",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
+ "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.0",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
+ "node_modules/handlebars/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
+ "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasha": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
+ "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==",
+ "dev": true,
+ "dependencies": {
+ "is-stream": "^2.0.0",
+ "type-fest": "^0.8.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/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==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/hoek": {
+ "version": "6.1.3",
+ "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
+ "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==",
+ "deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues."
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true
+ },
+ "node_modules/html-minifier": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
+ "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==",
+ "dependencies": {
+ "camel-case": "^3.0.0",
+ "clean-css": "^4.2.1",
+ "commander": "^2.19.0",
+ "he": "^1.2.0",
+ "param-case": "^2.1.1",
+ "relateurl": "^0.2.7",
+ "uglify-js": "^3.5.1"
+ },
+ "bin": {
+ "html-minifier": "cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/html-minifier/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ },
+ "node_modules/htmlparser2": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
+ "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "domhandler": "^4.0.0",
+ "domutils": "^2.5.2",
+ "entities": "^2.0.0"
+ }
+ },
+ "node_modules/http-assert": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz",
+ "integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==",
+ "dependencies": {
+ "deep-equal": "~1.0.1",
+ "http-errors": "~1.8.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/http-errors": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
+ "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
+ "dependencies": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/ignore": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
+ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inflation": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz",
+ "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
+ },
+ "node_modules/interpret": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
+ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
+ "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
+ "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/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==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-obj": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+ "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
+ "dev": true
+ },
+ "node_modules/is-windows": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
+ "dev": true
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
+ "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-hook": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz",
+ "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==",
+ "dev": true,
+ "dependencies": {
+ "append-transform": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
+ "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.7.5",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.0.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-processinfo": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz",
+ "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==",
+ "dev": true,
+ "dependencies": {
+ "archy": "^1.0.0",
+ "cross-spawn": "^7.0.0",
+ "istanbul-lib-coverage": "^3.0.0-alpha.1",
+ "make-dir": "^3.0.0",
+ "p-map": "^3.0.0",
+ "rimraf": "^3.0.0",
+ "uuid": "^3.3.3"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-processinfo/node_modules/make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/istanbul-lib-processinfo/node_modules/uuid": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
+ "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
+ "dev": true,
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
+ "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
+ "dev": true,
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^3.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-report/node_modules/make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.3.tgz",
+ "integrity": "sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg==",
+ "dev": true,
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/js-beautify": {
+ "version": "1.14.0",
+ "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.0.tgz",
+ "integrity": "sha512-yuck9KirNSCAwyNJbqW+BxJqJ0NLJ4PwBUzQQACl5O3qHMBXVkXb/rD0ilh/Lat/tn88zSZ+CAHOlk0DsY7GuQ==",
+ "dependencies": {
+ "config-chain": "^1.1.12",
+ "editorconfig": "^0.15.3",
+ "glob": "^7.1.3",
+ "nopt": "^5.0.0"
+ },
+ "bin": {
+ "css-beautify": "js/bin/css-beautify.js",
+ "html-beautify": "js/bin/html-beautify.js",
+ "js-beautify": "js/bin/js-beautify.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsdoctypeparser": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-8.0.0.tgz",
+ "integrity": "sha512-eLCs6s4JqN8TjFJfgdiLHRvogLhOAJz+5RIA2FtoMe6ZDyuvghvppnlIToqAEnVbxRqLMrfnNXpW8FpmR6IMBw==",
+ "dev": true,
+ "bin": {
+ "jsdoctypeparser": "bin/jsdoctypeparser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/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=",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
+ "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.5"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/juice": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/juice/-/juice-7.0.0.tgz",
+ "integrity": "sha512-AjKQX31KKN+uJs+zaf+GW8mBO/f/0NqSh2moTMyvwBY+4/lXIYTU8D8I2h6BAV3Xnz6GGsbalUyFqbYMe+Vh+Q==",
+ "dependencies": {
+ "cheerio": "^1.0.0-rc.3",
+ "commander": "^5.1.0",
+ "mensch": "^0.3.4",
+ "slick": "^1.12.2",
+ "web-resource-inliner": "^5.0.0"
+ },
+ "bin": {
+ "juice": "bin/juice"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/juice/node_modules/commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/keygrip": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
+ "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
+ "dependencies": {
+ "tsscmp": "1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/koa": {
+ "version": "2.13.4",
+ "resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz",
+ "integrity": "sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==",
+ "dependencies": {
+ "accepts": "^1.3.5",
+ "cache-content-type": "^1.0.0",
+ "content-disposition": "~0.5.2",
+ "content-type": "^1.0.4",
+ "cookies": "~0.8.0",
+ "debug": "^4.3.2",
+ "delegates": "^1.0.0",
+ "depd": "^2.0.0",
+ "destroy": "^1.0.4",
+ "encodeurl": "^1.0.2",
+ "escape-html": "^1.0.3",
+ "fresh": "~0.5.2",
+ "http-assert": "^1.3.0",
+ "http-errors": "^1.6.3",
+ "is-generator-function": "^1.0.7",
+ "koa-compose": "^4.1.0",
+ "koa-convert": "^2.0.0",
+ "on-finished": "^2.3.0",
+ "only": "~0.0.2",
+ "parseurl": "^1.3.2",
+ "statuses": "^1.5.0",
+ "type-is": "^1.6.16",
+ "vary": "^1.1.2"
+ },
+ "engines": {
+ "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4"
+ }
+ },
+ "node_modules/koa-body": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/koa-body/-/koa-body-4.2.0.tgz",
+ "integrity": "sha512-wdGu7b9amk4Fnk/ytH8GuWwfs4fsB5iNkY8kZPpgQVb04QZSv85T0M8reb+cJmvLE8cjPYvBzRikD3s6qz8OoA==",
+ "dependencies": {
+ "@types/formidable": "^1.0.31",
+ "co-body": "^5.1.1",
+ "formidable": "^1.1.1"
+ }
+ },
+ "node_modules/koa-compose": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
+ "integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
+ },
+ "node_modules/koa-convert": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz",
+ "integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==",
+ "dependencies": {
+ "co": "^4.6.0",
+ "koa-compose": "^4.1.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/koa-mount": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/koa-mount/-/koa-mount-4.0.0.tgz",
+ "integrity": "sha512-rm71jaA/P+6HeCpoRhmCv8KVBIi0tfGuO/dMKicbQnQW/YJntJ6MnnspkodoA4QstMVEZArsCphmd0bJEtoMjQ==",
+ "dependencies": {
+ "debug": "^4.0.1",
+ "koa-compose": "^4.1.0"
+ },
+ "engines": {
+ "node": ">= 7.6.0"
+ }
+ },
+ "node_modules/koa-qs": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/koa-qs/-/koa-qs-3.0.0.tgz",
+ "integrity": "sha512-05IB5KirwMs3heWW26iTz46HuMAtrlrRMus/aNH1BRDocLyF/099EtCB0MIfQpRuT0TISvaTsWwSy2gctIWiGA==",
+ "dependencies": {
+ "merge-descriptors": "^1.0.1",
+ "qs": "^6.9.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/koa-send": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz",
+ "integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==",
+ "dependencies": {
+ "debug": "^4.1.1",
+ "http-errors": "^1.7.3",
+ "resolve-path": "^1.4.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/koa-static": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz",
+ "integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==",
+ "dependencies": {
+ "debug": "^3.1.0",
+ "koa-send": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 7.6.0"
+ }
+ },
+ "node_modules/koa-static/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/koa/node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/locreq": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/locreq/-/locreq-2.0.2.tgz",
+ "integrity": "sha512-77HrzBGmSNZMeL12NOf+7PLmdjuIdX+sqLQYts65oaH/gcbiNIGB+RdGCfDrhv/WCMScgOELEjDnuSPlnat7Ew==",
+ "dependencies": {
+ "@types/node": "^14.14.16"
+ }
+ },
+ "node_modules/locreq/node_modules/@types/node": {
+ "version": "14.18.9",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.9.tgz",
+ "integrity": "sha512-j11XSuRuAlft6vLDEX4RvhqC0KxNxx6QIyMXNb0vHHSNPXTPeiy3algESWmOOIzEtiEL0qiowPU3ewW9hHVa7Q=="
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "node_modules/lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
+ "dev": true
+ },
+ "node_modules/lodash.flattendeep": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
+ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
+ "dev": true
+ },
+ "node_modules/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==",
+ "dev": true
+ },
+ "node_modules/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=",
+ "dev": true
+ },
+ "node_modules/log-symbols": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
+ "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/lower-case": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
+ "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw="
+ },
+ "node_modules/lru-cache": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
+ "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
+ "dependencies": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "node_modules/lunr": {
+ "version": "2.3.9",
+ "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
+ "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow=="
+ },
+ "node_modules/make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "dev": true,
+ "dependencies": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
+ "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/marked": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-1.0.0.tgz",
+ "integrity": "sha512-Wo+L1pWTVibfrSr+TTtMuiMfNzmZWiOPeO7rZsQUY5bgsxpHesBEcIWJloWVTFnrMXnf/TL30eTFSGJddmQAng==",
+ "bin": {
+ "marked": "bin/marked"
+ },
+ "engines": {
+ "node": ">= 8.16.2"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/memory-pager": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
+ "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
+ "optional": true
+ },
+ "node_modules/mensch": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/mensch/-/mensch-0.3.4.tgz",
+ "integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g=="
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
+ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
+ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.51.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
+ "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.34",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
+ "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
+ "dependencies": {
+ "mime-db": "1.51.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
+ },
+ "node_modules/mjml": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml/-/mjml-4.11.0.tgz",
+ "integrity": "sha512-kYuCAds/8F7m7xNEs3TFkrc0jxnNYIkexQIUNByPLQJFoFRltpgXLSdoyreGAniQtDGITPE+p8FIocLUBKsOHg==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "mjml-cli": "4.11.0",
+ "mjml-core": "4.11.0",
+ "mjml-migrate": "4.11.0",
+ "mjml-preset-core": "4.11.0",
+ "mjml-validator": "4.11.0"
+ },
+ "bin": {
+ "mjml": "bin/mjml"
+ }
+ },
+ "node_modules/mjml-accordion": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-accordion/-/mjml-accordion-4.11.0.tgz",
+ "integrity": "sha512-u6cPMl4z8JeRIq0sGHWfzwE5SqwBhSPHJ8wElhfU7CK6gAoUTz4BIL/03da2whXk0S34n5CSU453JpuWV+3bQQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-body": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-body/-/mjml-body-4.11.0.tgz",
+ "integrity": "sha512-+SQXOjKOr9IMblmslrUbv+ahF/SkqT7mAuix1P/F9ev3aS+WN7Gy/lyJLaq1zhSQCmzrBDovHez3bJ7NGToU0g==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-button": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-button/-/mjml-button-4.11.0.tgz",
+ "integrity": "sha512-v/MwA2Kq2MlHJwrajdAqUihjAQivD8FpkpOAcqdgqI1ffaEDzd6FGFt5qOtVD9BncChQ4a51haOnPd+kbBLlCA==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-carousel": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-carousel/-/mjml-carousel-4.11.0.tgz",
+ "integrity": "sha512-/owKKSg3DNes1rauPPhlGCFdZ4zzoxdztPLGOm9TSjkbL5q2cN9NMfzNdTYLnnVG5G5XWX0THjDeeq+bGnHw8w==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-cli": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-cli/-/mjml-cli-4.11.0.tgz",
+ "integrity": "sha512-jgkxNY+sY+CwiUlO6VX8cwVjlLBXIzE7X4fXkQ2RjXpbAvsN8uDafST8oL8PDlxNIjOwK6YJySzZSLXSKTF5Zg==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "chokidar": "^3.0.0",
+ "glob": "^7.1.1",
+ "html-minifier": "^4.0.0",
+ "js-beautify": "^1.6.14",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0",
+ "mjml-migrate": "4.11.0",
+ "mjml-parser-xml": "4.11.0",
+ "mjml-validator": "4.11.0",
+ "yargs": "^16.1.0"
+ },
+ "bin": {
+ "mjml-cli": "bin/mjml"
+ }
+ },
+ "node_modules/mjml-column": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-column/-/mjml-column-4.11.0.tgz",
+ "integrity": "sha512-yuupexywYXuXTvxxGLPZw6S/D6fz4b41ZarOkEPW8Pbj7FkfnBTO3QokAS5KapJ9x6sIAVs+cCgUul87dwOBzg==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-core": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-core/-/mjml-core-4.11.0.tgz",
+ "integrity": "sha512-UTI1exu9/0lOF40aacAzC9A7RrJPcay7WYurYsb+X2LbDyfBlSx5ZCtuUTHwLfIz3PL6rSg8yrZ3KtlmhQJ/kQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "cheerio": "1.0.0-rc.10",
+ "detect-node": "2.0.4",
+ "html-minifier": "^4.0.0",
+ "js-beautify": "^1.6.14",
+ "juice": "^7.0.0",
+ "lodash": "^4.17.21",
+ "mjml-migrate": "4.11.0",
+ "mjml-parser-xml": "4.11.0",
+ "mjml-validator": "4.11.0"
+ }
+ },
+ "node_modules/mjml-divider": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-divider/-/mjml-divider-4.11.0.tgz",
+ "integrity": "sha512-jS8Sa7uuFTmThtrcV3FICtbqmA0yJplldaNJwW5upiq7MEXuSwLNzjNeodaTpsVWevf/stE3C4lBA3+V4ascMg==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-group": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-group/-/mjml-group-4.11.0.tgz",
+ "integrity": "sha512-Yv1ZcPNk4bxOK/eol6bjJvRJBaOCzVY88QO8IfCQifAZuiXhatxwsuwaRKNcTi4cB+IHwl4JguZHgsFRi/Gf/g==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-head": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-head/-/mjml-head-4.11.0.tgz",
+ "integrity": "sha512-KNaSsOlf5FNwHyZQD6YNZN2Eo/o7n+mZISFLyp9MvNFaT3NKIRJDaInD1WjN+w2aHdXAw4sDV3+/9/EET2bh1A==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-head-attributes": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-head-attributes/-/mjml-head-attributes-4.11.0.tgz",
+ "integrity": "sha512-azeDRLGH7cU6PoXLd08E/H3UDHFsblBTcme++OWrj5B21vaFguOBySO2eWFTyWLthy+xst8FftWV46f8BWvciw==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-head-breakpoint": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-head-breakpoint/-/mjml-head-breakpoint-4.11.0.tgz",
+ "integrity": "sha512-OQ/WpXHagGoiUmBjoMHuxdigyLQrHNL6+Op0LHO87vN1GH2ap4YLcSSegIsThQLi/I7V4/JFZbzS5jV4xd4SMg==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-head-font": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-head-font/-/mjml-head-font-4.11.0.tgz",
+ "integrity": "sha512-AJQ9lhNzNr0hwPjUID76LNna3U8ycmFH1lyipZOWHTivOVGkSYs8PaboxORfU/QAEDKo/p8LafBAoDPEdSigxA==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-head-html-attributes": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-head-html-attributes/-/mjml-head-html-attributes-4.11.0.tgz",
+ "integrity": "sha512-Gew9EAuqFu9QR3g+8FyE9WHNMszx1ejzo8dRDIuTaBCDEpaIaPVO7G5rGhT7ADqZufeYtRhBXfXjcShPD/a30g==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-head-preview": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-head-preview/-/mjml-head-preview-4.11.0.tgz",
+ "integrity": "sha512-f79+OtwC8CYcQpglGNfm3s74qVecdwLlDm9DD/LJvZwIdaALeIfZF36nz6+rtCLMhND+wxgqxqkmbbuS6AbO+A==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-head-style": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-head-style/-/mjml-head-style-4.11.0.tgz",
+ "integrity": "sha512-jw0r9Ld56SkJmDUBx+27xOH+oY2O06FBcKSJIkZLJ/sefbjgJa2/ti2eso/LeGgrmTw8zge7g1pp0Fl+kPjsGA==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-head-title": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-head-title/-/mjml-head-title-4.11.0.tgz",
+ "integrity": "sha512-mjYsKoE9+5LI8V0mK9SAKVKspF19TVius2q5I1FXLRdBmt4Ei87CdrSui+iixGrug0Lwt4P2W3+mK8kVGNnJAQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-hero": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-hero/-/mjml-hero-4.11.0.tgz",
+ "integrity": "sha512-tZDCGjQrDICwbsDnLvfVEsQ5+GdrIozB3oO3NxC6m2Eq04VKNBkIqq+QvJyouOxzJ3CZgO2B4rylzxc6YXuHsw==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-image": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-image/-/mjml-image-4.11.0.tgz",
+ "integrity": "sha512-qjvKS/x2arDNgKppPecmg69VyXdQbb1CNVqPwowJLyfjioTw4hxQ93suWoBKJJojRjkwauj9IRMC8TR9ffn0HQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-migrate": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-migrate/-/mjml-migrate-4.11.0.tgz",
+ "integrity": "sha512-Y+9U4w9LwlTkfTkHX9GdalIQDO4JQxboG4PM8g7vRKNhKSZDZH8QSr0SNhX0+fMQmjb9b0nztWbMVVvNZfMoPQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "js-beautify": "^1.6.14",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0",
+ "mjml-parser-xml": "4.11.0",
+ "yargs": "^16.1.0"
+ },
+ "bin": {
+ "migrate": "lib/cli.js"
+ }
+ },
+ "node_modules/mjml-navbar": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-navbar/-/mjml-navbar-4.11.0.tgz",
+ "integrity": "sha512-FEd+8RD6ra8652jXdMbhfhzT1YY8TA30c34qjJ+ULlFgvLH4GNnYRIOHp/Mgd/L38Qf3bhK/rK9ELBidJ36dLQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-parser-xml": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-parser-xml/-/mjml-parser-xml-4.11.0.tgz",
+ "integrity": "sha512-3toQ9UKyfzXWXJ7PlTExBjzGXAzJNORv39sorPv5sG2KJsvPC6NE+e+/1GyqYFhk4JffHoDfd4mQ6w050qYATQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "detect-node": "2.0.4",
+ "htmlparser2": "^4.1.0",
+ "lodash": "^4.17.15"
+ }
+ },
+ "node_modules/mjml-parser-xml/node_modules/domhandler": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
+ "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
+ "dependencies": {
+ "domelementtype": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/mjml-parser-xml/node_modules/htmlparser2": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
+ "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "domhandler": "^3.0.0",
+ "domutils": "^2.0.0",
+ "entities": "^2.0.0"
+ }
+ },
+ "node_modules/mjml-preset-core": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-preset-core/-/mjml-preset-core-4.11.0.tgz",
+ "integrity": "sha512-HU9ZFzS+A7Dx0B/EbnqYjdcIQQuxpOVRfFReQBlllZYwjWaRUjDIeIjF+cdnCb9QveuSNo4msIG00h/MKPYiGQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "mjml-accordion": "4.11.0",
+ "mjml-body": "4.11.0",
+ "mjml-button": "4.11.0",
+ "mjml-carousel": "4.11.0",
+ "mjml-column": "4.11.0",
+ "mjml-divider": "4.11.0",
+ "mjml-group": "4.11.0",
+ "mjml-head": "4.11.0",
+ "mjml-head-attributes": "4.11.0",
+ "mjml-head-breakpoint": "4.11.0",
+ "mjml-head-font": "4.11.0",
+ "mjml-head-html-attributes": "4.11.0",
+ "mjml-head-preview": "4.11.0",
+ "mjml-head-style": "4.11.0",
+ "mjml-head-title": "4.11.0",
+ "mjml-hero": "4.11.0",
+ "mjml-image": "4.11.0",
+ "mjml-navbar": "4.11.0",
+ "mjml-raw": "4.11.0",
+ "mjml-section": "4.11.0",
+ "mjml-social": "4.11.0",
+ "mjml-spacer": "4.11.0",
+ "mjml-table": "4.11.0",
+ "mjml-text": "4.11.0",
+ "mjml-wrapper": "4.11.0"
+ }
+ },
+ "node_modules/mjml-raw": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-raw/-/mjml-raw-4.11.0.tgz",
+ "integrity": "sha512-DyUwC/JrE8tF7v9XaKQpQ/yAg5tT2uAWSDI6J5x3t3TNFJmRPd3iorSu8v6t1s3OiekuxfagsDDPLFuzpGwZSw==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-section": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-section/-/mjml-section-4.11.0.tgz",
+ "integrity": "sha512-OpinxE019Z1symrEFku3UddsvSql2aolcAiOThFuAAXz3+tUuooofGMy/XyyMOuOnktOx/5PMcVFsV84/Jye/g==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-social": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-social/-/mjml-social-4.11.0.tgz",
+ "integrity": "sha512-tM5njGtang0VRWt+XCuMTnZP2IJehUd+kdsC7CnMKQhYI2X4vzEaOBLgXRWvhcT4pSBzEJkXB9sQ+y7JmLO10g==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-spacer": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-spacer/-/mjml-spacer-4.11.0.tgz",
+ "integrity": "sha512-9s6PjFgznKEFgFZCSa4vTYVDQ6kRH5ucMHGraoHS4VMZLA8QIaVakHd4Sl0n+SGWCqair4xZ3vYYMhOBKIXmMw==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-table": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-table/-/mjml-table-4.11.0.tgz",
+ "integrity": "sha512-ccniRz1MoDqKS6zoNM59xi81M7zy/tkvd/6weyH9XAZiU7ATgOxoBuIMy+d0uSTlKPWNwoi2FqR5YSedxT2YPw==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-text": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-text/-/mjml-text-4.11.0.tgz",
+ "integrity": "sha512-xrY5+uepxUg+q5KKuKX2s9KQnnlsMN5aoCt0JSbjt4H9ZwBpqXPD4Z2uJ8eZS33FvnXzUYPNVdKralvXnrsXKA==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0"
+ }
+ },
+ "node_modules/mjml-validator": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-validator/-/mjml-validator-4.11.0.tgz",
+ "integrity": "sha512-oDL9tHcL4PaCZMwH6T/lLpS7LV9cm9lIwnzJy+y5/S81MGMV6kPr6xXHgS0A01G7sseg6+rHgqBnUgzUob4Ilg==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6"
+ }
+ },
+ "node_modules/mjml-wrapper": {
+ "version": "4.11.0",
+ "resolved": "https://registry.npmjs.org/mjml-wrapper/-/mjml-wrapper-4.11.0.tgz",
+ "integrity": "sha512-WXGKxS+DlYalx5ofwq3bttj26BLEcaueeQ+0BcffXIELojUzd0+xTyX09v0QemUCBmKpHB2QaKMGhzYuSkupyg==",
+ "dependencies": {
+ "@babel/runtime": "^7.14.6",
+ "lodash": "^4.17.21",
+ "mjml-core": "4.11.0",
+ "mjml-section": "4.11.0"
+ }
+ },
+ "node_modules/mocha": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz",
+ "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==",
+ "dev": true,
+ "dependencies": {
+ "@ungap/promise-all-settled": "1.1.2",
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.1",
+ "debug": "4.3.1",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "7.1.6",
+ "growl": "1.10.5",
+ "he": "1.2.0",
+ "js-yaml": "4.0.0",
+ "log-symbols": "4.0.0",
+ "minimatch": "3.0.4",
+ "ms": "2.1.3",
+ "nanoid": "3.1.20",
+ "serialize-javascript": "5.0.1",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "which": "2.0.2",
+ "wide-align": "1.1.3",
+ "workerpool": "6.1.0",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "bin": {
+ "_mocha": "bin/_mocha",
+ "mocha": "bin/mocha"
+ },
+ "engines": {
+ "node": ">= 10.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mochajs"
+ }
+ },
+ "node_modules/mocha/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "node_modules/mocha/node_modules/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==",
+ "dev": true,
+ "dependencies": {
+ "anymatch": "~3.1.1",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.0",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.5.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.1"
+ }
+ },
+ "node_modules/mocha/node_modules/debug": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+ "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/mocha/node_modules/debug/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/mocha/node_modules/glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "dev": true,
+ "dependencies": {
+ "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"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/mocha/node_modules/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==",
+ "dev": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/mocha/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "node_modules/mocha/node_modules/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==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/mocha/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/mongodb": {
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz",
+ "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==",
+ "dependencies": {
+ "bl": "^2.2.1",
+ "bson": "^1.1.4",
+ "denque": "^1.4.1",
+ "optional-require": "^1.1.8",
+ "safe-buffer": "^5.1.2"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "optionalDependencies": {
+ "saslprep": "^1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "aws4": {
+ "optional": true
+ },
+ "bson-ext": {
+ "optional": true
+ },
+ "kerberos": {
+ "optional": true
+ },
+ "mongodb-client-encryption": {
+ "optional": true
+ },
+ "mongodb-extjson": {
+ "optional": true
+ },
+ "snappy": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/mongodb/node_modules/bson": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
+ "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==",
+ "engines": {
+ "node": ">=0.6.19"
+ }
+ },
+ "node_modules/mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/nanoid": {
+ "version": "3.1.20",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
+ "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==",
+ "dev": true,
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
+ "dev": true
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
+ "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/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=="
+ },
+ "node_modules/no-case": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
+ "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
+ "dependencies": {
+ "lower-case": "^1.1.1"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.6.7",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+ "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-preload": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
+ "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==",
+ "dev": true,
+ "dependencies": {
+ "process-on-spawn": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz",
+ "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==",
+ "dev": true
+ },
+ "node_modules/nodemailer": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.7.2.tgz",
+ "integrity": "sha512-Dz7zVwlef4k5R71fdmxwR8Q39fiboGbu3xgswkzGwczUfjp873rVxt1O46+Fh0j1ORnAC6L9+heI8uUpO6DT7Q==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/nopt": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+ "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
+ "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/nyc": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz",
+ "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==",
+ "dev": true,
+ "dependencies": {
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "caching-transform": "^4.0.0",
+ "convert-source-map": "^1.7.0",
+ "decamelize": "^1.2.0",
+ "find-cache-dir": "^3.2.0",
+ "find-up": "^4.1.0",
+ "foreground-child": "^2.0.0",
+ "get-package-type": "^0.1.0",
+ "glob": "^7.1.6",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-hook": "^3.0.0",
+ "istanbul-lib-instrument": "^4.0.0",
+ "istanbul-lib-processinfo": "^2.0.2",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.0.2",
+ "make-dir": "^3.0.0",
+ "node-preload": "^0.2.1",
+ "p-map": "^3.0.0",
+ "process-on-spawn": "^1.0.0",
+ "resolve-from": "^5.0.0",
+ "rimraf": "^3.0.0",
+ "signal-exit": "^3.0.2",
+ "spawn-wrap": "^2.0.0",
+ "test-exclude": "^6.0.0",
+ "yargs": "^15.0.2"
+ },
+ "bin": {
+ "nyc": "bin/nyc.js"
+ },
+ "engines": {
+ "node": ">=8.9"
+ }
+ },
+ "node_modules/nyc/node_modules/cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/nyc/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nyc/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nyc/node_modules/make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/nyc/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/nyc/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nyc/node_modules/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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nyc/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nyc/node_modules/y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+ "dev": true
+ },
+ "node_modules/nyc/node_modules/yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nyc/node_modules/yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/object-hash": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
+ "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.12.0",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
+ "integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
+ "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "define-properties": "^1.1.3",
+ "has-symbols": "^1.0.1",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/only": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
+ "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
+ },
+ "node_modules/optional-require": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz",
+ "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==",
+ "dependencies": {
+ "require-at": "^1.0.6"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "dependencies": {
+ "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"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
+ "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
+ "dev": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/package-hash": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz",
+ "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.15",
+ "hasha": "^5.0.0",
+ "lodash.flattendeep": "^4.4.0",
+ "release-zalgo": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/param-case": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
+ "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
+ "dependencies": {
+ "no-case": "^2.2.0"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-ms": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz",
+ "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-srcset": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
+ "integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE="
+ },
+ "node_modules/parse5": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
+ "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
+ },
+ "node_modules/parse5-htmlparser2-tree-adapter": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
+ "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
+ "dependencies": {
+ "parse5": "^6.0.1"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/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=="
+ },
+ "node_modules/path-to-regexp": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.0.tgz",
+ "integrity": "sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg=="
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/postcss/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="
+ },
+ "node_modules/postcss/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
+ "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/pretty-ms": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz",
+ "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==",
+ "dependencies": {
+ "parse-ms": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "node_modules/process-on-spawn": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz",
+ "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==",
+ "dev": true,
+ "dependencies": {
+ "fromentries": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/proto-list": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
+ "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk="
+ },
+ "node_modules/pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
+ },
+ "node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.10.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
+ "integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
+ "dependencies": {
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz",
+ "integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==",
+ "dependencies": {
+ "bytes": "3.1.1",
+ "http-errors": "1.8.1",
+ "iconv-lite": "0.4.24",
+ "unpipe": "1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/rechoir": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
+ "dependencies": {
+ "resolve": "^1.1.6"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/regenerate": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
+ "dev": true
+ },
+ "node_modules/regenerate-unicode-properties": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz",
+ "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==",
+ "dev": true,
+ "dependencies": {
+ "regenerate": "^1.4.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.13.9",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
+ "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
+ },
+ "node_modules/regenerator-transform": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz",
+ "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.8.4"
+ }
+ },
+ "node_modules/regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/regexpu-core": {
+ "version": "4.8.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz",
+ "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==",
+ "dev": true,
+ "dependencies": {
+ "regenerate": "^1.4.2",
+ "regenerate-unicode-properties": "^9.0.0",
+ "regjsgen": "^0.5.2",
+ "regjsparser": "^0.7.0",
+ "unicode-match-property-ecmascript": "^2.0.0",
+ "unicode-match-property-value-ecmascript": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regextras": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/regextras/-/regextras-0.7.1.tgz",
+ "integrity": "sha512-9YXf6xtW+qzQ+hcMQXx95MOvfqXFgsKDZodX3qZB0x2n5Z94ioetIITsBtvJbiOyxa/6s9AtyweBLCdPmPko/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.1.14"
+ }
+ },
+ "node_modules/regjsgen": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz",
+ "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==",
+ "dev": true
+ },
+ "node_modules/regjsparser": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz",
+ "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==",
+ "dev": true,
+ "dependencies": {
+ "jsesc": "~0.5.0"
+ },
+ "bin": {
+ "regjsparser": "bin/parser"
+ }
+ },
+ "node_modules/regjsparser/node_modules/jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ }
+ },
+ "node_modules/relateurl": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
+ "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/release-zalgo": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz",
+ "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=",
+ "dev": true,
+ "dependencies": {
+ "es6-error": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/require-at": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz",
+ "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "node_modules/resolve": {
+ "version": "1.22.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
+ "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
+ "dependencies": {
+ "is-core-module": "^2.8.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve-path": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz",
+ "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=",
+ "dependencies": {
+ "http-errors": "~1.6.2",
+ "path-is-absolute": "1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/resolve-path/node_modules/http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
+ "dependencies": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/resolve-path/node_modules/inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
+ },
+ "node_modules/resolve-path/node_modules/setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
+ "node_modules/sanitize-html": {
+ "version": "1.27.5",
+ "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.5.tgz",
+ "integrity": "sha512-M4M5iXDAUEcZKLXkmk90zSYWEtk5NH3JmojQxKxV371fnMh+x9t1rqdmXaGoyEHw3z/X/8vnFhKjGL5xFGOJ3A==",
+ "dependencies": {
+ "htmlparser2": "^4.1.0",
+ "lodash": "^4.17.15",
+ "parse-srcset": "^1.0.2",
+ "postcss": "^7.0.27"
+ }
+ },
+ "node_modules/sanitize-html/node_modules/domhandler": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
+ "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
+ "dependencies": {
+ "domelementtype": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/sanitize-html/node_modules/htmlparser2": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
+ "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "domhandler": "^3.0.0",
+ "domutils": "^2.0.0",
+ "entities": "^2.0.0"
+ }
+ },
+ "node_modules/saslprep": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
+ "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
+ "optional": true,
+ "dependencies": {
+ "sparse-bitfield": "^3.0.3"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/serialize-javascript": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
+ "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+ "dev": true
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shelljs": {
+ "version": "0.8.5",
+ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
+ "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
+ "dependencies": {
+ "glob": "^7.0.0",
+ "interpret": "^1.0.0",
+ "rechoir": "^0.6.2"
+ },
+ "bin": {
+ "shjs": "bin/shjs"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/shortid": {
+ "version": "2.2.16",
+ "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz",
+ "integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==",
+ "dependencies": {
+ "nanoid": "^2.1.0"
+ }
+ },
+ "node_modules/shortid/node_modules/nanoid": {
+ "version": "2.1.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
+ "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA=="
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/sigmund": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
+ "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA="
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.6",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
+ "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==",
+ "dev": true
+ },
+ "node_modules/simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "node_modules/slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/slick": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/slick/-/slick-1.12.2.tgz",
+ "integrity": "sha1-vQSN23TefRymkV+qSldXCzVQwtc=",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sparse-bitfield": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
+ "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
+ "optional": true,
+ "dependencies": {
+ "memory-pager": "^1.0.2"
+ }
+ },
+ "node_modules/spawn-wrap": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz",
+ "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^2.0.0",
+ "is-windows": "^1.0.2",
+ "make-dir": "^3.0.0",
+ "rimraf": "^3.0.0",
+ "signal-exit": "^3.0.2",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/spawn-wrap/node_modules/make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/spdx-exceptions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
+ "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+ "dev": true
+ },
+ "node_modules/spdx-expression-parse": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+ "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+ "dev": true,
+ "dependencies": {
+ "spdx-exceptions": "^2.1.0",
+ "spdx-license-ids": "^3.0.0"
+ }
+ },
+ "node_modules/spdx-license-ids": {
+ "version": "3.0.11",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
+ "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==",
+ "dev": true
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "node_modules/statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/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,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/table": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz",
+ "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^8.0.1",
+ "lodash.truncate": "^4.4.2",
+ "slice-ansi": "^4.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/table/node_modules/ajv": {
+ "version": "8.9.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
+ "integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/table/node_modules/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==",
+ "dev": true
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
+ "dev": true
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
+ },
+ "node_modules/tslib": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
+ "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
+ },
+ "node_modules/tsscmp": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
+ "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==",
+ "engines": {
+ "node": ">=0.6.x"
+ }
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/tsutils/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typedarray-to-buffer": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
+ "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
+ "dev": true,
+ "dependencies": {
+ "is-typedarray": "^1.0.0"
+ }
+ },
+ "node_modules/typedoc": {
+ "version": "0.17.8",
+ "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.17.8.tgz",
+ "integrity": "sha512-/OyrHCJ8jtzu+QZ+771YaxQ9s4g5Z3XsQE3Ma7q+BL392xxBn4UMvvCdVnqKC2T/dz03/VXSLVKOP3lHmDdc/w==",
+ "dependencies": {
+ "fs-extra": "^8.1.0",
+ "handlebars": "^4.7.6",
+ "highlight.js": "^10.0.0",
+ "lodash": "^4.17.15",
+ "lunr": "^2.3.8",
+ "marked": "1.0.0",
+ "minimatch": "^3.0.0",
+ "progress": "^2.0.3",
+ "shelljs": "^0.8.4",
+ "typedoc-default-themes": "^0.10.2"
+ },
+ "bin": {
+ "typedoc": "bin/typedoc"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ },
+ "peerDependencies": {
+ "typescript": ">=3.8.3"
+ }
+ },
+ "node_modules/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==",
+ "dependencies": {
+ "lunr": "^2.3.8"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.5.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
+ "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/uglify-js": {
+ "version": "3.14.5",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.5.tgz",
+ "integrity": "sha512-qZukoSxOG0urUTvjc2ERMTcAy+BiFh3weWAkeurLwjrCba73poHmG3E36XEjd/JGukMzwTL7uCxZiAexj8ppvQ==",
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/unicode-canonical-property-names-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
+ "dev": true,
+ "dependencies": {
+ "unicode-canonical-property-names-ecmascript": "^2.0.0",
+ "unicode-property-aliases-ecmascript": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-value-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-property-aliases-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/upper-case": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
+ "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg="
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/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==",
+ "dev": true
+ },
+ "node_modules/valid-data-url": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-3.0.1.tgz",
+ "integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/web-resource-inliner": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-5.0.0.tgz",
+ "integrity": "sha512-AIihwH+ZmdHfkJm7BjSXiEClVt4zUFqX4YlFAzjL13wLtDuUneSaFvDBTbdYRecs35SiU7iNKbMnN+++wVfb6A==",
+ "dependencies": {
+ "ansi-colors": "^4.1.1",
+ "escape-goat": "^3.0.0",
+ "htmlparser2": "^4.0.0",
+ "mime": "^2.4.6",
+ "node-fetch": "^2.6.0",
+ "valid-data-url": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/web-resource-inliner/node_modules/domhandler": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
+ "integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
+ "dependencies": {
+ "domelementtype": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/web-resource-inliner/node_modules/htmlparser2": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
+ "integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "domhandler": "^3.0.0",
+ "domutils": "^2.0.0",
+ "entities": "^2.0.0"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
+ "dev": true
+ },
+ "node_modules/wide-align": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
+ "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^1.0.2 || 2"
+ }
+ },
+ "node_modules/wide-align/node_modules/ansi-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/wide-align/node_modules/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,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/wide-align/node_modules/string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+ "dev": true,
+ "dependencies": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/wide-align/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/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==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
+ },
+ "node_modules/workerpool": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz",
+ "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "node_modules/write-file-atomic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
+ "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
+ "dev": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "is-typedarray": "^1.0.0",
+ "signal-exit": "^3.0.2",
+ "typedarray-to-buffer": "^3.1.5"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
+ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
+ },
+ "node_modules/yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "dependencies": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-unparser/node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yargs-unparser/node_modules/decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ylru": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz",
+ "integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ==",
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ },
"dependencies": {
"@babel/cli": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.16.8.tgz",
"integrity": "sha512-FTKBbxyk5TclXOGmwYyqelqP5IF6hMxaeJskd85jbR5jBfYlwqgwAbJwnixi1ZBbTqKfFuAA95mdmUFeSRwyJA==",
"dev": true,
"requires": {
"@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3",
"chokidar": "^3.4.0",
"commander": "^4.0.1",
"convert-source-map": "^1.1.0",
"fs-readdir-recursive": "^1.1.0",
"glob": "^7.0.0",
"make-dir": "^2.1.0",
"slash": "^2.0.0",
"source-map": "^0.5.0"
}
},
"@babel/code-frame": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz",
"integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==",
"dev": true,
"requires": {
"@babel/highlight": "^7.16.7"
}
},
"@babel/compat-data": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.8.tgz",
"integrity": "sha512-m7OkX0IdKLKPpBlJtF561YJal5y/jyI5fNfWbPxh2D/nbzzGI4qRyrD8xO2jB24u7l+5I2a43scCG2IrfjC50Q==",
"dev": true
},
"@babel/core": {
"version": "7.16.12",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.12.tgz",
"integrity": "sha512-dK5PtG1uiN2ikk++5OzSYsitZKny4wOCD0nrO4TqnW4BVBTQ2NGS3NgilvT/TEyxTST7LNyWV/T4tXDoD3fOgg==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.16.7",
"@babel/generator": "^7.16.8",
"@babel/helper-compilation-targets": "^7.16.7",
"@babel/helper-module-transforms": "^7.16.7",
"@babel/helpers": "^7.16.7",
"@babel/parser": "^7.16.12",
"@babel/template": "^7.16.7",
"@babel/traverse": "^7.16.10",
"@babel/types": "^7.16.8",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.1.2",
"semver": "^6.3.0",
"source-map": "^0.5.0"
}
},
"@babel/generator": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.8.tgz",
"integrity": "sha512-1ojZwE9+lOXzcWdWmO6TbUzDfqLD39CmEhN8+2cX9XkDo5yW1OpgfejfliysR2AWLpMamTiOiAp/mtroaymhpw==",
"dev": true,
"requires": {
"@babel/types": "^7.16.8",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
}
},
"@babel/helper-annotate-as-pure": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz",
"integrity": "sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==",
"dev": true,
"requires": {
"@babel/types": "^7.16.7"
}
},
"@babel/helper-builder-binary-assignment-operator-visitor": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz",
"integrity": "sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==",
"dev": true,
"requires": {
"@babel/helper-explode-assignable-expression": "^7.16.7",
"@babel/types": "^7.16.7"
}
},
"@babel/helper-compilation-targets": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz",
"integrity": "sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.16.4",
"@babel/helper-validator-option": "^7.16.7",
"browserslist": "^4.17.5",
"semver": "^6.3.0"
}
},
"@babel/helper-create-class-features-plugin": {
"version": "7.16.10",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.10.tgz",
"integrity": "sha512-wDeej0pu3WN/ffTxMNCPW5UCiOav8IcLRxSIyp/9+IF2xJUM9h/OYjg0IJLHaL6F8oU8kqMz9nc1vryXhMsgXg==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.16.7",
"@babel/helper-environment-visitor": "^7.16.7",
"@babel/helper-function-name": "^7.16.7",
"@babel/helper-member-expression-to-functions": "^7.16.7",
"@babel/helper-optimise-call-expression": "^7.16.7",
"@babel/helper-replace-supers": "^7.16.7",
"@babel/helper-split-export-declaration": "^7.16.7"
}
},
"@babel/helper-create-regexp-features-plugin": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.7.tgz",
"integrity": "sha512-fk5A6ymfp+O5+p2yCkXAu5Kyj6v0xh0RBeNcAkYUMDvvAAoxvSKXn+Jb37t/yWFiQVDFK1ELpUTD8/aLhCPu+g==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.16.7",
"regexpu-core": "^4.7.1"
}
},
"@babel/helper-define-polyfill-provider": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz",
"integrity": "sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==",
"dev": true,
"requires": {
"@babel/helper-compilation-targets": "^7.13.0",
"@babel/helper-module-imports": "^7.12.13",
"@babel/helper-plugin-utils": "^7.13.0",
"@babel/traverse": "^7.13.0",
"debug": "^4.1.1",
"lodash.debounce": "^4.0.8",
"resolve": "^1.14.2",
"semver": "^6.1.2"
}
},
"@babel/helper-environment-visitor": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz",
"integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==",
"dev": true,
"requires": {
"@babel/types": "^7.16.7"
}
},
"@babel/helper-explode-assignable-expression": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz",
"integrity": "sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==",
"dev": true,
"requires": {
"@babel/types": "^7.16.7"
}
},
"@babel/helper-function-name": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz",
"integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==",
"dev": true,
"requires": {
"@babel/helper-get-function-arity": "^7.16.7",
"@babel/template": "^7.16.7",
"@babel/types": "^7.16.7"
}
},
"@babel/helper-get-function-arity": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz",
"integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==",
"dev": true,
"requires": {
"@babel/types": "^7.16.7"
}
},
"@babel/helper-hoist-variables": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz",
"integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==",
"dev": true,
"requires": {
"@babel/types": "^7.16.7"
}
},
"@babel/helper-member-expression-to-functions": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz",
"integrity": "sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==",
"dev": true,
"requires": {
"@babel/types": "^7.16.7"
}
},
"@babel/helper-module-imports": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz",
"integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==",
"dev": true,
"requires": {
"@babel/types": "^7.16.7"
}
},
"@babel/helper-module-transforms": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.7.tgz",
"integrity": "sha512-gaqtLDxJEFCeQbYp9aLAefjhkKdjKcdh6DB7jniIGU3Pz52WAmP268zK0VgPz9hUNkMSYeH976K2/Y6yPadpng==",
"dev": true,
"requires": {
"@babel/helper-environment-visitor": "^7.16.7",
"@babel/helper-module-imports": "^7.16.7",
"@babel/helper-simple-access": "^7.16.7",
"@babel/helper-split-export-declaration": "^7.16.7",
"@babel/helper-validator-identifier": "^7.16.7",
"@babel/template": "^7.16.7",
"@babel/traverse": "^7.16.7",
"@babel/types": "^7.16.7"
}
},
"@babel/helper-optimise-call-expression": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz",
"integrity": "sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==",
"dev": true,
"requires": {
"@babel/types": "^7.16.7"
}
},
"@babel/helper-plugin-utils": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz",
"integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==",
"dev": true
},
"@babel/helper-remap-async-to-generator": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz",
"integrity": "sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.16.7",
"@babel/helper-wrap-function": "^7.16.8",
"@babel/types": "^7.16.8"
}
},
"@babel/helper-replace-supers": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz",
"integrity": "sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==",
"dev": true,
"requires": {
"@babel/helper-environment-visitor": "^7.16.7",
"@babel/helper-member-expression-to-functions": "^7.16.7",
"@babel/helper-optimise-call-expression": "^7.16.7",
"@babel/traverse": "^7.16.7",
"@babel/types": "^7.16.7"
}
},
"@babel/helper-simple-access": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz",
"integrity": "sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==",
"dev": true,
"requires": {
"@babel/types": "^7.16.7"
}
},
"@babel/helper-skip-transparent-expression-wrappers": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz",
"integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==",
"dev": true,
"requires": {
"@babel/types": "^7.16.0"
}
},
"@babel/helper-split-export-declaration": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz",
"integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==",
"dev": true,
"requires": {
"@babel/types": "^7.16.7"
}
},
"@babel/helper-validator-identifier": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz",
"integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==",
"dev": true
},
"@babel/helper-validator-option": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz",
"integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==",
"dev": true
},
"@babel/helper-wrap-function": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz",
"integrity": "sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==",
"dev": true,
"requires": {
"@babel/helper-function-name": "^7.16.7",
"@babel/template": "^7.16.7",
"@babel/traverse": "^7.16.8",
"@babel/types": "^7.16.8"
}
},
"@babel/helpers": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.7.tgz",
"integrity": "sha512-9ZDoqtfY7AuEOt3cxchfii6C7GDyyMBffktR5B2jvWv8u2+efwvpnVKXMWzNehqy68tKgAfSwfdw/lWpthS2bw==",
"dev": true,
"requires": {
"@babel/template": "^7.16.7",
"@babel/traverse": "^7.16.7",
"@babel/types": "^7.16.7"
}
},
"@babel/highlight": {
"version": "7.16.10",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz",
"integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.16.7",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
"dev": true
},
"escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
"dev": true
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
"dev": true
},
"supports-color": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
"requires": {
"has-flag": "^3.0.0"
}
}
}
},
"@babel/parser": {
"version": "7.16.12",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.12.tgz",
"integrity": "sha512-VfaV15po8RiZssrkPweyvbGVSe4x2y+aciFCgn0n0/SJMR22cwofRV1mtnJQYcSB1wUTaA/X1LnA3es66MCO5A==",
"dev": true
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz",
"integrity": "sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz",
"integrity": "sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
"@babel/plugin-proposal-optional-chaining": "^7.16.7"
}
},
"@babel/plugin-proposal-async-generator-functions": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz",
"integrity": "sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/helper-remap-async-to-generator": "^7.16.8",
"@babel/plugin-syntax-async-generators": "^7.8.4"
}
},
"@babel/plugin-proposal-class-properties": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz",
"integrity": "sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==",
"dev": true,
"requires": {
"@babel/helper-create-class-features-plugin": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-proposal-class-static-block": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.7.tgz",
"integrity": "sha512-dgqJJrcZoG/4CkMopzhPJjGxsIe9A8RlkQLnL/Vhhx8AA9ZuaRwGSlscSh42hazc7WSrya/IK7mTeoF0DP9tEw==",
"dev": true,
"requires": {
"@babel/helper-create-class-features-plugin": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-class-static-block": "^7.14.5"
}
},
"@babel/plugin-proposal-dynamic-import": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz",
"integrity": "sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-dynamic-import": "^7.8.3"
}
},
"@babel/plugin-proposal-export-namespace-from": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz",
"integrity": "sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-export-namespace-from": "^7.8.3"
}
},
"@babel/plugin-proposal-json-strings": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz",
"integrity": "sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-json-strings": "^7.8.3"
}
},
"@babel/plugin-proposal-logical-assignment-operators": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz",
"integrity": "sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
}
},
"@babel/plugin-proposal-nullish-coalescing-operator": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz",
"integrity": "sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
}
},
"@babel/plugin-proposal-numeric-separator": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz",
"integrity": "sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-numeric-separator": "^7.10.4"
}
},
"@babel/plugin-proposal-object-rest-spread": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.7.tgz",
"integrity": "sha512-3O0Y4+dw94HA86qSg9IHfyPktgR7q3gpNVAeiKQd+8jBKFaU5NQS1Yatgo4wY+UFNuLjvxcSmzcsHqrhgTyBUA==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.16.4",
"@babel/helper-compilation-targets": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-object-rest-spread": "^7.8.3",
"@babel/plugin-transform-parameters": "^7.16.7"
}
},
"@babel/plugin-proposal-optional-catch-binding": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz",
"integrity": "sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
}
},
"@babel/plugin-proposal-optional-chaining": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz",
"integrity": "sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
"@babel/plugin-syntax-optional-chaining": "^7.8.3"
}
},
"@babel/plugin-proposal-private-methods": {
"version": "7.16.11",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz",
"integrity": "sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==",
"dev": true,
"requires": {
"@babel/helper-create-class-features-plugin": "^7.16.10",
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-proposal-private-property-in-object": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz",
"integrity": "sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.16.7",
"@babel/helper-create-class-features-plugin": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-private-property-in-object": "^7.14.5"
}
},
"@babel/plugin-proposal-unicode-property-regex": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz",
"integrity": "sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==",
"dev": true,
"requires": {
"@babel/helper-create-regexp-features-plugin": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-syntax-async-generators": {
"version": "7.8.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
"integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
},
"@babel/plugin-syntax-class-properties": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
"integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.12.13"
}
},
"@babel/plugin-syntax-class-static-block": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
"integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.14.5"
}
},
"@babel/plugin-syntax-dynamic-import": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
"integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
},
"@babel/plugin-syntax-export-namespace-from": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
"integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.3"
}
},
"@babel/plugin-syntax-json-strings": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
"integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
},
"@babel/plugin-syntax-jsx": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz",
"integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-syntax-logical-assignment-operators": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
"integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-syntax-nullish-coalescing-operator": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
"integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
},
"@babel/plugin-syntax-numeric-separator": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
"integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.10.4"
}
},
"@babel/plugin-syntax-object-rest-spread": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
"integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
},
"@babel/plugin-syntax-optional-catch-binding": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
"integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
},
"@babel/plugin-syntax-optional-chaining": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
"integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.8.0"
}
},
"@babel/plugin-syntax-private-property-in-object": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
"integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.14.5"
}
},
"@babel/plugin-syntax-top-level-await": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
"integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.14.5"
}
},
"@babel/plugin-transform-arrow-functions": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz",
"integrity": "sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-async-to-generator": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz",
"integrity": "sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==",
"dev": true,
"requires": {
"@babel/helper-module-imports": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/helper-remap-async-to-generator": "^7.16.8"
}
},
"@babel/plugin-transform-block-scoped-functions": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz",
"integrity": "sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-block-scoping": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz",
"integrity": "sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-classes": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz",
"integrity": "sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.16.7",
"@babel/helper-environment-visitor": "^7.16.7",
"@babel/helper-function-name": "^7.16.7",
"@babel/helper-optimise-call-expression": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/helper-replace-supers": "^7.16.7",
"@babel/helper-split-export-declaration": "^7.16.7",
"globals": "^11.1.0"
}
},
"@babel/plugin-transform-computed-properties": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz",
"integrity": "sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-destructuring": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.7.tgz",
"integrity": "sha512-VqAwhTHBnu5xBVDCvrvqJbtLUa++qZaWC0Fgr2mqokBlulZARGyIvZDoqbPlPaKImQ9dKAcCzbv+ul//uqu70A==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-dotall-regex": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz",
"integrity": "sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==",
"dev": true,
"requires": {
"@babel/helper-create-regexp-features-plugin": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-duplicate-keys": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz",
"integrity": "sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-exponentiation-operator": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz",
"integrity": "sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==",
"dev": true,
"requires": {
"@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-for-of": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz",
"integrity": "sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-function-name": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz",
"integrity": "sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==",
"dev": true,
"requires": {
"@babel/helper-compilation-targets": "^7.16.7",
"@babel/helper-function-name": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-literals": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz",
"integrity": "sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-member-expression-literals": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz",
"integrity": "sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-modules-amd": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz",
"integrity": "sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==",
"dev": true,
"requires": {
"@babel/helper-module-transforms": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"babel-plugin-dynamic-import-node": "^2.3.3"
}
},
"@babel/plugin-transform-modules-commonjs": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz",
"integrity": "sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==",
"dev": true,
"requires": {
"@babel/helper-module-transforms": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/helper-simple-access": "^7.16.7",
"babel-plugin-dynamic-import-node": "^2.3.3"
}
},
"@babel/plugin-transform-modules-systemjs": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz",
"integrity": "sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==",
"dev": true,
"requires": {
"@babel/helper-hoist-variables": "^7.16.7",
"@babel/helper-module-transforms": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/helper-validator-identifier": "^7.16.7",
"babel-plugin-dynamic-import-node": "^2.3.3"
}
},
"@babel/plugin-transform-modules-umd": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz",
"integrity": "sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==",
"dev": true,
"requires": {
"@babel/helper-module-transforms": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-named-capturing-groups-regex": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz",
"integrity": "sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==",
"dev": true,
"requires": {
"@babel/helper-create-regexp-features-plugin": "^7.16.7"
}
},
"@babel/plugin-transform-new-target": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz",
"integrity": "sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-object-super": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz",
"integrity": "sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/helper-replace-supers": "^7.16.7"
}
},
"@babel/plugin-transform-parameters": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz",
"integrity": "sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-property-literals": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz",
"integrity": "sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-react-display-name": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz",
"integrity": "sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-react-jsx": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.7.tgz",
"integrity": "sha512-8D16ye66fxiE8m890w0BpPpngG9o9OVBBy0gH2E+2AR7qMR2ZpTYJEqLxAsoroenMId0p/wMW+Blc0meDgu0Ag==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.16.7",
"@babel/helper-module-imports": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/plugin-syntax-jsx": "^7.16.7",
"@babel/types": "^7.16.7"
}
},
"@babel/plugin-transform-react-jsx-development": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz",
"integrity": "sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==",
"dev": true,
"requires": {
"@babel/plugin-transform-react-jsx": "^7.16.7"
}
},
"@babel/plugin-transform-react-pure-annotations": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz",
"integrity": "sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==",
"dev": true,
"requires": {
"@babel/helper-annotate-as-pure": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-regenerator": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz",
"integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==",
"dev": true,
"requires": {
"regenerator-transform": "^0.14.2"
}
},
"@babel/plugin-transform-reserved-words": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz",
"integrity": "sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-shorthand-properties": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz",
"integrity": "sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-spread": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz",
"integrity": "sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/helper-skip-transparent-expression-wrappers": "^7.16.0"
}
},
"@babel/plugin-transform-sticky-regex": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz",
"integrity": "sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-template-literals": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz",
"integrity": "sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-typeof-symbol": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz",
"integrity": "sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-unicode-escapes": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz",
"integrity": "sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/plugin-transform-unicode-regex": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz",
"integrity": "sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==",
"dev": true,
"requires": {
"@babel/helper-create-regexp-features-plugin": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7"
}
},
"@babel/polyfill": {
"version": "7.12.1",
"resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz",
"integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==",
"requires": {
"core-js": "^2.6.5",
"regenerator-runtime": "^0.13.4"
}
},
"@babel/preset-env": {
"version": "7.16.11",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.11.tgz",
"integrity": "sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.16.8",
"@babel/helper-compilation-targets": "^7.16.7",
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/helper-validator-option": "^7.16.7",
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.7",
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.7",
"@babel/plugin-proposal-async-generator-functions": "^7.16.8",
"@babel/plugin-proposal-class-properties": "^7.16.7",
"@babel/plugin-proposal-class-static-block": "^7.16.7",
"@babel/plugin-proposal-dynamic-import": "^7.16.7",
"@babel/plugin-proposal-export-namespace-from": "^7.16.7",
"@babel/plugin-proposal-json-strings": "^7.16.7",
"@babel/plugin-proposal-logical-assignment-operators": "^7.16.7",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7",
"@babel/plugin-proposal-numeric-separator": "^7.16.7",
"@babel/plugin-proposal-object-rest-spread": "^7.16.7",
"@babel/plugin-proposal-optional-catch-binding": "^7.16.7",
"@babel/plugin-proposal-optional-chaining": "^7.16.7",
"@babel/plugin-proposal-private-methods": "^7.16.11",
"@babel/plugin-proposal-private-property-in-object": "^7.16.7",
"@babel/plugin-proposal-unicode-property-regex": "^7.16.7",
"@babel/plugin-syntax-async-generators": "^7.8.4",
"@babel/plugin-syntax-class-properties": "^7.12.13",
"@babel/plugin-syntax-class-static-block": "^7.14.5",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-syntax-export-namespace-from": "^7.8.3",
"@babel/plugin-syntax-json-strings": "^7.8.3",
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
"@babel/plugin-syntax-numeric-separator": "^7.10.4",
"@babel/plugin-syntax-object-rest-spread": "^7.8.3",
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
"@babel/plugin-syntax-optional-chaining": "^7.8.3",
"@babel/plugin-syntax-private-property-in-object": "^7.14.5",
"@babel/plugin-syntax-top-level-await": "^7.14.5",
"@babel/plugin-transform-arrow-functions": "^7.16.7",
"@babel/plugin-transform-async-to-generator": "^7.16.8",
"@babel/plugin-transform-block-scoped-functions": "^7.16.7",
"@babel/plugin-transform-block-scoping": "^7.16.7",
"@babel/plugin-transform-classes": "^7.16.7",
"@babel/plugin-transform-computed-properties": "^7.16.7",
"@babel/plugin-transform-destructuring": "^7.16.7",
"@babel/plugin-transform-dotall-regex": "^7.16.7",
"@babel/plugin-transform-duplicate-keys": "^7.16.7",
"@babel/plugin-transform-exponentiation-operator": "^7.16.7",
"@babel/plugin-transform-for-of": "^7.16.7",
"@babel/plugin-transform-function-name": "^7.16.7",
"@babel/plugin-transform-literals": "^7.16.7",
"@babel/plugin-transform-member-expression-literals": "^7.16.7",
"@babel/plugin-transform-modules-amd": "^7.16.7",
"@babel/plugin-transform-modules-commonjs": "^7.16.8",
"@babel/plugin-transform-modules-systemjs": "^7.16.7",
"@babel/plugin-transform-modules-umd": "^7.16.7",
"@babel/plugin-transform-named-capturing-groups-regex": "^7.16.8",
"@babel/plugin-transform-new-target": "^7.16.7",
"@babel/plugin-transform-object-super": "^7.16.7",
"@babel/plugin-transform-parameters": "^7.16.7",
"@babel/plugin-transform-property-literals": "^7.16.7",
"@babel/plugin-transform-regenerator": "^7.16.7",
"@babel/plugin-transform-reserved-words": "^7.16.7",
"@babel/plugin-transform-shorthand-properties": "^7.16.7",
"@babel/plugin-transform-spread": "^7.16.7",
"@babel/plugin-transform-sticky-regex": "^7.16.7",
"@babel/plugin-transform-template-literals": "^7.16.7",
"@babel/plugin-transform-typeof-symbol": "^7.16.7",
"@babel/plugin-transform-unicode-escapes": "^7.16.7",
"@babel/plugin-transform-unicode-regex": "^7.16.7",
"@babel/preset-modules": "^0.1.5",
"@babel/types": "^7.16.8",
"babel-plugin-polyfill-corejs2": "^0.3.0",
"babel-plugin-polyfill-corejs3": "^0.5.0",
"babel-plugin-polyfill-regenerator": "^0.3.0",
"core-js-compat": "^3.20.2",
"semver": "^6.3.0"
}
},
"@babel/preset-modules": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz",
"integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.0.0",
"@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
"@babel/plugin-transform-dotall-regex": "^7.4.4",
"@babel/types": "^7.4.4",
"esutils": "^2.0.2"
}
},
"@babel/preset-react": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.16.7.tgz",
"integrity": "sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==",
"dev": true,
"requires": {
"@babel/helper-plugin-utils": "^7.16.7",
"@babel/helper-validator-option": "^7.16.7",
"@babel/plugin-transform-react-display-name": "^7.16.7",
"@babel/plugin-transform-react-jsx": "^7.16.7",
"@babel/plugin-transform-react-jsx-development": "^7.16.7",
"@babel/plugin-transform-react-pure-annotations": "^7.16.7"
}
},
"@babel/runtime": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.7.tgz",
"integrity": "sha512-9E9FJowqAsytyOY6LG+1KuueckRL+aQW+mKvXRXnuFGyRAyepJPmEo9vgMfXUA6O9u3IeEdv9MAkppFcaQwogQ==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
},
"@babel/template": {
"version": "7.16.7",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz",
"integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.16.7",
"@babel/parser": "^7.16.7",
"@babel/types": "^7.16.7"
}
},
"@babel/traverse": {
"version": "7.16.10",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.10.tgz",
"integrity": "sha512-yzuaYXoRJBGMlBhsMJoUW7G1UmSb/eXr/JHYM/MsOJgavJibLwASijW7oXBdw3NQ6T0bW7Ty5P/VarOs9cHmqw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.16.7",
"@babel/generator": "^7.16.8",
"@babel/helper-environment-visitor": "^7.16.7",
"@babel/helper-function-name": "^7.16.7",
"@babel/helper-hoist-variables": "^7.16.7",
"@babel/helper-split-export-declaration": "^7.16.7",
"@babel/parser": "^7.16.10",
"@babel/types": "^7.16.8",
"debug": "^4.1.0",
"globals": "^11.1.0"
}
},
"@babel/types": {
"version": "7.16.8",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz",
"integrity": "sha512-smN2DQc5s4M7fntyjGtyIPbRJv6wW4rU/94fmYJ7PKQuZkC0qGMHXJbg6sNGt12JmVr4k5YaptI/XtiLJBnmIg==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.16.7",
"to-fast-properties": "^2.0.0"
}
},
"@eslint/eslintrc": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
"integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==",
"dev": true,
"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": {
"globals": {
"version": "13.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
"integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
"dev": true,
"requires": {
"type-fest": "^0.20.2"
}
},
"type-fest": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true
}
}
},
"@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==",
"dev": true,
"requires": {
"@humanwhocodes/object-schema": "^1.2.0",
"debug": "^4.1.1",
"minimatch": "^3.0.4"
}
},
"@humanwhocodes/object-schema": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
"dev": true
},
"@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
"integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
"dev": true,
"requires": {
"camelcase": "^5.3.1",
"find-up": "^4.1.0",
"get-package-type": "^0.1.0",
"js-yaml": "^3.13.1",
"resolve-from": "^5.0.0"
},
"dependencies": {
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"requires": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
}
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"requires": {
"p-locate": "^4.1.0"
}
},
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"requires": {
"p-limit": "^2.2.0"
}
},
"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": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
"integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
"dev": true
},
"@koa/router": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/@koa/router/-/router-10.1.1.tgz",
"integrity": "sha512-ORNjq5z4EmQPriKbR0ER3k4Gh7YGNhWDL7JBW+8wXDrHLbWYKYSJaOJ9aN06npF5tbTxe2JBOsurpJDAvjiXKw==",
"requires": {
"debug": "^4.1.1",
"http-errors": "^1.7.3",
"koa-compose": "^4.1.0",
"methods": "^1.1.2",
"path-to-regexp": "^6.1.0"
}
},
"@nicolo-ribaudo/chokidar-2": {
"version": "2.1.8-no-fsevents.3",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz",
"integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==",
"dev": true,
"optional": true
},
+ "@sealcode/ts-predicates": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.2.5.tgz",
+ "integrity": "sha512-mALqlRBsjLkroDb3B/m6aYIB4/7kIh6s3R9diCR4EdrUzKyAHtXdgV5SdZyj6llxPOzJt3VYokXvOQbZazw5kg=="
+ },
"@types/accepts": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz",
"integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==",
"requires": {
"@types/node": "*"
}
},
"@types/bluebird": {
"version": "3.5.36",
"resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.36.tgz",
"integrity": "sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q=="
},
"@types/body-parser": {
"version": "1.19.2",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
"integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
"requires": {
"@types/connect": "*",
"@types/node": "*"
}
},
"@types/boom": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/@types/boom/-/boom-7.3.1.tgz",
"integrity": "sha512-9952U+NySPQ35Xr8CU0lHrC3vBuqjh2xmK87l06uW8PN4ePHOqhtjrJV5+e7lqgb4UtzwUHELkbxEXxnPXLlTA=="
},
"@types/bson": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.2.0.tgz",
"integrity": "sha512-ELCPqAdroMdcuxqwMgUpifQyRoTpyYCNr1V9xKyF40VsBobsj+BbWNRvwGchMgBPGqkw655ypkjj2MEF5ywVwg==",
"requires": {
"bson": "*"
}
},
"@types/clone": {
"version": "0.1.30",
"resolved": "https://registry.npmjs.org/@types/clone/-/clone-0.1.30.tgz",
"integrity": "sha1-5zZWSMG0ITalnH1QQGN7O1yDthQ="
},
"@types/color": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.2.tgz",
"integrity": "sha512-INiJl6sfNn8iyC5paxVzqiVUEj2boIlFki02uRTAkKwAj++7aAF+ZfEv/XrIeBa0XI/fTZuDHW8rEEcEVnON+Q==",
"requires": {
"@types/color-convert": "*"
}
},
"@types/color-convert": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.0.tgz",
"integrity": "sha512-m7GG7IKKGuJUXvkZ1qqG3ChccdIM/qBBo913z+Xft0nKCX4hAU/IxKwZBU4cpRZ7GS5kV4vOblUkILtSShCPXQ==",
"requires": {
"@types/color-name": "*"
}
},
"@types/color-hash": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/color-hash/-/color-hash-1.0.2.tgz",
"integrity": "sha512-QJCVXSVRse+mMvzWQ8vH6AcKxtqCgHPHf5abAdGn86DEeQdUpSJnKAeCa1+hZuohaUF3l4RhigC9akRx82Bwig=="
},
"@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
},
"@types/connect": {
"version": "3.4.35",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
"integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
"requires": {
"@types/node": "*"
}
},
"@types/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.4.tgz",
"integrity": "sha512-0mPF08jn9zYI0n0Q/Pnz7C4kThdSt+6LD4amsrYDDpgBfrVWa3TcCOxKX1zkGgYniGagRv8heN2cbh+CAn+uuQ=="
},
"@types/cookies": {
"version": "0.7.7",
"resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz",
"integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==",
"requires": {
"@types/connect": "*",
"@types/express": "*",
"@types/keygrip": "*",
"@types/node": "*"
}
},
"@types/escape-html": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/escape-html/-/escape-html-1.0.1.tgz",
"integrity": "sha512-4mI1FuUUZiuT95fSVqvZxp/ssQK9zsa86S43h9x3zPOSU9BBJ+BfDkXwuaU7BfsD+e7U0/cUUfJFk3iW2M4okA=="
},
"@types/eslint-visitor-keys": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
"integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
"dev": true
},
"@types/express": {
"version": "4.17.13",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz",
"integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==",
"requires": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.18",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"@types/express-serve-static-core": {
"version": "4.17.28",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz",
"integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==",
"requires": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*"
}
},
"@types/formidable": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.2.5.tgz",
"integrity": "sha512-zu3mQJa4hDNubEMViSj937602XdDGzK7Q5pJ5QmLUbNxclbo9tZGt5jtwM352ssZ+pqo5V4H14TBvT/ALqQQcA==",
"requires": {
"@types/node": "*"
}
},
"@types/http-assert": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.3.tgz",
"integrity": "sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA=="
},
"@types/http-errors": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-1.8.2.tgz",
"integrity": "sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w=="
},
"@types/json-schema": {
"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==",
"dev": true
},
"@types/keygrip": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz",
"integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw=="
},
"@types/koa": {
"version": "2.13.4",
"resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.13.4.tgz",
"integrity": "sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==",
"requires": {
"@types/accepts": "*",
"@types/content-disposition": "*",
"@types/cookies": "*",
"@types/http-assert": "*",
"@types/http-errors": "*",
"@types/keygrip": "*",
"@types/koa-compose": "*",
"@types/node": "*"
}
},
+ "@types/koa__router": {
+ "version": "8.0.11",
+ "resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-8.0.11.tgz",
+ "integrity": "sha512-WXgKWpBsbS14kzmzD9LeFapOIa678h7zvUHxDwXwSx4ETKXhXLVUAToX6jZ/U7EihM7qwyD9W/BZvB0MRu7MTQ==",
+ "requires": {
+ "@types/koa": "*"
+ }
+ },
"@types/koa-compose": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz",
"integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==",
"requires": {
"@types/koa": "*"
}
},
"@types/koa-mount": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/koa-mount/-/koa-mount-4.0.1.tgz",
"integrity": "sha512-HNeg80CVS9Dfq8dGYqCZZCAUm7g6jPCNJ1ydqVLEJxLrjmeburpvq+lOZkE4rxBZ6O38dr3tj9IA3IfbdoI05w==",
"requires": {
"@types/koa": "*"
}
},
"@types/koa-qs": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@types/koa-qs/-/koa-qs-2.0.0.tgz",
"integrity": "sha512-cBfbUvW70JsU2FCgUCFOoretdvayGzRJ2vEyNQbnZ7vb2pZ/QA+gcNzE6nVxxCcrcnRtGB7tXIRHqHPXS51utA==",
"requires": {
"@types/koa": "*"
}
},
"@types/koa-send": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/@types/koa-send/-/koa-send-4.1.3.tgz",
"integrity": "sha512-daaTqPZlgjIJycSTNjKpHYuKhXYP30atFc1pBcy6HHqB9+vcymDgYTguPdx9tO4HMOqNyz6bz/zqpxt5eLR+VA==",
"requires": {
"@types/koa": "*"
}
},
"@types/koa-static": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/koa-static/-/koa-static-4.0.2.tgz",
"integrity": "sha512-ns/zHg+K6XVPMuohjpOlpkR1WLa4VJ9czgUP9bxkCDn0JZBtUWbD/wKDZzPGDclkQK1bpAEScufCHOy8cbfL0w==",
"requires": {
"@types/koa": "*",
"@types/koa-send": "*"
}
},
- "@types/koa__router": {
- "version": "8.0.11",
- "resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-8.0.11.tgz",
- "integrity": "sha512-WXgKWpBsbS14kzmzD9LeFapOIa678h7zvUHxDwXwSx4ETKXhXLVUAToX6jZ/U7EihM7qwyD9W/BZvB0MRu7MTQ==",
- "requires": {
- "@types/koa": "*"
- }
- },
"@types/mime": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz",
"integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q=="
},
"@types/mjml": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/@types/mjml/-/mjml-4.7.0.tgz",
"integrity": "sha512-aWWu8Lxq2SexXGs+lBPRUpN3kFf0sDRo3Y4jz7BQ15cQvMfyZOadgFJsNlHmDqI6D2Qjx0PIK+1f9IMXgq9vTA==",
"requires": {
"@types/mjml-core": "*"
}
},
"@types/mjml-core": {
"version": "4.7.1",
"resolved": "https://registry.npmjs.org/@types/mjml-core/-/mjml-core-4.7.1.tgz",
"integrity": "sha512-k5IRafi93tyZBGF+0BTrcBDvG47OueI+Q7TC4V4UjGQn0AMVvL3Y+S26QF/UHMmMJW5r1hxLyv3StX2/+FatFg=="
},
"@types/mocha": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
"integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w=="
},
"@types/mongodb": {
"version": "3.6.20",
"resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.20.tgz",
"integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==",
"requires": {
"@types/bson": "*",
"@types/node": "*"
}
},
"@types/node": {
"version": "13.13.52",
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.52.tgz",
"integrity": "sha512-s3nugnZumCC//n4moGGe6tkNMyYEdaDBitVjwPxXmR5lnMG5dHePinH2EdxkG3Rh1ghFHHixAG4NJhpJW1rthQ=="
},
"@types/nodemailer": {
"version": "6.4.4",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.4.tgz",
"integrity": "sha512-Ksw4t7iliXeYGvIQcSIgWQ5BLuC/mljIEbjf615svhZL10PE9t+ei8O9gDaD3FPCasUJn9KTLwz2JFJyiiyuqw==",
"requires": {
"@types/node": "*"
}
},
"@types/object-hash": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/@types/object-hash/-/object-hash-1.3.4.tgz",
"integrity": "sha512-xFdpkAkikBgqBdG9vIlsqffDV8GpvnPEzs0IUtr1v3BEB97ijsFQ4RXVbUZwjFThhB4MDSTUfvmxUD5PGx0wXA=="
},
"@types/qs": {
"version": "6.9.7",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
},
"@types/range-parser": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw=="
},
"@types/serve-static": {
"version": "1.13.10",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz",
"integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==",
"requires": {
"@types/mime": "^1",
"@types/node": "*"
},
"dependencies": {
"@types/mime": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
}
}
},
"@types/shortid": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/shortid/-/shortid-0.0.29.tgz",
"integrity": "sha1-gJPuBBam4r8qpjOBCRFLP7/6Dps="
},
"@types/uuid": {
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="
},
"@typescript-eslint/eslint-plugin": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.10.1.tgz",
"integrity": "sha512-PQg0emRtzZFWq6PxBcdxRH3QIQiyFO3WCVpRL3fgj5oQS3CDs3AeAKfv4DxNhzn8ITdNJGJ4D3Qw8eAJf3lXeQ==",
"dev": true,
"requires": {
"@typescript-eslint/experimental-utils": "3.10.1",
"debug": "^4.1.1",
"functional-red-black-tree": "^1.0.1",
"regexpp": "^3.0.0",
"semver": "^7.3.2",
"tsutils": "^3.17.1"
},
"dependencies": {
"lru-cache": {
"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"
}
},
"semver": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
},
"@typescript-eslint/experimental-utils": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz",
"integrity": "sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.3",
"@typescript-eslint/types": "3.10.1",
"@typescript-eslint/typescript-estree": "3.10.1",
"eslint-scope": "^5.0.0",
"eslint-utils": "^2.0.0"
}
},
"@typescript-eslint/parser": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-3.10.1.tgz",
"integrity": "sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw==",
"dev": true,
"requires": {
"@types/eslint-visitor-keys": "^1.0.0",
"@typescript-eslint/experimental-utils": "3.10.1",
"@typescript-eslint/types": "3.10.1",
"@typescript-eslint/typescript-estree": "3.10.1",
"eslint-visitor-keys": "^1.1.0"
}
},
"@typescript-eslint/types": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-3.10.1.tgz",
"integrity": "sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz",
"integrity": "sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w==",
"dev": true,
"requires": {
"@typescript-eslint/types": "3.10.1",
"@typescript-eslint/visitor-keys": "3.10.1",
"debug": "^4.1.1",
"glob": "^7.1.6",
"is-glob": "^4.0.1",
"lodash": "^4.17.15",
"semver": "^7.3.2",
"tsutils": "^3.17.1"
},
"dependencies": {
"lru-cache": {
"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"
}
},
"semver": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
},
"@typescript-eslint/visitor-keys": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz",
"integrity": "sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ==",
"dev": true,
"requires": {
"eslint-visitor-keys": "^1.1.0"
}
},
"@ungap/promise-all-settled": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
"integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
"dev": true
},
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
},
"accepts": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
"requires": {
"mime-types": "~2.1.24",
"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==",
"dev": true
},
"acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"aggregate-error": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
"integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
"dev": true,
"requires": {
"clean-stack": "^2.0.0",
"indent-string": "^4.0.0"
}
},
"ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"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=="
},
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"anymatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"append-transform": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz",
"integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==",
"dev": true,
"requires": {
"default-require-extensions": "^3.0.0"
}
},
"archy": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
"integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=",
"dev": true
},
"argparse": {
"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"
}
},
"astral-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
"dev": true
},
"axios": {
"version": "0.18.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.1.tgz",
"integrity": "sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g==",
"requires": {
"follow-redirects": "1.5.10",
"is-buffer": "^2.0.2"
}
},
"babel-plugin-dynamic-import-node": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
"integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
"dev": true,
"requires": {
"object.assign": "^4.1.0"
}
},
"babel-plugin-polyfill-corejs2": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz",
"integrity": "sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.13.11",
"@babel/helper-define-polyfill-provider": "^0.3.1",
"semver": "^6.1.1"
}
},
"babel-plugin-polyfill-corejs3": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.1.tgz",
"integrity": "sha512-TihqEe4sQcb/QcPJvxe94/9RZuLQuF1+To4WqQcRvc+3J3gLCPIPgDKzGLG6zmQLfH3nn25heRuDNkS2KR4I8A==",
"dev": true,
"requires": {
"@babel/helper-define-polyfill-provider": "^0.3.1",
"core-js-compat": "^3.20.0"
}
},
"babel-plugin-polyfill-regenerator": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz",
"integrity": "sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==",
"dev": true,
"requires": {
"@babel/helper-define-polyfill-provider": "^0.3.1"
}
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
},
"bl": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
"integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
"requires": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
}
},
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
},
"boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
},
"boom": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz",
"integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==",
"requires": {
"hoek": "6.x.x"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"requires": {
"fill-range": "^7.0.1"
}
},
"browser-stdout": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
"dev": true
},
"browserslist": {
"version": "4.19.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz",
"integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001286",
"electron-to-chromium": "^1.4.17",
"escalade": "^3.1.1",
"node-releases": "^2.0.1",
"picocolors": "^1.0.0"
}
},
"bson": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/bson/-/bson-4.6.1.tgz",
"integrity": "sha512-I1LQ7Hz5zgwR4QquilLNZwbhPw0Apx7i7X9kGMBTsqPdml/03Q9NBtD9nt/19ahjlphktQImrnderxqpzeVDjw==",
"requires": {
"buffer": "^5.6.0"
}
},
"buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"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==",
"dev": true
},
"bytes": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz",
"integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg=="
},
"cache-content-type": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz",
"integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==",
"requires": {
"mime-types": "^2.1.18",
"ylru": "^1.2.0"
}
},
"caching-transform": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz",
"integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==",
"dev": true,
"requires": {
"hasha": "^5.0.0",
"make-dir": "^3.0.0",
"package-hash": "^4.0.0",
"write-file-atomic": "^3.0.0"
},
"dependencies": {
"make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dev": true,
"requires": {
"semver": "^6.0.0"
}
}
}
},
"call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"requires": {
"function-bind": "^1.1.1",
"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==",
"dev": true
},
"camel-case": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
"integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=",
"requires": {
"no-case": "^2.2.0",
"upper-case": "^1.1.1"
}
},
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001301",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001301.tgz",
"integrity": "sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA==",
"dev": true
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"cheerio": {
"version": "1.0.0-rc.10",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
"integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
"requires": {
"cheerio-select": "^1.5.0",
"dom-serializer": "^1.3.2",
"domhandler": "^4.2.0",
"htmlparser2": "^6.1.0",
"parse5": "^6.0.1",
"parse5-htmlparser2-tree-adapter": "^6.0.1",
"tslib": "^2.2.0"
}
},
"cheerio-select": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz",
"integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==",
"requires": {
"css-select": "^4.1.3",
"css-what": "^5.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0",
"domutils": "^2.7.0"
}
},
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
"requires": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"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.6.0"
}
},
"clean-css": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
"integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==",
"requires": {
"source-map": "~0.6.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}
}
},
"clean-stack": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
"dev": true
},
"cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
"clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
},
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
},
"co-body": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/co-body/-/co-body-5.2.0.tgz",
"integrity": "sha512-sX/LQ7LqUhgyaxzbe7IqwPeTr2yfpfUIQ/dgpKo6ZI4y4lpQA0YxAomWIY+7I7rHWcG02PG+OuPREzMW/5tszQ==",
"requires": {
"inflation": "^2.0.0",
"qs": "^6.4.0",
"raw-body": "^2.2.0",
"type-is": "^1.6.14"
}
},
"color": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.1.tgz",
"integrity": "sha512-MFJr0uY4RvTQUKvPq7dh9grVOTYSFeXja2mBXioCGjnjJoXrAp9jJ1NQTDR73c9nwBSAQiNKloKl5zq9WB9UPw==",
"requires": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-hash": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/color-hash/-/color-hash-1.1.1.tgz",
"integrity": "sha512-OOZ2pKPuon1H7/77G0+xzSRDgITsik/kYzfJxmCBEI4ozM6UFhZ1aaZ6OhASbDwolHUq5PTRnhDle9FR72tqbw=="
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"color-string": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz",
"integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==",
"requires": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
"dev": true
},
"comment-parser": {
"version": "0.7.6",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.7.6.tgz",
"integrity": "sha512-GKNxVA7/iuTnAqGADlTWX4tkhzxZKXp5fLJqKTlQLHkE65XDUKutZ3BHaJC5IGcper2tT3QRD1xr4o3jNpgXXg==",
"dev": true
},
"commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
"dev": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"config-chain": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
"integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
"requires": {
"ini": "^1.3.4",
"proto-list": "~1.2.1"
}
},
"content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
"requires": {
"safe-buffer": "5.2.1"
},
"dependencies": {
"safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
}
}
},
"content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
},
"convert-source-map": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
"integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
"dev": true,
"requires": {
"safe-buffer": "~5.1.1"
}
},
"cookies": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz",
"integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==",
"requires": {
"depd": "~2.0.0",
"keygrip": "~1.1.0"
},
"dependencies": {
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
}
}
},
"core-js": {
"version": "2.6.12",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
},
"core-js-compat": {
"version": "3.20.3",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.20.3.tgz",
"integrity": "sha512-c8M5h0IkNZ+I92QhIpuSijOxGAcj3lgpsWdkCqmUTZNwidujF4r3pi6x1DCN+Vcs5qTS2XWWMfWSuCqyupX8gw==",
"dev": true,
"requires": {
"browserslist": "^4.19.1",
"semver": "7.0.0"
},
"dependencies": {
"semver": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
"integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
"dev": true
}
}
},
"core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"dev": true,
"requires": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
}
},
"css-select": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz",
"integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==",
"requires": {
"boolbase": "^1.0.0",
"css-what": "^5.1.0",
"domhandler": "^4.3.0",
"domutils": "^2.8.0",
"nth-check": "^2.0.1"
}
},
"css-what": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
"integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw=="
},
"debug": {
"version": "4.3.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
"integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
"requires": {
"ms": "2.1.2"
}
},
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
"dev": true
},
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
},
"deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
"deepmerge": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg=="
},
"default-require-extensions": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz",
"integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==",
"dev": true,
"requires": {
"strip-bom": "^4.0.0"
}
},
"define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
"dev": true,
"requires": {
"object-keys": "^1.0.12"
}
},
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
},
"denque": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz",
"integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw=="
},
"depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
},
"detect-node": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw=="
},
"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
},
"doctrine": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
"integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
"dev": true,
"requires": {
"esutils": "^2.0.2"
}
},
"dom-serializer": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
"entities": "^2.0.0"
}
},
"domelementtype": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
},
"domhandler": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
"integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
"requires": {
"domelementtype": "^2.2.0"
}
},
"domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"requires": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
}
},
"dot-prop": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
"integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
"requires": {
"is-obj": "^2.0.0"
}
},
"editorconfig": {
"version": "0.15.3",
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz",
"integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==",
"requires": {
"commander": "^2.19.0",
"lru-cache": "^4.1.5",
"semver": "^5.6.0",
"sigmund": "^1.0.1"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
}
}
},
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"electron-to-chromium": {
"version": "1.4.51",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.51.tgz",
"integrity": "sha512-JNEmcYl3mk1tGQmy0EvL5eik/CKSBuzAyGP0QFdG6LIgxQe3II0BL1m2zKc2MZMf3uGqHWE1TFddJML0RpjSHQ==",
"dev": true
},
"emittery": {
"version": "git+ssh://git@github.com/sindresorhus/emittery.git#7db4644126c66f062062c0ea103f95a4f7235c35",
"from": "emittery@github:sindresorhus/emittery#7db46441"
},
"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=="
},
"encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
},
"enquirer": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
"integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
"dev": true,
"requires": {
"ansi-colors": "^4.1.1"
}
},
"entities": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
},
"es6-error": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
"dev": true
},
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
},
"escape-goat": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz",
"integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw=="
},
"escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
},
"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==",
"dev": true
},
"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==",
"dev": true,
"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==",
"dev": true,
"requires": {
"@babel/highlight": "^7.10.4"
}
},
"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==",
"dev": true
},
"globals": {
"version": "13.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz",
"integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==",
"dev": true,
"requires": {
"type-fest": "^0.20.2"
}
},
"lru-cache": {
"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"
}
},
"semver": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"type-fest": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"dev": true
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
},
"eslint-config-prettier": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz",
"integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==",
- "dev": true
+ "dev": true,
+ "requires": {}
},
"eslint-plugin-es": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz",
"integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==",
"dev": true,
"requires": {
"eslint-utils": "^2.0.0",
"regexpp": "^3.0.0"
}
},
"eslint-plugin-jsdoc": {
"version": "29.2.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-29.2.0.tgz",
"integrity": "sha512-B1a8LWPkkxyxIp4y3pnRQR18j03Wp+V9gDE7IjQG/MvWAzp5gqXM0q71gXRAZMvWUjujAsNg8B9v1csl+/zkvw==",
"dev": true,
"requires": {
"comment-parser": "^0.7.5",
"debug": "^4.1.1",
"jsdoctypeparser": "^8.0.0",
"lodash": "^4.17.15",
"regextras": "^0.7.1",
"semver": "^7.3.2",
"spdx-expression-parse": "^3.0.1"
},
"dependencies": {
"lru-cache": {
"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"
}
},
"semver": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
},
"eslint-plugin-node": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz",
"integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==",
"dev": true,
"requires": {
"eslint-plugin-es": "^3.0.0",
"eslint-utils": "^2.0.0",
"ignore": "^5.1.1",
"minimatch": "^3.0.4",
"resolve": "^1.10.1",
"semver": "^6.1.0"
},
"dependencies": {
"ignore": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
"dev": true
}
}
},
"eslint-plugin-prettier": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz",
"integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==",
"dev": true,
"requires": {
"prettier-linter-helpers": "^1.0.0"
}
},
"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==",
"dev": true,
"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==",
"dev": true,
"requires": {
"eslint-visitor-keys": "^1.1.0"
}
},
"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==",
"dev": true
},
"espree": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
"integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
"dev": true,
"requires": {
"acorn": "^7.4.0",
"acorn-jsx": "^5.3.1",
"eslint-visitor-keys": "^1.3.0"
}
},
"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
},
"esquery": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
"integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
"dev": true,
"requires": {
"estraverse": "^5.1.0"
},
"dependencies": {
"estraverse": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true
}
}
},
"esrecurse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
"requires": {
"estraverse": "^5.2.0"
},
"dependencies": {
"estraverse": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true
}
}
},
"estraverse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true
},
"esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true
},
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
"fast-diff": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
"dev": true
},
"fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
"dev": true
},
"fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
"dev": true
},
"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==",
"dev": true,
"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",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"requires": {
"to-regex-range": "^5.0.1"
}
},
"find-cache-dir": {
"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",
"make-dir": "^3.0.2",
"pkg-dir": "^4.1.0"
},
"dependencies": {
"make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dev": true,
"requires": {
"semver": "^6.0.0"
}
}
}
},
"find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
"requires": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
}
},
"flat": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
"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==",
"dev": true,
"requires": {
"flatted": "^3.1.0",
"rimraf": "^3.0.2"
}
},
"flatted": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz",
"integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw==",
"dev": true
},
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
"requires": {
"debug": "=3.1.0"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
}
}
},
"foreground-child": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
"integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
"dev": true,
"requires": {
"cross-spawn": "^7.0.0",
"signal-exit": "^3.0.2"
}
},
"formidable": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz",
"integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ=="
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
},
"fromentries": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
"integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
"dev": true
},
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"requires": {
"graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
}
},
"fs-readdir-recursive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
"integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
"dev": true
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"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=",
"dev": true
},
"gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
},
"get-intrinsic": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
"requires": {
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1"
}
},
"get-package-type": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
"dev": true
},
"get-port": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz",
"integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ=="
},
"glob": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"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"
}
},
"glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"requires": {
"is-glob": "^4.0.1"
}
},
"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
},
"graceful-fs": {
"version": "4.2.9",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz",
"integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ=="
},
"growl": {
"version": "1.10.5",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
"dev": true
},
"handlebars": {
"version": "4.7.7",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz",
"integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==",
"requires": {
"minimist": "^1.2.5",
"neo-async": "^2.6.0",
"source-map": "^0.6.1",
"uglify-js": "^3.1.4",
"wordwrap": "^1.0.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"requires": {
"function-bind": "^1.1.1"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"has-symbols": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
},
"has-tostringtag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"requires": {
"has-symbols": "^1.0.2"
}
},
"hasha": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
"integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==",
"dev": true,
"requires": {
"is-stream": "^2.0.0",
"type-fest": "^0.8.0"
}
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"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=="
},
"hoek": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
"integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ=="
},
"html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
"html-minifier": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
"integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==",
"requires": {
"camel-case": "^3.0.0",
"clean-css": "^4.2.1",
"commander": "^2.19.0",
"he": "^1.2.0",
"param-case": "^2.1.1",
"relateurl": "^0.2.7",
"uglify-js": "^3.5.1"
},
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
}
}
},
"htmlparser2": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.0.0",
"domutils": "^2.5.2",
"entities": "^2.0.0"
}
},
"http-assert": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz",
"integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==",
"requires": {
"deep-equal": "~1.0.1",
"http-errors": "~1.8.0"
}
},
"http-errors": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.1"
}
},
"iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"ignore": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
"dev": true
},
"import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
"dev": true,
"requires": {
"parent-module": "^1.0.0",
"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
},
"indent-string": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
"dev": true
},
"inflation": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/inflation/-/inflation-2.0.0.tgz",
"integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8="
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA=="
},
"is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-buffer": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz",
"integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ=="
},
"is-core-module": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz",
"integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==",
"requires": {
"has": "^1.0.3"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
},
"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=="
},
"is-generator-function": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
"integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
"requires": {
"has-tostringtag": "^1.0.0"
}
},
"is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"is-obj": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
"integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="
},
"is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"dev": true
},
"is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"dev": true
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
"dev": true
},
"is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
"dev": true
},
"isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"istanbul-lib-coverage": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz",
"integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==",
"dev": true
},
"istanbul-lib-hook": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz",
"integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==",
"dev": true,
"requires": {
"append-transform": "^2.0.0"
}
},
"istanbul-lib-instrument": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
"integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
"dev": true,
"requires": {
"@babel/core": "^7.7.5",
"@istanbuljs/schema": "^0.1.2",
"istanbul-lib-coverage": "^3.0.0",
"semver": "^6.3.0"
}
},
"istanbul-lib-processinfo": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz",
"integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==",
"dev": true,
"requires": {
"archy": "^1.0.0",
"cross-spawn": "^7.0.0",
"istanbul-lib-coverage": "^3.0.0-alpha.1",
"make-dir": "^3.0.0",
"p-map": "^3.0.0",
"rimraf": "^3.0.0",
"uuid": "^3.3.3"
},
"dependencies": {
"make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dev": true,
"requires": {
"semver": "^6.0.0"
}
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"dev": true
}
}
},
"istanbul-lib-report": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
"integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==",
"dev": true,
"requires": {
"istanbul-lib-coverage": "^3.0.0",
"make-dir": "^3.0.0",
"supports-color": "^7.1.0"
},
"dependencies": {
"make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dev": true,
"requires": {
"semver": "^6.0.0"
}
}
}
},
"istanbul-lib-source-maps": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
"integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
"dev": true,
"requires": {
"debug": "^4.1.1",
"istanbul-lib-coverage": "^3.0.0",
"source-map": "^0.6.1"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
"istanbul-reports": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.3.tgz",
"integrity": "sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg==",
"dev": true,
"requires": {
"html-escaper": "^2.0.0",
"istanbul-lib-report": "^3.0.0"
}
},
"js-beautify": {
"version": "1.14.0",
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.0.tgz",
"integrity": "sha512-yuck9KirNSCAwyNJbqW+BxJqJ0NLJ4PwBUzQQACl5O3qHMBXVkXb/rD0ilh/Lat/tn88zSZ+CAHOlk0DsY7GuQ==",
"requires": {
"config-chain": "^1.1.12",
"editorconfig": "^0.15.3",
"glob": "^7.1.3",
"nopt": "^5.0.0"
}
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
},
"js-yaml": {
"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"
}
},
"jsdoctypeparser": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-8.0.0.tgz",
"integrity": "sha512-eLCs6s4JqN8TjFJfgdiLHRvogLhOAJz+5RIA2FtoMe6ZDyuvghvppnlIToqAEnVbxRqLMrfnNXpW8FpmR6IMBw==",
"dev": true
},
"jsesc": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
"dev": true
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
"dev": true
},
"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=",
"dev": true
},
"json5": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
},
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"requires": {
"graceful-fs": "^4.1.6"
}
},
"juice": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/juice/-/juice-7.0.0.tgz",
"integrity": "sha512-AjKQX31KKN+uJs+zaf+GW8mBO/f/0NqSh2moTMyvwBY+4/lXIYTU8D8I2h6BAV3Xnz6GGsbalUyFqbYMe+Vh+Q==",
"requires": {
"cheerio": "^1.0.0-rc.3",
"commander": "^5.1.0",
"mensch": "^0.3.4",
"slick": "^1.12.2",
"web-resource-inliner": "^5.0.0"
},
"dependencies": {
"commander": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="
}
}
},
"keygrip": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
"integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
"requires": {
"tsscmp": "1.0.6"
}
},
"koa": {
"version": "2.13.4",
"resolved": "https://registry.npmjs.org/koa/-/koa-2.13.4.tgz",
"integrity": "sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g==",
"requires": {
"accepts": "^1.3.5",
"cache-content-type": "^1.0.0",
"content-disposition": "~0.5.2",
"content-type": "^1.0.4",
"cookies": "~0.8.0",
"debug": "^4.3.2",
"delegates": "^1.0.0",
"depd": "^2.0.0",
"destroy": "^1.0.4",
"encodeurl": "^1.0.2",
"escape-html": "^1.0.3",
"fresh": "~0.5.2",
"http-assert": "^1.3.0",
"http-errors": "^1.6.3",
"is-generator-function": "^1.0.7",
"koa-compose": "^4.1.0",
"koa-convert": "^2.0.0",
"on-finished": "^2.3.0",
"only": "~0.0.2",
"parseurl": "^1.3.2",
"statuses": "^1.5.0",
"type-is": "^1.6.16",
"vary": "^1.1.2"
},
"dependencies": {
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
}
}
},
"koa-body": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/koa-body/-/koa-body-4.2.0.tgz",
"integrity": "sha512-wdGu7b9amk4Fnk/ytH8GuWwfs4fsB5iNkY8kZPpgQVb04QZSv85T0M8reb+cJmvLE8cjPYvBzRikD3s6qz8OoA==",
"requires": {
"@types/formidable": "^1.0.31",
"co-body": "^5.1.1",
"formidable": "^1.1.1"
}
},
"koa-compose": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
"integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
},
"koa-convert": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz",
"integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==",
"requires": {
"co": "^4.6.0",
"koa-compose": "^4.1.0"
}
},
"koa-mount": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/koa-mount/-/koa-mount-4.0.0.tgz",
"integrity": "sha512-rm71jaA/P+6HeCpoRhmCv8KVBIi0tfGuO/dMKicbQnQW/YJntJ6MnnspkodoA4QstMVEZArsCphmd0bJEtoMjQ==",
"requires": {
"debug": "^4.0.1",
"koa-compose": "^4.1.0"
}
},
"koa-qs": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/koa-qs/-/koa-qs-3.0.0.tgz",
"integrity": "sha512-05IB5KirwMs3heWW26iTz46HuMAtrlrRMus/aNH1BRDocLyF/099EtCB0MIfQpRuT0TISvaTsWwSy2gctIWiGA==",
"requires": {
"merge-descriptors": "^1.0.1",
"qs": "^6.9.4"
}
},
"koa-send": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz",
"integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==",
"requires": {
"debug": "^4.1.1",
"http-errors": "^1.7.3",
"resolve-path": "^1.4.0"
}
},
"koa-static": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz",
"integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==",
"requires": {
"debug": "^3.1.0",
"koa-send": "^5.0.0"
},
"dependencies": {
"debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"requires": {
"ms": "^2.1.1"
}
}
}
},
"levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
"requires": {
"prelude-ls": "^1.2.1",
"type-check": "~0.4.0"
}
},
"locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"requires": {
"p-locate": "^5.0.0"
}
},
"locreq": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/locreq/-/locreq-2.0.2.tgz",
"integrity": "sha512-77HrzBGmSNZMeL12NOf+7PLmdjuIdX+sqLQYts65oaH/gcbiNIGB+RdGCfDrhv/WCMScgOELEjDnuSPlnat7Ew==",
"requires": {
"@types/node": "^14.14.16"
},
"dependencies": {
"@types/node": {
"version": "14.18.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.9.tgz",
"integrity": "sha512-j11XSuRuAlft6vLDEX4RvhqC0KxNxx6QIyMXNb0vHHSNPXTPeiy3algESWmOOIzEtiEL0qiowPU3ewW9hHVa7Q=="
}
}
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
"dev": true
},
"lodash.flattendeep": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
"integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
"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==",
"dev": true
},
"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=",
"dev": true
},
"log-symbols": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz",
"integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==",
"dev": true,
"requires": {
"chalk": "^4.0.0"
}
},
"lower-case": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
"integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw="
},
"lru-cache": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
"requires": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
}
},
"lunr": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
"integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow=="
},
"make-dir": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
"integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
"dev": true,
"requires": {
"pify": "^4.0.1",
"semver": "^5.6.0"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
},
"marked": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-1.0.0.tgz",
"integrity": "sha512-Wo+L1pWTVibfrSr+TTtMuiMfNzmZWiOPeO7rZsQUY5bgsxpHesBEcIWJloWVTFnrMXnf/TL30eTFSGJddmQAng=="
},
"media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"optional": true
},
"mensch": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/mensch/-/mensch-0.3.4.tgz",
"integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g=="
},
"merge-descriptors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
},
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
},
"mime": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="
},
"mime-db": {
"version": "1.51.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
"integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
},
"mime-types": {
"version": "2.1.34",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
"integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
"requires": {
"mime-db": "1.51.0"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
},
"mjml": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml/-/mjml-4.11.0.tgz",
"integrity": "sha512-kYuCAds/8F7m7xNEs3TFkrc0jxnNYIkexQIUNByPLQJFoFRltpgXLSdoyreGAniQtDGITPE+p8FIocLUBKsOHg==",
"requires": {
"@babel/runtime": "^7.14.6",
"mjml-cli": "4.11.0",
"mjml-core": "4.11.0",
"mjml-migrate": "4.11.0",
"mjml-preset-core": "4.11.0",
"mjml-validator": "4.11.0"
}
},
"mjml-accordion": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-accordion/-/mjml-accordion-4.11.0.tgz",
"integrity": "sha512-u6cPMl4z8JeRIq0sGHWfzwE5SqwBhSPHJ8wElhfU7CK6gAoUTz4BIL/03da2whXk0S34n5CSU453JpuWV+3bQQ==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-body": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-body/-/mjml-body-4.11.0.tgz",
"integrity": "sha512-+SQXOjKOr9IMblmslrUbv+ahF/SkqT7mAuix1P/F9ev3aS+WN7Gy/lyJLaq1zhSQCmzrBDovHez3bJ7NGToU0g==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-button": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-button/-/mjml-button-4.11.0.tgz",
"integrity": "sha512-v/MwA2Kq2MlHJwrajdAqUihjAQivD8FpkpOAcqdgqI1ffaEDzd6FGFt5qOtVD9BncChQ4a51haOnPd+kbBLlCA==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-carousel": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-carousel/-/mjml-carousel-4.11.0.tgz",
"integrity": "sha512-/owKKSg3DNes1rauPPhlGCFdZ4zzoxdztPLGOm9TSjkbL5q2cN9NMfzNdTYLnnVG5G5XWX0THjDeeq+bGnHw8w==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-cli": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-cli/-/mjml-cli-4.11.0.tgz",
"integrity": "sha512-jgkxNY+sY+CwiUlO6VX8cwVjlLBXIzE7X4fXkQ2RjXpbAvsN8uDafST8oL8PDlxNIjOwK6YJySzZSLXSKTF5Zg==",
"requires": {
"@babel/runtime": "^7.14.6",
"chokidar": "^3.0.0",
"glob": "^7.1.1",
"html-minifier": "^4.0.0",
"js-beautify": "^1.6.14",
"lodash": "^4.17.21",
"mjml-core": "4.11.0",
"mjml-migrate": "4.11.0",
"mjml-parser-xml": "4.11.0",
"mjml-validator": "4.11.0",
"yargs": "^16.1.0"
}
},
"mjml-column": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-column/-/mjml-column-4.11.0.tgz",
"integrity": "sha512-yuupexywYXuXTvxxGLPZw6S/D6fz4b41ZarOkEPW8Pbj7FkfnBTO3QokAS5KapJ9x6sIAVs+cCgUul87dwOBzg==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-core": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-core/-/mjml-core-4.11.0.tgz",
"integrity": "sha512-UTI1exu9/0lOF40aacAzC9A7RrJPcay7WYurYsb+X2LbDyfBlSx5ZCtuUTHwLfIz3PL6rSg8yrZ3KtlmhQJ/kQ==",
"requires": {
"@babel/runtime": "^7.14.6",
"cheerio": "1.0.0-rc.10",
"detect-node": "2.0.4",
"html-minifier": "^4.0.0",
"js-beautify": "^1.6.14",
"juice": "^7.0.0",
"lodash": "^4.17.21",
"mjml-migrate": "4.11.0",
"mjml-parser-xml": "4.11.0",
"mjml-validator": "4.11.0"
}
},
"mjml-divider": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-divider/-/mjml-divider-4.11.0.tgz",
"integrity": "sha512-jS8Sa7uuFTmThtrcV3FICtbqmA0yJplldaNJwW5upiq7MEXuSwLNzjNeodaTpsVWevf/stE3C4lBA3+V4ascMg==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-group": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-group/-/mjml-group-4.11.0.tgz",
"integrity": "sha512-Yv1ZcPNk4bxOK/eol6bjJvRJBaOCzVY88QO8IfCQifAZuiXhatxwsuwaRKNcTi4cB+IHwl4JguZHgsFRi/Gf/g==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-head": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-head/-/mjml-head-4.11.0.tgz",
"integrity": "sha512-KNaSsOlf5FNwHyZQD6YNZN2Eo/o7n+mZISFLyp9MvNFaT3NKIRJDaInD1WjN+w2aHdXAw4sDV3+/9/EET2bh1A==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-head-attributes": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-head-attributes/-/mjml-head-attributes-4.11.0.tgz",
"integrity": "sha512-azeDRLGH7cU6PoXLd08E/H3UDHFsblBTcme++OWrj5B21vaFguOBySO2eWFTyWLthy+xst8FftWV46f8BWvciw==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-head-breakpoint": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-head-breakpoint/-/mjml-head-breakpoint-4.11.0.tgz",
"integrity": "sha512-OQ/WpXHagGoiUmBjoMHuxdigyLQrHNL6+Op0LHO87vN1GH2ap4YLcSSegIsThQLi/I7V4/JFZbzS5jV4xd4SMg==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-head-font": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-head-font/-/mjml-head-font-4.11.0.tgz",
"integrity": "sha512-AJQ9lhNzNr0hwPjUID76LNna3U8ycmFH1lyipZOWHTivOVGkSYs8PaboxORfU/QAEDKo/p8LafBAoDPEdSigxA==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-head-html-attributes": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-head-html-attributes/-/mjml-head-html-attributes-4.11.0.tgz",
"integrity": "sha512-Gew9EAuqFu9QR3g+8FyE9WHNMszx1ejzo8dRDIuTaBCDEpaIaPVO7G5rGhT7ADqZufeYtRhBXfXjcShPD/a30g==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-head-preview": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-head-preview/-/mjml-head-preview-4.11.0.tgz",
"integrity": "sha512-f79+OtwC8CYcQpglGNfm3s74qVecdwLlDm9DD/LJvZwIdaALeIfZF36nz6+rtCLMhND+wxgqxqkmbbuS6AbO+A==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-head-style": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-head-style/-/mjml-head-style-4.11.0.tgz",
"integrity": "sha512-jw0r9Ld56SkJmDUBx+27xOH+oY2O06FBcKSJIkZLJ/sefbjgJa2/ti2eso/LeGgrmTw8zge7g1pp0Fl+kPjsGA==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-head-title": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-head-title/-/mjml-head-title-4.11.0.tgz",
"integrity": "sha512-mjYsKoE9+5LI8V0mK9SAKVKspF19TVius2q5I1FXLRdBmt4Ei87CdrSui+iixGrug0Lwt4P2W3+mK8kVGNnJAQ==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-hero": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-hero/-/mjml-hero-4.11.0.tgz",
"integrity": "sha512-tZDCGjQrDICwbsDnLvfVEsQ5+GdrIozB3oO3NxC6m2Eq04VKNBkIqq+QvJyouOxzJ3CZgO2B4rylzxc6YXuHsw==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-image": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-image/-/mjml-image-4.11.0.tgz",
"integrity": "sha512-qjvKS/x2arDNgKppPecmg69VyXdQbb1CNVqPwowJLyfjioTw4hxQ93suWoBKJJojRjkwauj9IRMC8TR9ffn0HQ==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-migrate": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-migrate/-/mjml-migrate-4.11.0.tgz",
"integrity": "sha512-Y+9U4w9LwlTkfTkHX9GdalIQDO4JQxboG4PM8g7vRKNhKSZDZH8QSr0SNhX0+fMQmjb9b0nztWbMVVvNZfMoPQ==",
"requires": {
"@babel/runtime": "^7.14.6",
"js-beautify": "^1.6.14",
"lodash": "^4.17.21",
"mjml-core": "4.11.0",
"mjml-parser-xml": "4.11.0",
"yargs": "^16.1.0"
}
},
"mjml-navbar": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-navbar/-/mjml-navbar-4.11.0.tgz",
"integrity": "sha512-FEd+8RD6ra8652jXdMbhfhzT1YY8TA30c34qjJ+ULlFgvLH4GNnYRIOHp/Mgd/L38Qf3bhK/rK9ELBidJ36dLQ==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-parser-xml": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-parser-xml/-/mjml-parser-xml-4.11.0.tgz",
"integrity": "sha512-3toQ9UKyfzXWXJ7PlTExBjzGXAzJNORv39sorPv5sG2KJsvPC6NE+e+/1GyqYFhk4JffHoDfd4mQ6w050qYATQ==",
"requires": {
"@babel/runtime": "^7.14.6",
"detect-node": "2.0.4",
"htmlparser2": "^4.1.0",
"lodash": "^4.17.15"
},
"dependencies": {
"domhandler": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
"requires": {
"domelementtype": "^2.0.1"
}
},
"htmlparser2": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
"integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^3.0.0",
"domutils": "^2.0.0",
"entities": "^2.0.0"
}
}
}
},
"mjml-preset-core": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-preset-core/-/mjml-preset-core-4.11.0.tgz",
"integrity": "sha512-HU9ZFzS+A7Dx0B/EbnqYjdcIQQuxpOVRfFReQBlllZYwjWaRUjDIeIjF+cdnCb9QveuSNo4msIG00h/MKPYiGQ==",
"requires": {
"@babel/runtime": "^7.14.6",
"mjml-accordion": "4.11.0",
"mjml-body": "4.11.0",
"mjml-button": "4.11.0",
"mjml-carousel": "4.11.0",
"mjml-column": "4.11.0",
"mjml-divider": "4.11.0",
"mjml-group": "4.11.0",
"mjml-head": "4.11.0",
"mjml-head-attributes": "4.11.0",
"mjml-head-breakpoint": "4.11.0",
"mjml-head-font": "4.11.0",
"mjml-head-html-attributes": "4.11.0",
"mjml-head-preview": "4.11.0",
"mjml-head-style": "4.11.0",
"mjml-head-title": "4.11.0",
"mjml-hero": "4.11.0",
"mjml-image": "4.11.0",
"mjml-navbar": "4.11.0",
"mjml-raw": "4.11.0",
"mjml-section": "4.11.0",
"mjml-social": "4.11.0",
"mjml-spacer": "4.11.0",
"mjml-table": "4.11.0",
"mjml-text": "4.11.0",
"mjml-wrapper": "4.11.0"
}
},
"mjml-raw": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-raw/-/mjml-raw-4.11.0.tgz",
"integrity": "sha512-DyUwC/JrE8tF7v9XaKQpQ/yAg5tT2uAWSDI6J5x3t3TNFJmRPd3iorSu8v6t1s3OiekuxfagsDDPLFuzpGwZSw==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-section": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-section/-/mjml-section-4.11.0.tgz",
"integrity": "sha512-OpinxE019Z1symrEFku3UddsvSql2aolcAiOThFuAAXz3+tUuooofGMy/XyyMOuOnktOx/5PMcVFsV84/Jye/g==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-social": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-social/-/mjml-social-4.11.0.tgz",
"integrity": "sha512-tM5njGtang0VRWt+XCuMTnZP2IJehUd+kdsC7CnMKQhYI2X4vzEaOBLgXRWvhcT4pSBzEJkXB9sQ+y7JmLO10g==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-spacer": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-spacer/-/mjml-spacer-4.11.0.tgz",
"integrity": "sha512-9s6PjFgznKEFgFZCSa4vTYVDQ6kRH5ucMHGraoHS4VMZLA8QIaVakHd4Sl0n+SGWCqair4xZ3vYYMhOBKIXmMw==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-table": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-table/-/mjml-table-4.11.0.tgz",
"integrity": "sha512-ccniRz1MoDqKS6zoNM59xi81M7zy/tkvd/6weyH9XAZiU7ATgOxoBuIMy+d0uSTlKPWNwoi2FqR5YSedxT2YPw==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-text": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-text/-/mjml-text-4.11.0.tgz",
"integrity": "sha512-xrY5+uepxUg+q5KKuKX2s9KQnnlsMN5aoCt0JSbjt4H9ZwBpqXPD4Z2uJ8eZS33FvnXzUYPNVdKralvXnrsXKA==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0"
}
},
"mjml-validator": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-validator/-/mjml-validator-4.11.0.tgz",
"integrity": "sha512-oDL9tHcL4PaCZMwH6T/lLpS7LV9cm9lIwnzJy+y5/S81MGMV6kPr6xXHgS0A01G7sseg6+rHgqBnUgzUob4Ilg==",
"requires": {
"@babel/runtime": "^7.14.6"
}
},
"mjml-wrapper": {
"version": "4.11.0",
"resolved": "https://registry.npmjs.org/mjml-wrapper/-/mjml-wrapper-4.11.0.tgz",
"integrity": "sha512-WXGKxS+DlYalx5ofwq3bttj26BLEcaueeQ+0BcffXIELojUzd0+xTyX09v0QemUCBmKpHB2QaKMGhzYuSkupyg==",
"requires": {
"@babel/runtime": "^7.14.6",
"lodash": "^4.17.21",
"mjml-core": "4.11.0",
"mjml-section": "4.11.0"
}
},
"mocha": {
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz",
"integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==",
"dev": true,
"requires": {
"@ungap/promise-all-settled": "1.1.2",
"ansi-colors": "4.1.1",
"browser-stdout": "1.3.1",
"chokidar": "3.5.1",
"debug": "4.3.1",
"diff": "5.0.0",
"escape-string-regexp": "4.0.0",
"find-up": "5.0.0",
"glob": "7.1.6",
"growl": "1.10.5",
"he": "1.2.0",
"js-yaml": "4.0.0",
"log-symbols": "4.0.0",
"minimatch": "3.0.4",
"ms": "2.1.3",
"nanoid": "3.1.20",
"serialize-javascript": "5.0.1",
"strip-json-comments": "3.1.1",
"supports-color": "8.1.1",
"which": "2.0.2",
"wide-align": "1.1.3",
"workerpool": "6.1.0",
"yargs": "16.2.0",
"yargs-parser": "20.2.4",
"yargs-unparser": "2.0.0"
},
"dependencies": {
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"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==",
"dev": true,
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.3.1",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.5.0"
}
},
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"requires": {
"ms": "2.1.2"
},
"dependencies": {
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}
}
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
"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"
}
},
"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==",
"dev": true,
"requires": {
"argparse": "^2.0.1"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"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==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
}
},
"supports-color": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"mongodb": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz",
"integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==",
"requires": {
"bl": "^2.2.1",
"bson": "^1.1.4",
"denque": "^1.4.1",
"optional-require": "^1.1.8",
"safe-buffer": "^5.1.2",
"saslprep": "^1.0.0"
},
"dependencies": {
"bson": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz",
"integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg=="
}
}
},
"mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"dev": true
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"nanoid": {
"version": "3.1.20",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
"integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==",
"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=",
"dev": true
},
"negotiator": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
"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=="
},
"no-case": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
"integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
"requires": {
"lower-case": "^1.1.1"
}
},
"node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"requires": {
"whatwg-url": "^5.0.0"
}
},
"node-preload": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
"integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==",
"dev": true,
"requires": {
"process-on-spawn": "^1.0.0"
}
},
"node-releases": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz",
"integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==",
"dev": true
},
"nodemailer": {
"version": "6.7.2",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.7.2.tgz",
"integrity": "sha512-Dz7zVwlef4k5R71fdmxwR8Q39fiboGbu3xgswkzGwczUfjp873rVxt1O46+Fh0j1ORnAC6L9+heI8uUpO6DT7Q=="
},
"nopt": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
"requires": {
"abbrev": "1"
}
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
},
"nth-check": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
"integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
"requires": {
"boolbase": "^1.0.0"
}
},
"nyc": {
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz",
"integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==",
"dev": true,
"requires": {
"@istanbuljs/load-nyc-config": "^1.0.0",
"@istanbuljs/schema": "^0.1.2",
"caching-transform": "^4.0.0",
"convert-source-map": "^1.7.0",
"decamelize": "^1.2.0",
"find-cache-dir": "^3.2.0",
"find-up": "^4.1.0",
"foreground-child": "^2.0.0",
"get-package-type": "^0.1.0",
"glob": "^7.1.6",
"istanbul-lib-coverage": "^3.0.0",
"istanbul-lib-hook": "^3.0.0",
"istanbul-lib-instrument": "^4.0.0",
"istanbul-lib-processinfo": "^2.0.2",
"istanbul-lib-report": "^3.0.0",
"istanbul-lib-source-maps": "^4.0.0",
"istanbul-reports": "^3.0.2",
"make-dir": "^3.0.0",
"node-preload": "^0.2.1",
"p-map": "^3.0.0",
"process-on-spawn": "^1.0.0",
"resolve-from": "^5.0.0",
"rimraf": "^3.0.0",
"signal-exit": "^3.0.2",
"spawn-wrap": "^2.0.0",
"test-exclude": "^6.0.0",
"yargs": "^15.0.2"
},
"dependencies": {
"cliui": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
"dev": true,
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0"
}
},
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"requires": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
}
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"requires": {
"p-locate": "^4.1.0"
}
},
"make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dev": true,
"requires": {
"semver": "^6.0.0"
}
},
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"requires": {
"p-limit": "^2.2.0"
}
},
"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",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"dev": true,
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
}
},
"y18n": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
"dev": true
},
"yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"dev": true,
"requires": {
"cliui": "^6.0.0",
"decamelize": "^1.2.0",
"find-up": "^4.1.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^4.2.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.2"
}
},
"yargs-parser": {
"version": "18.1.3",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
}
},
"object-hash": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
"integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw=="
},
"object-inspect": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
"integrity": "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
},
"object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true
},
"object.assign": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
"integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
"dev": true,
"requires": {
"call-bind": "^1.0.0",
"define-properties": "^1.1.3",
"has-symbols": "^1.0.1",
"object-keys": "^1.1.1"
}
},
"on-finished": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
"requires": {
"ee-first": "1.1.1"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"only": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
"integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
},
"optional-require": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz",
"integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==",
"requires": {
"require-at": "^1.0.6"
}
},
"optionator": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
"integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
"dev": true,
"requires": {
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
"levn": "^0.4.1",
"prelude-ls": "^1.2.1",
"type-check": "^0.4.0",
"word-wrap": "^1.2.3"
}
},
"p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"requires": {
"yocto-queue": "^0.1.0"
}
},
"p-locate": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
"requires": {
"p-limit": "^3.0.2"
}
},
"p-map": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
"integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
"dev": true,
"requires": {
"aggregate-error": "^3.0.0"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
"package-hash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz",
"integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.15",
"hasha": "^5.0.0",
"lodash.flattendeep": "^4.4.0",
"release-zalgo": "^1.0.0"
}
},
"param-case": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
"integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=",
"requires": {
"no-case": "^2.2.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==",
"dev": true,
"requires": {
"callsites": "^3.0.0"
}
},
"parse-ms": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz",
"integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA=="
},
"parse-srcset": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
"integrity": "sha1-8r0iH2zJcKk42IVWq8WJyqqiveE="
},
"parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"parse5-htmlparser2-tree-adapter": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
"integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
"requires": {
"parse5": "^6.0.1"
}
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
},
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
},
"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
},
"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=="
},
"path-to-regexp": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.0.tgz",
"integrity": "sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg=="
},
"picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"dev": true
},
"picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
},
"pify": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
"integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
"dev": true
},
"pkg-dir": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
"dev": true,
"requires": {
"find-up": "^4.0.0"
},
"dependencies": {
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"requires": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
}
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"requires": {
"p-locate": "^4.1.0"
}
},
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"requires": {
"p-limit": "^2.2.0"
}
}
}
},
"postcss": {
"version": "7.0.39",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
"integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
"requires": {
"picocolors": "^0.2.1",
"source-map": "^0.6.1"
},
"dependencies": {
"picocolors": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
"integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
}
}
},
"prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true
},
"prettier": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
"integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
"dev": true
},
"prettier-linter-helpers": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
"dev": true,
"requires": {
"fast-diff": "^1.1.2"
}
},
"pretty-ms": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz",
"integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==",
"requires": {
"parse-ms": "^2.1.0"
}
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"process-on-spawn": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz",
"integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==",
"dev": true,
"requires": {
"fromentries": "^1.2.0"
}
},
"progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
},
"proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
"integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk="
},
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"dev": true
},
"qs": {
"version": "6.10.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
"integrity": "sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==",
"requires": {
"side-channel": "^1.0.4"
}
},
"randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"requires": {
"safe-buffer": "^5.1.0"
}
},
"raw-body": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.2.tgz",
"integrity": "sha512-RPMAFUJP19WIet/99ngh6Iv8fzAbqum4Li7AD6DtGaW2RpMB/11xDoalPiJMTbu6I3hkbMVkATvZrqb9EEqeeQ==",
"requires": {
"bytes": "3.1.1",
"http-errors": "1.8.1",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
}
},
"readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"requires": {
"picomatch": "^2.2.1"
}
},
"rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
"requires": {
"resolve": "^1.1.6"
}
},
"regenerate": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
"integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
"dev": true
},
"regenerate-unicode-properties": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz",
"integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==",
"dev": true,
"requires": {
"regenerate": "^1.4.2"
}
},
"regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
},
"regenerator-transform": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz",
"integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==",
"dev": true,
"requires": {
"@babel/runtime": "^7.8.4"
}
},
"regexpp": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
"dev": true
},
"regexpu-core": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz",
"integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==",
"dev": true,
"requires": {
"regenerate": "^1.4.2",
"regenerate-unicode-properties": "^9.0.0",
"regjsgen": "^0.5.2",
"regjsparser": "^0.7.0",
"unicode-match-property-ecmascript": "^2.0.0",
"unicode-match-property-value-ecmascript": "^2.0.0"
}
},
"regextras": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/regextras/-/regextras-0.7.1.tgz",
"integrity": "sha512-9YXf6xtW+qzQ+hcMQXx95MOvfqXFgsKDZodX3qZB0x2n5Z94ioetIITsBtvJbiOyxa/6s9AtyweBLCdPmPko/w==",
"dev": true
},
"regjsgen": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz",
"integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==",
"dev": true
},
"regjsparser": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz",
"integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==",
"dev": true,
"requires": {
"jsesc": "~0.5.0"
},
"dependencies": {
"jsesc": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
"integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=",
"dev": true
}
}
},
"relateurl": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
"integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk="
},
"release-zalgo": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz",
"integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=",
"dev": true,
"requires": {
"es6-error": "^4.0.1"
}
},
"require-at": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz",
"integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g=="
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
},
"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==",
"dev": true
},
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
"dev": true
},
"resolve": {
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz",
"integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==",
"requires": {
"is-core-module": "^2.8.1",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
}
},
"resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true
},
"resolve-path": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz",
"integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=",
"requires": {
"http-errors": "~1.6.2",
"path-is-absolute": "1.0.1"
},
"dependencies": {
"http-errors": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.0",
"statuses": ">= 1.4.0 < 2"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ=="
}
}
},
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sanitize-html": {
"version": "1.27.5",
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.5.tgz",
"integrity": "sha512-M4M5iXDAUEcZKLXkmk90zSYWEtk5NH3JmojQxKxV371fnMh+x9t1rqdmXaGoyEHw3z/X/8vnFhKjGL5xFGOJ3A==",
"requires": {
"htmlparser2": "^4.1.0",
"lodash": "^4.17.15",
"parse-srcset": "^1.0.2",
"postcss": "^7.0.27"
},
"dependencies": {
"domhandler": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
"requires": {
"domelementtype": "^2.0.1"
}
},
"htmlparser2": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
"integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^3.0.0",
"domutils": "^2.0.0",
"entities": "^2.0.0"
}
}
}
},
"saslprep": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
"optional": true,
"requires": {
"sparse-bitfield": "^3.0.3"
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
},
"serialize-javascript": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz",
"integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==",
"dev": true,
"requires": {
"randombytes": "^2.1.0"
}
},
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"dev": true
},
"setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
"requires": {
"shebang-regex": "^3.0.0"
}
},
"shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true
},
"shelljs": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
"integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
"requires": {
"glob": "^7.0.0",
"interpret": "^1.0.0",
"rechoir": "^0.6.2"
}
},
"shortid": {
"version": "2.2.16",
"resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.16.tgz",
"integrity": "sha512-Ugt+GIZqvGXCIItnsL+lvFJOiN7RYqlGy7QE41O3YC1xbNSeDGIRO7xg2JJXIAj1cAGnOeC1r7/T9pgrtQbv4g==",
"requires": {
"nanoid": "^2.1.0"
},
"dependencies": {
"nanoid": {
"version": "2.1.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
"integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA=="
}
}
},
"side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
"requires": {
"call-bind": "^1.0.0",
"get-intrinsic": "^1.0.2",
"object-inspect": "^1.9.0"
}
},
"sigmund": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
"integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA="
},
"signal-exit": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
"integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==",
"dev": true
},
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=",
"requires": {
"is-arrayish": "^0.3.1"
}
},
"slash": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
"integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
"dev": true
},
"slice-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
"integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
"dev": true,
"requires": {
"ansi-styles": "^4.0.0",
"astral-regex": "^2.0.0",
"is-fullwidth-code-point": "^3.0.0"
}
},
"slick": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/slick/-/slick-1.12.2.tgz",
"integrity": "sha1-vQSN23TefRymkV+qSldXCzVQwtc="
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
"dev": true
},
"source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
"sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
"optional": true,
"requires": {
"memory-pager": "^1.0.2"
}
},
"spawn-wrap": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz",
"integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==",
"dev": true,
"requires": {
"foreground-child": "^2.0.0",
"is-windows": "^1.0.2",
"make-dir": "^3.0.0",
"rimraf": "^3.0.0",
"signal-exit": "^3.0.2",
"which": "^2.0.1"
},
"dependencies": {
"make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dev": true,
"requires": {
"semver": "^6.0.0"
}
}
}
},
"spdx-exceptions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
"dev": true
},
"spdx-expression-parse": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
"dev": true,
"requires": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
"spdx-license-ids": {
"version": "3.0.11",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
"integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==",
"dev": true
},
"sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true
},
"statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
"string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"requires": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
}
},
- "string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- },
"strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"requires": {
"ansi-regex": "^5.0.1"
}
},
"strip-bom": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
"integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
"dev": true
},
"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
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"requires": {
"has-flag": "^4.0.0"
}
},
"supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
},
"table": {
"version": "6.8.0",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz",
"integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==",
"dev": true,
"requires": {
"ajv": "^8.0.1",
"lodash.truncate": "^4.4.2",
"slice-ansi": "^4.0.0",
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1"
},
"dependencies": {
"ajv": {
"version": "8.9.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.9.0.tgz",
"integrity": "sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==",
"dev": true,
"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==",
"dev": true
}
}
},
"test-exclude": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
"integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
"dev": true,
"requires": {
"@istanbuljs/schema": "^0.1.2",
"glob": "^7.1.4",
"minimatch": "^3.0.4"
}
},
"text-table": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
"integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
"dev": true
},
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
"dev": true
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"requires": {
"is-number": "^7.0.0"
}
},
"toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
},
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
},
"tslib": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz",
"integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw=="
},
"tsscmp": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
"integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA=="
},
"tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"requires": {
"tslib": "^1.8.1"
},
"dependencies": {
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
}
}
},
"type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"dev": true,
"requires": {
"prelude-ls": "^1.2.1"
}
},
"type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"dev": true
},
"type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"requires": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
}
},
"typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
"dev": true,
"requires": {
"is-typedarray": "^1.0.0"
}
},
"typedoc": {
"version": "0.17.8",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.17.8.tgz",
"integrity": "sha512-/OyrHCJ8jtzu+QZ+771YaxQ9s4g5Z3XsQE3Ma7q+BL392xxBn4UMvvCdVnqKC2T/dz03/VXSLVKOP3lHmDdc/w==",
"requires": {
"fs-extra": "^8.1.0",
"handlebars": "^4.7.6",
"highlight.js": "^10.0.0",
"lodash": "^4.17.15",
"lunr": "^2.3.8",
"marked": "1.0.0",
"minimatch": "^3.0.0",
"progress": "^2.0.3",
"shelljs": "^0.8.4",
"typedoc-default-themes": "^0.10.2"
}
},
"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==",
"requires": {
"lunr": "^2.3.8"
}
},
"typescript": {
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
- "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
- "dev": true
+ "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA=="
},
"uglify-js": {
"version": "3.14.5",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.5.tgz",
"integrity": "sha512-qZukoSxOG0urUTvjc2ERMTcAy+BiFh3weWAkeurLwjrCba73poHmG3E36XEjd/JGukMzwTL7uCxZiAexj8ppvQ=="
},
"unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
"integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
"dev": true
},
"unicode-match-property-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
"integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
"dev": true,
"requires": {
"unicode-canonical-property-names-ecmascript": "^2.0.0",
"unicode-property-aliases-ecmascript": "^2.0.0"
}
},
"unicode-match-property-value-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz",
"integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==",
"dev": true
},
"unicode-property-aliases-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz",
"integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==",
"dev": true
},
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
},
"unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
},
"upper-case": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
"integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg="
},
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
"requires": {
"punycode": "^2.1.0"
}
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
},
"uuid": {
"version": "8.3.2",
"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==",
"dev": true
},
"valid-data-url": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-3.0.1.tgz",
"integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA=="
},
"vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
},
"web-resource-inliner": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-5.0.0.tgz",
"integrity": "sha512-AIihwH+ZmdHfkJm7BjSXiEClVt4zUFqX4YlFAzjL13wLtDuUneSaFvDBTbdYRecs35SiU7iNKbMnN+++wVfb6A==",
"requires": {
"ansi-colors": "^4.1.1",
"escape-goat": "^3.0.0",
"htmlparser2": "^4.0.0",
"mime": "^2.4.6",
"node-fetch": "^2.6.0",
"valid-data-url": "^3.0.0"
},
"dependencies": {
"domhandler": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
"requires": {
"domelementtype": "^2.0.1"
}
},
"htmlparser2": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
"integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^3.0.0",
"domutils": "^2.0.0",
"entities": "^2.0.0"
}
}
}
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
},
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
"dev": true
},
"wide-align": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
"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==",
"dev": true
},
"wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus="
},
"workerpool": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz",
"integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==",
"dev": true
},
"wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"write-file-atomic": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
"integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
"dev": true,
"requires": {
"imurmurhash": "^0.1.4",
"is-typedarray": "^1.0.0",
"signal-exit": "^3.0.2",
"typedarray-to-buffer": "^3.1.5"
}
},
"y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
},
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
},
"yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"requires": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
}
},
"yargs-parser": {
"version": "20.2.4",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
"integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA=="
},
"yargs-unparser": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
"integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
"dev": true,
"requires": {
"camelcase": "^6.0.0",
"decamelize": "^4.0.0",
"flat": "^5.0.2",
"is-plain-obj": "^2.1.0"
},
"dependencies": {
"camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true
},
"decamelize": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
"integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
"dev": true
}
}
},
"ylru": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ylru/-/ylru-1.2.1.tgz",
"integrity": "sha512-faQrqNMzcPCHGVC2aaOINk13K+aaBDUPjGWl0teOXywElLjyVAB6Oe2jj62jHYtwsU49jXhScYbvPENK+6zAvQ=="
},
"yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true
}
}
}
diff --git a/package.json b/package.json
index cb4086a2..949a4790 100644
--- a/package.json
+++ b/package.json
@@ -1,102 +1,103 @@
{
"name": "sealious",
"homepage": "http://sealious.github.io/",
"version": "0.14.10",
"description": "A declarative framework for fast & easy app development.",
"main": "./lib/src/main.js",
"types": "./@types/src/main.d.ts",
"scripts": {
"test-debug": "npm run test-cmd -- --debug",
"test-cmd": "node test.js",
"test": "npm run test-cmd -- ",
"build": "rm -rf ./lib && tsc",
"watch": "npm run build -- --watch",
"test-reports": "npm run build && rm -fr .xunit coverage && docker-compose up -d db mailcatcher && npm run test -- --cover --test-report",
"cover-html": "npm run test-reports -- --cover-html && xdg-open coverage/lcov-report/index.html",
"docs": "typedoc --out docs src --exclude '**/*+(test).ts' --mode file --toc Collection,Field,Policy,App --categorizeByGroup false --stripInternal"
},
"repository": {
"type": "git",
"url": "https://github.com/sealcode/sealious"
},
"author": "The Sealious team (http://github.com/Sealious)",
"license": "BSD-2-Clause",
"bugs": {
"url": "https://github.com/Sealious/Sealious/issues"
},
"dependencies": {
"@babel/polyfill": "^7.0.0",
"@koa/router": "^10.0.0",
+ "@sealcode/ts-predicates": "^0.2.5",
"@types/bluebird": "^3.5.30",
"@types/boom": "^7.3.0",
"@types/clone": "^0.1.30",
"@types/color": "^3.0.1",
"@types/color-hash": "^1.0.0",
"@types/escape-html": "^1.0.0",
"@types/koa": "^2.11.6",
"@types/koa__router": "*",
"@types/koa-mount": "^4.0.0",
"@types/koa-qs": "^2.0.0",
"@types/koa-send": "^4.1.2",
"@types/koa-static": "^4.0.1",
"@types/mime": "^2.0.2",
"@types/mjml": "^4.0.4",
"@types/mocha": "^7.0.2",
"@types/mongodb": "^3.5.20",
"@types/node": "^13.13.4",
"@types/nodemailer": "^6.4.0",
"@types/object-hash": "^1.3.3",
"@types/shortid": "0.0.29",
"@types/uuid": "^8.3.0",
"axios": "^0.18.1",
"bluebird": "^3.4.6",
"boom": "^7.3.0",
"chalk": "^4.1.0",
"clone": "^1.0.2",
"color": "latest",
"color-hash": "^1.0.3",
"deepmerge": "^4.2.2",
"dot-prop": "^5.2.0",
"emittery": "github:sindresorhus/emittery#7db46441",
"escape-html": "^1.0.3",
"get-port": "^5.1.1",
"koa": "^2.13.0",
"koa-body": "^4.2.0",
"koa-mount": "^4.0.0",
"koa-qs": "^3.0.0",
"koa-send": "^5.0.1",
"koa-static": "^5.0.0",
"locreq": "^2.0.2",
"mime": "^2.4.6",
"mjml": "^4.2.0",
"mongodb": "^3.6.2",
"nodemailer": "^6.4.6",
"object-hash": "^2.0.3",
"pretty-ms": "^7.0.0",
"qs": "^6.5.1",
"sanitize-html": "^1.13.0",
"shortid": "^2.2.6",
"typedoc": "^0.17.8",
"uuid": "^8.3.2"
},
"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/core": "^7.0.0",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"@typescript-eslint/eslint-plugin": "^3.6.0",
"@typescript-eslint/parser": "^3.6.0",
"eslint": "^7.4.0",
"eslint-config-prettier": "^7.1.0",
"eslint-plugin-jsdoc": "^29.1.3",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.3.0",
"mocha": "^8.2.1",
"mri": "^1.1.6",
"nyc": "^15.1.0",
"prettier": "^2.2.1",
"source-map-support": "^0.5.19",
"typescript": "^4.1.3"
}
}
diff --git a/src/app/app.ts b/src/app/app.ts
index 3264a245..5e4c0157 100644
--- a/src/app/app.ts
+++ b/src/app/app.ts
@@ -1,259 +1,260 @@
import locreq_curry from "locreq";
const locreq = locreq_curry(__dirname);
import assert from "assert";
-import Mailer from "../email/mailer";
+import type Mailer from "../email/mailer";
import Emittery from "emittery";
import Datastore from "../datastore/datastore";
-import Metadata from "./metadata";
-import Config, { PartialConfig } from "./config";
+import type Metadata from "./metadata";
+import type Config from "./config";
+import type { PartialConfig } from "./config";
import Manifest, { ManifestData } from "./manifest";
import BaseCollections from "./collections/base-collections";
import Logger from "./logger";
import ConfigManager from "./config-manager";
import HttpServer from "../http/http";
import Context, { SuperContext } from "../context";
-import Collection from "../chip-types/collection";
+import type Collection from "../chip-types/collection";
import { MetadataFactory, i18nFactory } from "../main";
-import Users from "./collections/users";
-import Sessions from "./collections/sessions";
+import type Users from "./collections/users";
+import type Sessions from "./collections/sessions";
import LoggerMailer from "../email/logger-mailer";
import Router from "@koa/router";
import sessionRouter from "../http/routes/session";
import extractContext from "../http/extract-context";
import logo from "../http/routes/logo";
import uploaded_files from "../http/routes/uploaded-files";
import fs from "fs";
const default_config = locreq("default_config.json") as Config;
export type AppEvents = "starting" | "started" | "stopping" | "stopped";
/** The heart of your, well app. It all starts with `new App(...)` */
abstract class App {
/** The current status of the app */
status: "stopped" | "running" | "starting" | "stopping";
emitter = new Emittery();
/** The base collections including users, registration intents, etc */
static BaseCollections = BaseCollections;
/** The manifest assigned to this app. Stores things like the app name, domain, logo*/
abstract manifest: ManifestData;
/** The function that's used to generate translated versions of phrases */
i18n: (phrase_id: string, params?: unknown[]) => string;
/** ConfigManager instance. It serves the config based on default
* values and the config object provided to the app constructor */
ConfigManager: ConfigManager;
/** The {@link Logger} instance assigned to this application */
Logger: Logger;
/** The server that runs the REST API routing and allows to add custom routes etc */
HTTPServer: HttpServer;
/** The mongoDB client connected to the database specified in the app config */
Datastore: Datastore;
/** The Metadata manager assigned to this app. Used to store
* certain state information that's not meant to be shown to the
* user
*
* @internal
*/
Metadata: Metadata;
/** The collections defined within the given app. */
abstract collections: {
users: Users;
sessions: Sessions;
[name: string]: Collection;
};
/** A shorthand-way to create a new SuperContext: `new app.SuperContext()`. */
public SuperContext: new () => SuperContext;
/** A shorthand-way to create a new context: `new app.Context()`. */
public Context: new () => Context;
abstract config: PartialConfig;
public mailer: Mailer = new LoggerMailer();
/** The app constructor.
*
* @param custom_config Specify the details, such as database
* address and the port to listen on. This is private information
* and won't be shown to user. See {@link Config}
*
* @param manifest Specify additional information, such as the
* URL, logo or the main color of the app. This is public
* information.
*/
constructor() {
this.ConfigManager = new ConfigManager();
for (const key in default_config) {
this.ConfigManager.setDefault(
key,
default_config[key as keyof Config]
);
}
this.status = "stopped";
this.Logger = new Logger("error");
this.HTTPServer = new HttpServer(this);
this.Datastore = new Datastore(this);
this.Metadata = new MetadataFactory(this);
const app = this;
/** Shorthand way to create a {@link SuperContext} */
this.SuperContext = class extends SuperContext {
/** This constructor does not take any parameters as the
* {@link App} instance is automatically filled in */
constructor() {
super(app);
}
};
/** Shorthand way to create a {@link Context} */
this.Context = class extends Context {
/** This constructor does not take any parameters as the
* {@link App} instance is automatically filled in */
constructor() {
super(app);
}
};
}
/** Initializes all the collection fields, prepares all the hooks,
* connects to the database and starts the app, serving the REST
* API */
async start(): Promise<void> {
this.ConfigManager.setRoot(this.config);
const promises = [];
const uploadPath = this.ConfigManager.get("upload_path");
assert(uploadPath, "'upload_path' not set in config");
if (!fs.existsSync(uploadPath)) {
fs.mkdirSync(uploadPath, { recursive: false });
}
this.Logger.setLevel(this.ConfigManager.get("logger").level);
this.i18n = i18nFactory(this.manifest.default_language);
new Manifest(this.manifest).validate();
this.status = "starting";
assert(
["dev", "production"].includes(
this.ConfigManager.get("core").environment
),
`"core.environment" config should be either "dev" or "production"`
);
for (const [name, collection] of Object.entries(this.collections)) {
promises.push(collection.init(this, name));
}
await Promise.all(promises);
await this.emitter.emit("starting");
await this.Datastore.start();
await this.mailer.init(this);
this.initRouter();
await this.HTTPServer.start();
await this.emit("started");
this.status = "running";
}
/** Stops the HTTP server, disconnects from the DB */
async stop(): Promise<void> {
this.status = "stopping";
await this.emit("stopping");
await this.HTTPServer.stop();
await this.Datastore.stop();
this.status = "stopped";
await this.emit("stopped");
this.emitter.clearListeners();
for (const collection of Object.values(this.collections)) {
collection.clearListeners();
}
}
/** Removes all data inside the app. USE WITH CAUTION
* @internal
*/
async removeAllData(): Promise<void> {
await Promise.all(
Object.keys(this.collections).map((collection_name) =>
this.Datastore.remove(collection_name, {}, "just_one" && false)
)
);
}
/** Allows to listen for basic app status change events */
on(
event_name: AppEvents,
callback: () => Promise<void> | void
): Emittery.UnsubscribeFn {
return this.emitter.on(event_name, callback);
}
emit(event_name: string, data?: unknown): Promise<void> {
return this.emitter.emit(event_name, data);
}
/** registers a collection within the app
* @internal
*/
registerCollection(collection: Collection): void {
this.collections[collection.name] = collection;
}
initRouter(): void {
const router = this.HTTPServer.router;
router.use("/api/v1/", extractContext(), async (ctx, next) => {
await next();
ctx.$app.Logger.debug("HTTP RESPONSE", "Responding with", ctx.body);
});
router.use(async (ctx, next) => {
ctx.$app.Logger.info("REQUEST", `${ctx.method} ${ctx.url}`, {
query: ctx.query as unknown,
body: ctx.request.body as unknown,
});
await next();
});
router.use(
"/api/v1/uploaded-files",
uploaded_files.routes(),
uploaded_files.allowedMethods()
);
const collections_router = new Router();
for (const collection of Object.values(this.collections)) {
const collection_router = collection.getRouter();
collections_router.use(
`/${collection.name
.replace(/\(/g, "\\(")
.replace(/\)/g, "\\)")}`, //to enable "(" and ")" in collection names (see and.subtest.ts)
collection_router.routes(),
collection_router.allowedMethods()
);
}
router.use(
"/api/v1/collections",
collections_router.routes(),
collections_router.allowedMethods()
);
router.use(
"/api/v1/sessions",
sessionRouter.routes(),
sessionRouter.allowedMethods()
);
router.get("/assets/logo", logo);
}
}
export default App;
diff --git a/src/app/base-chips/field-types/boolean.subtest.ts b/src/app/base-chips/field-types/boolean.subtest.ts
index 9aec414e..c380669b 100644
--- a/src/app/base-chips/field-types/boolean.subtest.ts
+++ b/src/app/base-chips/field-types/boolean.subtest.ts
@@ -1,118 +1,120 @@
import assert from "assert";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
import { assertThrowsAsync } from "../../../test_utils/assert-throws-async";
import { App, Collection, FieldTypes, Policies } from "../../../main";
-import { TestAppType } from "../../../test_utils/test-app";
const URL = "/api/v1/collections/boolseals";
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
const boolseals = new (class extends Collection {
name = "boolseals";
fields = {
is_old: FieldTypes.Required(new FieldTypes.Boolean()),
};
defaultPolicy = new Policies.Public();
})();
return class extends t {
collections = {
...App.BaseCollections,
boolseals,
};
};
}
describe("boolean", () => {
it("Allows to insert values considered correct", async () =>
withRunningApp(extend, async ({ rest_api }) => {
const cases = [
[true, true],
[false, false],
["true", true],
["false", false],
["1", true],
["0", false],
[1, true],
[0, false],
];
for (const [field_value, saved_value] of cases) {
const { is_old } = await rest_api.post(URL, {
is_old: field_value,
});
assert.equal(
is_old,
saved_value,
`While entering ${field_value}, the stored value should be ${saved_value}, but was ${is_old}`
);
}
}));
it("Doesn't let undefined in", () =>
withRunningApp(extend, async ({ rest_api }) => {
await assertThrowsAsync(
() => rest_api.post(`${URL}`, { is_old: undefined }),
(error) =>
assert.deepEqual(
error.response.data.data.field_messages.is_old.message,
"Missing value for field 'is_old'."
)
);
}));
it("Doesn't let '' in", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await assertThrowsAsync(
() => rest_api.post(`${URL}`, { is_old: "" }),
(error) => {
assert.strictEqual(error.response.status, 403);
assert.deepStrictEqual(
error.response.data.data.field_messages.is_old.message,
app.i18n("invalid_boolean", [""])
);
}
);
}));
it("Doesn't let unwelcomed values in", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
const cases = [
[null, "Missing value for field 'is_old'."],
[{}, app.i18n("invalid_boolean", [{}])],
[[], app.i18n("invalid_boolean", [[]])],
[[false], app.i18n("invalid_boolean", [[false]])],
[{ a: true }, app.i18n("invalid_boolean", [{ a: true }])],
];
await Promise.all(
cases.map(([value, error_message]) =>
assertThrowsAsync(
() => rest_api.post(`${URL}`, { is_old: value }),
(error) => {
assert.equal(error.response.status, 403);
assert.deepEqual(
error.response.data.data.field_messages.is_old
.message,
error_message
);
}
)
)
);
}));
it("lets filter by literal false value", () =>
withRunningApp(extend, async ({ app }) => {
await app.collections.boolseals.create(new app.SuperContext(), {
is_old: true,
});
await app.collections.boolseals.create(new app.SuperContext(), {
is_old: false,
});
const { items: seals } = await app.collections.boolseals
.list(new app.SuperContext())
.filter({ is_old: false })
.fetch();
assert.strictEqual(seals.length, 1);
}));
});
diff --git a/src/app/base-chips/field-types/cached-value.subtest.ts b/src/app/base-chips/field-types/cached-value.subtest.ts
index af2b7f64..dcf3f454 100644
--- a/src/app/base-chips/field-types/cached-value.subtest.ts
+++ b/src/app/base-chips/field-types/cached-value.subtest.ts
@@ -1,547 +1,565 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import assert from "assert";
import {
withStoppedApp,
withRunningApp,
+ TestAppConstructor,
} from "../../../test_utils/with-test-app";
import { assertThrowsAsync } from "../../../test_utils/assert-throws-async";
import { getDateTime } from "../../../utils/get-datetime";
import { App, Context, Collection, FieldTypes, Field } from "../../../main";
import Bluebird from "bluebird";
-import { TestAppType } from "../../../test_utils/test-app";
-import ItemList, { ItemListResult } from "../../../chip-types/item-list";
-import { RefreshCondition } from "./cached-value";
+import type { ItemListResult } from "../../../chip-types/item-list";
+import type { RefreshCondition } from "./cached-value";
import { EventDescription } from "../../delegate-listener";
-import MockRestApi, {
+import type MockRestApi from "../../../test_utils/rest-api";
+import type {
CollectionResponse,
ItemCreatedResponse,
ItemResponse,
} from "../../../test_utils/rest-api";
+import { TestApp } from "../../../test_utils/test-app";
const action_to_status: { [name: string]: string } = {
create: "created",
open: "open",
suspend: "suspended",
close: "closed",
};
const MIN_VALUE = 0;
-const extend = (
- is_status_field_desired: boolean,
- clear_database_on_stop = true
-) => (t: TestAppType) => {
- const account_fields: { [field_name: string]: Field } = {
- username: new FieldTypes.Username(),
- number: new FieldTypes.CachedValue(
- new FieldTypes.Int({
- min: MIN_VALUE,
- }),
- {
- get_value: async () => {
- return 0;
- },
- refresh_on: [],
+const extend =
+ (is_status_field_desired: boolean, clear_database_on_stop = true) =>
+ (t: TestAppConstructor) => {
+ const account_fields: { [field_name: string]: Field } = {
+ username: new FieldTypes.Username(),
+ number: new FieldTypes.CachedValue(
+ new FieldTypes.Int({
+ min: MIN_VALUE,
+ }),
+ {
+ get_value: async () => {
+ return 0;
+ },
+ refresh_on: [],
+ initial_value: 0,
+ }
+ ),
+ date_time: new FieldTypes.CachedValue(new FieldTypes.DateTime(), {
+ get_value: async () => new Date("2018-01-01").getTime(),
+ refresh_on: make_refresh_on(),
initial_value: 0,
- }
- ),
- date_time: new FieldTypes.CachedValue(new FieldTypes.DateTime(), {
- get_value: async () => new Date("2018-01-01").getTime(),
- refresh_on: make_refresh_on(),
- initial_value: 0,
- }),
- };
- if (is_status_field_desired) {
- account_fields.status = new FieldTypes.CachedValue(
- new FieldTypes.Enum(Object.values(action_to_status)),
- {
- get_value: async (context: Context, resource_id: string) => {
- context.app.Logger.debug3(
- "STATUS FIELD",
- `calculating value for ${resource_id}`
- );
- const {
- items,
- } = await context.app.collections.actions
- .list(new context.app.SuperContext())
- .filter({ account: resource_id })
- .sort({ "_metadata.modified_at": "desc" })
- .paginate({ items: 1 })
- .fetch();
- context.app.Logger.debug3(
- "STATUS FIELD",
- "New cached value is",
- action_to_status[
+ }),
+ };
+ if (is_status_field_desired) {
+ account_fields.status = new FieldTypes.CachedValue(
+ new FieldTypes.Enum(Object.values(action_to_status)),
+ {
+ get_value: async (
+ context: Context,
+ resource_id: string
+ ) => {
+ context.app.Logger.debug3(
+ "STATUS FIELD",
+ `calculating value for ${resource_id}`
+ );
+ const { items } = await context.app.collections.actions
+ .list(new context.app.SuperContext())
+ .filter({ account: resource_id })
+ .sort({ "_metadata.modified_at": "desc" })
+ .paginate({ items: 1 })
+ .fetch();
+ context.app.Logger.debug3(
+ "STATUS FIELD",
+ "New cached value is",
+ action_to_status[
+ items[0].get(
+ "name"
+ ) as keyof typeof action_to_status
+ ]
+ );
+ return action_to_status[
items[0].get(
"name"
) as keyof typeof action_to_status
- ]
- );
- return action_to_status[
- items[0].get("name") as keyof typeof action_to_status
- ];
- },
- refresh_on: make_refresh_on(),
- initial_value: "created",
- }
- );
- }
- const accounts = new (class extends Collection {
- name = "accounts";
- fields = {
- ...account_fields,
- };
- })();
+ ];
+ },
+ refresh_on: make_refresh_on(),
+ initial_value: "created",
+ }
+ );
+ }
+ const accounts = new (class extends Collection {
+ name = "accounts";
+ fields = {
+ ...account_fields,
+ };
+ })();
- const actions = new (class extends Collection {
- name = "actions";
- fields = {
- name: new FieldTypes.Enum(["create", "open", "suspend", "close"]),
- account: new FieldTypes.SingleReference("accounts"),
- };
- })();
+ const actions = new (class extends Collection {
+ name = "actions";
+ fields = {
+ name: new FieldTypes.Enum([
+ "create",
+ "open",
+ "suspend",
+ "close",
+ ]),
+ account: new FieldTypes.SingleReference("accounts"),
+ };
+ })();
- return class extends t {
- collections = {
- ...App.BaseCollections,
- actions,
- accounts,
+ return class extends t {
+ collections = {
+ ...App.BaseCollections,
+ actions,
+ accounts,
+ };
+ clear_database_on_stop = clear_database_on_stop;
};
- clear_database_on_stop = clear_database_on_stop;
};
-};
describe("cached-value", () => {
async function add_account(
rest_api: MockRestApi,
account: { username: string; number?: number; date_time?: string }
) {
const { id } = (await rest_api.post(
"/api/v1/collections/accounts",
account
)) as ItemCreatedResponse;
await rest_api.post("/api/v1/collections/actions", {
name: "create",
account: id,
});
return id;
}
async function add_a_few_accounts(app: App) {
return Bluebird.map([1, 2, 3, 4, 5], async (i) =>
app.collections.accounts.suCreate({
username: `user_${i}`,
number: i,
})
);
}
it("Correctly fills in cached-values if such field is added later", async () => {
let account_ids: string[] = [];
await withStoppedApp(
extend(false, false),
async ({ app, rest_api }) => {
await app.start();
account_ids = await Bluebird.map(
["user_1", "user_2"],
(username) => add_account(rest_api, { username })
);
await rest_api.post("/api/v1/collections/actions", {
name: "suspend",
account: account_ids[1],
});
},
"cached-fill"
);
await withRunningApp(
extend(true),
async ({ rest_api }) => {
await assert_status_equals(rest_api, account_ids[0], "created");
await assert_status_equals(
rest_api,
account_ids[1],
"suspended"
);
},
"cached-fill"
);
});
it("Correctly updates cached-value on create", async () =>
withRunningApp(extend(true), async ({ rest_api }) => {
const account_ids = await Bluebird.map(
["user_1", "user_2"],
(username) => add_account(rest_api, { username })
);
await assert_status_equals(rest_api, account_ids[0], "created");
const actions = ["open", "suspend", "close"];
await Bluebird.each(actions, async (action) => {
await rest_api.post("/api/v1/collections/actions", {
name: action,
account: account_ids[0],
});
const status = action_to_status[action];
await assert_status_equals(rest_api, account_ids[0], status);
await assert_status_equals(rest_api, account_ids[1], "created");
});
}));
it("Correctly updates cached-value on update", async () =>
withRunningApp(extend(true), async ({ rest_api }) => {
const account_id = await add_account(rest_api, {
username: "user_1",
});
const {
items: [{ id: action_id }],
} = (await rest_api.get("/api/v1/collections/actions", {
data: { account: account_id }, // TODO: check if passing the query here works under the new MockRestAPI
})) as CollectionResponse;
await rest_api.patch(`/api/v1/collections/actions/${action_id}`, {
name: "open",
});
await assert_status_equals(rest_api, account_id, "open");
}));
it("Respects is_proper_value of base field type", async () =>
withRunningApp(extend(true), async ({ app }) => {
const value = -1;
await assertThrowsAsync(
async () =>
app.collections.accounts.suCreate({
username: "user_2",
number: value,
}),
(error) => {
assert.strictEqual(
//@eslint-ignore
error.data.field_messages.number.message,
app.i18n("too_small_integer", [value, MIN_VALUE])
);
}
);
}));
it("Respects filters of base field type", async () =>
withRunningApp(extend(true), async ({ app, rest_api }) => {
await add_a_few_accounts(app);
const { items: accounts } = (await rest_api.get(
"/api/v1/collections/accounts?filter[number][>]=3"
)) as CollectionResponse;
assert.strictEqual(accounts.length, 2);
}));
it("Respects format of base field type", async () =>
withRunningApp(extend(true), async ({ rest_api }) => {
const id = await add_account(rest_api, { username: "user_1" });
const expected_datetime = getDateTime(
new Date("2018-01-01"),
"yyyy-mm-dd hh:mm:ss"
);
- const actual_datetime = ((await rest_api.get(
- `/api/v1/collections/accounts/${id}?format[date_time]=human_readable`
- )) as CollectionResponse).items[0].date_time as string;
+ const actual_datetime = (
+ (await rest_api.get(
+ `/api/v1/collections/accounts/${id}?format[date_time]=human_readable`
+ )) as CollectionResponse
+ ).items[0].date_time as string;
assert.strictEqual(actual_datetime, expected_datetime);
}));
it("Properly responds to recursive edits", async () =>
- withStoppedApp(extend(true), async ({ app, app_class }) => {
- await assertThrowsAsync(
- async () => {
- const HappyNumbers = class HappyNumbers extends Collection {
- fields = {
- number: new FieldTypes.Int(),
- double_number: new FieldTypes.CachedValue(
- new FieldTypes.Int(),
- {
- get_value: async (
- context: Context,
- number_id: string
- ) => {
- const response = await app.collections[
- "happy-numbers"
- ]
- .list(context)
- .ids([number_id])
- .fetch();
- return (
- (response.items[0].get(
- "number"
- ) as number) * 2
- );
- },
- refresh_on: [
- {
- event: new EventDescription(
- "happy-numbers",
- "after:create"
- ),
- resource_id_getter: async (
- _,
- item
- ) => [item.id],
+ withStoppedApp(
+ extend(true),
+ async ({ app, app_class, base_url, uniq_id, env, port }) => {
+ await assertThrowsAsync(
+ async () => {
+ const HappyNumbers = class HappyNumbers extends Collection {
+ fields = {
+ number: new FieldTypes.Int(),
+ double_number: new FieldTypes.CachedValue(
+ new FieldTypes.Int(),
+ {
+ get_value: async (
+ context: Context,
+ number_id: string
+ ) => {
+ const response =
+ // @ts-ignore
+ await app.collections[
+ "happy-numbers"
+ ]
+ .list(context)
+ .ids([number_id])
+ .fetch();
+ return (
+ (response.items[0].get(
+ "number"
+ ) as number) * 2
+ );
},
- ],
- initial_value: 0,
- }
- ),
+ refresh_on: [
+ {
+ event: new EventDescription(
+ "happy-numbers",
+ "after:create"
+ ),
+ resource_id_getter: async (
+ _,
+ item
+ ) => [item.id],
+ },
+ ],
+ initial_value: 0,
+ }
+ ),
+ };
};
- };
- const new_app = new (class extends app_class {
- collections = {
- ...super.collections,
- "happy-numbers": new HappyNumbers(),
- };
- })();
- await new_app.start();
- },
- (e) => {
- assert.strictEqual(
- e.message,
- `In the happy-numbers collection definition you've tried to create the double_number cached-value field that refers to the collection itself. Consider using 'derived-value' field type to avoid problems with endless recurrence.`
- );
- }
- );
- }));
+ const new_app = new (class extends app_class {
+ collections = {
+ ...super.collections,
+ "happy-numbers": new HappyNumbers(),
+ };
+ })(uniq_id, env, port, base_url);
+ await new_app.start();
+ },
+ (e) => {
+ assert.strictEqual(
+ e.message,
+ `In the happy-numbers collection definition you've tried to create the double_number cached-value field that refers to the collection itself. Consider using 'derived-value' field type to avoid problems with endless recurrence.`
+ );
+ }
+ );
+ }
+ ));
it("should pass friendship scenario", async () => {
return withRunningApp(
(test_app_type) => {
return class extends test_app_type {
collections = {
- ...test_app_type.BaseCollections,
+ ...TestApp.BaseCollections,
people: new (class extends Collection {
fields = {
name: new FieldTypes.Text(),
popularity: new FieldTypes.CachedValue(
new FieldTypes.Int({ min: 0 }),
{
refresh_on: [
{
event: new EventDescription(
"who-likes-who",
"after:create"
),
resource_id_getter: async (
_,
item
) => [
item.get(
"likes_this_person"
) as string,
],
},
],
get_value: async function (
context,
item_id
) {
- const is_liked_by = (await context.app.collections[
- "who-likes-who"
- ]
- .suList()
- .filter({
- likes_this_person: item_id,
- })
- .fetch()) as ItemListResult<any>;
+ const is_liked_by =
+ (await context.app.collections[
+ "who-likes-who"
+ ]
+ .suList()
+ .filter({
+ likes_this_person:
+ item_id,
+ })
+ .fetch()) as ItemListResult<any>;
return is_liked_by.items.length;
},
initial_value: 0,
}
),
};
})(),
"who-likes-who": new (class extends Collection {
fields = {
this_person: new FieldTypes.SingleReference(
"people"
),
- likes_this_person: new FieldTypes.SingleReference(
- "people"
- ),
+ likes_this_person:
+ new FieldTypes.SingleReference("people"),
};
})(),
};
};
},
async ({ rest_api }) => {
const alice = await rest_api.post(
"/api/v1/collections/people",
{
name: "alice",
}
);
const bob = await rest_api.post("/api/v1/collections/people", {
name: "bob",
});
const friendship = await rest_api.post(
"/api/v1/collections/who-likes-who",
{
this_person: bob.id as string,
likes_this_person: alice.id as string,
}
);
const response = await rest_api.get(
`/api/v1/collections/people/${alice.id}`
);
assert.strictEqual(response.items[0].popularity, 1);
await rest_api.delete(
`/api/v1/collections/who-likes-who/${friendship.id}`
);
}
);
});
it("behaves correctly when the initial value is null", () =>
withRunningApp(
(test_app) =>
class extends test_app {
collections = {
...App.BaseCollections,
jobs: new (class extends Collection {
fields = {
title: new FieldTypes.Text(),
};
})(),
hasdefault: new (class extends Collection {
fields = {
isdefault: new FieldTypes.CachedValue(
new FieldTypes.SingleReference("jobs"),
{
refresh_on: [
{
event: new EventDescription(
"jobs",
"after:edit"
),
resource_id_getter: async (
_,
item
) => [item.id],
},
],
get_value: async function (
context,
item_id
) {
- const job = await context.app.collections[
- "jobs"
- ].getByID(context, item_id);
+ const job =
+ await context.app.collections[
+ "jobs"
+ ].getByID(context, item_id);
return job.id;
},
initial_value: null,
}
),
};
})(),
};
},
async ({ app }) => {
const hasdefault = await app.collections.hasdefault.suCreate(
{}
);
assert.strictEqual(hasdefault.get("isdefault"), null);
}
));
it("handles field types that depend on being .inited", () =>
withRunningApp(
(test_app) =>
class extends test_app {
collections = {
...App.BaseCollections,
jobs: new (class extends Collection {
fields = {
title: new FieldTypes.Text(),
hasjob: new FieldTypes.SingleReference(
"hasjob"
),
};
})(),
hasjob: new (class extends Collection {
fields = {
job: new FieldTypes.CachedValue(
new FieldTypes.SingleReference("jobs"),
{
refresh_on: [
{
event: new EventDescription(
"jobs",
"after:create"
),
resource_id_getter: async (
_,
item
) => [item.get("hasjob")],
},
],
get_value: async function (
context,
item_id
) {
const {
items: [job],
} = await context.app.collections.jobs
.suList()
.filter({ hasjob: item_id })
.fetch();
return job.id;
},
initial_value: null,
}
),
};
})(),
};
},
async ({ app }) => {
const hasjob = await app.collections.hasjob.suCreate({});
const job = await app.collections.jobs.suCreate({
title: "any",
hasjob: hasjob.id,
});
const {
items: [hasjob_after],
} = await app.collections.hasjob.suList().fetch();
assert.strictEqual(hasjob_after.get("job"), job.id);
}
));
});
function make_refresh_on(): RefreshCondition[] {
return [
{
event: new EventDescription("actions", "after:create"),
resource_id_getter: async (_, item) => [
item.get("account") as string,
],
},
{
event: new EventDescription("actions", "after:edit"),
resource_id_getter: async (_, resource) => [
resource.get("account") as string,
],
},
];
}
async function assert_status_equals(
rest_api: MockRestApi,
account_id: string,
expected_status: string
) {
const { items } = (await rest_api.get(
`/api/v1/collections/accounts/${account_id}`
)) as ItemResponse;
assert.strictEqual(items[0].status, expected_status);
}
diff --git a/src/app/base-chips/field-types/cached-value.ts b/src/app/base-chips/field-types/cached-value.ts
index 43440050..10b8e3a5 100644
--- a/src/app/base-chips/field-types/cached-value.ts
+++ b/src/app/base-chips/field-types/cached-value.ts
@@ -1,204 +1,204 @@
-import { App, Field, Context, CollectionItem } from "../../../main";
+import type { App, Field, Context, CollectionItem } from "../../../main";
import HybridField from "../../../chip-types/field-hybrid";
import ItemList from "../../../chip-types/item-list";
-import { EventDescription } from "../../delegate-listener";
+import type { EventDescription } from "../../delegate-listener";
import { BadContext } from "../../../response/errors";
import isEmpty from "../../../utils/is-empty";
export type RefreshCondition = {
event: EventDescription;
resource_id_getter: (
context: Context,
item: CollectionItem,
event: EventDescription
) => Promise<string[]>;
};
type GetValue<T extends Field> = (
context: Context,
resource_id: string
) => Promise<Parameters<T["encode"]>[1]>;
type CachedValueSettings<T extends Field> = {
refresh_on: RefreshCondition[];
get_value: GetValue<T>;
initial_value: Parameters<T["encode"]>[1];
};
export default class CachedValue<T extends Field> extends HybridField<T> {
typeName = "cached-value";
app: App;
refresh_on: RefreshCondition[];
get_value: GetValue<T>;
hasDefaultValue: () => true;
private initial_value: Parameters<T["encode"]>[1];
constructor(base_field: T, params: CachedValueSettings<T>) {
super(base_field);
super.setParams(params);
this.refresh_on = params.refresh_on;
this.get_value = params.get_value;
this.initial_value = params.initial_value;
}
async init(app: App) {
await super.init(app);
await this.virtual_field.init(app);
this.checkForPossibleRecursiveEdits();
const create_action = this.refresh_on.find(({ event }) =>
event.event_name.includes("create")
);
if (create_action) {
app.on("started", () =>
this.refresh_outdated_cache_values(create_action)
);
}
for (let { event, resource_id_getter } of this.refresh_on) {
event.attachTo(app, async ([context, item, event]) => {
const cache_resource_ids = await resource_id_getter(
context,
item,
event
);
if (!Array.isArray(cache_resource_ids)) {
throw new Error(
`resource_id_getter return value should be an array of strings, got: ${JSON.stringify(
cache_resource_ids
)}`
);
}
app.Logger.debug3("CACHED VALUE", "Inside hook", {
cache_resource_ids,
});
const promises = [];
for (const cache_resource_id of cache_resource_ids) {
promises.push(
this.get_value(context, cache_resource_id).then(
async (value) => {
const item = await context.app.collections[
this.collection.name
].suGetByID(cache_resource_id);
item.set(this.name, value);
await item.save(new app.SuperContext());
}
)
);
}
await Promise.all(promises);
});
}
}
checkForPossibleRecursiveEdits() {
const doesAnyMatches = this.refresh_on.some(
({ event }) => event.collection_name === this.collection.name
);
if (doesAnyMatches) {
throw new Error(
"In the " +
this.collection.name +
" collection definition you've tried to create the " +
this.name +
" cached-value field that refers to the collection itself. Consider using 'derived-value' field type to avoid problems with endless recurrence."
);
}
}
private async refresh_outdated_cache_values(condition: RefreshCondition) {
const referenced_collection_name = condition.event.collection_name;
const response = await new ItemList(
this.app.collections[referenced_collection_name],
new this.app.SuperContext()
)
.sort({ "_metadata.modified_at": "desc" })
.paginate({ items: 1 })
.fetch();
if (response.empty) {
return;
}
const last_modified_timestamp = response.items[0]._metadata.modified_at;
const outdated_resources = await this.app.Datastore.aggregate(
this.collection.name,
[
{
$match: {
$or: [
{
[`${this.name}.timestamp`]: {
$lt: last_modified_timestamp,
},
},
{ [this.name]: { $exists: false } },
],
},
},
]
);
this.app.Logger.debug3("CACHED", "Outdated items", outdated_resources);
if (!outdated_resources) {
return;
}
const context = new this.app.SuperContext();
for (let resource of outdated_resources) {
const value = await this.get_value(context, resource.id);
const cache_value = await this.encode(context, value);
this.app.Logger.debug3(
"CACHED",
`New value for item ${resource.id}.${this.name}`,
value
);
await this.app.Datastore.update(
this.collection.name,
{ id: resource.id },
{ $set: { [this.name]: cache_value } }
);
}
}
async getDefaultValue(_: Context) {
return this.initial_value;
}
async encode(context: Context, new_value: any) {
const encoded_value = await super.encode(context, new_value);
const ret = { timestamp: Date.now(), value: encoded_value };
context.app.Logger.debug3("CACHED VALUE", "Encode", { new_value, ret });
return ret;
}
async decode(
context: Context,
db_value: { timestamp: number; value: any },
old_value: any,
format: any
) {
return super.decode(context, db_value.value, old_value, format);
}
async isProperValue(
context: Context,
new_value: Parameters<T["checkValue"]>[1],
old_value: Parameters<T["checkValue"]>[2]
) {
if (!isEmpty(new_value) && !context.is_super) {
throw new BadContext("This is a read-only field");
}
return this.virtual_field.checkValue(context, new_value, old_value);
}
async getValuePath() {
return `${this.name}.value`;
}
}
diff --git a/src/app/base-chips/field-types/control-access.subtest.ts b/src/app/base-chips/field-types/control-access.subtest.ts
index 4597a549..cee3156f 100644
--- a/src/app/base-chips/field-types/control-access.subtest.ts
+++ b/src/app/base-chips/field-types/control-access.subtest.ts
@@ -1,229 +1,233 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import assert from "assert";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
import { assertThrowsAsync } from "../../../test_utils/assert-throws-async";
import { App, Collection, Context, FieldTypes, Policies } from "../../../main";
-import { TestAppType } from "../../../test_utils/test-app";
-import MockRestApi, {
+import type MockRestApi from "../../../test_utils/rest-api";
+import type {
CollectionResponse,
ItemCreatedResponse,
} from "../../../test_utils/rest-api";
-import { AxiosError, AxiosRequestConfig } from "axios";
+import type { AxiosError, AxiosRequestConfig } from "axios";
import asyncForEach from "../../../utils/async-foreach";
+import { TestApp } from "../../../test_utils/test-app";
const SSH_KEYS_URL = "/api/v1/collections/ssh-keys";
let session: AxiosRequestConfig = {};
const username = "regular-user";
const MIN_TEXT_LENGTH = 3;
type Key = { [access in "_public" | "_private"]: string };
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
"ssh-keys": new (class extends Collection {
fields = {
public: new FieldTypes.Text(),
private: new FieldTypes.ControlAccess(
new FieldTypes.Text({ min_length: MIN_TEXT_LENGTH }),
{
target_policies: {
show: new Policies.LoggedIn(),
edit: new Policies.LoggedIn(),
},
value_when_not_allowed: "Forbidden",
}
),
};
policies = {
create: new Policies.LoggedIn(),
};
})(),
};
};
}
async function setupUsers(App: App, rest_api: MockRestApi) {
const password = "it-really-doesnt-matter";
await App.collections.users.suCreate({
username,
password,
});
session = await rest_api.login({
username,
password,
});
}
async function fillKeysCollections(App: App) {
const keys: Key[] = [
{
_public: "a-public-key",
_private: "seeeeecret",
},
{
_public: "go-get-it",
_private: "you-cannot-see",
},
];
await asyncForEach(keys, async ({ _public, _private }) => {
await App.collections["ssh-keys"].suCreate({
public: _public,
private: _private,
});
});
}
async function setup(app: App, rest_api: MockRestApi) {
await fillKeysCollections(app);
await setupUsers(app, rest_api);
}
describe("control-access", () => {
it("Hides a protected value from not-logged", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app, rest_api);
const { items: ssh_keys } = (await rest_api.get(
SSH_KEYS_URL
)) as CollectionResponse;
ssh_keys.forEach((key) => {
assert.deepStrictEqual(key.private, "Forbidden");
});
}));
it("Uncovers a protected value for logged", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app, rest_api);
const { items: ssh_keys } = (await rest_api.get(
SSH_KEYS_URL,
session
)) as CollectionResponse;
ssh_keys.forEach((key) => {
assert((key.private as string).length >= 3);
});
}));
it("Respects given field type constraints", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
const too_short_text = "XD";
await setup(app, rest_api);
await assertThrowsAsync(
() =>
rest_api.post(
SSH_KEYS_URL,
{
public: "XDDDDDDDDDDDD",
private: too_short_text,
},
session
),
(e: AxiosError) =>
assert.strictEqual(
e?.response?.data?.data?.field_messages?.private
?.message,
app.i18n("too_short_text", [
too_short_text,
MIN_TEXT_LENGTH,
])
)
);
}));
it("Allows logged to update a protected field", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app, rest_api);
const key = (await rest_api.post(
SSH_KEYS_URL,
{
public: "123123",
private: "321321",
},
session
)) as ItemCreatedResponse;
const {
items: [updated_key],
} = (await rest_api.patch(
`${SSH_KEYS_URL}/${key.id}`,
{
private: "654321",
},
session
)) as CollectionResponse;
assert.deepStrictEqual(updated_key.private, "654321");
}));
it("Doesn't allow not logged to update a protected field", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app, rest_api);
const key = (await rest_api.post(
SSH_KEYS_URL,
{
public: "123123",
private: "321321",
},
session
)) as ItemCreatedResponse;
await assertThrowsAsync(
() =>
rest_api.patch(`${SSH_KEYS_URL}/${key.id}`, {
private: "331c6883dd6010864b7ead130be77cd5",
}),
(e) =>
assert.strictEqual(
e.response.data.data.field_messages.private.message,
app.i18n("policy_logged_in_deny")
)
);
}));
it("Honors the default value of the field", async () =>
withRunningApp(
(test_app) =>
class extends test_app {
collections = {
...App.BaseCollections,
tasks: new (class extends Collection {
fields = {
title: new FieldTypes.Text(),
done: new FieldTypes.ControlAccess(
new (class extends FieldTypes.Boolean {
hasDefaultValue = () => true;
async getDefaultValue() {
return false;
}
})(),
{
target_policies: {
show: new Policies.Public(),
edit: new Policies.Super(),
},
value_when_not_allowed: null,
}
),
};
defaultPolicy = new Policies.Public();
})(),
};
},
async ({ app }) => {
const task = await app.collections.tasks.create(
new Context(app, new Date().getTime(), null, null),
{ title: "" }
);
assert.strictEqual(task.get("done"), false);
}
));
});
diff --git a/src/app/base-chips/field-types/control-access.ts b/src/app/base-chips/field-types/control-access.ts
index b7d409ce..67f7666e 100644
--- a/src/app/base-chips/field-types/control-access.ts
+++ b/src/app/base-chips/field-types/control-access.ts
@@ -1,93 +1,90 @@
+import { Field, Context, Policy, App, ExtractStorage } from "../../../main";
import {
- Field,
- Context,
- Policy,
+ ExtractParams,
+ ExtractOutput,
HybridField,
- App,
- ExtractStorage,
-} from "../../../main";
-import { ExtractParams, ExtractOutput } from "../../../chip-types/field";
+} from "../../../chip-types/field";
type Params<T extends Field> = {
target_policies: { [key in "show" | "edit"]: Policy };
value_when_not_allowed: ExtractOutput<T>;
};
export default class ControlAccess<T extends Field> extends HybridField<T> {
typeName = "control-access";
edit_strategy: Policy;
show_strategy: Policy;
value_when_not_allowed: ExtractOutput<T>;
app: App;
constructor(base_field: T, params: Params<T>) {
super(base_field);
this.edit_strategy = params.target_policies.edit;
this.show_strategy = params.target_policies.show;
this.value_when_not_allowed = params.value_when_not_allowed;
}
async isProperValue(
context: Context,
new_value: Parameters<T["checkValue"]>[1],
old_value: Parameters<T["checkValue"]>[2]
) {
if (!context.is_super) {
const result = await this.edit_strategy.check(context);
if (result && !result?.allowed) {
return Field.invalid(result.reason);
}
}
return this.virtual_field.checkValue(context, new_value, old_value);
}
async decode(
context: Context,
value_in_db: ExtractStorage<T>,
old_value: ExtractOutput<T>,
format_params: ExtractParams<T>
) {
if (!context.is_super) {
context.app.Logger.debug2(
"CONTROL ACCESS",
`Checking the access to field ${this.name}...`,
{ value_in_db }
);
const result = await this.show_strategy.check(context);
if (result && !result.allowed) {
context.app.Logger.debug2(
"CONTROL ACCESS",
`Access to field '${this.name}' not allowed!`,
result
);
value_in_db = await this.encode(
context,
this.value_when_not_allowed
);
} else if (result?.allowed) {
context.app.Logger.debug2(
"CONTROL ACCESS",
`Access to field '${this.name}' is allowed!`,
result
);
}
}
const ret = await this.virtual_field.decode(
context,
value_in_db,
old_value,
format_params
);
return ret;
}
hasDefaultValue() {
return this.virtual_field.hasDefaultValue();
}
getDefaultValue(context: Context) {
return this.virtual_field.getDefaultValue(context);
}
}
diff --git a/src/app/base-chips/field-types/derived-value.subtest.ts b/src/app/base-chips/field-types/derived-value.subtest.ts
index 9524c5d2..1b314c4b 100644
--- a/src/app/base-chips/field-types/derived-value.subtest.ts
+++ b/src/app/base-chips/field-types/derived-value.subtest.ts
@@ -1,253 +1,258 @@
import assert from "assert";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
import { assertThrowsAsync } from "../../../test_utils/assert-throws-async";
import { Collection, FieldTypes, Field, App } from "../../../main";
-import { DerivingFn } from "./derived-value";
-import { TestAppType } from "../../../test_utils/test-app";
+import type { DerivingFn } from "./derived-value";
import { sleep } from "../../../test_utils/sleep";
+import { TestApp } from "../../../test_utils/test-app";
-const extend = <T extends Field = FieldTypes.Text>(derived_value_params: {
- deriving_fn: DerivingFn<T>;
- fields: string[];
-}) => (t: TestAppType) => {
- return class extends t {
- collections = {
- ...t.BaseCollections,
- people: new (class extends Collection {
- name = "people";
- fields = {
- username: new FieldTypes.Text(),
- surname: new FieldTypes.Text(),
- name_and_surname: new FieldTypes.DerivedValue(
- new FieldTypes.Text(),
- // @ts-ignore
- {
- ...derived_value_params,
- }
- ),
- age: new FieldTypes.Int(),
- };
- })(),
+const extend =
+ <T extends Field = FieldTypes.Text>(derived_value_params: {
+ deriving_fn: DerivingFn<T>;
+ fields: string[];
+ }) =>
+ (t: TestAppConstructor) => {
+ return class extends t {
+ collections = {
+ ...TestApp.BaseCollections,
+ people: new (class extends Collection {
+ name = "people";
+ fields = {
+ username: new FieldTypes.Text(),
+ surname: new FieldTypes.Text(),
+ name_and_surname: new FieldTypes.DerivedValue(
+ new FieldTypes.Text(),
+ // @ts-ignore
+ {
+ ...derived_value_params,
+ }
+ ),
+ age: new FieldTypes.Int(),
+ };
+ })(),
+ };
};
};
-};
describe("derived-value", () => {
it("properly reacts to pre:create handler", async () =>
withRunningApp(
extend({
fields: ["username", "surname"],
deriving_fn: async (username: string, surname: string) =>
`${username} ${surname}`,
}),
async ({ rest_api }) => {
const person = await rest_api.post(
"/api/v1/collections/people",
{
username: "Jan",
surname: "Kowalski",
}
);
assert.deepStrictEqual(person.name_and_surname, "Jan Kowalski");
}
));
it("properly reacts to pre:edit handler", async () =>
withRunningApp(
extend({
fields: ["username", "surname"],
deriving_fn: async (username: string, surname: string) =>
`${username} ${surname}`,
}),
async ({ rest_api }) => {
const person = await rest_api.post(
"/api/v1/collections/people",
{
username: "Jan",
surname: "Kowalski",
}
);
assert.deepStrictEqual("Jan Kowalski", person.name_and_surname);
const {
items: [updated_person],
} = await rest_api.patch(
`/api/v1/collections/people/${person.id}`,
{
username: "Janusz",
}
);
assert.deepStrictEqual(updated_person.username, "Janusz");
assert.deepStrictEqual(
updated_person.name_and_surname,
"Janusz Kowalski"
);
const {
items: [updated_person2],
} = await rest_api.patch(
`/api/v1/collections/people/${person.id}`,
{
username: "John",
surname: "Doe",
}
);
assert.deepStrictEqual(updated_person2.username, "John");
assert.deepStrictEqual(updated_person2.surname, "Doe");
assert.deepStrictEqual(
updated_person2.name_and_surname,
"John Doe"
);
}
));
it("value isn't undefined after edit on fields other than the ones concerning derived_value", async () =>
withRunningApp(
extend({
fields: ["username", "surname"],
deriving_fn: async (username: string, surname: string) =>
`${username} ${surname}`,
}),
async ({ rest_api }) => {
const person = await rest_api.post(
"/api/v1/collections/people",
{
username: "Jan",
surname: "Kowalski",
age: 60,
}
);
assert.deepStrictEqual(60, person.age);
const {
items: [updated_person],
} = await rest_api.patch(
`/api/v1/collections/people/${person.id}`,
{
age: 22,
}
);
assert.deepStrictEqual(updated_person.age, 22);
assert.deepStrictEqual(
updated_person.name_and_surname,
"Jan Kowalski"
);
}
));
it("throws when the value returned from deriving_fn is unnacceptable by target_field_type of derived-value", async () => {
const str = 555;
- withRunningApp(
+ await withRunningApp(
extend<FieldTypes.Int>({
fields: ["username", "surname"],
deriving_fn: async (_: string, __: string) => str,
}),
async ({ app, rest_api }) => {
await assertThrowsAsync(
async () => {
await rest_api.post("/api/v1/collections/people", {
username: "Jan",
surname: "Kowalski",
});
},
(error) => {
assert.deepStrictEqual(
error.response.data.data.field_messages
.name_and_surname.message,
app.i18n("invalid_text", [str, typeof str])
);
}
);
}
);
it("should init the base field with the given app", () =>
withRunningApp(
- (app_class: TestAppType) => {
+ (app_class: TestAppConstructor) => {
return class extends app_class {
collections = {
- ...app_class.BaseCollections,
+ ...TestApp.BaseCollections,
A: new (class extends Collection {
fields = {
simple: new FieldTypes.Text(),
derived: new FieldTypes.DerivedValue(
new FieldTypes.SingleReference("A"),
{
fields: ["simple"],
deriving_fn: async (simple) => {
return "any_id"; // this isn't a proper ID, and the SingleReference should detect that by being able to access the `this.app` instance and reading the database. If any other error than "bad id" will be thrown, it means that the base field is not initiated properly
},
}
),
};
})(),
};
};
},
async ({ app }) => {
await assertThrowsAsync(
() =>
app.collections.A.create(new app.SuperContext(), {
simple: "anything",
}),
(error) =>
assert.strictEqual(error.message, "Invalid values!")
);
}
));
});
it("avoids a race condition when there is a derived field and a before:edit listener on the collection", () =>
withRunningApp(
(test_class) =>
class extends test_class {
collections = {
- ...test_class.BaseCollections,
+ ...TestApp.BaseCollections,
products: new (class Products extends Collection {
fields: Record<string, Field> = {
name: new FieldTypes.Text(),
category: new FieldTypes.DerivedValue(
new FieldTypes.Text(),
{
fields: ["name"],
deriving_fn: async (name: string) => {
await sleep(0);
return `${name} after sleep`;
},
}
),
};
async init(app: App, name: string): Promise<void> {
await super.init(app, name);
this.on(
"before:edit",
async ([context, product]) => {
await product.decode(context);
product.get("name");
await sleep(100);
product.get("name"); // should throw an error "decode first" if there's a race condition
}
);
}
})(),
};
},
async ({ app }) => {
const product = await app.collections.products.create(
new app.SuperContext(),
{ name: "aaa" }
);
product.setMultiple({ name: "bbb" });
await product.save(new app.SuperContext());
}
));
});
diff --git a/src/app/base-chips/field-types/derived-value.ts b/src/app/base-chips/field-types/derived-value.ts
index b90e2cfd..6733529e 100644
--- a/src/app/base-chips/field-types/derived-value.ts
+++ b/src/app/base-chips/field-types/derived-value.ts
@@ -1,103 +1,104 @@
-import { HybridField, Field, ExtractOutput, App } from "../../../main";
+import type { Field, ExtractOutput, App } from "../../../main";
+import { HybridField } from "../../../chip-types/field";
/*
todo: make the deriving_fn more type-safe by reading the types of the fields?
*/
export type DerivingFn<T extends Field> = (
...args: any[]
) => Promise<ExtractOutput<T>>;
export default class DerivedValue<T extends Field> extends HybridField<T> {
typeName = "derived-value";
fields: string[];
deriving_fn: DerivingFn<T>;
constructor(
base_field: T,
params: {
fields: string[];
deriving_fn: DerivingFn<T>;
}
) {
super(base_field);
if (typeof params.deriving_fn !== "function") {
throw new Error(
"Error: 'deriving_fn' param in name_and_surname derived-value field is not a function."
);
}
super.setParams(params);
this.fields = params.fields;
this.deriving_fn = params.deriving_fn;
if (typeof this.deriving_fn !== "function") {
throw new Error(
`'derived_fn' param in ${this.name} derived-value field is not a function.`
);
}
if (!Array.isArray(this.fields)) {
throw new Error(
`'fields' param in ${this.name} derived-value field is not an array.`
);
}
}
async init(app: App) {
super.init(app);
const not_matching_fields = this.fields.filter(
(field) => !Object.keys(this.collection.fields).includes(field)
);
if (not_matching_fields.length) {
throw new Error(
`Missing declaration for fields from derived-value params: ${not_matching_fields
.map((field) => `'${field}'`)
.join(", ")} in ${
this.collection.name
} collection. REMEMBER: 'derived-value' field must be declared *after* the fields it depends on.`
);
}
this.collection.on("before:create", async ([context, item]) => {
context.app.Logger.debug2(
"FIELD.DERIVED VALUE",
"Before:create handler"
);
const derived_fn_args = this.fields.map((field_name) => {
const value = item.body.getInput(field_name);
return value === undefined || value === null ? "" : value;
});
context.app.Logger.debug3(
"FIELD.DERIVED VALUE",
"Passing to derived_fn:",
derived_fn_args
);
const derived_value = await this.deriving_fn(...derived_fn_args);
item.set(this.name, derived_value);
});
this.collection.on("before:edit", async ([context, item]) => {
if (
!this.fields.some((field) =>
item.body.changed_fields.has(field)
)
) {
return;
}
context.app.Logger.debug("DERIVED VALUE", "Handling before:edit", {
item_body: item.body,
});
await item.decode(context);
const derived_fn_args = this.fields.map((field_name) =>
item.get(field_name, true)
);
const derived_value = await this.deriving_fn(...derived_fn_args);
context.app.Logger.debug2("DERIVED VALUE", "Setting new value", {
[this.name]: derived_value,
});
item.set(this.name, derived_value);
});
}
}
diff --git a/src/app/base-chips/field-types/disallow-update.subtest.ts b/src/app/base-chips/field-types/disallow-update.subtest.ts
index a8fb2b4e..6e993ade 100644
--- a/src/app/base-chips/field-types/disallow-update.subtest.ts
+++ b/src/app/base-chips/field-types/disallow-update.subtest.ts
@@ -1,108 +1,111 @@
import {
Field,
Context,
Collection,
FieldTypes,
Policies,
} from "../../../main";
import assert from "assert";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
import { assertThrowsAsync } from "../../../test_utils/assert-throws-async";
-import { TestAppType } from "../../../test_utils/test-app";
+import { TestApp } from "../../../test_utils/test-app";
const url = "/api/v1/collections/constseals";
class NullOrFive extends Field {
typeName = "null-or-five";
async isProperValue(_: Context, new_value: any, __: any) {
if (new_value === null || new_value === 5) {
return Field.valid();
}
return Field.invalid("Null or five, you got it?");
}
}
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
constseals: new (class extends Collection {
fields = {
age: new FieldTypes.DisallowUpdate(
new FieldTypes.Int({ min: 0 })
),
attribute: new FieldTypes.DisallowUpdate(new NullOrFive()),
};
defaultPolicy = new Policies.Public();
})(),
};
};
}
describe("disallow-update", () => {
it("Respects target field type", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
const age = "abc";
await assertThrowsAsync(
() => rest_api.post(url, { age: "abc", attribute: 5 }),
(error) => {
assert.deepStrictEqual(
error.response.data.data.field_messages.age.message,
app.i18n("invalid_integer", [age])
);
}
);
}));
it("Respects target field params", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
const age = -2;
await assertThrowsAsync(
() => rest_api.post(url, { age: age }),
(error) =>
assert.deepEqual(
error.response.data.data.field_messages.age.message,
app.i18n("too_small_integer", [age, 0])
)
);
}));
it("Initially allows to insert a value", () =>
withRunningApp(extend, async ({ rest_api }) => {
await rest_api.post(url, { age: 2, attribute: 5 });
}));
it("Rejects a new value if there's an old value", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
const { id } = await rest_api.post(url, {
age: 18,
attribute: null,
});
await assertThrowsAsync(
() => rest_api.patch(`${url}/${id}`, { age: 21 }),
(error) =>
assert.deepEqual(
error.response.data.data.field_messages.age.message,
app.i18n("invalid_update")
)
);
}));
it("Rejects a new value if the old value is `null`", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
const { id } = await rest_api.post(url, {
age: 21,
attribute: null,
});
await assertThrowsAsync(
() => rest_api.patch(`${url}/${id}`, { attribute: 5 }),
(error) =>
assert.deepEqual(
error.response.data.data.field_messages.attribute
.message,
app.i18n("invalid_update")
)
);
}));
});
diff --git a/src/app/base-chips/field-types/disallow-update.ts b/src/app/base-chips/field-types/disallow-update.ts
index 141889cb..6b6c14d4 100644
--- a/src/app/base-chips/field-types/disallow-update.ts
+++ b/src/app/base-chips/field-types/disallow-update.ts
@@ -1,24 +1,25 @@
-import { HybridField, Field, Context, SuperContext } from "../../../main";
+import { Field, Context } from "../../../main";
+import { HybridField } from "../../../chip-types/field";
export default class DisallowUpdate<T extends Field> extends HybridField<T> {
typeName = "disallow-update";
async isProperValue(
context: Context,
new_value: Parameters<T["checkValue"]>[1],
old_value?: Parameters<T["checkValue"]>[2]
) {
context.app.Logger.debug3(
"DISALLOW-UPDATE",
"Checking if this field already has a value",
{ new_value, old_value }
);
if (old_value === undefined) {
return this.virtual_field.checkValue(
new context.app.SuperContext(),
new_value,
old_value
);
}
return Field.invalid(context.app.i18n("invalid_update"));
}
}
diff --git a/src/app/base-chips/field-types/file.ts b/src/app/base-chips/field-types/file.ts
index 27e59a0a..c8342905 100644
--- a/src/app/base-chips/field-types/file.ts
+++ b/src/app/base-chips/field-types/file.ts
@@ -1,52 +1,49 @@
import { Field, Context, File } from "../../../main";
-import { FileDBEntry } from "../../../data-structures/file";
-
-type FileOutput = string | File;
-type FileFormat = "internal" | "url";
+import type { FileDBEntry } from "../../../data-structures/file";
export type FileStorageFormat = FileDBEntry;
export abstract class FileStorage extends Field {
handles_large_data = true;
get_default_file: (context: Context) => Promise<File>;
async isProperValue(context: Context, value: File) {
if (typeof value === "string") {
return Field.valid();
}
if (value === null || value instanceof File) {
return Field.valid();
}
return Field.invalid(context.app.i18n("invalid_file_storage"));
}
setParams(params: {
get_default_file: (context: Context) => Promise<File>;
}) {
this.get_default_file = params.get_default_file;
}
async encode(_: Context, file: File) {
if (file === null) {
return null;
}
await file.save();
return file.toDBEntry();
}
}
/** Takes a {@File} instance as input, stores it in the FS and then decodes to a URL.
*
* **Params**:
* - `get_default_file` - ()=>Promise<{@link File}> - if no file is provided, then this file will be used in it's stead
*/
export default class FileField extends FileStorage {
typeName = "file";
async decode(_: Context, db_value: FileStorageFormat | null, __: any) {
if (db_value === null) {
return null;
}
const file = await File.fromID(this.app, db_value.id);
return file.getURL();
}
}
diff --git a/src/app/base-chips/field-types/float.ts b/src/app/base-chips/field-types/float.ts
index 3c95ea87..d42b1299 100644
--- a/src/app/base-chips/field-types/float.ts
+++ b/src/app/base-chips/field-types/float.ts
@@ -1,58 +1,58 @@
-import { ValidationResult } from "../../../chip-types/field";
+import type { ValidationResult } from "../../../chip-types/field";
import { Context, Errors, Field } from "../../../main";
import humanComparatorToQuery, {
ComparatorObject,
DBComparator,
HumanComparator,
} from "../../../utils/human-comparator-to-query";
/** Stores a floating point number. DOes not take params. Does not allow range filtering. @todo: add range filtering */
export default class Float extends Field {
typeName = "float";
async isProperValue(
context: Context,
input: number
): Promise<ValidationResult> {
const test = parseFloat(input.toString());
if (test === null || isNaN(test) || isNaN(input) === true) {
return Field.invalid(context.app.i18n("invalid_float", [input]));
} else {
return Field.valid();
}
}
async filterToQuery(
_: Context,
field_filter: number | string | ComparatorObject<number>
) {
if (typeof field_filter !== "object") {
return {
$eq: parseFloat(field_filter.toString()),
};
}
// treating filter as a query here
const new_filter: { [db_comp in DBComparator]?: number } = {};
for (const comparator in field_filter) {
const new_comparator = humanComparatorToQuery(
comparator as HumanComparator
);
if (new_comparator === undefined) {
throw new Errors.ValidationError(
`Unknown comparator: '${comparator}'.`
);
}
new_filter[new_comparator] = parseFloat(
field_filter[comparator as HumanComparator].toString()
);
}
return new_filter;
}
async encode(_: any, value: number | string) {
if (value === null) {
return null;
}
const parsed_float = parseFloat(value.toString());
return parsed_float;
}
}
diff --git a/src/app/base-chips/field-types/int.subtest.ts b/src/app/base-chips/field-types/int.subtest.ts
index 0a7cf23a..3eb190c3 100644
--- a/src/app/base-chips/field-types/int.subtest.ts
+++ b/src/app/base-chips/field-types/int.subtest.ts
@@ -1,168 +1,171 @@
import Axios from "axios";
import { equal, deepEqual } from "assert";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
import { assertThrowsAsync } from "../../../test_utils/assert-throws-async";
-import { IntStorageParams } from "./int";
+import type { IntStorageParams } from "./int";
import { Collection, FieldTypes } from "../../../main";
-import { TestAppType } from "../../../test_utils/test-app";
+import { TestApp } from "../../../test_utils/test-app";
describe("int", () => {
const COLLECTION_NAME = "ages";
- const extend = (params?: IntStorageParams) => (t: TestAppType) => {
+ const extend = (params?: IntStorageParams) => (t: TestAppConstructor) => {
const col = new (class extends Collection {
name = COLLECTION_NAME;
fields = {
age: new FieldTypes.Int(params || {}),
};
})();
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
[COLLECTION_NAME]: col,
};
};
};
function assertFormatIsNotAccepted(provided_value: any) {
return withRunningApp(extend(), async ({ app, base_url }) => {
await assertThrowsAsync(
() =>
Axios.post(
`${base_url}/api/v1/collections/${COLLECTION_NAME}`,
{
age: provided_value,
}
),
(e) => {
equal(
e.response.data.data.field_messages.age.message,
app.i18n("invalid_integer", [provided_value])
);
}
);
});
}
it("should allow an integer value", async () =>
withRunningApp(extend(), async ({ base_url }) => {
const { data: response } = await Axios.post(
`${base_url}/api/v1/collections/${COLLECTION_NAME}`,
{
age: 10,
}
);
equal(response.age, 10);
}));
it("should allow a string which can be interpreted as an integer value", async () =>
withRunningApp(extend(), async ({ base_url }) => {
const { data: response } = await Axios.post(
`${base_url}/api/v1/collections/${COLLECTION_NAME}`,
{
age: "1",
}
);
equal(response.age, 1);
}));
it("should respect given min and max value", async () => {
const min = 30;
const max = 50;
- withRunningApp(
+ await withRunningApp(
extend({ min: min, max: max }),
async ({ app, base_url }) => {
let age = 29;
await assertThrowsAsync(
() =>
Axios.post(
`${base_url}/api/v1/collections/${COLLECTION_NAME}`,
{
age: age,
}
),
(e) => {
equal(
- e.response.data.data.age.message,
+ e.response?.data?.data?.field_messages.age.message,
app.i18n("too_small_integer", [age, min])
);
}
);
age = 51;
await assertThrowsAsync(
() =>
Axios.post(
`${base_url}/api/v1/collections/${COLLECTION_NAME}`,
{
age: age,
}
),
(e) => {
equal(
- e.response.data.data.age.message,
+ e.response?.data?.data?.field_messages.age.message,
app.i18n("too_big_integer", [age, max])
);
}
);
}
);
});
it("should let proper a string as an integer value in the defined range", async () =>
withRunningApp(extend({ min: -2, max: 6 }), async ({ base_url }) => {
return Axios.post(
`${base_url}/api/v1/collections/${COLLECTION_NAME}`,
{
age: "-1",
}
).then((response) => deepEqual(response.status, 201));
}));
it("should allow a largest integer value", async () =>
withRunningApp(extend(), async ({ base_url }) => {
const { data: response } = await Axios.post(
`${base_url}/api/v1/collections/${COLLECTION_NAME}`,
{
age: Number.MAX_SAFE_INTEGER,
}
);
equal(response.age, Number.MAX_SAFE_INTEGER);
}));
it("should allow a smallest integer value provided as a string value", async () =>
withRunningApp(extend(), async ({ base_url }) => {
const { data: response } = await Axios.post(
`${base_url}/api/v1/collections/${COLLECTION_NAME}`,
{
age: Number.MIN_SAFE_INTEGER.toString(),
}
);
equal(response.age, Number.MIN_SAFE_INTEGER);
}));
it("should allow a string with whitespace characters which can be interpreted as an integer value", async () =>
withRunningApp(extend(), async ({ base_url }) => {
const { data: response } = await Axios.post(
`${base_url}/api/v1/collections/${COLLECTION_NAME}`,
{
age: " -20 ",
}
);
equal(response.age, -20);
}));
it("shouldn't allow a boolean value", async () =>
await assertFormatIsNotAccepted(true));
it("shouldn't allow an object value", async () =>
await assertFormatIsNotAccepted({}));
it("shouldn't allow a string which cannot be interpreted as an integer value", async () =>
await assertFormatIsNotAccepted("2013ffff"));
it("shouldn't allow a float number which cannot be interpreted as an integer value", async () =>
await assertFormatIsNotAccepted(1.2));
it("shouldn't allow a float number inserted as a string which cannot be interpreted as an integer value", async () =>
await assertFormatIsNotAccepted("1.2"));
});
diff --git a/src/app/base-chips/field-types/json-object.subtest.ts b/src/app/base-chips/field-types/json-object.subtest.ts
index 495909d8..a61430ba 100644
--- a/src/app/base-chips/field-types/json-object.subtest.ts
+++ b/src/app/base-chips/field-types/json-object.subtest.ts
@@ -1,137 +1,140 @@
import assert from "assert";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
import { assertThrowsAsync } from "../../../test_utils/assert-throws-async";
import { Collection, FieldTypes } from "../../../main";
-import { TestAppType } from "../../../test_utils/test-app";
+import { TestApp } from "../../../test_utils/test-app";
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
seals: new (class extends Collection {
fields = {
name: new FieldTypes.Text(),
metadata: new FieldTypes.JsonObject(),
};
})(),
};
};
}
describe("json-object", () => {
it("Correctly adds and edits record with json field", async () =>
withRunningApp(extend, async ({ rest_api }) => {
const item = {
name: "Hoover",
metadata: {
gender: "male",
weight: 300,
},
};
const { id } = await rest_api.post(
"/api/v1/collections/seals",
item
);
let {
items: [{ name, metadata }],
} = (await rest_api.get(`/api/v1/collections/seals/${id}`)) as any;
assert.deepEqual({ name, metadata }, item);
item.metadata.weight = 320;
await rest_api.patch(`/api/v1/collections/seals/${id}`, item);
let {
items: [{ name: name2, metadata: metadata2 }],
} = (await rest_api.get(`/api/v1/collections/seals/${id}`)) as any;
assert.deepEqual({ name: name2, metadata: metadata2 }, item);
}));
it("Doesn't allow to post a primitive", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await assertThrowsAsync(
() =>
rest_api.post("/api/v1/collections/seals", {
name: "Hoover",
metadata: "atadatem",
}),
(e) =>
assert.equal(
e.response.data.data.field_messages.metadata.message,
app.i18n("invalid_json_object")
)
);
}));
it("Respects filter passed to query", async () =>
withRunningApp(extend, async ({ rest_api }) => {
await rest_api.post("/api/v1/collections/seals", {
name: "Hoover",
metadata: {
gender: "male",
weight: 300,
},
});
await rest_api.post("/api/v1/collections/seals", {
name: "Maksiu",
metadata: {
gender: "male",
weight: 280,
},
});
let seals = (await rest_api.get("/api/v1/collections/seals")).items;
assert.equal(seals.length, 2);
seals = (
await rest_api.get(
"/api/v1/collections/seals?filter[name]=Hoover"
)
).items;
assert.equal(seals[0].name, "Hoover");
seals = (
await rest_api.get(
"/api/v1/collections/seals?filter[metadata][weight]=280"
)
).items;
assert.equal(seals.length, 1);
assert.equal(seals[0].name, "Maksiu");
}));
it("Respects filter passed to query when value can be parsed as number", async () =>
withRunningApp(extend, async ({ rest_api }) => {
const seals = [
{
name: "Hoover",
metadata: {
gender: "male",
weight: "300.253",
},
},
{
name: "Maksiu",
metadata: {
gender: "male",
weight: "280",
},
},
];
for (let seal of seals) {
await rest_api.post("/api/v1/collections/seals", seal);
}
for (let seal of seals) {
let { items: actual_seals } = await rest_api.get(
`/api/v1/collections/seals?filter[metadata][weight]=${seal.metadata.weight}`
);
assert.equal(actual_seals.length, 1);
assert.equal(actual_seals[0].name, seal.name);
}
}));
});
diff --git a/src/app/base-chips/field-types/password.subtest.ts b/src/app/base-chips/field-types/password.subtest.ts
index 081ccf38..43e61f18 100644
--- a/src/app/base-chips/field-types/password.subtest.ts
+++ b/src/app/base-chips/field-types/password.subtest.ts
@@ -1,61 +1,61 @@
import assert from "assert";
import { withRunningApp } from "../../../test_utils/with-test-app";
import SecureHasher from "../../../utils/secure-hasher";
-import App from "../../app";
+import type App from "../../app";
describe("password", () => {
const password = "it-really-doesnt-matter";
const username = "some-user";
let user_id: string;
async function setup(app: App) {
user_id = (
await app.collections.users.suCreate({
username,
password,
})
).id;
}
it("Hides password", async () =>
withRunningApp(null, async ({ app, rest_api }) => {
await setup(app);
const session = await rest_api.login({
username,
password,
});
assert.ok(
!(
await rest_api.get(
`/api/v1/collections/users/${user_id}`,
session
)
).password
);
assert.equal(
(await app.collections.users.suGetByID(user_id)).get(
"password"
),
"secret"
);
}));
it("Stores correct password value", async () =>
withRunningApp(null, async ({ app }) => {
await setup(app);
const hashed_password = (
await app.Datastore.find("users", {
id: user_id,
})
)[0].password as string;
assert.ok(await SecureHasher.matches(password, hashed_password));
assert.ok(
!(await SecureHasher.matches("wrong-password", hashed_password))
);
assert.ok(!(await SecureHasher.matches("", hashed_password)));
}));
});
diff --git a/src/app/base-chips/field-types/required.ts b/src/app/base-chips/field-types/required.ts
index 4db968fc..b369199f 100644
--- a/src/app/base-chips/field-types/required.ts
+++ b/src/app/base-chips/field-types/required.ts
@@ -1,6 +1,6 @@
-import { Field } from "../../../main";
+import type { Field, RequiredField } from "../../../main";
-export default function Required(T: Field) {
+export default function Required(T: Field): RequiredField {
T.setRequired(true);
- return T;
+ return T as RequiredField;
}
diff --git a/src/app/base-chips/field-types/reverse-single-reference.subtest.ts b/src/app/base-chips/field-types/reverse-single-reference.subtest.ts
index 47712f7f..05d897d5 100644
--- a/src/app/base-chips/field-types/reverse-single-reference.subtest.ts
+++ b/src/app/base-chips/field-types/reverse-single-reference.subtest.ts
@@ -1,319 +1,325 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import assert from "assert";
import Bluebird from "bluebird";
import {
App,
Collection,
Collections,
Field,
FieldTypes,
Policies,
} from "../../../main";
-import { CollectionResponse } from "../../../test_utils/rest-api";
-import { TestAppType } from "../../../test_utils/test-app";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import type { CollectionResponse } from "../../../test_utils/rest-api";
+import { TestApp } from "../../../test_utils/test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
const extend = (with_reverse = true, clear_database = true) =>
- function (t: TestAppType) {
+ function (t: TestAppConstructor) {
const b_fields: { [name: string]: Field } = {
number: new FieldTypes.Int(),
};
if (with_reverse) {
b_fields.references_in_a = new FieldTypes.ReverseSingleReference({
referencing_collection: "A",
referencing_field: "reference_to_b",
});
}
return class extends t {
clear_database_on_stop = clear_database;
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
A: new (class extends Collection {
fields = {
reference_to_b: new FieldTypes.SingleReference("B"),
pairity: new FieldTypes.Text(),
};
})(),
B: new (class extends Collection {
fields = b_fields;
})(),
};
};
};
describe("reverse-single-reference", () => {
async function createResources(app: App) {
const numbers = [1, 2, 3];
const bs = await Bluebird.map(numbers, (number) =>
app.collections.B.suCreate({
number,
})
);
for (const b of bs) {
for (let i = 1; i <= (b.get("number") as number); i++) {
await app.collections.A.suCreate({
reference_to_b: b.id,
pairity: i % 2 ? "odd" : "even",
});
}
}
}
it("recreates the cached values if the field has just been added", async () => {
await withRunningApp(
extend(false, false),
async ({ app }) => {
await createResources(app);
},
"cache-recreate"
);
await withRunningApp(
extend(true),
async ({ rest_api }) => {
const {
items: [result],
} = (await rest_api.get(
"/api/v1/collections/B?filter[number]=1"
)) as CollectionResponse<{ references_in_a: string }>;
assert.ok(result.references_in_a);
assert.strictEqual(result.references_in_a.length, 1);
const {
items: [result2],
} = (await rest_api.get(
"/api/v1/collections/B?filter[number]=2"
)) as CollectionResponse<{ references_in_a: string }>;
assert(result2.references_in_a);
assert.strictEqual(result2.references_in_a.length, 2);
},
"cache-recreate"
);
});
it("updates the cached value when a new reference is created", async () => {
await withRunningApp(extend(true), async ({ app, rest_api }) => {
await createResources(app);
const {
items: [result],
} = (await rest_api.get(
"/api/v1/collections/B?filter[number]=2"
)) as CollectionResponse;
assert(result.references_in_a instanceof Array);
assert.strictEqual(result.references_in_a.length, 2);
});
});
it("updates the cached value when an old reference is deleted", async () =>
withRunningApp(extend(true), async ({ app, rest_api }) => {
await createResources(app);
const { items } = (await rest_api.get(
"/api/v1/collections/B?filter[number]=2"
)) as CollectionResponse<{ references_in_a: string }>;
const referencing_id = items[0].references_in_a[0];
await rest_api.delete(`/api/v1/collections/A/${referencing_id}`);
const {
items: [new_result2],
} = (await rest_api.get(
"/api/v1/collections/B?filter[number]=2"
)) as CollectionResponse<{ references_in_a: string }>;
assert.strictEqual(new_result2.references_in_a.length, 1);
}));
it("updates the cached value when an old reference is edited to a new one", async () =>
withRunningApp(extend(true), async ({ rest_api, app }) => {
await createResources(app);
const {
items: [result1],
} = (await rest_api.get(
"/api/v1/collections/B?filter[number]=1"
)) as CollectionResponse;
const {
items: [result2],
} = (await rest_api.get(
"/api/v1/collections/B?filter[number]=2"
)) as CollectionResponse<{ references_in_a: string }>;
const referencing_id = result2.references_in_a[0];
await rest_api.patch(`/api/v1/collections/A/${referencing_id}`, {
reference_to_b: result1.id,
});
const {
items: [new_result2],
} = (await rest_api.get(
"/api/v1/collections/B?filter[number]=2"
)) as CollectionResponse<{ references_in_a: string }>;
assert.strictEqual(new_result2.references_in_a.length, 1);
const {
items: [new_result1],
} = (await rest_api.get(
"/api/v1/collections/B?filter[number]=1"
)) as CollectionResponse<{ references_in_a: string }>;
assert.strictEqual(new_result1.references_in_a.length, 2);
}));
it("updates the cached value when an old reference is edited to an empty one", async () =>
withRunningApp(extend(true), async ({ rest_api, app }) => {
await createResources(app);
await rest_api.get("/api/v1/collections/B?filter[number]=1");
const {
items: [result2],
} = (await rest_api.get(
"/api/v1/collections/B?filter[number]=2"
)) as CollectionResponse<{ references_in_a: string }>;
const referencing_id = result2.references_in_a[0];
await rest_api.patch(`/api/v1/collections/A/${referencing_id}`, {
reference_to_b: "",
});
const {
items: [new_result2],
} = (await rest_api.get(
"/api/v1/collections/B?filter[number]=2"
)) as CollectionResponse<{ references_in_a: string }>;
assert.strictEqual(new_result2.references_in_a.length, 1);
}));
it("allows to filter by a value of the referencing resource", async () =>
withRunningApp(extend(true), async ({ rest_api, app }) => {
await createResources(app);
let { items: results } = (await rest_api.get(
"/api/v1/collections/B?filter[references_in_a][pairity]=non-existant"
)) as CollectionResponse;
assert.strictEqual(results.length, 0);
- results = ((await rest_api.get(
- "/api/v1/collections/B?filter[references_in_a][pairity]=odd"
- )) as CollectionResponse).items;
+ results = (
+ (await rest_api.get(
+ "/api/v1/collections/B?filter[references_in_a][pairity]=odd"
+ )) as CollectionResponse
+ ).items;
assert.strictEqual(results.length, 3);
- results = ((await rest_api.get(
- "/api/v1/collections/B?filter[references_in_a][pairity]=even&filter[number]=3"
- )) as CollectionResponse).items;
+ results = (
+ (await rest_api.get(
+ "/api/v1/collections/B?filter[references_in_a][pairity]=even&filter[number]=3"
+ )) as CollectionResponse
+ ).items;
assert.strictEqual(results.length, 1);
}));
it("allows to display the full body of the referencing resources", async () =>
withRunningApp(extend(true), async ({ rest_api, app }) => {
await createResources(app);
const { items, attachments } = (await rest_api.get(
"/api/v1/collections/B?attachments[references_in_a]=true"
)) as CollectionResponse<{ references_in_a: string }>;
const referenced_id = items[0].references_in_a[0];
assert.strictEqual(attachments[referenced_id].pairity, "odd");
}));
it("handles nested attachments", async () =>
withRunningApp(
- (test_app) =>
+ (test_app: TestAppConstructor) =>
class extends test_app {
collections = {
- ...App.BaseCollections,
+ ...TestApp.BaseCollections,
organizations: new (class extends Collection {
fields = {
name: FieldTypes.Required(
new FieldTypes.Text({
full_text_search: true,
min_length: 2,
max_length: 16,
})
),
};
})(),
"user-organization": new (class extends Collection {
fields = {
organization: FieldTypes.Required(
new FieldTypes.SingleReference(
"organizations"
)
),
user: FieldTypes.Required(
new FieldTypes.SingleReference("users")
),
};
})(),
users: new (class extends Collections.users {
fields = {
...App.BaseCollections.users.fields,
description: new FieldTypes.Text(),
- organizations: new FieldTypes.ReverseSingleReference(
- {
+ organizations:
+ new FieldTypes.ReverseSingleReference({
referencing_collection:
"user-organization",
referencing_field: "user",
- }
- ),
+ }),
};
policies = {
create: new Policies.Public(),
show: new Policies.Public(),
};
defaultPolicy = new Policies.Public();
})(),
};
},
async ({ app, rest_api }) => {
const user = await rest_api.post("/api/v1/collections/users", {
username: "user1",
password: "user1user1",
email: "user1@example.com",
});
const org = await rest_api.post(
"/api/v1/collections/organizations",
{
name: "org",
}
);
await rest_api.post("/api/v1/collections/user-organization", {
user: user.id,
organization: org.id,
});
const response = await rest_api.get(
"/api/v1/collections/users?attachments[organizations][organization]=true"
);
const rel_id = response.items[0].organizations[0];
const org_id = response.attachments[rel_id].organization;
assert.strictEqual(
response?.attachments?.[org_id]?.name,
"org"
);
const db_response = await app.collections.users
.suList()
- .attach(({
+ .attach({
organizations: { organization: true },
- } as unknown) as any)
+ } as unknown as any)
.fetch();
assert.strictEqual(
db_response.items[0]
.getAttachments(
/* @ts-ignore */
"organizations"
)[0]
.getAttachments("organization")[0]
.get("name"),
"org"
);
const user2 = await rest_api.post("/api/v1/collections/users", {
username: "user2",
password: "user2user2",
email: "user2@example.com",
});
const db_response2 = await app.collections.users
.suList()
.ids([user2.id])
- .attach(({
+ .attach({
organizations: { organization: true },
- } as unknown) as any)
+ } as unknown as any)
.fetch();
assert.deepStrictEqual(
db_response2.items[0].getAttachments(
/* @ts-ignore */
"organizations"
),
[]
);
}
));
});
diff --git a/src/app/base-chips/field-types/settable-by.subtest.ts b/src/app/base-chips/field-types/settable-by.subtest.ts
index 7bd7c3c0..9b1c5f0d 100644
--- a/src/app/base-chips/field-types/settable-by.subtest.ts
+++ b/src/app/base-chips/field-types/settable-by.subtest.ts
@@ -1,90 +1,93 @@
import assert from "assert";
import axios from "axios";
import { assertThrowsAsync } from "../../../test_utils/assert-throws-async";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
import { Collection, FieldTypes, Policies } from "../../../main";
-import { TestAppType } from "../../../test_utils/test-app";
+import { TestApp } from "../../../test_utils/test-app";
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
"forbidden-collection": new (class extends Collection {
fields = {
any: new FieldTypes.SettableBy(
new FieldTypes.Int(),
new Policies.Noone()
),
};
})(),
"allowed-collection": new (class extends Collection {
fields = {
any: new FieldTypes.SettableBy(
new FieldTypes.Int(),
new Policies.Public()
),
};
})(),
};
};
}
-describe("settable-by", async () => {
+describe("settable-by", () => {
it("should not allow any value when rejected by access strategy", async () =>
withRunningApp(extend, async ({ app, base_url }) => {
await assertThrowsAsync(
() =>
axios.post(
`${base_url}/api/v1/collections/forbidden-collection`,
{
any: "thing",
}
),
(e) =>
assert.equal(
e.response.data.data.field_messages.any.message,
app.i18n("policy_noone_deny")
)
);
}));
it("should allow proper value when accepted by access strategy", async () =>
withRunningApp(extend, async ({ base_url, rest_api }) => {
const response = (
await axios.post(
`${base_url}/api/v1/collections/allowed-collection`,
{
any: 1,
}
)
).data;
assert.equal(response.any, 1);
const {
items: [created_item],
} = await rest_api.get(
`/api/v1/collections/allowed-collection/${response.id}`
);
assert.equal(created_item.any, 1);
}));
it("should not allow invalid value when access strategy allows", async () =>
withRunningApp(extend, async ({ app, base_url }) => {
const value = "thing";
await assertThrowsAsync(
() =>
axios.post(
`${base_url}/api/v1/collections/allowed-collection`,
{
any: value,
}
),
(e) => {
assert.equal(
e.response.data.data.field_messages.any.message,
app.i18n("invalid_integer", [value])
);
}
);
}));
});
diff --git a/src/app/base-chips/field-types/settable-by.ts b/src/app/base-chips/field-types/settable-by.ts
index 7fa937f7..f2589dcd 100644
--- a/src/app/base-chips/field-types/settable-by.ts
+++ b/src/app/base-chips/field-types/settable-by.ts
@@ -1,25 +1,25 @@
import Field, { HybridField } from "../../../chip-types/field";
-import { Context } from "../../../main";
-import Policy from "../../../chip-types/policy";
+import type { Context } from "../../../main";
+import type Policy from "../../../chip-types/policy";
export default class SettableBy<T extends Field> extends HybridField<T> {
typeName = "settable-by";
policy: Policy;
constructor(base_field: T, policy: Policy) {
super(base_field);
this.policy = policy;
}
async isProperValue(
context: Context,
input: Parameters<T["encode"]>[1],
old_value: Parameters<T["encode"]>[2]
) {
const result = await this.policy.check(context);
if (result && !result.allowed) {
return Field.invalid(result.reason);
}
return this.virtual_field.checkValue(context, input, old_value);
}
}
diff --git a/src/app/base-chips/field-types/single-reference.subtest.ts b/src/app/base-chips/field-types/single-reference.subtest.ts
index 06e0741e..7380924c 100644
--- a/src/app/base-chips/field-types/single-reference.subtest.ts
+++ b/src/app/base-chips/field-types/single-reference.subtest.ts
@@ -1,463 +1,466 @@
import assert from "assert";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
import { assertThrowsAsync } from "../../../test_utils/assert-throws-async";
import { Collection, FieldTypes } from "../../../main";
-import { TestAppType } from "../../../test_utils/test-app";
-import { SerializedItemBody } from "../../../chip-types/collection-item";
-import MockRestApi from "../../../test_utils/rest-api";
+import type { SerializedItemBody } from "../../../chip-types/collection-item";
+import type MockRestApi from "../../../test_utils/rest-api";
+import { TestApp } from "../../../test_utils/test-app";
const A = "/api/v1/collections/A";
const B = "/api/v1/collections/B";
const C = "/api/v1/collections/C";
const Seals = "/api/v1/collections/seals";
const Water_Areas = "/api/v1/collections/water_areas";
const Water_Area_Types = "/api/v1/collections/water_area_types";
const Food = "/api/v1/collections/food";
describe("single_reference", () => {
describe("from A to B", () => {
- function extend(t: TestAppType) {
+ function extend(t: TestAppConstructor) {
const A = new (class extends Collection {
name = "A";
fields = {
reference_to_b: new FieldTypes.SingleReference("B"),
filtered_reference_to_b: new FieldTypes.SingleReference(
"B",
{ number: 1 }
),
};
})();
const B = new (class extends Collection {
name = "B";
fields = { number: new FieldTypes.Int() };
})();
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
A,
B,
};
};
}
it("should not allow a value that is not an existing id", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await assertThrowsAsync(
() =>
rest_api.post(A, {
reference_to_b: "non-existing-id",
}),
(e) =>
assert.equal(
e.response.data.data.field_messages.reference_to_b
.message,
app.i18n("invalid_single_reference", ["B"])
)
);
}));
it("should allow a value that exists in B", async () =>
withRunningApp(extend, async ({ rest_api }) => {
const { id } = await rest_api.post(B, { number: 1 });
await rest_api.post(A, {
reference_to_b: id,
});
}));
it("should not allow a value that exists in B but does not meet the filter criteria", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
const { id } = await rest_api.post(B, { number: 0 });
await assertThrowsAsync(
() =>
rest_api.post(A, {
filtered_reference_to_b: id,
}),
(e) =>
assert.equal(
e.response.data.data.field_messages
.filtered_reference_to_b.message,
app.i18n("invalid_single_reference", ["B"])
)
);
}));
it("should allow a value that exists in B and meets the filter criteria", async () =>
withRunningApp(extend, async ({ rest_api }) => {
const { id } = await rest_api.post(B, { number: 1 });
await rest_api.post(A, { filtered_reference_to_b: id });
}));
it("should be filterable by referenced collection fields", async () =>
withRunningApp(extend, async ({ rest_api }) => {
for (let number of [1, 2, 3]) {
const item = await rest_api.post(B, { number });
await rest_api.post(A, { reference_to_b: item.id });
}
const response = await rest_api.get(
`${A}?filter[reference_to_b][number]=3&attachments[reference_to_b]=true`
);
assert.equal(response.items.length, 1);
assert.equal(
response.attachments[response.items[0].reference_to_b]
.number,
3
);
}));
it("should be filterable by referenced collection field of referenced collection field", async () =>
withRunningApp(
(app_class) => {
// A => B => C
const A = new (class extends Collection {
name = "A";
fields = {
reference_to_b: new FieldTypes.SingleReference("B"),
};
})();
const B = new (class extends Collection {
name = "B";
fields = {
reference_to_c: new FieldTypes.SingleReference("C"),
};
})();
const C = new (class extends Collection {
name = "C";
fields = { number: new FieldTypes.Int() };
})();
return class extends app_class {
collections = {
- ...app_class.BaseCollections,
+ ...TestApp.BaseCollections,
A,
B,
C,
};
};
},
async ({ rest_api }) => {
let c_ids = [];
let b_ids = [];
for (let number of [1, 2, 3]) {
const { id } = await rest_api.post(
"/api/v1/collections/C",
{
number,
}
);
c_ids.push(id);
}
for (let c_id of c_ids) {
const { id } = await rest_api.post(
"/api/v1/collections/B",
{
reference_to_c: c_id,
}
);
b_ids.push(id);
}
for (let b_id of b_ids) {
await rest_api.post("/api/v1/collections/A", {
reference_to_b: b_id,
});
}
const response = await rest_api.get(
`/api/v1/collections/A?filter[reference_to_b][reference_to_c][number]=3&attachments[reference_to_b][reference_to_c]=true`
);
assert.equal(response.items.length, 1);
assert.equal(
response.attachments[
response.attachments[
response.items[0].reference_to_b
].reference_to_c
].number,
3
);
}
));
});
describe("from A to A", () => {
const items: { [name: string]: SerializedItemBody } = {};
- function extend(t: TestAppType) {
+ function extend(t: TestAppConstructor) {
const seals = new (class extends Collection {
name = "seals";
fields = {
name: new FieldTypes.Text(),
best_friend: new FieldTypes.SingleReference("seals"),
};
})();
return class extends t {
- collections = { ...t.BaseCollections, seals };
+ collections = { ...TestApp.BaseCollections, seals };
};
}
async function setup(rest_api: MockRestApi) {
items.hoover = await rest_api.post(Seals, {
name: "Hoover",
});
items.nelly = await rest_api.post(Seals, {
name: "Nelly",
best_friend: items.hoover.id,
});
items.maksiu = await rest_api.post(Seals, {
name: "Maksiu",
best_friend: items.nelly.id,
});
items.cycle = await rest_api.post(Seals, {
name: "Cycle",
});
await rest_api.patch(`${Seals}/${items.hoover.id}`, {
best_friend: items.maksiu.id,
});
await rest_api.patch(`${Seals}/${items.cycle.id}`, {
best_friend: items.cycle.id,
});
}
it("returns single attachment from a directly referenced collection", async () =>
withRunningApp(extend, async ({ rest_api }) => {
await setup(rest_api);
const {
items: [hoover, nelly, maksiu, cycle],
attachments,
} = await rest_api.get(
`${Seals}?attachments[best_friend]=true`
);
assert.equal(hoover.name, "Hoover");
assert.equal(nelly.name, "Nelly");
assert.equal(attachments[nelly.best_friend].name, "Hoover");
assert.equal(maksiu.name, "Maksiu");
assert.equal(attachments[maksiu.best_friend].name, "Nelly");
assert.equal(cycle.name, "Cycle");
assert.equal(attachments[cycle.best_friend].name, "Cycle");
}));
});
describe("attachments behaviour", () => {
const items: { [name: string]: SerializedItemBody } = {};
- function extend(t: TestAppType) {
+ function extend(t: TestAppConstructor) {
const seals = new (class extends Collection {
name = "seals";
fields = {
name: new FieldTypes.Text(),
water_area: new FieldTypes.SingleReference("water_areas"),
favourite_meal: new FieldTypes.SingleReference("food"),
};
})();
const water_areas = new (class extends Collection {
name = "water_areas";
fields = {
name: new FieldTypes.Text(),
type: new FieldTypes.SingleReference("water_area_types"),
};
})();
const water_area_types = new (class extends Collection {
name = "water_area_types";
fields = {
type_name: new FieldTypes.Text(),
how_good_for_seals: new FieldTypes.Text(),
};
})();
const food = new (class extends Collection {
name = "food";
fields = { food_name: new FieldTypes.Text() };
})();
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
seals,
water_areas,
water_area_types,
food,
};
};
}
async function setup(rest_api: MockRestApi) {
items.cool_sea = await rest_api.post(Water_Area_Types, {
type_name: "Cool Sea",
how_good_for_seals: "perfect",
});
items.warm_sea = await rest_api.post(Water_Area_Types, {
type_name: "Warm Sea",
how_good_for_seals: "okay",
});
items.warm_sea = await rest_api.post(Water_Area_Types, {
type_name: "Fantasy Sea",
how_good_for_seals: "hard_to_tell",
});
items.tuna = await rest_api.post(Food, {
food_name: "Tuna",
});
items.baltic_cod = await rest_api.post(Food, {
food_name: "Baltic Cod",
});
items.baltic_sea = await rest_api.post(Water_Areas, {
name: "Baltic Sea",
type: items.cool_sea.id,
});
items.arabic_sea = await rest_api.post(Water_Areas, {
name: "Arabic Sea",
type: items.warm_sea.id,
});
items.unused_sea = await rest_api.post(Water_Areas, {
name: "Unused Sea",
type: items.warm_sea.id,
});
items.hoover = await rest_api.post(Seals, {
name: "Hoover",
water_area: items.arabic_sea.id,
favourite_meal: items.tuna.id,
});
items.nelly = await rest_api.post(Seals, {
name: "Nelly",
water_area: items.baltic_sea.id,
favourite_meal: items.tuna.id,
});
items.maksiu = await rest_api.post(Seals, {
name: "Maksiu",
water_area: items.baltic_sea.id,
favourite_meal: items.baltic_cod.id,
});
}
it("returns single attachment from directly referenced collection", async () =>
withRunningApp(extend, async ({ rest_api }) => {
await setup(rest_api);
const {
items: seals,
attachments,
fields_with_attachments,
} = await rest_api.get(`${Seals}?attachments[water_area]=true`);
assert.equal(seals.length, 3);
assert.deepEqual(fields_with_attachments, ["water_area"]);
assert.deepEqual(attachments, {
[items.baltic_sea.id]: items.baltic_sea,
[items.arabic_sea.id]: items.arabic_sea,
});
}));
it("returns attachments when single resource is queried", async () =>
withRunningApp(extend, async ({ rest_api }) => {
await setup(rest_api);
const {
items: [seal],
attachments,
fields_with_attachments,
} = await rest_api.get(
`${Seals}/${items.maksiu.id}?attachments[water_area]=true`
);
assert.equal(seal.name, items.maksiu.name);
assert.deepEqual(fields_with_attachments, ["water_area"]);
assert.deepEqual(attachments, {
[items.baltic_sea.id]: items.baltic_sea,
});
}));
it("throws an error when not existing field is given to request", async () =>
withRunningApp(extend, async ({ rest_api }) => {
await setup(rest_api);
const scenarios = {
"[fake_field_1]": "fake_field_1",
"[fake_field_1][fake_field_2]": "fake_field_1",
"[water_area][fake_field_2]": "fake_field_2",
};
for (let field_prop of Object.keys(scenarios)) {
await assertThrowsAsync(
() =>
rest_api.get(
`${Seals}?attachments${field_prop}=true`
),
(e) => {
assert.equal(e.response.status, 404);
assert.equal(
e.response.data.message,
`Given field ${
scenarios[
field_prop as keyof typeof scenarios
]
} is not declared in collection!`
);
}
);
}
}));
it("throws an error when an inappropriate field is given to request", async () =>
withRunningApp(extend, async ({ rest_api }) => {
await setup(rest_api);
await assertThrowsAsync(
() => rest_api.get(`${Seals}?attachments[name]=true`),
(e) => {
assert.equal(e.response.status, 405);
assert.equal(
e.response.data.message,
"Field 'name' does not support attachments"
);
}
);
}));
it("returns multiple attachments", async () =>
withRunningApp(extend, async ({ rest_api }) => {
await setup(rest_api);
const {
items: seals,
attachments,
fields_with_attachments,
} = await rest_api.get(
`${Seals}?attachments[water_area][type]=true&attachments[favourite_meal]=true`
);
assert.equal(seals.length, 3);
assert.deepEqual(fields_with_attachments, [
"water_area",
"favourite_meal",
]);
assert.deepEqual(attachments, {
[items.cool_sea.id]: items.cool_sea,
[items.warm_sea.id]: items.warm_sea,
[items.baltic_sea.id]: items.baltic_sea,
[items.arabic_sea.id]: items.arabic_sea,
[items.tuna.id]: items.tuna,
[items.baltic_cod.id]: items.baltic_cod,
});
}));
});
});
diff --git a/src/app/base-chips/field-types/text-storage.ts b/src/app/base-chips/field-types/text-storage.ts
index 0396c340..67b29e02 100644
--- a/src/app/base-chips/field-types/text-storage.ts
+++ b/src/app/base-chips/field-types/text-storage.ts
@@ -1,81 +1,83 @@
import { Field, Context } from "../../../main";
-import { QueryStage } from "../../../datastore/query";
+import type { QueryStage } from "../../../datastore/query";
import escape from "escape-html";
type TextStorageFormat = { original: string; safe: string };
type TextFormatParam = keyof TextStorageFormat;
export default abstract class TextStorage extends Field {
async encode(context: Context, input: string | null) {
context.app.Logger.debug2("TEXT FIELD", "encode", {
name: this.name,
input,
});
if (input === null) {
return null;
}
const ret = {
original: input,
safe: escape(input),
};
context.app.Logger.debug3("TEXT FIELD", "encode/return", ret);
return ret;
}
async getAggregationStages(
_: Context,
filter_value: string | { regex: string | RegExp }
) {
if (!filter_value) {
return [];
}
let filter_in_query: Object | string;
if (typeof filter_value !== "string" && filter_value?.regex) {
const regex_options = "i";
filter_in_query = {
$regex: filter_value.regex,
$options: regex_options,
};
} else {
filter_in_query = filter_value;
}
return [
{
$match: {
$or: [
{
- [`${await this.getValuePath()}.original`]: filter_in_query,
+ [`${await this.getValuePath()}.original`]:
+ filter_in_query,
},
{
- [`${await this.getValuePath()}.safe`]: filter_in_query,
+ [`${await this.getValuePath()}.safe`]:
+ filter_in_query,
},
],
},
} as QueryStage,
];
}
async decode(
context: Context,
db_value: TextStorageFormat | null,
__: any,
format?: TextFormatParam
): Promise<string | null> {
if (db_value === null) {
return null;
}
context.app.Logger.debug2("TEXT FIELD", "decode", { db_value, format });
let ret;
if (db_value === null || db_value === undefined) {
ret = db_value;
} else if (!format) {
ret = db_value.safe;
} else {
ret = db_value[format] || db_value.safe;
}
context.app.Logger.debug3("TEXT FIELD", "decode/return", ret);
return ret;
}
}
diff --git a/src/app/base-chips/field-types/text.subtest.ts b/src/app/base-chips/field-types/text.subtest.ts
index f1581472..d3a38f76 100644
--- a/src/app/base-chips/field-types/text.subtest.ts
+++ b/src/app/base-chips/field-types/text.subtest.ts
@@ -1,116 +1,119 @@
import assert from "assert";
import axios from "axios";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
import { Collection, FieldTypes } from "../../../main";
-import { TestAppType } from "../../../test_utils/test-app";
+import { TestApp } from "../../../test_utils/test-app";
const extend = (
text_params: ConstructorParameters<typeof FieldTypes.Text>[0] = {}
) =>
- function (t: TestAppType) {
+ function (t: TestAppConstructor) {
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
surnames: new (class extends Collection {
fields = {
surname: new FieldTypes.Text(text_params),
};
})(),
};
};
};
describe("text", () => {
function assert_creation_error_factory({
base_url,
collection,
}: {
base_url: string;
collection: string;
}) {
return async ({
resource,
message,
}: {
resource: { [field_name: string]: any };
message: string;
}) => {
try {
await axios.post(
`${base_url}/api/v1/collections/${collection}`,
resource
);
throw "This should not pass";
} catch (e) {
assert.deepStrictEqual(
e.response.data.data.field_messages.surname.message,
message
);
}
};
}
it("shouldn't allow a value that isn't a string", async () =>
withRunningApp(extend(), async ({ app, base_url }) => {
const assert_creation_error = assert_creation_error_factory({
base_url,
collection: "surnames",
});
await assert_creation_error({
resource: { surname: false },
message: app.i18n("invalid_text", [false, typeof false]),
});
await assert_creation_error({
resource: { surname: {} },
message: app.i18n("invalid_text", [{}, typeof {}]),
});
}));
it("should respect given min and max length", async () => {
const min = 3;
const max = 5;
withRunningApp(
extend({ min_length: min, max_length: max }),
async ({ app, base_url }) => {
const assert_creation_error = assert_creation_error_factory({
base_url,
collection: "surnames",
});
let text = "lo";
await assert_creation_error({
resource: { surname: text },
message: app.i18n("too_short_text", [text, min]),
});
text = "abcdefghijk";
await assert_creation_error({
resource: { surname: text },
message: app.i18n("too_long_text", [text, max]),
});
}
);
});
it("should let proper string in", async () =>
withRunningApp(
extend({ min_length: 3, max_length: 5 }),
async ({ base_url }) => {
return axios
.post(`${base_url}/api/v1/collections/surnames`, {
surname: "1234",
})
.then((resp) => assert.deepEqual(resp.status, 201));
}
));
it("should respond with null when no value is stored", async () =>
withRunningApp(
extend({ min_length: 3, max_length: 5 }),
async ({ app }) => {
await app.collections.surnames.suCreate({});
const {
items: [surname],
} = await app.collections.surnames.suList().fetch();
assert.strictEqual(surname.get("surname"), null);
}
));
});
diff --git a/src/app/base-chips/field-types/username.ts b/src/app/base-chips/field-types/username.ts
index b48e75a4..4fec7d00 100644
--- a/src/app/base-chips/field-types/username.ts
+++ b/src/app/base-chips/field-types/username.ts
@@ -1,34 +1,34 @@
-import Context from "../../../context";
+import type Context from "../../../context";
import { Field } from "../../../main";
import me_synonyms from "../../../misc/me-synonyms";
import TextStorage from "./text-storage";
export default class Username extends TextStorage {
typeName = "username";
async isProperValue(
context: Context,
new_value: string,
old_value: string
) {
if (old_value === new_value) {
return Field.valid();
}
if (me_synonyms.indexOf(new_value) !== -1) {
return Field.invalid(
context.app.i18n("invalid_username", [new_value])
);
}
const response = await this.app.collections.users
.suList()
.filter({ username: new_value })
.fetch();
if (!response.empty) {
return Field.invalid(context.app.i18n("username_taken"));
}
return Field.valid();
}
}
diff --git a/src/app/base-chips/field-types/value-existing-in-collection.ts b/src/app/base-chips/field-types/value-existing-in-collection.ts
index d09005ce..f88418bb 100644
--- a/src/app/base-chips/field-types/value-existing-in-collection.ts
+++ b/src/app/base-chips/field-types/value-existing-in-collection.ts
@@ -1,74 +1,74 @@
import Field from "../../../chip-types/field";
-import { Context, App } from "../../../main";
+import type { Context, App } from "../../../main";
export default class ValueExistingInCollection extends Field {
typeName = "value-existing-in-collection";
target_field_name: string;
target_collection_name: string;
include_forbidden: boolean;
constructor(params: {
field: string;
collection: string;
include_forbidden: boolean;
}) {
super();
this.target_field_name = params.field;
this.target_collection_name = params.collection;
this.include_forbidden = params.include_forbidden;
}
async isProperValue(
context: Context,
new_value: unknown,
old_value: unknown
) {
const field = this.getField(context.app);
const collection = field.collection;
const result = await field.checkValue(context, new_value, old_value);
if (!result.valid) {
return result;
}
if (this.include_forbidden) {
context = new this.app.SuperContext();
}
const sealious_response = await collection
.list(context)
.filter({ [field.name]: new_value })
.fetch();
if (sealious_response.empty) {
return Field.invalid(
context.app.i18n("invalid_existing_value", [
collection.name,
field.name,
new_value,
])
);
}
return Field.valid();
}
getField(app: App) {
return app.collections[this.target_collection_name].fields[
this.target_field_name
];
}
encode(...args: Parameters<Field["encode"]>) {
return this.getField(args[0].app).encode(...args);
}
decode(...args: Parameters<Field["decode"]>) {
return this.getField(args[0].app).decode(...args);
}
filterToQuery(...args: Parameters<Field["filterToQuery"]>) {
return this.getField(args[0].app).filterToQuery(...args);
}
getAggregationStages(...args: Parameters<Field["getAggregationStages"]>) {
return this.getField(args[0].app).getAggregationStages(...args);
}
}
diff --git a/src/app/base-chips/special_filters/IsReferencedByResourcesMatching.subtest.ts b/src/app/base-chips/special_filters/IsReferencedByResourcesMatching.subtest.ts
index e574d881..b2972209 100644
--- a/src/app/base-chips/special_filters/IsReferencedByResourcesMatching.subtest.ts
+++ b/src/app/base-chips/special_filters/IsReferencedByResourcesMatching.subtest.ts
@@ -1,89 +1,92 @@
import * as assert from "assert";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
import { Collection, FieldTypes, Policies } from "../../../main";
import IsReferencedByResourcesMatching from "./IsReferencedByResourcesMatching";
-import { TestAppType } from "../../../test_utils/test-app";
import Users from "../../collections/users";
-import MockRestApi from "../../../test_utils/rest-api";
+import type MockRestApi from "../../../test_utils/rest-api";
+import { TestApp } from "../../../test_utils/test-app";
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
users: new (class extends Users {
policies = {
create: new Policies.Public(),
show: new Policies.Public(),
};
defaultPolicy = new Policies.Public();
named_filters = {
staff: new IsReferencedByResourcesMatching("users-roles", {
referencing_collection: "users-roles",
referencing_field: "user",
field_to_check: "role",
allowed_values: ["admin", "moderator"],
nopass_reason:
"Resource you want to retrieve does not match given filter.!",
}),
};
})(),
"users-roles": new (class extends Collection {
fields = {
user: new FieldTypes.SingleReference("users"),
role: new FieldTypes.Enum(["admin", "moderator", "user"]),
};
})(),
};
};
}
describe("IsReferencedByResourcesMatching", () => {
async function setup(rest_api: MockRestApi) {
const users = [
{
username: "admin",
password: "admin_password",
email: "any@example.com",
},
{
username: "moderator",
password: "moderator_password",
email: "any2@example.com",
},
{
username: "user",
password: "user_password",
email: "any3@example.com",
},
];
for (let user of users) {
const { id, username } = await rest_api.post(
"/api/v1/collections/users",
user
);
await rest_api.post("/api/v1/collections/users-roles", {
user: id,
role: username,
});
}
}
it("returns only users with role matching `allowed_values`", () =>
withRunningApp(extend, async ({ rest_api }) => {
await setup(rest_api);
return rest_api
.get("/api/v1/collections/users/@staff")
.then(({ items }: any) => {
assert.ok(items.length > 0);
items.forEach((user: any) => {
assert.ok(
user.username === "admin" ||
user.username === "moderator"
);
});
});
}));
});
diff --git a/src/app/base-chips/special_filters/IsReferencedByResourcesMatching.ts b/src/app/base-chips/special_filters/IsReferencedByResourcesMatching.ts
index 50ff5f03..1f6193a3 100644
--- a/src/app/base-chips/special_filters/IsReferencedByResourcesMatching.ts
+++ b/src/app/base-chips/special_filters/IsReferencedByResourcesMatching.ts
@@ -1,39 +1,40 @@
import * as assert from "assert";
-import { SpecialFilter, Query } from "../../../main";
+import { Query } from "../../../main";
+import SpecialFilter from "../../../chip-types/special-filter";
type Params = {
referencing_collection: string;
referencing_field: string;
field_to_check: string;
allowed_values: any[];
nopass_reason: string;
};
export default class IsReferencedByResourcesMatching extends SpecialFilter {
constructor(collection: string, public params: Params) {
super(collection, params);
const { allowed_values, nopass_reason } = params;
assert.ok(params);
assert.ok(Array.isArray(allowed_values));
assert.ok(typeof nopass_reason === "string");
}
async getFilteringQuery() {
const query = new Query();
const lookup_id = query.lookup({
from: this.getCollection().name,
localField: "id",
foreignField: this.params.referencing_field,
});
query.match({
[`${lookup_id}.${this.params.field_to_check}`]: {
$in: this.params.allowed_values,
},
});
return query;
}
getNopassReason() {
return this.params.nopass_reason;
}
}
diff --git a/src/app/base-chips/special_filters/matches.subtest.ts b/src/app/base-chips/special_filters/matches.subtest.ts
index 41a81005..3acb90ba 100644
--- a/src/app/base-chips/special_filters/matches.subtest.ts
+++ b/src/app/base-chips/special_filters/matches.subtest.ts
@@ -1,79 +1,82 @@
import * as assert from "assert";
-import { withRunningApp } from "../../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../../test_utils/with-test-app";
import { Collection, FieldTypes } from "../../../main";
import Matches from "./matches";
-import { TestAppType } from "../../../test_utils/test-app";
-import { SerializedItemBody } from "../../../chip-types/collection-item";
-import MockRestApi from "../../../test_utils/rest-api";
+import type { SerializedItemBody } from "../../../chip-types/collection-item";
+import type MockRestApi from "../../../test_utils/rest-api";
+import { TestApp } from "../../../test_utils/test-app";
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
numbers: new (class extends Collection {
fields = {
number: new FieldTypes.Int(),
};
named_filters = {
positive: new Matches("numbers", {
number: { ">": 0 },
}),
negative: new Matches("numbers", {
number: { "<": 0 },
}),
};
})(),
};
};
}
describe("Matches", () => {
async function setup(rest_api: MockRestApi) {
const numbers = [-2, -1, 0, 1, 2];
for (let number of numbers) {
await rest_api.post("/api/v1/collections/numbers", { number });
}
}
it("returns only positive numbers when using filter", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(rest_api);
const sealious_response = await app.collections.numbers
.suList()
.namedFilter("positive")
.fetch();
assert.deepEqual(
sealious_response.items.map((resource) =>
resource.get("number")
),
[1, 2]
);
}));
it("returns only positive numbers when using @positive filter", () =>
withRunningApp(extend, async ({ rest_api }) => {
await setup(rest_api);
const { items } = await rest_api.get(
"/api/v1/collections/numbers/@positive?sort[number]=asc"
);
assert.deepEqual(
items.map((resource: SerializedItemBody) => resource.number),
[1, 2]
);
}));
it("returns empty array when using both @positive and @negative filters", () =>
withRunningApp(extend, async ({ rest_api }) => {
await setup(rest_api);
const { items } = await rest_api.get(
"/api/v1/collections/numbers/@positive/@negative"
);
assert.deepEqual(
items.map((resource: SerializedItemBody) => resource.number),
[]
);
}));
});
diff --git a/src/app/base-chips/special_filters/matches.ts b/src/app/base-chips/special_filters/matches.ts
index 4f6b9b16..1f525fbd 100644
--- a/src/app/base-chips/special_filters/matches.ts
+++ b/src/app/base-chips/special_filters/matches.ts
@@ -1,29 +1,30 @@
-import { SpecialFilter, Query } from "../../../main";
-import QueryStage from "../../../datastore/query-stage";
+import { Query } from "../../../main";
+import type QueryStage from "../../../datastore/query-stage";
+import SpecialFilter from "../../../chip-types/special-filter";
export default class Matches extends SpecialFilter {
constructor(
collection_name: string,
public filter: { [field_name: string]: any }
) {
super(collection_name, filter);
}
async getFilteringQuery() {
let pipeline: QueryStage[] = [];
for (let field_name in this.filter) {
const field_pipeline = await this.getCollection().fields[
field_name
].getAggregationStages(
new this.app.SuperContext(),
this.filter[field_name]
);
pipeline = pipeline.concat(field_pipeline);
}
return Query.fromCustomPipeline(pipeline);
}
getNopassReason() {
return this.params.nopass_reason;
}
}
diff --git a/src/app/collections/sessions.ts b/src/app/collections/sessions.ts
index 1e503538..2ebd81fd 100644
--- a/src/app/collections/sessions.ts
+++ b/src/app/collections/sessions.ts
@@ -1,77 +1,78 @@
import Router from "@koa/router";
-import { ItemFields } from "../../chip-types/collection-item-body";
-import { Collection, Errors, FieldTypes, Policies } from "../../main";
+import Collection from "../../chip-types/collection";
+import type { ItemFields } from "../../chip-types/collection-item-body";
+import { Errors, FieldTypes, Policies } from "../../main";
import SecureHasher from "../../utils/secure-hasher";
export default class Sessions extends Collection {
name = "sessions";
fields = {
"session-id": new FieldTypes.SessionID(),
user: new FieldTypes.SingleReference("users"),
};
policies = {
list: new Policies.UserReferencedInField("user"),
};
defaultPolicy = new Policies.Super();
getRouter() {
const router = new Router();
router.delete("/current", async (ctx) => {
try {
const sessions = await ctx.$app.collections.sessions
.suList()
.filter({ "session-id": ctx.$context.session_id })
.fetch();
await Promise.all(
sessions.items.map(async (session) =>
session.remove(new this.app.SuperContext())
)
);
ctx.body = "You've been logged out";
} catch (e) {
return Promise.reject(
new Errors.BadContext("Invalid session id!")
);
}
});
const super_router = super.getRouter();
router.use(super_router.routes(), super_router.allowedMethods());
return router;
}
//returns a session ID to put in the cookie or throws an error if something went wrong
async login(username: string, password: string): Promise<string> {
if (!username) {
throw new Errors.InvalidCredentials("Missing username!");
}
if (!password) {
throw new Errors.InvalidCredentials("Missing password!");
}
const [user] = await this.app.Datastore.find("users", {
"username.safe": username,
});
if (!user) {
throw new Errors.InvalidCredentials("Incorrect username!");
}
const is_valid = await SecureHasher.matches(
password,
user.password as string
);
if (!is_valid) {
throw new Errors.InvalidCredentials("Incorrect password!");
}
const session = this.make({
user: user.id,
"session-id": null,
} as ItemFields<this>);
await session.save(new this.app.SuperContext());
const session_id = session.get("session-id");
return session_id as string;
}
}
diff --git a/src/app/collections/users.ts b/src/app/collections/users.ts
index bf6bc6b1..fa10296e 100644
--- a/src/app/collections/users.ts
+++ b/src/app/collections/users.ts
@@ -1,62 +1,61 @@
import Router from "@koa/router";
-import Policy from "../../chip-types/policy";
+import type Policy from "../../chip-types/policy";
import {
Collection,
- App,
FieldTypes,
Policies,
Context,
ActionName,
} from "../../main";
import { BadContext } from "../../response/errors";
import SecureHasher from "../../utils/secure-hasher";
export default class Users extends Collection {
fields = {
username: new FieldTypes.Username(),
password: new FieldTypes.Password(),
};
defaultPolicy: Policy = new Policies.Themselves();
policies = {
create: new Policies.Super(),
show: new Policies.Themselves(),
} as Partial<{ [a in ActionName]: Policy }>;
getRouter() {
const router = new Router();
router.get("/me", async (ctx) => {
if (typeof ctx.$context.user_id !== "string") {
throw new BadContext("You're not logged in!");
}
const user = this.list(ctx.$context)
.ids([ctx.$context.user_id])
.setParams(ctx.query);
ctx.body = (await user.fetch()).serialize() as Record<
string,
unknown
>;
});
const super_router = super.getRouter();
router.use(super_router.routes(), super_router.allowedMethods());
return router;
}
static async passwordMatches(
context: Context,
username: string,
password: string
) {
const [user] = await context.app.Datastore.find("users", {
"username.safe": username,
});
if (!user || !user.password) {
return false;
}
return await SecureHasher.matches(password, user.password as string);
}
}
diff --git a/src/app/config-manager.ts b/src/app/config-manager.ts
index 391481a7..c2d5750c 100644
--- a/src/app/config-manager.ts
+++ b/src/app/config-manager.ts
@@ -1,51 +1,50 @@
import dotProp from "dot-prop";
import merge from "deepmerge";
-import Config from "./config";
-import Mailer from "../email/mailer";
+import type Config from "./config";
type ConfigObject = { [key: string]: any };
export default class ConfigManager {
DEFAULT_CONFIG: ConfigObject;
CUSTOM_CONFIG: ConfigObject;
isLocked: boolean;
constructor() {
this.DEFAULT_CONFIG = {};
this.CUSTOM_CONFIG = {};
this.isLocked = false;
}
setDefault(key: string, value: any) {
this._setGivenConfig(this.DEFAULT_CONFIG, key, value);
}
getDefaultConfig(key: string) {
return dotProp.get(this.DEFAULT_CONFIG, key);
}
set(key: string, value: any) {
this._setGivenConfig(this.CUSTOM_CONFIG, key, value);
}
_setGivenConfig(config: ConfigObject, key: string, value: any) {
this._warnIfLocked();
dotProp.set(config, key, value);
}
_warnIfLocked() {
if (this.isLocked) {
console.warn(
"Warning: " +
"you shouldn't change config after ConfigManager was locked"
);
}
}
setRoot(params: ConfigObject) {
this._warnIfLocked();
this.CUSTOM_CONFIG = merge(this.CUSTOM_CONFIG, params);
}
get<Key extends keyof Config>(key: Key): Config[Key] {
return dotProp.get(
merge(this.DEFAULT_CONFIG, this.CUSTOM_CONFIG),
key
) as Config[Key];
}
lock() {
this.isLocked = true;
}
}
diff --git a/src/app/config.ts b/src/app/config.ts
index 3f59ad76..d68d9ac4 100644
--- a/src/app/config.ts
+++ b/src/app/config.ts
@@ -1,48 +1,48 @@
-import { LoggerLevel } from "./logger";
+import type { LoggerLevel } from "./logger";
export type Environment = "dev" | "production";
type Config = {
core: {
environment: Environment;
};
logger: {
level: LoggerLevel;
};
"www-server": {
port: number;
"api-base": string;
"session-cookie-name": string;
"max-payload-bytes": number;
};
datastore_mongo: {
host: string;
port: number;
db_name: string;
password: string;
};
roles: string[];
password_hash: {
iterations: number;
key_length: number;
salt_length: number;
};
image_formats: {};
accout_creation_success_path: false | string;
email: {
from_address: string;
from_name: string;
};
upload_path: string;
app: {
version: string;
};
};
export default Config;
type RecursivePartial<T> = {
[P in keyof T]?: RecursivePartial<T[P]>;
};
export type PartialConfig = RecursivePartial<Config>;
diff --git a/src/app/delegate-listener.ts b/src/app/delegate-listener.ts
index dd01f867..5237f088 100644
--- a/src/app/delegate-listener.ts
+++ b/src/app/delegate-listener.ts
@@ -1,13 +1,16 @@
-import { CollectionEvent, CollectionCallback } from "../chip-types/collection";
-import { App } from "../main";
+import type {
+ CollectionEvent,
+ CollectionCallback,
+} from "../chip-types/collection";
+import type { App } from "../main";
export class EventDescription {
constructor(
public collection_name: string,
public event_name: CollectionEvent
) {}
attachTo(app: App, callback: CollectionCallback) {
app.collections[this.collection_name].on(this.event_name, callback);
}
}
diff --git a/src/app/metadata.ts b/src/app/metadata.ts
index b7e349ab..1cfe117a 100644
--- a/src/app/metadata.ts
+++ b/src/app/metadata.ts
@@ -1,32 +1,32 @@
-import { App } from "../main";
+import type { App } from "../main";
const COLLECTION_NAME = "_metadata";
export default class Metadata {
db_collection_name = COLLECTION_NAME;
app: App;
constructor(app: App) {
this.app = app;
}
async get(key: string | number) {
const matches = await this.app.Datastore.find(COLLECTION_NAME, { key });
if (matches.length) {
return matches[0].value;
} else {
undefined;
}
}
async set(key: string, value: string | number) {
const matches = await this.app.Datastore.find(COLLECTION_NAME, { key });
if (matches.length) {
await this.app.Datastore.update(
COLLECTION_NAME,
{ key: key },
{ $set: { value: value } }
);
} else {
await this.app.Datastore.insert(COLLECTION_NAME, { key, value });
}
}
}
diff --git a/src/app/policy-types/and.subtest.ts b/src/app/policy-types/and.subtest.ts
index 07585296..f288f62e 100644
--- a/src/app/policy-types/and.subtest.ts
+++ b/src/app/policy-types/and.subtest.ts
@@ -1,128 +1,131 @@
import assert from "assert";
import Bluebird from "bluebird";
import { App, Collection, FieldTypes, Policies } from "../../main";
-import { withRunningApp } from "../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../test_utils/with-test-app";
import create_policies from "../../test_utils/policy-types/create-policies-with-complex-pipeline";
import And from "./and";
import { assertThrowsAsync } from "../../test_utils/assert-throws-async";
-import { TestAppType } from "../../test_utils/test-app";
+import { TestApp } from "../../test_utils/test-app";
const [ComplexDenyPipeline, ComplexAllowPipeline] = create_policies.allowDeny();
const collections_to_create = [
{
name: "collection-and(nested-and(allow,public),nested-or(allow,noone))",
policies: [
new And([new ComplexAllowPipeline(), new Policies.Public()]),
new Policies.Or([new ComplexAllowPipeline(), new Policies.Noone()]),
],
},
{
name: "collection-and(ComplexAllowPipeline,noone)",
policies: [new ComplexAllowPipeline(), new Policies.Noone()],
},
{
name: "collection-and(ComplexAllowPipeline,public)",
policies: [new ComplexAllowPipeline(), new Policies.Public()],
},
{
name: "collection-and(complexDenyPipeline,public)",
policies: [new ComplexDenyPipeline(), new Policies.Public()],
},
];
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
const collections: { [name: string]: Collection } = {};
for (const { name, policies } of collections_to_create) {
collections[name] = new (class extends Collection {
name = name;
fields = {
number: new FieldTypes.SingleReference("numbers"),
};
policies = {
list: new And(policies),
show: new And(policies),
create: new Policies.Public(),
};
})();
}
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
...collections,
numbers: new (class extends Collection {
name = "numbers";
fields = {
number: new FieldTypes.Int(),
};
})(),
};
};
}
describe("AndPolicy", () => {
async function setup(app: App) {
let numbers = await Bluebird.map([0, 1, 2], (n) =>
app.collections.numbers.suCreate({
number: n,
})
);
for (const number of numbers) {
await Bluebird.map(collections_to_create, ({ name }) =>
app.collections[name].suCreate({
number: number.id,
})
);
}
}
it("return everything for collection-and(nested-and(allow,public),nested-or(allow,noone))", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app);
return rest_api
.get(
"/api/v1/collections/collection-and(nested-and(allow,public),nested-or(allow,noone))"
)
.then(({ items }: { items: any[] }) =>
assert.equal(items.length, 3)
);
}));
it("returns nothing for and(ComplexAllowPipeline,noone)", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app);
await assertThrowsAsync(
() =>
rest_api.get(
"/api/v1/collections/collection-and(ComplexAllowPipeline,noone)"
),
(e) => {
assert.equal(
e.response.data.message,
app.i18n("policy_noone_deny")
);
}
);
}));
it("returns everything for and(ComplexAllowPipeline,public)", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app);
const { items } = await rest_api.get(
"/api/v1/collections/collection-and(ComplexAllowPipeline,public)"
);
assert.strictEqual(items.length, 3);
}));
it("returns nothing for and(complex-deny-pipeline,public)", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app);
const { items } = await rest_api.get(
"/api/v1/collections/collection-and(complexDenyPipeline,public)"
);
assert.strictEqual(items.length, 0);
}));
});
diff --git a/src/app/policy-types/and.ts b/src/app/policy-types/and.ts
index bf52d461..9b7ca7a7 100644
--- a/src/app/policy-types/and.ts
+++ b/src/app/policy-types/and.ts
@@ -1,39 +1,39 @@
import Bluebird from "bluebird";
import { And as AndQuery } from "../../datastore/query";
-import { Context, CollectionItem } from "../../main";
+import type { Context, CollectionItem } from "../../main";
import Policy, { ReducingPolicy } from "../../chip-types/policy";
export default class And extends ReducingPolicy {
static type_name = "and";
async _getRestrictingQuery(context: Context) {
const queries = await Bluebird.map(this.policies, (strategy) =>
strategy.getRestrictingQuery(context)
);
const ret = new AndQuery(...queries);
return ret;
}
isItemSensitive(context: Context) {
return Bluebird.map(this.policies, (strategy) =>
strategy.isItemSensitive(context)
).reduce((a, b) => a || b);
}
async checkerFunction(
context: Context,
item_getter: () => Promise<CollectionItem>
) {
const results = await this.checkAllPolicies(context, item_getter);
const negatives = results.filter((result) => result?.allowed === false);
if (negatives.length > 0) {
return Policy.deny(`${negatives.map((n) => n?.reason).join(", ")}`);
}
return Policy.allow(
`${results
.filter((r) => r !== null)
.map((r) => r?.reason)
.join(", ")}`
);
}
}
diff --git a/src/app/policy-types/if.subtest.ts b/src/app/policy-types/if.subtest.ts
index c64fd0de..7d81a5e7 100644
--- a/src/app/policy-types/if.subtest.ts
+++ b/src/app/policy-types/if.subtest.ts
@@ -1,126 +1,129 @@
import assert from "assert";
-import { withRunningApp } from "../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../test_utils/with-test-app";
import {
App,
Collection,
FieldTypes,
Policies,
SpecialFilters,
} from "../../main";
import Matches from "../base-chips/special_filters/matches";
-import { TestAppType } from "../../test_utils/test-app";
+import { TestApp } from "../../test_utils/test-app";
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
numbers: new (class extends Collection {
fields = {
number: new FieldTypes.Int(),
number_str: new FieldTypes.Text(),
};
named_filters = {
positive: new Matches("numbers", {
number: { ">": 0 },
}),
negative: new Matches("numbers", {
number: { "<": 0 },
}),
};
defaultPolicy = new Policies.If(
"numbers",
"negative",
Policies.LoggedIn,
Policies.Public
);
})(),
};
};
}
async function createResources(app: App) {
for (let number of [-1, 0, 1]) {
await app.collections.numbers.suCreate({
number,
number_str: number.toString(),
});
}
await app.collections.users.suCreate({
username: "user",
password: "password",
});
}
describe("if", () => {
it("should only use 'when_true' access strategy when the item passes the filter", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await createResources(app);
const session = await rest_api.login({
username: "user",
password: "password",
});
const { items: resources_when_logged_in } = await rest_api.get(
"/api/v1/collections/numbers?sort[number]=asc",
session
);
assert.equal(resources_when_logged_in.length, 3);
assert.equal(resources_when_logged_in[0].number, -1);
}));
it("should only use 'when_false' access strategy when the item doesn't pass the filter", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await createResources(app);
const { items: public_resources } = await rest_api.get(
"/api/v1/collections/numbers?sort[number]=asc"
);
assert.equal(public_resources.length, 2);
}));
it("should work properly with a boolean field set to false", async () =>
withRunningApp(
(test_app) =>
class extends test_app {
collections = {
- ...test_app.BaseCollections,
+ ...TestApp.BaseCollections,
tasks: new (class extends Collection {
fields = {
title: new FieldTypes.Text(),
done: new FieldTypes.Boolean(),
};
named_filters = {
todo: new SpecialFilters.Matches("tasks", {
done: false,
}),
};
policies = {
list: new Policies.If(
"tasks",
"todo",
new Policies.Public(),
new Policies.Noone()
),
};
})(),
};
},
async ({ app, rest_api }) => {
const data = {
username: "user",
password: "passwordpassword",
};
await app.collections.users.create(
new app.SuperContext(),
data
);
const session = await rest_api.login(data);
await rest_api.get("/api/v1/collections/tasks", session);
}
));
});
diff --git a/src/app/policy-types/if.ts b/src/app/policy-types/if.ts
index 3de60c95..096d9ee8 100644
--- a/src/app/policy-types/if.ts
+++ b/src/app/policy-types/if.ts
@@ -1,77 +1,77 @@
import {
Policies,
App,
Policy,
SpecialFilter,
Context,
- Queries,
CollectionItem,
+ Queries,
} from "../../main";
-import { PolicyDefinition } from "../../chip-types/policy";
+import type { PolicyDefinition } from "../../chip-types/policy";
export default class If extends Policy {
static type_name = "if";
collection_name: string;
filter_name: string;
strategy_when: { [key in "true" | "false"]: Policy };
constructor(
collection_name: string,
special_filter_name: string,
when_true: PolicyDefinition,
when_false: PolicyDefinition = Policies.Noone
) {
super([collection_name, special_filter_name, when_true, when_false]);
this.filter_name = special_filter_name;
this.collection_name = collection_name;
this.strategy_when = {
true: Policy.fromDefinition(when_true),
false: Policy.fromDefinition(when_false),
};
}
getFilter(app: App): SpecialFilter {
return app.collections[this.collection_name].getNamedFilter(
this.filter_name
);
}
async constructQuery(context: Context) {
const filtering_query = await this.getFilter(
context.app
).getFilteringQuery();
return new Queries.Or(
new Queries.And(
filtering_query,
await this.strategy_when.true.getRestrictingQuery(context)
),
new Queries.And(
new Queries.Not(filtering_query),
await this.strategy_when.false.getRestrictingQuery(context)
)
);
}
async _getRestrictingQuery(context: Context) {
return this.constructQuery(context);
}
async checkerFunction(
context: Context,
item_getter: () => Promise<CollectionItem>
) {
const item = await item_getter();
const query = await this.constructQuery(context);
query.match({ id: item.id });
const results = await context.app.Datastore.aggregate(
item.collection.name,
query.toPipeline()
);
if (!results.length) {
return Policy.deny(this.getFilter(context.app).getNopassReason());
}
return Policy.allow(
context.app.i18n("policy_if_allow", [this.filter_name])
);
}
isItemSensitive = async () => true;
}
diff --git a/src/app/policy-types/logged-in.ts b/src/app/policy-types/logged-in.ts
index 659e211f..c6127a57 100644
--- a/src/app/policy-types/logged-in.ts
+++ b/src/app/policy-types/logged-in.ts
@@ -1,22 +1,22 @@
import Policy from "../../chip-types/policy";
-import { Context } from "../../main";
+import type { Context } from "../../main";
import { AllowAll } from "../../datastore/allow-all";
import DenyAll from "../../datastore/deny-all";
export default class LoggedIn extends Policy {
static type_name = "logged-in";
async _getRestrictingQuery(context: Context) {
if (context.user_id) {
return new AllowAll();
}
return new DenyAll();
}
async checkerFunction(context: Context) {
if (context.user_id) {
return Policy.allow(context.app.i18n("policy_logged_in_allow"));
} else {
return Policy.deny(context.app.i18n("policy_logged_in_deny"));
}
}
}
diff --git a/src/app/policy-types/noone.ts b/src/app/policy-types/noone.ts
index bee48b5a..593ca8be 100644
--- a/src/app/policy-types/noone.ts
+++ b/src/app/policy-types/noone.ts
@@ -1,14 +1,14 @@
-import { Context } from "../../main";
+import type { Context } from "../../main";
import Policy from "../../chip-types/policy";
import DenyAll from "../../datastore/deny-all";
export default class Noone extends Policy {
static type_name = "noone";
async _getRestrictingQuery() {
return new DenyAll();
}
async checkerFunction(context: Context) {
return Policy.deny(context.app.i18n("policy_noone_deny"));
}
isItemSensitive = async () => false;
}
diff --git a/src/app/policy-types/not.subtest.ts b/src/app/policy-types/not.subtest.ts
index 47cbcf87..44513a11 100644
--- a/src/app/policy-types/not.subtest.ts
+++ b/src/app/policy-types/not.subtest.ts
@@ -1,168 +1,173 @@
import assert from "assert";
import Bluebird from "bluebird";
-import Context from "../../context";
+import type Context from "../../context";
import * as Sealious from "../../main";
import { Collection, CollectionItem, FieldTypes, Policies } from "../../main";
import { assertThrowsAsync } from "../../test_utils/assert-throws-async";
-import { withRunningApp } from "../../test_utils/with-test-app";
-import { TestAppType } from "../../test_utils/test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../test_utils/with-test-app";
import getAttachment from "../../test_utils/get-attachment";
+import { TestApp } from "../../test_utils/test-app";
function create_less_than_policy(number: number) {
return new (class extends Sealious.Policy {
async _getRestrictingQuery() {
const query = new Sealious.Query();
const id = query.lookup({
from: "numbers",
localField: "number",
foreignField: "id",
unwind: true,
});
query.match({
[`${id}.number`]: {
$lt: number,
},
});
return query;
}
async checkerFunction(
_: Context,
item_getter: () => Promise<CollectionItem>
) {
const item = await item_getter();
- const item_number = ((item as unknown) as {
- number: { number: number };
- }).number.number;
+ const item_number = (
+ item as unknown as {
+ number: { number: number };
+ }
+ ).number.number;
if (item_number >= number) {
return Sealious.Policy.deny(
`Given value is not lower than ${number}`
);
}
return Sealious.Policy.allow(`Number is less than ${number}`);
}
isItemSensitive = async () => true;
})();
}
const l = (n: number) => create_less_than_policy(n);
const collections_to_create = [
{
name: "collection-not(less-than(2))",
policy: l(2),
},
{
name: "collection-not(less-than(6))",
policy: l(6),
},
{
name: "collection-not(public)",
policy: new Policies.Public(),
},
{
name: "collection-not(noone)",
policy: new Policies.Noone(),
},
];
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
const collections_to_add: { [name: string]: Collection } = {};
for (const { name, policy } of collections_to_create) {
collections_to_add[name] = new (class extends Collection {
fields = {
number: new FieldTypes.SingleReference("numbers"),
};
policies = {
list: new Policies.Not(policy),
show: new Policies.Not(policy),
create: new Policies.Public(),
};
})();
}
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
...collections_to_add,
numbers: new (class extends Collection {
fields = {
number: new FieldTypes.Int(),
};
})(),
};
};
}
describe("NotPolicy", () => {
async function setup(app: Sealious.App) {
for (let i of [0, 1, 2, 3, 4]) {
const { id } = await app.collections.numbers.suCreate({
number: i,
});
await Bluebird.map(collections_to_create, ({ name }) =>
app.collections[name].suCreate({
number: id,
})
);
}
}
it("returns nothing for collection-not(public)", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app);
await assertThrowsAsync(
async () =>
await rest_api.get(
"/api/v1/collections/collection-not(public)"
),
(e) => {
assert.strictEqual((e as any).response.status, 401);
}
);
}));
it("returns everything for collection-not(noone)", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app);
const response = await rest_api.get(
"/api/v1/collections/collection-not(noone)?attachments[number]=true"
);
const numbers = response.items.map(
(item: any) => getAttachment(item, "number", response).number
);
assert.deepEqual(numbers, [0, 1, 2, 3, 4]);
}));
it("returns correct numbers for collection-not(less-than(2))", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app);
const response = await rest_api.get(
"/api/v1/collections/collection-not(less-than(2))?attachments[number]=true"
);
const numbers = response.items.map(
(item: any) => getAttachment(item, "number", response).number
);
assert.deepEqual(numbers, [2, 3, 4]);
}));
it("returns correct numbers for collection-not(less-than(6))", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await setup(app);
const response = await rest_api.get(
"/api/v1/collections/collection-not(less-than(6))?attachments[number]=true"
);
const numbers = response.items.map(
(item: any) => getAttachment(item, "number", response).number
);
assert.deepEqual(numbers, []);
}));
});
diff --git a/src/app/policy-types/not.ts b/src/app/policy-types/not.ts
index 5f246db9..0ce77008 100644
--- a/src/app/policy-types/not.ts
+++ b/src/app/policy-types/not.ts
@@ -1,41 +1,41 @@
import Policy from "../../chip-types/policy";
import * as Query from "../../datastore/query";
-import { CollectionItem, Context } from "../../main";
+import type { CollectionItem, Context } from "../../main";
export default class Not extends Policy {
static type_name = "not";
strategy_to_negate: Policy;
constructor(strategy: Policy) {
super(strategy);
this.strategy_to_negate = Policy.fromDefinition(strategy);
}
async _getRestrictingQuery(context: Context) {
//assuming "not" can take only one access strategy as a parameter
const query = await this.strategy_to_negate.getRestrictingQuery(
context
);
return new Query.Not(query);
}
async isItemSensitive(context: Context) {
return this.strategy_to_negate.isItemSensitive(context);
}
async checkerFunction(
context: Context,
item_getter: () => Promise<CollectionItem>
) {
const result = await this.strategy_to_negate.check(
context,
item_getter
);
if (result === null) {
return null;
}
if (result.allowed) {
return Policy.deny(
context.app.i18n("policy_not_allow", [result.reason])
);
}
return Policy.allow(`it's not true that "${result.reason}"`);
}
}
diff --git a/src/app/policy-types/or.subtest.ts b/src/app/policy-types/or.subtest.ts
index ba5bc808..fa79a7e1 100644
--- a/src/app/policy-types/or.subtest.ts
+++ b/src/app/policy-types/or.subtest.ts
@@ -1,126 +1,129 @@
import assert from "assert";
import Bluebird from "bluebird";
-import { withRunningApp } from "../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../test_utils/with-test-app";
import create_policies from "../../test_utils/policy-types/create-policies-with-complex-pipeline";
-import * as Sealious from "../../main";
+import type * as Sealious from "../../main";
import { Collection, FieldTypes, Policies, Policy } from "../../main";
-import { TestAppType } from "../../test_utils/test-app";
+import { TestApp } from "../../test_utils/test-app";
const [ComplexDenyPipeline, ComplexAllowPipeline] = create_policies.allowDeny();
const collections = [
{
name: "collection-or(nested-or(allow,noone),nested-and(allow,public))",
policies: [
new Policies.Or([new ComplexAllowPipeline(), new Policies.Noone()]),
new Policies.And([
new ComplexAllowPipeline(),
new Policies.Public(),
]),
],
},
{
name: "collection-or(complex-allow-pipeline,public)",
policies: [new ComplexAllowPipeline(), new Policies.Public()],
},
{
name: "collection-or(complex-deny-pipeline,noone)",
policies: [new ComplexDenyPipeline(), new Policies.Noone()],
},
{
name: "collection-or(complex-deny-pipeline,public)",
policies: [new ComplexDenyPipeline(), new Policies.Public()],
},
];
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
const numbers = new (class extends Collection {
name = "numbers";
fields = {
number: new FieldTypes.Int(),
};
})();
const collections_to_add: { [collection: string]: Collection } = {
numbers,
};
for (const { name, policies } of collections) {
collections_to_add[name] = new (class extends Collection {
name = name;
fields = {
number: new FieldTypes.SingleReference("numbers"),
};
policies = {
- list: new Policies.Or(policies as Policy[]),
- show: new Policies.Or(policies as Policy[]),
+ list: new Policies.Or(policies),
+ show: new Policies.Or(policies),
create: new Policies.Public(),
};
})();
}
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
...collections_to_add,
numbers,
};
};
}
async function createItems(app: Sealious.App) {
let numbers = await Bluebird.map([0, 1, 2], (n) =>
app.collections.numbers.suCreate({ number: n })
);
for (const number of numbers) {
await Bluebird.map(collections, ({ name }) =>
app.collections[name].suCreate({
number: number.id,
})
);
}
}
describe("OrPolicy", () => {
it("returns everything for collection-or(nested-or(allow,noone),nested-and(allow,public))", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await createItems(app);
return rest_api
.get(
"/api/v1/collections/collection-or(nested-or(allow,noone),nested-and(allow,public))"
)
.then(({ items }: any) => assert.equal(items.length, 3));
}));
it("returns everything for or(complex-allow-pipeline,public)", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await createItems(app);
return rest_api
.get(
"/api/v1/collections/collection-or(complex-allow-pipeline,public)"
)
.then(({ items }: any) => assert.equal(items.length, 3));
}));
it("returns nothing for or(complex-deny-pipeline,noone)", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await createItems(app);
return rest_api
.get(
"/api/v1/collections/collection-or(complex-deny-pipeline,noone)"
)
.then(({ items }: any) => assert.equal(items.length, 0));
}));
it("returns everything for or(complex-deny-pipeline,public)", () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await createItems(app);
return rest_api
.get(
"/api/v1/collections/collection-or(complex-deny-pipeline,public)"
)
.then(({ items }: any) => assert.equal(items.length, 3));
}));
});
diff --git a/src/app/policy-types/or.ts b/src/app/policy-types/or.ts
index 384bf31f..29e32f13 100644
--- a/src/app/policy-types/or.ts
+++ b/src/app/policy-types/or.ts
@@ -1,44 +1,44 @@
import Bluebird from "bluebird";
import Policy, {
ReducingPolicy,
PolicyDecision,
} from "../../chip-types/policy";
-import Context from "../../context";
+import type Context from "../../context";
import { AllowAll } from "../../datastore/allow-all";
import { default as QueryOr } from "../../datastore/query-or";
-import { CollectionItem } from "../../main";
+import type { CollectionItem } from "../../main";
export default class Or extends ReducingPolicy {
static type_name = "or";
async _getRestrictingQuery(context: Context) {
const queries = await Bluebird.map(this.policies, (strategy) =>
strategy.getRestrictingQuery(context)
);
if (queries.some((query) => query instanceof AllowAll)) {
return new AllowAll();
}
return new QueryOr(...queries);
}
async isItemSensitive(context: Context) {
return Bluebird.map(this.policies, (strategy) =>
strategy.isItemSensitive(context)
).reduce((a, b) => a || b, true);
}
async checkerFunction(
context: Context,
item_getter: () => Promise<CollectionItem>
) {
const results = await this.checkAllPolicies(context, item_getter);
const positives: Exclude<PolicyDecision, null>[] = results.filter(
(result) => result?.allowed === true
) as Exclude<PolicyDecision, null>[];
if (positives.length === 0) {
return Policy.deny(results.map((r) => `"${r?.reason}"`).join(", "));
}
return Policy.allow(positives[0].reason);
}
}
diff --git a/src/app/policy-types/owner.ts b/src/app/policy-types/owner.ts
index 06399fbd..3cca1b8c 100644
--- a/src/app/policy-types/owner.ts
+++ b/src/app/policy-types/owner.ts
@@ -1,33 +1,35 @@
import { Policy, Context, Query, CollectionItem } from "../../main";
import DenyAll from "../../datastore/deny-all";
-import { ItemMetadata } from "../../chip-types/collection-item";
+import type { ItemMetadata } from "../../chip-types/collection-item";
export default class Owner extends Policy {
static type_name = "owner";
async _getRestrictingQuery(context: Context) {
if (context.user_id) {
return Query.fromSingleMatch({
"_metadata.created_by": { $eq: context.user_id },
});
}
return new DenyAll();
}
async checkerFunction(
context: Context,
item_getter: () => Promise<CollectionItem>
) {
const response = await item_getter();
if (
context.user_id &&
context.user_id ===
- ((response as unknown) as {
- _metadata: ItemMetadata;
- })._metadata.created_by
+ (
+ response as unknown as {
+ _metadata: ItemMetadata;
+ }
+ )._metadata.created_by
) {
return Policy.allow(context.app.i18n("policy_owner_allow"));
} else {
return Policy.deny(context.app.i18n("policy_owner_deny"));
}
}
isItemSensitive = async () => true;
}
diff --git a/src/app/policy-types/same-as-for-resource-in-field.subtest.ts b/src/app/policy-types/same-as-for-resource-in-field.subtest.ts
index c0620e1e..e455cab0 100644
--- a/src/app/policy-types/same-as-for-resource-in-field.subtest.ts
+++ b/src/app/policy-types/same-as-for-resource-in-field.subtest.ts
@@ -1,494 +1,499 @@
import assert from "assert";
-import Policy from "../../chip-types/policy";
+import type Policy from "../../chip-types/policy";
import {
ActionName,
App,
Collection,
FieldTypes,
Policies,
Context,
} from "../../main";
import { assertThrowsAsync } from "../../test_utils/assert-throws-async";
-import MockRestApi from "../../test_utils/rest-api";
-import { TestAppType } from "../../test_utils/test-app";
-import { withRunningApp } from "../../test_utils/with-test-app";
+import type MockRestApi from "../../test_utils/rest-api";
+import { TestApp } from "../../test_utils/test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../test_utils/with-test-app";
import Matches from "../base-chips/special_filters/matches";
-const extend = (
- policies: {
+const extend =
+ (policies: {
[action_name in ActionName]?: Policy;
- }
-) => (t: TestAppType) => {
- const Numbers = new (class extends Collection {
- name = "numbers";
- fields = {
- number: new FieldTypes.Int(),
- };
- named_filters = {
- greater_than_1: new Matches("numbers", {
- number: { ">": 1 },
- }),
- };
- policies = policies;
- })();
-
- const NumberNotes = new (class extends Collection {
- name = "number-notes";
- fields = {
- note: new FieldTypes.Text(),
- number: new FieldTypes.SingleReference("numbers"),
- };
- policies = {
- create: new Policies.SameAsForResourceInField({
- action_name: "create",
- field: "number",
- collection_name: "number-notes",
- }),
- show: new Policies.SameAsForResourceInField({
- action_name: "show",
- field: "number",
- collection_name: "number-notes",
- }),
- edit: new Policies.SameAsForResourceInField({
- action_name: "edit",
- field: "number",
- collection_name: "number-notes",
- }),
- list: new Policies.SameAsForResourceInField({
- action_name: "list",
- field: "number",
- collection_name: "number-notes",
- }),
- };
- })();
-
- return class extends t {
- collections = {
- ...t.BaseCollections,
- "number-notes": NumberNotes,
- numbers: Numbers,
+ }) =>
+ (t: TestAppConstructor) => {
+ const Numbers = new (class extends Collection {
+ name = "numbers";
+ fields = {
+ number: new FieldTypes.Int(),
+ };
+ named_filters = {
+ greater_than_1: new Matches("numbers", {
+ number: { ">": 1 },
+ }),
+ };
+ policies = policies;
+ })();
+
+ const NumberNotes = new (class extends Collection {
+ name = "number-notes";
+ fields = {
+ note: new FieldTypes.Text(),
+ number: new FieldTypes.SingleReference("numbers"),
+ };
+ policies = {
+ create: new Policies.SameAsForResourceInField({
+ action_name: "create",
+ field: "number",
+ collection_name: "number-notes",
+ }),
+ show: new Policies.SameAsForResourceInField({
+ action_name: "show",
+ field: "number",
+ collection_name: "number-notes",
+ }),
+ edit: new Policies.SameAsForResourceInField({
+ action_name: "edit",
+ field: "number",
+ collection_name: "number-notes",
+ }),
+ list: new Policies.SameAsForResourceInField({
+ action_name: "list",
+ field: "number",
+ collection_name: "number-notes",
+ }),
+ };
+ })();
+
+ return class extends t {
+ collections = {
+ ...TestApp.BaseCollections,
+ "number-notes": NumberNotes,
+ numbers: Numbers,
+ };
};
};
-};
describe("SameAsForResourceInField", () => {
const sessions: { [username: string]: any } = {};
const numbers: number[] = [];
async function setup(app: App, rest_api: MockRestApi) {
numbers.splice(0, numbers.length); // to clear the array;
const password = "password";
for (const username of ["alice", "bob"]) {
await app.collections.users.suCreate({
username,
password,
});
sessions[username] = await rest_api.login({
username,
password,
});
}
for (const n of [0, 1, 2]) {
numbers.push(
(
await rest_api.post(
"/api/v1/collections/numbers",
{
number: n,
},
sessions.alice
)
).id
);
}
}
async function post_number_notes(rest_api: MockRestApi, user: string) {
const notes = [];
for (const number of numbers) {
notes.push(
await rest_api.post(
"/api/v1/collections/number-notes",
{
note: `Lorem ipsum ${notes.length + 1}`,
number: number,
},
sessions[user]
)
);
}
return notes;
}
it("returns everything for number-notes referring to own numbers", () =>
withRunningApp(
extend({
create: new Policies.Public(),
show: new Policies.Owner(),
}),
async ({ app, rest_api }) => {
await setup(app, rest_api);
const posted_notes = await post_number_notes(rest_api, "alice");
const { items: got_notes } = await rest_api.get(
"/api/v1/collections/number-notes",
sessions.alice
);
assert.strictEqual(got_notes.length, posted_notes.length);
}
));
it("returns nothing for number-notes referring to other user's numbers", () =>
withRunningApp(
extend({
create: new Policies.Public(),
show: new Policies.Owner(),
list: new Policies.Owner(),
}),
async ({ app, rest_api }) => {
await setup(app, rest_api);
await post_number_notes(rest_api, "alice");
const { items: got_notes } = await rest_api.get(
"/api/v1/collections/number-notes",
sessions.bob
);
assert.strictEqual(got_notes.length, 0);
}
));
it("returns item for number-notes referring to numbers with complex access strategy", () =>
withRunningApp(
extend({
create: new Policies.LoggedIn(),
list: new Policies.Or([
new Policies.Owner(),
new Policies.If(
"numbers",
"greater_than_1",
Policies.Public
),
]),
}),
async ({ app, rest_api }) => {
await setup(app, rest_api);
await post_number_notes(rest_api, "alice");
const { items: got_notes } = await rest_api.get(
"/api/v1/collections/number-notes",
sessions.bob
);
assert.strictEqual(got_notes.length, 1);
}
));
it("doesn't allow to edit number-notes referring to other user's numbers", () =>
withRunningApp(
extend({
create: new Policies.LoggedIn(),
edit: new Policies.Owner(),
show: new Policies.Owner(),
}),
async ({ app, rest_api }) => {
await setup(app, rest_api);
const posted_notes = await post_number_notes(rest_api, "alice");
await assertThrowsAsync(() =>
rest_api.patch(
`/api/v1/collections/number-notes/${
posted_notes[0].id as string
}`,
{ note: "Lorem ipsumm" },
sessions.bob
)
);
}
));
it("works on reverse single reference fields", () =>
withRunningApp(
(t) =>
class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
organizations: new (class extends Collection {
fields = {
name: new FieldTypes.Text(),
- user_assignments: new FieldTypes.ReverseSingleReference(
- {
+ user_assignments:
+ new FieldTypes.ReverseSingleReference({
referencing_collection:
"user_organizations",
referencing_field: "organization",
- }
- ),
+ }),
};
policies = {
list: new Policies.Or([
new Policies.SameAsForResourceInField({
collection_name: "organizations",
action_name: "show",
field: "user_assignments",
}),
new Policies.Super(),
]),
};
})(),
user_organizations: new (class extends Collection {
fields = {
user: new FieldTypes.SingleReference("users"),
organization: new FieldTypes.SingleReference(
"organizations"
),
};
policies = {
show: new Policies.UserReferencedInField(
"user"
),
};
})(),
projects: new (class extends Collection {
fields = {
name: new FieldTypes.Text(),
organization: new FieldTypes.SingleReference(
"organizations"
),
};
policies = {
list: new Policies.SameAsForResourceInField({
collection_name: "projects",
field: "organization",
action_name: "list",
}),
show: new Policies.SameAsForResourceInField({
collection_name: "projects",
field: "organization",
action_name: "list",
}),
edit: new Policies.SameAsForResourceInField({
collection_name: "projects",
field: "organization",
action_name: "list",
}),
};
})(),
};
},
async ({ app }) => {
const user1 = await app.collections.users.suCreate({
username: "user1",
password: "user1user1",
});
const user1_context = new Context(app, Date.now(), user1.id);
const user2 = await app.collections.users.suCreate({
username: "user2",
password: "user2user2",
});
const user2_context = new Context(app, Date.now(), user2.id);
const org1 = await app.collections.organizations.suCreate({
name: "org1",
});
await app.collections.user_organizations.suCreate({
user: user1.id,
organization: org1.id,
});
const org2 = await app.collections.organizations.suCreate({
name: "org2",
});
await app.collections.user_organizations.suCreate({
user: user2.id,
organization: org2.id,
});
const project = await app.collections.projects.suCreate({
organization: org1.id,
name: "project1",
});
assert.strictEqual(
(
await app.collections.organizations
.list(user1_context)
.fetch()
).items.length,
1
);
assert.strictEqual(
(
await app.collections.organizations
.list(user2_context)
.fetch()
).items.length,
1
);
- const {
- items: projects1,
- } = await app.collections.projects.list(user1_context).fetch();
+ const { items: projects1 } = await app.collections.projects
+ .list(user1_context)
+ .fetch();
assert.strictEqual(projects1.length, 1);
assert.strictEqual(projects1[0].get("name"), "project1");
assert.strictEqual(projects1[0].id, project.id);
assert.strictEqual(projects1[0].get("organization"), org1.id);
assert.strictEqual(
(await app.collections.projects.list(user2_context).fetch())
.items.length,
0
);
await assertThrowsAsync(
async () =>
app.collections.projects.getByID(
user2_context,
project.id
),
(e) => {
assert.notStrictEqual(e, null);
}
);
await assertThrowsAsync(async () =>
(await app.collections.projects.suGetByID(project.id))
.set("name", "takeover")
.save(user2_context)
);
}
));
it("behaves properly for SingleReference field", async () =>
withRunningApp(
(test_app) =>
class extends test_app {
collections = {
...App.BaseCollections,
organizations: new (class extends Collection {
fields = {
name: new FieldTypes.Text(),
- user_assignments: new FieldTypes.ReverseSingleReference(
- {
+ user_assignments:
+ new FieldTypes.ReverseSingleReference({
referencing_collection:
"user-organization",
referencing_field: "organization",
- }
- ),
+ }),
};
defaultPolicy = new Policies.Super();
policies = {
list: new Policies.Or([
new Policies.SameAsForResourceInField({
collection_name: "organizations",
action_name: "list",
field: "user_assignments",
}),
]),
};
})(),
- "user-organization": new (class UserOrganization extends Collection {
- fields = {
- organization: new FieldTypes.SingleReference(
- "organizations"
- ),
- user: new FieldTypes.SingleReference("users"),
- };
-
- defaultPolicy = new Policies.Super();
-
- policies = {
- list: new Policies.Or([
- new Policies.UserReferencedInField("user"),
- new Policies.Super(),
- ]),
- };
- })(),
+ "user-organization":
+ new (class UserOrganization extends Collection {
+ fields = {
+ organization:
+ new FieldTypes.SingleReference(
+ "organizations"
+ ),
+ user: new FieldTypes.SingleReference(
+ "users"
+ ),
+ };
+
+ defaultPolicy = new Policies.Super();
+
+ policies = {
+ list: new Policies.Or([
+ new Policies.UserReferencedInField(
+ "user"
+ ),
+ new Policies.Super(),
+ ]),
+ };
+ })(),
projects: new (class Projects extends Collection {
fields = {
name: FieldTypes.Required(
new FieldTypes.Text()
),
latest_job: new FieldTypes.SingleReference(
"jobs"
),
organization: new FieldTypes.SingleReference(
"organizations"
),
};
policies = {
list: new Policies.SameAsForResourceInField({
collection_name: "projects",
field: "organization",
action_name: "list",
}),
create: new Policies.Super(),
edit: new Policies.Super(),
};
})(),
jobs: new (class Job extends Collection {
fields = {
project: new FieldTypes.SingleReference(
"projects"
),
result: new FieldTypes.Text(),
};
policies = {
list: new Policies.SameAsForResourceInField({
collection_name: "jobs",
action_name: "list",
field: "project",
}),
create: new Policies.Super(),
edit: new Policies.Super(),
};
})(),
};
},
async ({ app }) => {
const user = await app.collections.users.suCreate({
username: "author",
password: "anyanyanyany",
});
- const organization = await app.collections.organizations.suCreate(
- { name: "org" }
- );
+ const organization =
+ await app.collections.organizations.suCreate({
+ name: "org",
+ });
await app.collections["user-organization"].suCreate({
user: user.id,
organization: organization.id,
});
const project = await app.collections.projects.suCreate({
name: "any",
organization: organization.id,
});
const job = await app.collections.jobs.suCreate({
project: project.id,
result: "I'm a job",
});
- const invisible_project = await app.collections.projects.suCreate(
- {
+ const invisible_project =
+ await app.collections.projects.suCreate({
name: "invisible",
- }
- );
+ });
await app.collections.jobs.suCreate({
project: invisible_project.id,
result: "I'm an invisible job",
});
- const {
- items: user_visible_jobs,
- } = await app.collections.jobs
+ const { items: user_visible_jobs } = await app.collections.jobs
.list(new Context(app, Date.now(), user.id))
.fetch();
assert.strictEqual(user_visible_jobs.length, 1);
}
));
});
diff --git a/src/app/policy-types/same-as-for-resource-in-field.ts b/src/app/policy-types/same-as-for-resource-in-field.ts
index 9a4d5079..f53231aa 100644
--- a/src/app/policy-types/same-as-for-resource-in-field.ts
+++ b/src/app/policy-types/same-as-for-resource-in-field.ts
@@ -1,140 +1,142 @@
-import { ActionName } from "../../action";
-import Collection from "../../chip-types/collection";
+import type { ActionName } from "../../action";
+import type Collection from "../../chip-types/collection";
import Policy from "../../chip-types/policy";
import { AllowAll } from "../../datastore/allow-all";
import DenyAll from "../../datastore/deny-all";
-import QueryStage from "../../datastore/query-stage";
+import type QueryStage from "../../datastore/query-stage";
import {
App,
CollectionItem,
Context,
Field,
FieldTypes,
Query,
} from "../../main";
export default class SameAsForResourceInField extends Policy {
static type_name = "same-as-for-resource-in-field";
current_collection: string;
field: string;
action_name: ActionName;
constructor({
action_name,
collection_name,
field,
}: {
action_name: ActionName;
collection_name: string;
field: string;
}) {
super({ action_name, collection_name, field });
this.current_collection = collection_name;
this.action_name = action_name;
this.field = field;
}
getCollection(app: App): Collection {
return app.collections[this.current_collection];
}
getReferencedCollection(context: Context): Collection {
const field = this.getField(context);
return field instanceof FieldTypes.SingleReference
? field.getTargetCollection(context)
- : (field as FieldTypes.ReverseSingleReference).getReferencingCollection();
+ : (
+ field as FieldTypes.ReverseSingleReference
+ ).getReferencingCollection();
}
getReferencedPolicy(context: Context): Policy {
return this.getReferencedCollection(context).getPolicy(
this.action_name
);
}
getField(context: Context): Field {
return this.getCollection(context.app).fields[this.field];
}
async _getRestrictingQuery(context: Context) {
const referenced_restricting_query = await this.getReferencedPolicy(
context
).getRestrictingQuery(context);
if (
referenced_restricting_query instanceof DenyAll ||
referenced_restricting_query instanceof AllowAll
) {
return referenced_restricting_query;
}
const query = new Query();
let parent_prefix: string;
if (this.getField(context) instanceof FieldTypes.SingleReference) {
parent_prefix = query.lookup({
from: this.getReferencedCollection(context).name,
localField: this.field,
foreignField: "id",
});
} else {
//assuming ReverseSingleReference;
parent_prefix = query.lookup({
from: this.getReferencedCollection(context).name,
let: { value: `$${this.field}.value` },
pipeline: [{ $match: { $expr: { $in: ["$id", "$$value"] } } }],
});
}
const referenced_restricting_pipeline = referenced_restricting_query
.prefix(parent_prefix)
.toPipeline();
const keep_fields: Record<string, Record<"$first", string>> = {
id: { $first: `$id` },
}; // this object will help preserve the original fields after $group stage, which serves as a reverse to $unwind
for (const field_name in this.getCollection(context.app).fields) {
keep_fields[field_name] = { $first: `$${field_name}` };
}
const pipeline: QueryStage[] = [
...query.toPipeline(),
{ $unwind: parent_prefix },
...referenced_restricting_pipeline,
{
$group: {
_id: "$_id",
[parent_prefix]: {
$push: `$${parent_prefix}`,
},
...keep_fields,
},
},
];
return Query.fromCustomPipeline(pipeline);
}
async checkerFunction(
context: Context,
item_getter: () => Promise<CollectionItem>
) {
if (!item_getter) {
return null;
}
const item: CollectionItem = await item_getter();
const field = await item.getDecoded(this.field, context);
const response = this.getReferencedCollection(context).suGetByID(
field as string
);
const ret = await this.getReferencedPolicy(context).check(
context,
() => response
);
return ret;
}
async isItemSensitive(context: Context) {
return this.getReferencedPolicy(context).isItemSensitive(context);
}
}
diff --git a/src/app/policy-types/super.ts b/src/app/policy-types/super.ts
index b0f938c9..9ed96bff 100644
--- a/src/app/policy-types/super.ts
+++ b/src/app/policy-types/super.ts
@@ -1,22 +1,22 @@
import Policy from "../../chip-types/policy";
-import Context from "../../context";
+import type Context from "../../context";
import DenyAll from "../../datastore/deny-all";
import { AllowAll } from "../../datastore/allow-all";
export default class Super extends Policy {
static type_name = "super";
async _getRestrictingQuery(context: Context) {
if (context.is_super) {
return new AllowAll();
}
return new DenyAll();
}
async checkerFunction(context: Context) {
if (context.is_super) {
return Policy.allow(context.app.i18n("policy_super_allow"));
} else {
return Policy.deny(context.app.i18n("policy_super_deny"));
}
}
isItemSensitive = async (_: Context) => false;
}
diff --git a/src/app/policy-types/user-referenced-in-field.subtest.ts b/src/app/policy-types/user-referenced-in-field.subtest.ts
index 52eae340..ce4cda44 100644
--- a/src/app/policy-types/user-referenced-in-field.subtest.ts
+++ b/src/app/policy-types/user-referenced-in-field.subtest.ts
@@ -1,54 +1,57 @@
import assert from "assert";
-import { withRunningApp } from "../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../test_utils/with-test-app";
import { Collection, FieldTypes, Policies } from "../../main";
-import { TestAppType } from "../../test_utils/test-app";
+import { TestApp } from "../../test_utils/test-app";
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
const pets = new (class extends Collection {
name = "pets";
fields = {
name: new FieldTypes.Text(),
owner: new FieldTypes.SingleReference("users"),
};
policies = {
create: new Policies.Public(),
};
defaultPolicy = new Policies.UserReferencedInField("owner");
})();
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
pets,
};
};
}
describe("user-referenced-in-field", () => {
it("should deny if the user isn't the one referenced in the field and allow if it is", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
for (let username of ["Alice", "Bob"]) {
const user = await app.collections.users.suCreate({
username,
password: "password",
});
await app.collections.pets.suCreate({
name: `${username}'s pet`,
owner: user.id,
});
}
const alice_session = await rest_api.login({
username: "Alice",
password: "password",
});
const { items } = await rest_api.get(
"/api/v1/collections/pets",
alice_session
);
assert.strictEqual(items.length, 1);
assert.strictEqual(items[0].name, "Alice&#39;s pet");
}));
});
diff --git a/src/app/policy-types/users-who-can.subtest.ts b/src/app/policy-types/users-who-can.subtest.ts
index 14f35445..5c25ab94 100644
--- a/src/app/policy-types/users-who-can.subtest.ts
+++ b/src/app/policy-types/users-who-can.subtest.ts
@@ -1,65 +1,68 @@
import assert from "assert";
-import { withRunningApp } from "../../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../../test_utils/with-test-app";
import { assertThrowsAsync } from "../../test_utils/assert-throws-async";
import axios from "axios";
import { Collection, FieldTypes, Policies } from "../../main";
-import { TestAppType } from "../../test_utils/test-app";
+import { TestApp } from "../../test_utils/test-app";
const extend = (bricks_allowed: boolean) =>
- function (t: TestAppType) {
+ function (t: TestAppConstructor) {
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
bricks: new (class extends Collection {
fields = {
number: new FieldTypes.Int(),
};
policies = {
create: bricks_allowed
? new Policies.Public()
: new Policies.Noone(),
};
})(),
houses: new (class extends Collection {
fields = {
number: new FieldTypes.Int(),
};
policies = {
create: new Policies.UsersWhoCan(["create", "bricks"]),
};
})(),
};
};
};
describe("users-who-can", () => {
it("should deny if the user can't perform the action", async () =>
withRunningApp(extend(false), async ({ app, base_url }) => {
await assertThrowsAsync(
async () =>
axios
.post(`${base_url}/api/v1/collections/houses`, {
address: "any",
})
.then(),
(e: any) => {
assert.equal(e.response.status, 401);
assert.equal(
e.response.data.message,
app.i18n("policy_users_who_can_deny", [
"create",
"bricks",
app.i18n("policy_noone_deny"),
])
);
}
);
}));
it("should allow if the user can't perform the action", async () =>
withRunningApp(extend(true), async ({ base_url }) => {
await axios.post(`${base_url}/api/v1/collections/houses`, {
address: "any",
});
}));
});
diff --git a/src/app/search.test.ts b/src/app/search.test.ts
index 0a5c84a7..c2fba142 100644
--- a/src/app/search.test.ts
+++ b/src/app/search.test.ts
@@ -1,52 +1,53 @@
import assert from "assert";
import Collection from "../chip-types/collection";
import { FieldTypes } from "../main";
+import { TestApp } from "../test_utils/test-app";
import { withRunningApp } from "../test_utils/with-test-app";
describe("search", () => {
it("Performs full-text-search", async () => {
return withRunningApp(
(test_app) => {
return class extends test_app {
collections = {
- ...test_app.BaseCollections,
+ ...TestApp.BaseCollections,
dogs: new (class extends Collection {
fields = {
name: new FieldTypes.Text({
full_text_search: true,
}),
};
})(),
};
};
},
async ({ app, rest_api }) => {
await app.collections.dogs.create(new app.Context(), {
name: "Nora",
});
await app.collections.dogs.create(new app.Context(), {
name: "Greta",
});
const { items } = await rest_api.get(
"/api/v1/collections/dogs?search=Greta"
);
assert.deepEqual(items.length, 1);
const { items: items2 } = await app.collections["dogs"]
.list(new app.Context())
.search("Nora")
.fetch();
assert.deepEqual(items2.length, 1);
const { items: items3 } = await app.collections["dogs"]
.list(new app.Context())
.search()
.fetch();
assert.deepEqual(items3.length, 2);
}
);
});
});
diff --git a/src/app/sort.subtest.ts b/src/app/sort.subtest.ts
index bbfee5a2..61fdec5e 100644
--- a/src/app/sort.subtest.ts
+++ b/src/app/sort.subtest.ts
@@ -1,107 +1,110 @@
import assert from "assert";
-import { withRunningApp } from "../test_utils/with-test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../test_utils/with-test-app";
import { assertThrowsAsync } from "../test_utils/assert-throws-async";
import { App, Collection, FieldTypes } from "../main";
-import { TestAppType } from "../test_utils/test-app";
-import { SerializedItemBody } from "../chip-types/collection-item";
-import MockRestApi from "../test_utils/rest-api";
+import type { SerializedItemBody } from "../chip-types/collection-item";
+import type MockRestApi from "../test_utils/rest-api";
+import { TestApp } from "../test_utils/test-app";
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor) {
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
water_areas: new (class extends Collection {
fields = {
name: new FieldTypes.Text(),
temperature: new FieldTypes.Int(),
};
})(),
seals: new (class extends Collection {
fields = {
name: new FieldTypes.Text(),
favorite_number: new FieldTypes.Int(),
water_area: new FieldTypes.SingleReference("water_areas"),
};
})(),
};
};
}
describe("sorting", () => {
const items: { [name: string]: SerializedItemBody } = {};
async function create_resources(app: App, rest_api: MockRestApi) {
items.baltic_sea = await rest_api.post(
"/api/v1/collections/water_areas",
{
name: "Baltic Sea",
temperature: 10,
}
);
items.arabic_sea = await rest_api.post(
"/api/v1/collections/water_areas",
{
name: "Arabic Sea",
temperature: 20,
}
);
const seals = [
{
name: "Hoover",
favorite_number: 3,
water_area: items.arabic_sea.id,
},
{
name: "Maksiu",
favorite_number: 3,
water_area: items.baltic_sea.id,
},
{
name: "Nelly",
favorite_number: 8,
water_area: items.baltic_sea.id,
},
];
const promises = [];
for (let seal of seals) {
promises.push(app.collections.seals.suCreate(seal));
}
await Promise.all(promises);
}
it("properly sorts for correct sort key", async () => {
return withRunningApp(extend, async ({ app, rest_api }) => {
await create_resources(app, rest_api);
const { items } = await rest_api.get(
"/api/v1/collections/seals?sort[favorite_number]=desc"
);
assert.deepEqual(
items.map((item: any) => item.favorite_number),
[8, 3, 3]
);
});
});
it("throws application error for incorrect sort key", async () =>
withRunningApp(extend, async ({ app, rest_api }) => {
await create_resources(app, rest_api);
await assertThrowsAsync(
async () =>
await rest_api.get(
"/api/v1/collections/seals?sort[favorite_number]=dsc"
),
(e) => {
assert.equal(e.response.status, 405);
assert.equal(
e.response.data.message,
`Unknown sort key: "dsc". Available sort keys are: desc, descending, asc, ascending.`
);
}
);
}));
});
diff --git a/src/chip-types/calculated-field.ts b/src/chip-types/calculated-field.ts
index f442de73..7b09a6c4 100644
--- a/src/chip-types/calculated-field.ts
+++ b/src/chip-types/calculated-field.ts
@@ -1,20 +1,20 @@
-import App from "../app/app";
-import Context from "../context";
-import { CollectionItem } from "../main";
-import Collection from "./collection";
+import type App from "../app/app";
+import type Context from "../context";
+import type { CollectionItem } from "../main";
+import type Collection from "./collection";
export default abstract class CalculatedField<ReturnType> {
app: App;
abstract name: string;
collection: Collection;
constructor(app: App, collection: Collection) {
this.app = app;
this.collection = collection;
}
abstract calculate(
context: Context,
item: CollectionItem<any>,
db_document: any
): Promise<ReturnType>;
}
diff --git a/src/chip-types/collection-item-body.ts b/src/chip-types/collection-item-body.ts
index 5d4345ec..e30d38be 100644
--- a/src/chip-types/collection-item-body.ts
+++ b/src/chip-types/collection-item-body.ts
@@ -1,218 +1,231 @@
-import Collection from "./collection";
-import { Context, ExtractInput } from "../main";
-import { ExtractOutput } from "./field";
+import type Collection from "./collection";
+import type { Context, ExtractInput } from "../main";
+import type { ExtractOutput, RequiredField } from "./field";
-export type ItemFields<T extends Collection> = {
- [field in keyof T["fields"]]: ExtractInput<T["fields"][field]>;
+export type FieldNames<T extends Collection> = keyof T["fields"] & string;
+
+export type RequiredItemFields<T extends Collection> = {
+ [FieldName in FieldNames<T> as T["fields"][FieldName] extends RequiredField
+ ? FieldName
+ : never]: ExtractInput<T["fields"][FieldName]>;
+};
+
+export type NonrequiredItemFields<T extends Collection> = {
+ [FieldName in FieldNames<T> as T["fields"][FieldName] extends RequiredField
+ ? never
+ : FieldName]: ExtractInput<T["fields"][FieldName]>;
};
+export type ItemFields<T extends Collection> = RequiredItemFields<T> &
+ Partial<NonrequiredItemFields<T>>;
+
export type ItemFieldsOutput<T extends Collection> = {
- [field in keyof T["fields"]]: ExtractOutput<T["fields"][field]>;
+ [field in FieldNames<T>]: ExtractOutput<T["fields"][field]>;
};
export default class CollectionItemBody<T extends Collection = any> {
changed_fields: Set<keyof ItemFields<T>> = new Set();
is_decoded = false;
is_encoded = false;
constructor(
public collection: T,
public raw_input: Partial<ItemFields<T>> = {},
public decoded: Partial<ItemFields<T>> = {},
public encoded: Partial<ItemFields<T>> = {}
) {
for (const field_name in raw_input) {
- if (!encoded[field_name]) {
- this.changed_fields.add(field_name);
+ if (!encoded[field_name as FieldNames<T>]) {
+ this.changed_fields.add(field_name as FieldNames<T>);
}
}
}
set<FieldName extends keyof ItemFields<T>>(
field_name: FieldName,
field_value: ItemFields<T>[FieldName]
) {
this.raw_input[field_name] = field_value;
this.is_decoded = false;
this.is_encoded = false;
this.changed_fields.add(field_name);
}
clearChangedFields() {
this.changed_fields.clear();
}
getDecoded<FieldName extends keyof ItemFields<T>>(field_name: FieldName) {
if (!this.is_decoded) {
throw new Error("Decode first!");
}
return this.decoded[field_name];
}
getInput<FieldName extends keyof ItemFields<T>>(field_name: FieldName) {
return this.raw_input[field_name];
}
getEncoded<FieldName extends keyof ItemFields<T>>(field_name: FieldName) {
return this.encoded[field_name];
}
/** Returns encoded values for every field */
async encode(context: Context): Promise<ItemFields<T>> {
context.app.Logger.debug3(
"ITEM BODY",
"encode",
this.changed_fields.values()
);
const encoded: Partial<ItemFields<T>> = {};
const promises = [];
for (const field_name of this.changed_fields.values()) {
const to_encode = this.raw_input[field_name];
context.app.Logger.debug3("ITEM BODY", "encoding value", {
[field_name]: this.raw_input[field_name],
is_the_value_empty:
to_encode === undefined || to_encode === null,
});
if (!this.collection.fields[field_name as string]) {
// field does not exist in this collection
continue;
}
if (to_encode === undefined) {
- encoded[field_name] = null;
+ encoded[field_name as FieldNames<T>] = null;
continue;
}
promises.push(
this.collection.fields[field_name as string]
.encode(context, to_encode)
.then((value) => {
- encoded[field_name] = value;
+ encoded[field_name as FieldNames<T>] = value;
})
);
}
await Promise.all(promises);
this.encoded = encoded;
this.is_encoded = true;
context.app.Logger.debug2("ITEM BODY", "encode result", this.encoded);
return this.encoded as ItemFields<T>;
}
async decode(
context: Context,
format: { [field_name: string]: any } = {}
): Promise<CollectionItemBody<T>> {
if (this.is_decoded) return this;
context.app.Logger.debug3("ITEM BODY", "Decoding item", {
format,
body: this.encoded,
});
const promises: Promise<any>[] = [];
for (const field_name in this.encoded) {
if (!this.collection.fields?.[field_name]) {
continue;
}
promises.push(
this.collection.fields?.[field_name]
.decode(
context,
- this.encoded[field_name],
+ this.encoded[field_name as FieldNames<T>],
null,
format?.[field_name]
)
.then((decoded_value) => {
this.decoded = {
...this.decoded,
[field_name]: decoded_value,
};
context.app.Logger.debug3(
"ITEM BODY",
"Decoded value",
{
[field_name]: decoded_value,
}
);
})
);
}
await Promise.all(promises);
this.is_decoded = true;
return this;
}
static fromDB(
collection: Collection,
database_entry: { [field_name: string]: any }
) {
delete database_entry._id; //the mongo ID
return new CollectionItemBody<typeof collection>(
collection,
{},
{},
database_entry
);
}
static fromDecoded<T extends Collection>(
collection: T,
decoded: Partial<ItemFields<T>>
) {
return new CollectionItemBody<T>(collection, {}, decoded, {});
}
copy(): CollectionItemBody<T> {
return new CollectionItemBody<T>(
this.collection,
{ ...this.raw_input },
{ ...this.decoded },
{ ...this.encoded }
);
}
async validate(
context: Context,
original_body: CollectionItemBody,
replace_mode: boolean //if true, meaning that if a field has no value, it should be deleted
): Promise<{
valid: boolean;
errors: { [f in keyof ItemFields<T>]?: { message: string } };
}> {
const promises = [];
const errors: { [f in keyof ItemFields<T>]?: { message: string } } = {};
let valid = true;
const fields_to_check = new Set(this.changed_fields.values());
if (replace_mode) {
for (const field of this.collection.getRequiredFields()) {
- fields_to_check.add(field.name);
+ fields_to_check.add(field.name as FieldNames<T>);
}
}
for (const field_name of fields_to_check) {
if (!this.collection.fields[field_name as string]) {
// field does not exist
continue;
}
promises.push(
this.collection.fields[field_name as string]
.checkValue(
context,
this.raw_input[field_name],
- original_body.encoded[field_name]
+ original_body.encoded[field_name as FieldNames<T>]
)
.then(async (result) => {
if (!result.valid) {
valid = false;
errors[field_name] = {
message: result.reason as string,
};
}
})
);
}
await Promise.all(promises);
return { valid, errors };
}
static empty<T extends Collection>(collection: T) {
return new CollectionItemBody<T>(collection, {}, {}, {});
}
}
diff --git a/src/chip-types/collection-item.test.ts b/src/chip-types/collection-item.test.ts
index d2de0ac2..4d45bea0 100644
--- a/src/chip-types/collection-item.test.ts
+++ b/src/chip-types/collection-item.test.ts
@@ -1,169 +1,169 @@
import assert from "assert";
import { App, Collection, Context, FieldTypes, SuperContext } from "../main";
import { assertThrowsAsync } from "../test_utils/assert-throws-async";
import { withRunningApp } from "../test_utils/with-test-app";
-import CollectionItemBody from "./collection-item-body";
+import type CollectionItemBody from "./collection-item-body";
describe("CollectionItem", () => {
it("first inserts, then updates on successive .save() calls", async () =>
withRunningApp(
(test_app) =>
class extends test_app {
collections = {
...App.BaseCollections,
entries: new (class extends Collection {
fields = { title: new FieldTypes.Text() };
})(),
};
},
async ({ app }) => {
const entry = await app.collections.entries.suCreate({
title: "title",
});
entry.set("title", "title2");
await entry.save(new SuperContext(app));
const { items: entries } = await app.collections.entries
.suList()
.fetch();
assert.strictEqual(entries.length, 1);
assert.strictEqual(entries[0].get("title"), "title2");
}
));
it("first inserts, then updates on successive .save() calls (in after:create hook)", async () =>
withRunningApp(
(test_app) =>
class extends test_app {
collections = {
...App.BaseCollections,
entries: new (class extends Collection {
fields = { title: new FieldTypes.Text() };
async init(app: App, name: string) {
await super.init(app, name);
this.on("after:create", async ([_, entry]) => {
entry.set("title", "title-overwritten");
await entry.save(new SuperContext(app));
});
}
})(),
};
},
async ({ app }) => {
const entry = await app.collections.entries.suCreate({
title: "title",
});
await entry.save(new SuperContext(app));
const { items: entries } = await app.collections.entries
.suList()
.fetch();
assert.strictEqual(entries.length, 1);
assert.strictEqual(
entries[0].get("title"),
"title-overwritten"
);
}
));
it("enables using custom validation ran after individual fields validation", async () =>
withRunningApp(
(test_app) =>
class extends test_app {
collections = {
...App.BaseCollections,
entries: new (class extends Collection {
fields = {
title: new FieldTypes.Text(),
length: new FieldTypes.Int(),
};
async validate() {
return [
{
error: "length of the 'title' should be equal to 'length'",
fields: ["title", "length"],
},
];
}
})(),
};
},
async ({ app }) => {
await assertThrowsAsync(
() =>
app.collections.entries.suCreate({
title: "one",
length: 4,
}),
(e) => {
assert.strictEqual(e.message, "Invalid field values");
assert.deepStrictEqual(e.data, {
collection: "entries",
other_messages: [],
field_messages: {
title: {
message:
"length of the 'title' should be equal to 'length'",
},
length: {
message:
"length of the 'title' should be equal to 'length'",
},
},
});
}
);
}
));
it("works correctly with examples from docs", async () =>
withRunningApp(
(test_app) =>
class extends test_app {
collections = {
...App.BaseCollections,
entries: new (class extends Collection {
fields = {
color: new FieldTypes.Color(),
};
async validate(
_: Context,
body: CollectionItemBody
) {
if (
(body.getInput("color") as string).includes(
"green"
)
) {
return [
{
error: "Green is not a creative color",
fields: ["color"],
},
];
}
return [];
}
})(),
};
},
async ({ app }) => {
await assertThrowsAsync(
() =>
app.collections.entries.suCreate({
color: "green",
}),
(e) => {
assert.strictEqual(e.message, "Invalid field values");
assert.deepStrictEqual(e.data, {
collection: "entries",
other_messages: [],
field_messages: {
color: {
message: "Green is not a creative color",
},
},
});
}
);
}
));
});
diff --git a/src/chip-types/collection-item.ts b/src/chip-types/collection-item.ts
index ad003dd2..eb66f0dc 100644
--- a/src/chip-types/collection-item.ts
+++ b/src/chip-types/collection-item.ts
@@ -1,448 +1,449 @@
-import Collection from "./collection";
-import Context from "../context";
+import type Collection from "./collection";
+import type Context from "../context";
import {
DeveloperError,
BadContext,
ValidationError,
FieldsError,
} from "../response/errors";
import shortid from "shortid";
-import { AttachmentOptions, ItemListResult } from "./item-list";
+import type { AttachmentOptions, ItemListResult } from "./item-list";
import CollectionItemBody, {
+ FieldNames,
ItemFields,
ItemFieldsOutput,
} from "./collection-item-body";
-import { PolicyDecision } from "./policy";
+import type { PolicyDecision } from "./policy";
import isEmpty from "../utils/is-empty";
export type ItemMetadata = {
modified_at: number;
created_at: number;
created_by: string | null;
};
export type SerializedItem = ReturnType<CollectionItem["serialize"]>;
export type SerializedItemBody = ReturnType<CollectionItem["serializeBody"]>;
/** CollectionItem */
export default class CollectionItem<T extends Collection = any> {
id: string;
fields_with_attachments: string[] = [];
attachments: Record<string, CollectionItem<T>>;
private attachments_loaded = false;
private save_mode: "update" | "insert" = "insert";
public original_body: CollectionItemBody;
public has_been_replaced = false;
private parent_list: ItemListResult<T> | null;
constructor(
public collection: T,
public body: CollectionItemBody,
public _metadata: ItemMetadata = {
modified_at: Date.now(),
created_at: Date.now(),
created_by: null,
},
id?: string,
attachments?: Record<string, CollectionItem>
) {
collection.app.Logger.debug3("ITEM", "Creating an item from body", {
body,
});
this.id = shortid();
if (id) {
this.id = id;
this.save_mode = "update";
}
if (attachments) {
this.attachments_loaded = true;
}
this.original_body = body.copy();
this.attachments = attachments || {};
}
/** Checks whether or not it is allowed to save the given item to the DB using given context */
private async canSave(context: Context): Promise<PolicyDecision> {
const action = this.save_mode === "insert" ? "create" : "edit";
return this.collection
.getPolicy(action)
.check(context, async () => this);
}
private async canDelete(context: Context): Promise<PolicyDecision> {
return this.collection
.getPolicy("delete")
.check(context, async () => this);
}
private async throwIfInvalid(
action: "create" | "edit",
context: Context,
replace_mode: boolean //if true, meaning that if a field has no value, it should be deleted
) {
context.app.Logger.debug3("ITEM", "Saving item/about to validate");
const { valid, errors } = await this.body.validate(
context,
this.original_body,
replace_mode
);
await this.gatherDefaultValues(context);
context.app.Logger.debug3("ITEM", "Saving item/validation result", {
valid,
errors,
});
if (!valid) {
throw new FieldsError(this.collection, errors);
}
const collection_validation_errors = await this.collection.validate(
context,
this.body,
this.original_body,
action
);
if (collection_validation_errors.length > 0) {
const field_messages = {} as Record<string, string[]>;
const other_messages = [] as string[];
for (const collection_validation_error of collection_validation_errors) {
if ((collection_validation_error.fields || []).length == 0) {
other_messages.push(collection_validation_error.error);
} else {
for (const field of collection_validation_error.fields ||
[]) {
if (!field_messages[field]) {
field_messages[field] = [];
}
field_messages[field].push(
collection_validation_error.error
);
}
}
}
throw new FieldsError(
this.collection,
Object.fromEntries(
Object.entries(field_messages).map(([field, value]) => [
field,
{ message: value.join(" | ") },
])
),
other_messages
);
}
}
/** Save the item to the database */
async save(context: Context) {
context.app.Logger.debug2("ITEM", "Saving item", this.body);
const can_save = await this.canSave(context);
if (can_save === null) {
throw new DeveloperError("Policy didn't give a verdict");
}
if (!can_save?.allowed) {
throw new BadContext(can_save.reason);
}
if (this.save_mode === "insert") {
this._metadata = {
created_at: Date.now(),
modified_at: Date.now(),
created_by: context.user_id,
};
await this.collection.emit("before:create", [context, this]);
await this.throwIfInvalid("create", context, true);
const encoded = await this.body.encode(context);
context.app.Logger.debug3("ITEM", "creating a new item", {
metadata: this._metadata,
});
await context.app.Datastore.insert(this.collection.name, {
id: this.id,
...encoded,
_metadata: this._metadata,
});
await this.decode(context);
this.save_mode = "update";
await this.collection.emit("after:create", [context, this]);
} else {
this._metadata.modified_at = Date.now();
context.app.Logger.debug3("ITEM", "updating an existing item", {
metadata: this._metadata,
});
await this.collection.emit("before:edit", [context, this]);
await this.throwIfInvalid("edit", context, this.has_been_replaced);
const encoded = await this.body.encode(context);
await context.app.Datastore.update(
this.collection.name,
{ id: this.id },
{
$set: { ...encoded, _metadata: this._metadata },
}
);
await this.decode(context);
await this.collection.emit("after:edit", [context, this]);
}
this.body.clearChangedFields();
return this;
}
async gatherDefaultValues(context: Context) {
context.app.Logger.debug2("ITEM", "Gathering default values");
const promises = [];
for (const field_name of Object.keys(this.collection.fields)) {
if (
isEmpty(this.body.getInput(field_name)) &&
isEmpty(this.body.getEncoded(field_name)) &&
this.collection.fields[field_name].hasDefaultValue()
) {
context.app.Logger.debug3(
"ITEM",
`Gathering default values/${field_name}`
);
promises.push(
this.collection.fields[field_name]
.getDefaultValue(context)
.then((value) => {
this.set(field_name, value);
})
);
}
}
await Promise.all(promises);
}
/** sets a value */
- set<FieldName extends keyof ItemFields<T>>(
+ set<FieldName extends FieldNames<T>>(
field_name: FieldName,
field_value: ItemFields<T>[FieldName]
): CollectionItem<T> {
this.body.set(field_name, field_value);
return this;
}
setMultiple(values: Partial<ItemFields<T>>): this {
- for (const field_name in values) {
- this.set(field_name, values[field_name]);
+ for (const [field_name, value] of Object.entries(values)) {
+ this.set(field_name, value);
}
return this;
}
replace(values: Partial<ItemFields<T>>) {
this.body = CollectionItemBody.empty<T>(this.collection);
this.setMultiple(values);
this.has_been_replaced = true;
}
- get<FieldName extends keyof ItemFields<T>>(
+ get<FieldName extends FieldNames<T>>(
field_name: FieldName,
include_raw = false
): ItemFieldsOutput<T>[FieldName] {
if (include_raw) {
if (this.body.raw_input[field_name]) {
return this.body.raw_input[
field_name
] as ItemFieldsOutput<T>[FieldName];
}
}
return this.body.getDecoded(
field_name
) as ItemFieldsOutput<T>[FieldName];
}
/**
* if has decoded value it return this otherwise it decode it in first place
* @param field_name name of field we want to get decoded
* @param context
*/
- async getDecoded<FieldName extends keyof ItemFields<T>>(
+ async getDecoded<FieldName extends FieldNames<T>>(
field_name: FieldName,
context: Context
): Promise<unknown> {
if (this.body.raw_input[field_name]) {
await this.body.encode(context);
await this.body.decode(context);
return this.body.decoded[field_name];
}
if (this.body.encoded[field_name]) {
await this.body.decode(context);
return this.body.decoded[field_name];
}
}
async getDecodedBody(
context: Context,
format: Parameters<CollectionItemBody["decode"]>[1]
) {
if (!this.body.is_decoded) {
await this.body.decode(context, format);
}
return this.body.decoded;
}
async remove(context: Context) {
context.app.Logger.debug("ITEM", "remove", this.id);
if (this.save_mode === "insert") {
throw new Error("This item does not yet exist in the database");
}
const decision = await this.canDelete(context);
if (!decision?.allowed) {
throw new BadContext(decision?.reason || "Not allowed");
}
await this.collection.emit("before:remove", [context, this]);
await context.app.Datastore.remove(
this.collection.name,
{ id: this.id },
true
);
await this.collection.emit("after:remove", [context, this]);
}
async delete(context: Context) {
return this.remove(context);
}
serialize(): {
items: any[];
attachments: Record<string, any>;
fields_with_attachments: string[];
} {
if (!this.body.is_decoded) {
throw new Error("First decode the item");
}
return {
items: [this.serializeBody()],
attachments: Object.fromEntries(
Object.values(this.attachments).map((item) => [
item.id,
item.serializeBody(),
])
),
fields_with_attachments: this.fields_with_attachments,
};
}
async decode(
context: Context,
format: { [field_name: string]: any } = {}
): Promise<CollectionItem<T>> {
await this.body.decode(context, format);
return this;
}
serializeBody(): { id: string } & ItemFields<T> {
return { id: this.id, ...this.body.decoded } as {
id: string;
} & ItemFields<T>;
}
async safeLoadAttachments(context: Context, attachment_options: unknown) {
if (attachment_options === undefined) {
attachment_options = {};
}
if (typeof attachment_options != "object") {
throw new ValidationError(
`Expected attachment params to be an object, got ${JSON.stringify(
attachment_options
)}`
);
}
for (const key in attachment_options) {
if (!(key in this.collection.fields)) {
throw new ValidationError(
`Unknown field name in attachments param: ${key}`
);
}
}
return this.loadAttachments(
context,
attachment_options as AttachmentOptions<T>
);
}
async loadAttachments(
context: Context,
attachment_options: AttachmentOptions<T> = {}
): Promise<this> {
// TODO: This function is kinda like a duplicate of `fetchAttachments` from ItemList?
if (this.attachments_loaded) {
throw new Error("Attachments already loaded");
}
this.attachments = {};
const promises = [];
for (const field of Object.values(this.collection.fields)) {
promises.push(
field
.getAttachments(
context,
- [this.get(field.name)],
- attachment_options[field.name]
+ [this.get(field.name as FieldNames<T>)],
+ attachment_options[field.name as FieldNames<T>]
)
.then((attachmentsList) => {
if (!attachmentsList.empty) {
this.fields_with_attachments.push(field.name);
}
this.attachments = {
...this.attachments,
...attachmentsList.flattenWithAttachments(),
};
})
);
}
await Promise.all(promises);
this.attachments_loaded = true;
return this;
}
static fromSerialized<T extends Collection>(
collection: T,
data: { id: string; _metadata: ItemMetadata },
attachments: { [id: string]: any }
) {
const body = CollectionItemBody.fromDecoded<T>(
collection,
data as Partial<ItemFields<T>>
);
return new CollectionItem<T>(
collection,
body,
data._metadata,
(data as { id: string }).id,
attachments
);
}
fetchAs(context: Context) {
return this.collection.getByID(context, this.id);
}
- getAttachments<FieldName extends keyof ItemFields<T>>(
+ getAttachments<FieldName extends FieldNames<T>>(
field_name: FieldName
): CollectionItem[] {
if (
!this.fields_with_attachments.includes(field_name as string) &&
!this.parent_list?.fields_with_attachments.includes(
field_name as string
)
) {
throw new Error("No attachments loaded for this field");
}
if (!this.body.decoded) {
throw new Error("Decode first!");
}
const value = this.body.getDecoded(field_name) as string | string[];
const ids = Array.isArray(value) ? value : [value];
let attachments_source: Record<string, CollectionItem>;
if (this.parent_list) {
attachments_source = this.parent_list.attachments;
} else if (this.attachments_loaded) {
attachments_source = this.attachments;
} else {
throw new Error("Attachments list could not be reached");
}
return ids.map((id) => attachments_source[id]);
}
setParentList(list: ItemListResult<T>) {
this.parent_list = list;
}
}
diff --git a/src/chip-types/collection.test.ts b/src/chip-types/collection.test.ts
index 569d3273..4244b15a 100644
--- a/src/chip-types/collection.test.ts
+++ b/src/chip-types/collection.test.ts
@@ -1,79 +1,136 @@
import assert from "assert";
import Int from "../app/base-chips/field-types/int";
-import { App, Policies } from "../main";
-import { withRunningApp } from "../test_utils/with-test-app";
-import { TestAppType } from "../test_utils/test-app";
+import { App, FieldTypes, Policies } from "../main";
+import type { TestApp } from "../test_utils/test-app";
+import {
+ TestAppConstructor,
+ withRunningApp,
+ withStoppedApp,
+} from "../test_utils/with-test-app";
import Collection from "./collection";
type Policies = Collection["policies"];
-function extend(t: TestAppType, passedPolicies: Policies = {}) {
+function extend(t: TestAppConstructor<TestApp>, passedPolicies: Policies = {}) {
return class extends t {
collections = {
...App.BaseCollections,
coins: new (class extends Collection {
fields = { value: new Int() };
policies = passedPolicies;
})(),
};
};
}
describe("collection router", () => {
it("propertly responds to a GET request to list resources", async () =>
withRunningApp(extend, async ({ rest_api }) => {
await rest_api.post("/api/v1/collections/coins", { value: 2 });
const response = await rest_api.get("/api/v1/collections/coins");
assert.ok(response.items[0].id);
assert.strictEqual(response.items[0].value, 2);
}));
});
describe("policy sharing for list and show", () => {
it("proper inheritance of list policy from show policy", () => {
return withRunningApp(
(t) => {
return extend(t, { show: new Policies.Noone() });
},
async ({ app }) => {
assert.strictEqual(
app.collections.coins.getPolicy("list") instanceof
Policies.Noone,
true
);
}
);
});
it("proper inheritance of show policy from list policy", () => {
return withRunningApp(
(t) => {
return extend(t, { list: new Policies.Noone() });
},
async ({ app }) => {
assert.strictEqual(
app.collections.coins.getPolicy("show") instanceof
Policies.Noone,
true
);
}
);
});
it("action policy is favoured over inherited policy", () => {
return withRunningApp(
(t) => {
return extend(t, {
list: new Policies.Noone(),
show: new Policies.LoggedIn(),
});
},
async ({ app }) => {
assert.strictEqual(
app.collections.coins.getPolicy("list") instanceof
Policies.Noone,
true
);
}
);
});
});
+
+describe("types", () => {
+ it("throws a ts error when a required field is missing", () => {
+ // this test does not have to run in runitme, just creating a code structure to reflect the use case mentioned here: https://forum.sealcode.org/t/sealious-problem-z-typami/1399/3
+
+ return withRunningApp(
+ (t: TestAppConstructor<TestApp>) =>
+ class TheApp extends t {
+ collections = {
+ ...App.BaseCollections,
+ withRequired:
+ new (class withRequired extends Collection {
+ fields = {
+ required: FieldTypes.Required(
+ new FieldTypes.Int()
+ ),
+ };
+ })(),
+ };
+ },
+ async ({ app }) => {
+ await app.collections.withRequired.create(
+ new app.SuperContext(),
+ { required: 2 } // try removing or renaming this property and you should get an error
+ );
+ await app.collections.withRequired.suCreate({ required: 2 });
+ }
+ );
+ });
+
+ it("doesn't throw a ts error when a non-required field is missing", () => {
+ return withRunningApp(
+ (t: TestAppConstructor<TestApp>) =>
+ class TheApp extends t {
+ collections = {
+ ...App.BaseCollections,
+ withRequired:
+ new (class withRequired extends Collection {
+ fields = {
+ nonrequired: new FieldTypes.Int(),
+ };
+ })(),
+ };
+ },
+ async ({ app }) => {
+ await app.collections.withRequired.create(
+ new app.SuperContext(),
+ {}
+ );
+ }
+ );
+ });
+});
diff --git a/src/chip-types/collection.ts b/src/chip-types/collection.ts
index 9c047fa6..396baa62 100644
--- a/src/chip-types/collection.ts
+++ b/src/chip-types/collection.ts
@@ -1,315 +1,326 @@
import Router from "@koa/router";
import Emittery from "emittery";
-import { ActionName } from "../action";
-import App from "../app/app";
-import { EventDescription } from "../app/delegate-listener";
+import type { ActionName } from "../action";
+import type App from "../app/app";
+import type { EventDescription } from "../app/delegate-listener";
import Public from "../app/policy-types/public";
-import Context from "../context";
+import type Context from "../context";
import parseBody from "../http/parse-body";
-import { BadContext, FieldsError, NotFound } from "../response/errors";
-import CalculatedField from "./calculated-field";
-import CollectionItem from "./collection-item";
+import { BadContext, NotFound } from "../response/errors";
+import type CalculatedField from "./calculated-field";
+import CollectionItem, { ItemMetadata } from "./collection-item";
import CollectionItemBody, { ItemFields } from "./collection-item-body";
-import Field from "./field";
+import type Field from "./field";
import ItemList from "./item-list";
-import Policy from "./policy";
-import SpecialFilter from "./special-filter";
+import type Policy from "./policy";
+import type SpecialFilter from "./special-filter";
export type CollectionEvent =
| "before:create"
| "after:create"
| "before:remove"
| "after:remove"
| "before:edit"
| "after:edit";
export type CollectionCallback = ([context, item, event]: [
Context,
CollectionItem,
EventDescription
]) => Promise<void>;
export type CollectionValidationResult = { error: string; fields: string[] }[];
/** Creates a collection. All collections are automatically served via
* the REST API, with permissions set by the Policies */
export default abstract class Collection {
abstract fields: { [fieldName: string]: Field };
private emitter = new Emittery();
/** the name of the collection, will be used as part of the URI in
* the REST API */
name: string;
/** policies for this collection. Who can do what */
policies: Partial<{ [a in ActionName]: Policy }> = {};
/** The policy to use when deciding on an action not specified in
* `policies` */
defaultPolicy: Policy = new Public();
/** The app this collection is tied to */
app: App;
named_filters: Record<string, SpecialFilter> = {};
calculated_fields: Record<string, CalculatedField<unknown>> = {};
/** initializes the fields @internal */
async initFieldDetails(): Promise<void> {
const promises = [];
for (const [field_name, field] of Object.entries(this.fields)) {
field.setCollection(this);
field.setName(field_name);
promises.push(field.init(this.app));
}
await Promise.all(promises);
}
async suCreate(data: ItemFields<this>): Promise<CollectionItem<this>> {
return this.create(new this.app.SuperContext(), data);
}
/* the "unsafe" flavor of CRUD functions are meant for cases where you want
to just get the errror message and parse it - for example, when you want to
get a nice error that can be used to display errors in a form */
async suCreateUnsafe(
data: Record<string, unknown>
): Promise<CollectionItem<this>> {
return this.createUnsafe(new this.app.SuperContext(), data);
}
async create(
context: Context,
- data: Partial<ItemFields<this>>
+ data: ItemFields<this>
): Promise<CollectionItem<this>> {
return this.make(data).save(context);
}
/* the "unsafe" flavor of CRUD functions are meant for cases where you want
to just get the errror message and parse it - for example, when you want to
get a nice error that can be used to display errors in a form */
async createUnsafe(
context: Context,
data: Record<string, unknown>
): Promise<CollectionItem<this>> {
return this.make(data as Partial<ItemFields<this>>).save(context);
}
/** Makes a new item object that can be saved later */
make(input?: Partial<ItemFields<this>>): CollectionItem<this> {
return new CollectionItem<this>(
this,
new CollectionItemBody(this, input, {}, {})
);
}
async suGetByID(id: string): Promise<CollectionItem<this>> {
return this.getByID(new this.app.SuperContext(), id);
}
async getByID(context: Context, id: string): Promise<CollectionItem<this>> {
const policy = this.getPolicy("show");
if (!(await policy.isItemSensitive(context))) {
const result = await policy.check(context);
if (!result?.allowed) {
throw new BadContext(result?.reason as string);
}
}
const results = (await context.app.Datastore.aggregate(this.name, [
{ $match: { id } },
...(await policy.getRestrictingQuery(context)).toPipeline(),
- ])) as ItemFields<this>[];
+ ])) as Record<string, unknown>[];
if (!results.length) {
throw new NotFound(`${this.name}: id ${id} not found`);
}
const ret = new CollectionItem(
this,
- new CollectionItemBody(this, {}, {}, results[0]),
- results[0]._metadata,
+ new CollectionItemBody(
+ this,
+ {},
+ {},
+ results[0] as unknown as ItemFields<this>
+ ),
+ results[0]._metadata as ItemMetadata,
id
);
await ret.decode(context);
return ret;
}
async suRemoveByID(id: string): Promise<void> {
await this.removeByID(new this.app.SuperContext(), id);
}
async removeByID(context: Context, id: string): Promise<void> {
const result = await this.getPolicy("delete").check(context, () =>
this.getByID(context, id)
);
if (!result?.allowed) {
throw new BadContext(result?.reason as string);
}
await context.app.Datastore.remove(this.name, { id: id }, true);
}
/** Get a policy for given action, an inherited policy, or the default
* policy, if no policy is specified for this action */
getPolicy(action: ActionName): Policy {
const policy = this.policies[action];
if (policy !== undefined) {
return policy;
}
// show and list are actions that can use each others' policies.
if (action === "show" && this.policies["list"]) {
return this.policies["list"];
} else if (action === "list" && this.policies["show"]) {
return this.policies["show"];
}
return this.defaultPolicy;
}
/** Initialize all the fields and filters
* @internal
*/
async init(app: App, collection_name: string): Promise<void> {
this.name = collection_name;
this.app = app;
await this.initFieldDetails();
for (const filter of Object.values(this.named_filters)) {
filter.init(app);
}
}
/** Whether or not any of the fields' behavior depends on the
* current values of themselves or other fields
*
* @param action_name
* the action for which to check @internal
*/
isOldValueSensitive(action_name: ActionName): boolean {
for (const field_name in this.fields) {
if (this.fields[field_name].isOldValueSensitive(action_name)) {
return true;
}
}
return false;
}
/** Return a named filter from the collection
* @param filter_name the name of the filter
*/
getNamedFilter(filter_name: string): SpecialFilter {
return this.named_filters[filter_name];
}
suList(): ItemList<this> {
return this.list(new this.app.SuperContext());
}
list(context: Context): ItemList<this> {
return new ItemList<this>(this, context);
}
- createFromDB(document: ItemFields<this>): CollectionItem<this> {
+ createFromDB(document: Record<string, unknown>): CollectionItem<this> {
const id = document?.id;
delete document.id;
delete document._id;
+
return new CollectionItem<this>(
this,
- new CollectionItemBody(this, {}, {}, document),
- document._metadata,
- id
+ new CollectionItemBody(
+ this,
+ {},
+ {},
+ document as unknown as ItemFields<this>
+ ),
+ document._metadata as ItemMetadata,
+ id as string
);
}
on(
event_name: CollectionEvent,
cb: CollectionCallback
): Emittery.UnsubscribeFn {
return this.emitter.on(event_name, cb);
}
getRequiredFields(): Field[] {
return Object.values(this.fields).filter((field) => field.required);
}
setPolicy(action: ActionName, policy: Policy): this {
this.policies[action] = policy;
return this;
}
getRouter(): Router {
const router = new Router();
router.get(["/", "/@:filter1", "/@:filter1/@:filter2"], async (ctx) => {
const list = this.list(ctx.$context).setParams(ctx.query);
for (const key of ["filter1", "filter2"]) {
if (ctx.params[key]) {
list.namedFilter(ctx.params[key]);
}
}
ctx.body = (await list.fetch()).serialize();
});
router.post("/", parseBody(), async (ctx) => {
const item = this.make();
item.setMultiple(ctx.request.body);
await item.save(ctx.$context);
await item.decode(ctx.$context);
ctx.body = item.serializeBody();
ctx.status = 201;
});
router.get("/:id", async (ctx) => {
const [ret] = await this.list(ctx.$context)
.ids([ctx.params.id])
.safeFormat(ctx.query.format)
.fetch();
await ret.safeLoadAttachments(ctx.$context, ctx.query.attachments);
ctx.body = ret.serialize();
});
router.patch("/:id", parseBody(), async (ctx) => {
const item = await this.getByID(ctx.$context, ctx.params.id);
item.setMultiple(ctx.request.body);
await item.save(ctx.$context);
await item.decode(ctx.$context);
ctx.body = item.serialize();
});
router.put("/:id", parseBody(), async (ctx) => {
const item = await this.getByID(ctx.$context, ctx.params.id);
item.replace(ctx.request.body);
await item.save(ctx.$context);
await item.decode(ctx.$context);
ctx.body = item.serialize();
});
router.delete("/:id", async (ctx) => {
await (
await this.getByID(ctx.$context, ctx.params.id)
).remove(ctx.$context);
ctx.status = 204; // "No content"
});
return router;
}
clearListeners() {
this.emitter.clearListeners();
}
emit(event_name: string, event_data?: any): Promise<void> {
return this.emitter.emitSerial(event_name, event_data);
}
async validate(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
context: Context,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
new_body: CollectionItemBody,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
old_body: CollectionItemBody,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
action: "create" | "edit"
): Promise<CollectionValidationResult> {
// empty function, meant to be overwritten in order to implement custom validation logic
return [];
}
}
diff --git a/src/chip-types/field-hybrid.ts b/src/chip-types/field-hybrid.ts
index 414ff92b..e0a89e31 100644
--- a/src/chip-types/field-hybrid.ts
+++ b/src/chip-types/field-hybrid.ts
@@ -1,81 +1,81 @@
import Field, { Depromisify } from "./field";
-import Context from "../context";
-import { App, Collection, ItemListResult } from "../main";
+import type Context from "../context";
+import type { App, Collection, ItemListResult } from "../main";
/*
A hybrid field is one that takes a field type as a param. All
uncustomized methods should be taken from that given field type
*/
export default abstract class HybridField<T extends Field> extends Field {
virtual_field: T;
constructor(base_field: T) {
super();
this.virtual_field = base_field;
}
setName(name: string) {
super.setName(name);
this.virtual_field.setName(name);
}
setCollection(collection: Collection) {
super.setCollection(collection);
this.virtual_field.setCollection(collection);
}
async encode(
context: Context,
value: Parameters<T["encode"]>[1],
old_value?: Parameters<T["encode"]>[2]
) {
return this.virtual_field.encode(context, value, old_value);
}
async filterToQuery(context: Context, filter: any) {
return this.virtual_field.filterToQuery(context, filter);
}
async isProperValue(
context: Context,
new_value: Parameters<T["checkValue"]>[1],
old_value: Parameters<T["checkValue"]>[2]
) {
return this.virtual_field.checkValue(context, new_value, old_value);
}
async decode(
context: Context,
decoded_value: Depromisify<ReturnType<this["encode"]>>,
old_value: Parameters<T["decode"]>[2],
format: Parameters<T["decode"]>[3]
) {
return this.virtual_field.decode(
context,
decoded_value,
old_value,
format
);
}
async getAttachments(
context: Context,
values: any[],
attachment_options: any
): Promise<ItemListResult<any>> {
return this.virtual_field.getAttachments(
context,
values,
attachment_options
);
}
async init(app: App) {
await super.init(app);
await this.virtual_field.init(app);
}
}
diff --git a/src/chip-types/field.ts b/src/chip-types/field.ts
index 4078991d..206d0f86 100644
--- a/src/chip-types/field.ts
+++ b/src/chip-types/field.ts
@@ -1,274 +1,277 @@
-import Collection from "./collection";
-import Context from "../context";
-import { ActionName } from "../action";
-import { App } from "../main";
-import QueryStage, { MatchBody } from "../datastore/query-stage";
+import type Collection from "./collection";
+import type Context from "../context";
+import type { ActionName } from "../action";
+import type { App } from "../main";
+import type QueryStage from "../datastore/query-stage";
+import type { MatchBody } from "../datastore/query-stage";
import { ItemListResult } from "./item-list";
import { BadSubjectAction } from "../response/errors";
import isEmpty from "../utils/is-empty";
export type Depromisify<T> = T extends Promise<infer V> ? V : T;
export type ExtractParams<F extends Field> = Parameters<F["setParams"]>[0];
export type ExtractInput<F extends Field> = Parameters<F["encode"]>[1];
export type ExtractOutput<F extends Field> = Depromisify<
ReturnType<F["decode"]>
>;
export type ExtractStorage<F extends Field> = Depromisify<
ReturnType<F["encode"]>
>;
export type ValidationResult = {
valid: boolean;
reason?: string;
};
/** The field class itself. Stores information on the field name, and
* methods that decide waht values are valid and how they are
* stored. The {@link Field} class describes a type of field in
* general (like "Text" and "Number"), and a {@link Field} instance
* describes one particular field in a collection (like "name" and
* "age").
*
* Extend this class to create fields with custom behavior.
*
* **The recommended way to create a field for a collection is {@link
* FieldDefinitionHelper}, as it performs type checking of the
* field params.**
*
* Some of the most useful field types include:
* * {@link Boolean}
* * {@link DateField | Date}
* * {@link Datetime}
* * {@link Email}
* * {@link Enum}
* * {@link FileField | Field}
* * {@link Float}
* * {@link Html}
* * {@link Image}
* * {@link Int}
* * {@link SingleReference}
* * {@link Text}
*/
export default abstract class Field {
/** the name of the field */
name: string;
/** the app that the field exists in
* @internal
*/
app: App;
/** The display hints specified for this field */
display_hints: any;
/** Whether or not the field handles large data
* @todo: see if there's any viability in storing this
*/
handles_large_data: boolean = false;
/** The collection this field is attached to */
collection: Collection;
/** Whether or not this field should always have a value. Creating
* a resource with a value missing for a required field will throw
* an error */
required: boolean;
/** Sets the collection @internal */
setCollection(collection: Collection) {
this.collection = collection;
}
setRequired(required: boolean) {
this.required = required;
return this;
}
/** Sets the name @internal */
setName(name: string) {
this.name = name;
}
/** This method is used to set and process the params upon the
* field's creation when the app starts up. The type of argument
* of this method determines type checking that's performed by
* @{link FieldDefinitionHelper}. */
setParams(_: any): void {}
/** Return a summary of this field */
getSpecification() {
return {
name: this.name,
type: this.typeName,
display_hints: this.display_hints,
};
}
/** Whether or not this field should have a dedicated index in the
* database */
hasIndex():
| boolean
| "text"
| { [subfield_name: string]: boolean | "text" } {
return false;
}
/** Value path is where inside a single record should the DB look
* for the field's value when filtering resources. Some fields use
* complex objects for storage and overwrite this method, and
* thanks to that they don't have to reimplement {@link
* Field.getAggregationStages} */
async getValuePath(): Promise<string> {
return this.name;
}
abstract typeName: string;
protected abstract isProperValue(
context: Context,
new_value: unknown,
old_value: unknown
): Promise<ValidationResult>;
public async checkValue(
context: Context,
new_value: unknown,
old_value: unknown
): Promise<ValidationResult> {
if (isEmpty(new_value) && this.required) {
return Field.invalid(`Missing value for field '${this.name}'.`);
} else if (isEmpty(new_value)) {
return Field.valid();
} else {
return this.isProperValue(context, new_value, old_value);
}
}
/** Decides how to store the given value in the database, based on
* the context and previous value of the field */
async encode(_: Context, value: any | null, __?: any): Promise<any> {
return value as any;
}
/** Reverse to the {@link Field.encode} function. Takes what's inside the database and returns the value in a given format */
async decode(
context: Context,
storage_value: Depromisify<ReturnType<this["encode"]>>,
old_value: any,
format_params: any
): Promise<unknown | null> {
context.app.Logger.debug3("FIELD DECODE", this.name, {
storage_value,
old_value,
});
return storage_value as unknown;
}
/** Generates a mongo query based on the filter value */
async filterToQuery(context: Context, filter: any): Promise<any> {
return this.encode(context, filter);
}
/** Whether or not the db should create a fulltext index on this field */
async fullTextSearchEnabled(): Promise<boolean> {
return false;
}
/** Whether or not a field has a default value - that is, a value
* given to the field if no value is provided */
hasDefaultValue() {
return true;
}
/** The default value that will be assigned to the field if no
* value is given */
async getDefaultValue(
_: Context
): Promise<Parameters<this["encode"]>[1] | null> {
return null;
}
/** Whether or not any of the methods of the field depend on the
* previous value of the field */
isOldValueSensitive(_: ActionName) {
return false;
}
/** Used to signal a positive decision from within {@link
* Field.isProperValue}. */
static valid(): ValidationResult {
return { valid: true };
}
/** Used to signal a negative decition from within {@link
* Field.isProperValue}. */
static invalid(reason: string): ValidationResult {
return { valid: false, reason };
}
/** Runs when the app is being started. Hooks can be set up within
* this function */
async init(app: App): Promise<void> {
this.app = app;
}
async getAttachments(
context: Context,
values: any[], // this method gets called once for multiple resources, to limit the number of queries. Field values of all the resources are passed in this array
attachment_options: any
): Promise<ItemListResult<any>> {
if (attachment_options !== undefined) {
throw new BadSubjectAction(
`Field '${this.name}' does not support attachments`
);
}
return new ItemListResult([], [], {});
}
/** Creates parts of a Mongo Pipieline that will be used to filter
* the items when listing items of a collection */
async getAggregationStages(
context: Context,
field_filter: unknown
): Promise<QueryStage[]> {
context.app.Logger.debug2(
"FIELD",
`${this.name}.getAggregationStages`,
field_filter
);
if (field_filter === undefined) return [];
const value_path = await this.getValuePath();
let $match: MatchBody = {};
if (field_filter === null) {
$match = {
$or: [
{ [value_path]: { $exists: false } },
{ [value_path]: null },
],
};
} else if (field_filter instanceof Array) {
$match = {
[value_path]: {
$in: await Promise.all(
field_filter.map((value) => this.encode(context, value))
),
},
};
} else {
const [value_path, filter_value] = await Promise.all([
this.getValuePath(),
this.filterToQuery(context, field_filter),
]);
context.app.Logger.debug3("FIELD", "getAggregationStages", {
value_path,
filter_value,
});
$match = {
[value_path]: filter_value,
};
}
return [{ $match }];
}
}
+export type RequiredField = Field & { required: true };
+
export { default as HybridField } from "./field-hybrid";
export * from "./field-hybrid";
diff --git a/src/chip-types/item-list.ts b/src/chip-types/item-list.ts
index a53b1860..fee619b1 100644
--- a/src/chip-types/item-list.ts
+++ b/src/chip-types/item-list.ts
@@ -1,427 +1,428 @@
import CollectionItem from "./collection-item";
-import Collection from "./collection";
+import type Collection from "./collection";
import { Context, Query } from "../main";
import {
BadContext,
NotFound,
BadSubjectAction,
ValidationError,
} from "../response/errors";
-import QueryStage from "../datastore/query-stage";
+import type QueryStage from "../datastore/query-stage";
import sealious_to_mongo_sort_param from "../utils/mongo-sorts";
-import { ItemFields } from "./collection-item-body";
+import type { FieldNames, ItemFields } from "./collection-item-body";
type FilterT<T extends Collection> = Partial<ItemFields<T>>;
type PaginationParams = {
page: number;
items: number;
forward_buffer: number;
};
type SortParams<T extends Collection> = Partial<
{
[key in keyof T["fields"]]: keyof typeof sealious_to_mongo_sort_param;
} & {
"_metadata.created_at": keyof typeof sealious_to_mongo_sort_param;
"_metadata.modified_at": keyof typeof sealious_to_mongo_sort_param;
}
>;
-type FormatParam<T extends Collection> = Partial<
- {
- [key in keyof T["fields"]]: any;
- }
->;
+type FormatParam<T extends Collection> = Partial<{
+ [key in keyof T["fields"]]: any;
+}>;
type AllInOneParams<T extends Collection> = {
search: Parameters<ItemList<T>["search"]>[0];
sort: Parameters<ItemList<T>["sort"]>[0];
filter: Parameters<ItemList<T>["filter"]>[0];
pagination: Parameters<ItemList<T>["paginate"]>[0];
attachments: Parameters<ItemList<T>["attach"]>[0];
format: Parameters<ItemList<T>["format"]>[0];
};
/** Which fields to fetch attachments for. Can be nested, as one
* resource can point to another one and that one can also have
* attachments
*/
-export type AttachmentOptions<T extends Collection> = Partial<
- {
- [key in keyof T["fields"]]: any;
- }
->;
+export type AttachmentOptions<T extends Collection> = Partial<{
+ [key in keyof ItemFields<T>]: any;
+}>;
export default class ItemList<T extends Collection> {
public fields_with_attachments_fetched: string[] = [];
private _attachments_options: AttachmentOptions<T> = {};
private _filter: FilterT<T>;
private _format: FormatParam<T>;
private _ids: string[];
private _search: string;
private _sort: SortParams<T>;
private context: Context;
private collection: Collection;
private aggregation_stages: QueryStage[] = [];
private await_before_fetch: Promise<any>[] = [];
private is_paginated = false;
private is_sorted = false;
private pagination: Partial<PaginationParams> = {};
constructor(collection: T, context: Context) {
this.context = context;
this.collection = collection;
this.await_before_fetch = [
this.collection
.getPolicy("list")
.getRestrictingQuery(context)
.then((query) => {
const pipeline = query.toPipeline();
return pipeline;
})
.then((stages) => this.aggregation_stages.push(...stages)),
];
}
filter(filter?: FilterT<T>): ItemList<T> {
if (this._filter) {
throw new Error("Filter already set");
}
if (!filter) {
return this;
}
this._filter = filter;
- for (const field_name in filter) {
+ for (const [field_name, filter_value] of Object.entries(filter)) {
this.context.app.Logger.debug3(
"ITEM",
"Setting filter for field:",
- { [field_name]: filter[field_name] }
+ { [field_name]: filter_value }
);
if (!this.collection.fields[field_name]) {
throw new Error(
`Unknown field: '${field_name}' in '${this.collection.name}' collection`
);
}
const promise = this.collection.fields[field_name]
- .getAggregationStages(this.context, filter[field_name])
+ .getAggregationStages(this.context, filter_value)
.then((stages) => {
this.aggregation_stages.push(...stages);
this.context.app.Logger.debug3(
"ITEM",
"Adding aggregation stage for field",
{ [field_name]: stages }
);
});
this.await_before_fetch.push(promise);
}
return this;
}
validateFormatParam(format: unknown): FormatParam<T> {
if (format === undefined) {
return {};
}
if (typeof format !== "object") {
throw new ValidationError("Format should be a proper object");
}
for (const key in format) {
if (!(key in this.collection.fields)) {
throw new ValidationError(
`Invalid field name in filter: ${key}`
);
}
}
return format as FormatParam<T>;
}
// this method should only be used when dealing with user input. Otherwise use the `format` method, as it's type safe and any issues shoyuld arise during the build process
safeFormat(format: unknown): this {
this.validateFormatParam(format);
return this.format(format as FormatParam<T>);
}
format(format?: FormatParam<T>): this {
if (this._format) {
throw new Error("Already formatted!");
}
if (format) {
this._format = format;
}
return this;
}
paginate(pagination_params?: Partial<PaginationParams>): ItemList<T> {
if (!pagination_params) {
return this;
}
this.pagination = pagination_params;
this.is_paginated = true;
return this;
}
search(term?: string): ItemList<T> {
if (!term) {
return this;
}
if (this._search) {
throw new Error("Search term already set");
}
this.aggregation_stages.push({
$match: {
$text: {
$search: term.toString(),
$caseSensitive: false,
$diacriticSensitive: false,
},
},
});
return this;
}
ids(ids: string[]): ItemList<T> {
if (this._ids) {
throw new Error("ids already filtered");
}
this.aggregation_stages.push(
...Query.fromSingleMatch({
id: { $in: ids },
}).toPipeline()
);
return this;
}
namedFilter(filter_name: string): ItemList<T> {
this.await_before_fetch.push(
this.collection.named_filters[filter_name]
.getFilteringQuery()
.then((query) => {
this.aggregation_stages.push(...query.toPipeline());
})
);
return this;
}
attach(attachment_options?: AttachmentOptions<T>): ItemList<T> {
if (attachment_options === undefined || !attachment_options) {
return this;
}
this.context.app.Logger.debug3(
"ITEM LIST",
"Attaching fields:",
attachment_options
);
//can be called multiple times
- for (const field_name of Object.keys(attachment_options)) {
- const field = this.collection.fields[field_name];
- if (!field) {
+ for (const [field_name] of Object.entries(attachment_options)) {
+ if (!this.collection.fields[field_name]) {
+ field_name;
throw new NotFound(
`Given field ${field_name} is not declared in collection!`
);
}
- this.fields_with_attachments_fetched.push(field_name);
+
+ this.fields_with_attachments_fetched.push(
+ field_name as unknown as FieldNames<T>
+ );
}
this._attachments_options = attachment_options;
return this;
}
private async fetchAttachments(items: CollectionItem<T>[]) {
const promises: Promise<any>[] = [];
let attachments: { [id: string]: CollectionItem<T> } = {};
for (const field_name of this.fields_with_attachments_fetched) {
+ const collection = this.collection;
this.context.app.Logger.debug2(
"ATTACH",
`Loading attachments for ${field_name}`
);
+
promises.push(
- this.collection.fields[field_name]
+ collection.fields[field_name]
.getAttachments(
this.context,
items.map((item) => item.get(field_name) as unknown),
- this._attachments_options[field_name]
+ this._attachments_options[field_name as FieldNames<T>]
)
.then((attachmentsList) => {
attachments = {
...attachments,
...attachmentsList.flattenWithAttachments(),
};
this.context.app.Logger.debug3(
"ATTACH",
`Fetched attachments for ${field_name}:`,
attachmentsList
);
})
);
}
await Promise.all(promises);
return attachments;
}
/**
* execute crated database request
*/
async fetch(): Promise<ItemListResult<T>> {
const result = await this.collection
.getPolicy("show")
.check(this.context);
if (result !== null && !result.allowed) {
throw new BadContext(result.reason);
}
const aggregation_stages = await this.getAggregationStages();
const documents = await this.context.app.Datastore.aggregate(
this.collection.name,
aggregation_stages,
{}
);
const item_promises: Promise<CollectionItem<T>>[] = [];
for (const document of documents) {
const item = this.collection.createFromDB(document);
item_promises.push(
item.decode(this.context, this._format) as Promise<
CollectionItem<T>
>
);
}
const items = await Promise.all(item_promises);
const attachments = await this.fetchAttachments(items);
return new ItemListResult(
items,
this.fields_with_attachments_fetched,
attachments
);
}
public async getAggregationStages() {
await Promise.all(this.await_before_fetch);
this.await_before_fetch = [];
return [
...this.aggregation_stages,
...this.getSortingStages(),
...this.getPaginationStages(),
];
}
public sort(sort_params?: SortParams<T>) {
if (!sort_params) {
return this;
}
this.is_sorted = true;
this._sort = sort_params;
return this;
}
public setParams(params: Partial<AllInOneParams<T>>) {
return this.filter(params.filter)
.paginate(params.pagination)
.sort(params?.sort)
.search(params?.search)
.attach(params?.attachments)
.format(params?.format);
}
private getSortingStages() {
if (!this.is_sorted) {
return [];
}
const $sort: { [field_name: string]: -1 | 1 } = {};
for (const [field_name, sort_value] of Object.entries(this._sort)) {
if (sort_value === undefined) {
continue;
}
const mongo_sort_param = sealious_to_mongo_sort_param[sort_value];
if (!mongo_sort_param) {
const available_sort_keys = Object.keys(
sealious_to_mongo_sort_param
).join(", ");
throw new BadSubjectAction(
`Unknown sort key: ${JSON.stringify(
this._sort[field_name]
)}. Available sort keys are: ${available_sort_keys}.`
);
}
$sort[field_name] = mongo_sort_param as -1 | 1;
}
return [{ $sort }];
}
private getPaginationStages(): QueryStage[] {
if (!this.is_paginated) {
return [];
}
const full_pagination_params: PaginationParams = {
page: 1,
items: 10,
forward_buffer: 0,
...this.pagination,
};
const $skip =
(full_pagination_params.page - 1) * full_pagination_params.items;
const $limit =
full_pagination_params.items +
full_pagination_params.forward_buffer || 0;
// prettier-ignore
return [ {$skip}, {$limit} ];
}
}
export class ItemListResult<T extends Collection> {
constructor(
public items: CollectionItem<T>[],
public fields_with_attachments: string[],
public attachments: { [id: string]: CollectionItem } = {}
) {
items.forEach((item) => item.setParentList(this));
}
// this generator method makes the instance of this class iterable with for..of
*[Symbol.iterator](): Iterator<CollectionItem<T>> {
for (const item of this.items) {
yield item;
}
}
get empty(): boolean {
return this.items.length === 0;
}
serialize() {
return {
items: this.items.map((item) => item.serializeBody()),
attachments: Object.fromEntries(
Object.entries(this.attachments).map(([id, item]) => [
id,
item.serializeBody(),
])
),
fields_with_attachments: this.fields_with_attachments,
};
}
static fromSerialized<T extends Collection>(
collection: T,
serialized: {
items: any[];
attachments: { [id: string]: any };
fields_with_attachments: string[];
}
) {
return new ItemListResult<T>(
serialized.items.map((item_data) =>
CollectionItem.fromSerialized(
collection,
item_data,
serialized.attachments
)
),
serialized.fields_with_attachments,
serialized.attachments
);
}
flattenWithAttachments() {
return {
...this.attachments,
...Object.fromEntries(this.items.map((item) => [item.id, item])),
};
}
}
diff --git a/src/chip-types/policy.ts b/src/chip-types/policy.ts
index 1f4a374e..246012d3 100644
--- a/src/chip-types/policy.ts
+++ b/src/chip-types/policy.ts
@@ -1,111 +1,111 @@
-import Context from "../context";
-import Query from "../datastore/query";
+import type Context from "../context";
+import type Query from "../datastore/query";
import { AllowAll } from "../datastore/allow-all";
-import { CollectionItem } from "../main";
+import type { CollectionItem } from "../main";
export type PolicyDefinition = [PolicyClass, any] | Policy | PolicyClass;
export type PolicyDecision = {
allowed: boolean;
reason: string;
} | null;
export type PolicyClass = {
new (params?: any): Policy;
type_name: string;
};
export default abstract class Policy {
static type_name: string;
constructor(public params: any = {}) {
this.params = params;
}
// return null if not possible to give an answer
abstract checkerFunction(
context: Context,
item_getter?: () => Promise<CollectionItem<any>>
): Promise<PolicyDecision | null>;
async isItemSensitive(_: Context) {
return false;
}
protected abstract _getRestrictingQuery(context: Context): Promise<Query>;
async getRestrictingQuery(context: Context): Promise<Query> {
if (context.is_super) {
return new AllowAll();
}
return this._getRestrictingQuery(context);
}
async check(
context: Context,
item_getter?: () => Promise<CollectionItem<any>>
): Promise<PolicyDecision | null> {
context.app.Logger.debug3(
"POLICY",
`Checking policy`,
{
this: this,
context,
},
1
);
if (context.is_super) {
return Policy.allow(context.app.i18n("policy_allow"));
}
const is_item_sensitive = await this.isItemSensitive(context);
if (is_item_sensitive && item_getter === undefined) {
return null;
}
return this.checkerFunction(context, item_getter);
}
public static fromDefinition(definition: PolicyDefinition): Policy {
let ret: Policy | null = null;
if (definition instanceof Policy) {
ret = definition;
} else if (Array.isArray(definition)) {
ret = new definition[0](definition[1]);
} else if (typeof definition == "function") {
ret = new (definition as PolicyClass)({});
}
if (!ret) {
throw new Error("could not read the definition");
}
return ret;
}
static allow(reason: string) {
return { allowed: true, reason };
}
static deny(reason: string) {
return { allowed: false, reason };
}
}
export abstract class ReducingPolicy extends Policy {
policies: Policy[];
constructor(params: Policy[]) {
super(params);
this.policies = params.map((definition) =>
Policy.fromDefinition(definition)
);
}
checkAllPolicies(
context: Context,
item_getter?: () => Promise<CollectionItem>
): Promise<PolicyDecision[]> {
return Promise.all(
this.policies.map((strategy) =>
strategy.check(context, item_getter)
)
);
}
}
diff --git a/src/chip-types/special-filter.ts b/src/chip-types/special-filter.ts
index 95a44cde..74e64552 100644
--- a/src/chip-types/special-filter.ts
+++ b/src/chip-types/special-filter.ts
@@ -1,41 +1,42 @@
-import App from "../app/app";
-import Query, { QueryStage } from "../datastore/query";
+import type App from "../app/app";
+import type Query from "../datastore/query";
+import type { QueryStage } from "../datastore/query";
export default abstract class SpecialFilter {
params: any;
app: App;
collection_name: string;
constructor(collection_name: string, params: any) {
this.params = params;
this.collection_name = collection_name;
}
init(app: App) {
this.app = app;
}
abstract getFilteringQuery(): Promise<Query>;
abstract getNopassReason(): string;
getCollection() {
return this.app.collections[this.collection_name];
}
async checkSingleResource(app: App, resource_id: string) {
const documents = await app.Datastore.aggregate(
this.getCollection().name,
[
{ $match: { id: resource_id } },
...(await this.getFilteringQuery()).toPipeline(),
] as QueryStage[]
);
return documents.length
? SpecialFilter.pass()
: SpecialFilter.nopass(this.getNopassReason());
}
static pass = async () => ({ passed: true });
static nopass = async (reason: string) => ({ passed: false, reason });
}
diff --git a/src/context.ts b/src/context.ts
index fcb4e6b9..fb6d220c 100644
--- a/src/context.ts
+++ b/src/context.ts
@@ -1,52 +1,52 @@
-import App from "./app/app";
-import { CollectionItem } from "./main";
+import type App from "./app/app";
+import type { CollectionItem } from "./main";
export default class Context {
timestamp: number;
ip: string | null;
user_id: string | null;
user_data: null | Promise<CollectionItem> = null;
loading_user_data: boolean;
session_id: string | null;
is_super = false;
original_context: Context | null;
constructor(
public app: App,
timestamp: number = Date.now(),
user_id?: string | null,
session_id?: string | null
) {
this.original_context = this;
this.loading_user_data = false;
this.timestamp = timestamp;
this.user_id = user_id || null;
this.session_id = session_id || null;
}
async getUserData(app: App): Promise<CollectionItem | null> {
if (this.user_data) {
return this.user_data;
}
if (this.user_id === null) {
return null;
}
const c = new SuperContext(this.app);
this.user_data = app.collections.users.getByID(c, this.user_id);
return this.user_data;
}
toDBEntry() {
return {
timestamp: this.timestamp,
ip: this.ip,
user_id: this.user_id,
session_id: this.session_id,
};
}
}
export class SuperContext extends Context {
is_super = true;
}
diff --git a/src/data-structures/file.test.ts b/src/data-structures/file.test.ts
index 108be179..5871c391 100644
--- a/src/data-structures/file.test.ts
+++ b/src/data-structures/file.test.ts
@@ -1,47 +1,48 @@
import assert from "assert";
import File from "./file";
import FileField from "../app/base-chips/field-types/file";
import { Collection, SuperContext } from "../main";
import { withRunningApp } from "../test_utils/with-test-app";
+import { TestApp } from "../test_utils/test-utils";
describe("file", () => {
it("should return hello world file", () => {
return withRunningApp(
(test_app_type) => {
return class extends test_app_type {
collections = {
- ...test_app_type.BaseCollections,
+ ...TestApp.BaseCollections,
with_file: new (class extends Collection {
fields = {
file: new FileField(),
};
})(),
};
};
},
async ({ app, rest_api }) => {
const context = new SuperContext(app);
const buff = Buffer.from("Hello world!", "utf-8");
const file = await File.fromData(app, buff, "test-file.txt");
const response = await app.collections.with_file.create(
context,
{
file,
}
);
const item = await app.collections.with_file.getByID(
context,
response.id
);
const api_response = await rest_api.get(
item.get("file") as string
);
assert.strictEqual(api_response, "Hello world!");
}
);
});
});
diff --git a/src/data-structures/file.ts b/src/data-structures/file.ts
index fda21feb..a5787649 100644
--- a/src/data-structures/file.ts
+++ b/src/data-structures/file.ts
@@ -1,151 +1,151 @@
-import { App } from "../main";
+import type { App } from "../main";
import UUIDGenerator from "shortid";
import fs, { ReadStream } from "fs";
import { basename } from "path";
import { getType } from "mime";
import { Readable } from "stream";
import locreq_curry from "locreq";
const locreq = locreq_curry(__dirname);
export type FileDBEntry = {
filename: string;
id: string;
};
export default class File {
filename?: string;
mime_type?: string;
id?: string;
private app: App;
data?: Readable;
constructor(app: App) {
this.app = app;
}
getDataPath(): string | null {
if (!this.id) {
return null;
}
const upload_path = this.app.ConfigManager.get("upload_path");
const data_path = locreq.resolve(`${upload_path}/${this.id}`);
return data_path;
}
getMimeType(): string {
if (!this.filename) {
throw new Error("Set filename first");
}
return getType(this.filename) || "unknown";
}
getStream() {
const path = this.getDataPath();
if (!path) {
return null;
}
return fs.createReadStream(path);
}
getURL() {
if (this.id === undefined) {
throw new Error("id not set!");
}
if (this.filename === undefined) {
throw new Error("filename not set!");
}
return `/api/v1/uploaded-files/${this.id}/${this.filename}`;
}
static async fromID(app: App, id: string) {
const matches = await app.Datastore.find("files", { id });
const file_data = matches[0] as FileDBEntry;
const ret = new FileFromDB(app);
ret.filename = file_data.filename;
ret.id = id;
return ret;
}
static async fromPath(
app: App,
path: string,
filename: string = basename(path)
) {
const ret = new FileFromPath(app);
ret.filename = filename;
ret.data = fs.createReadStream(path);
return ret;
}
static async fromData(
app: App,
buffer: Buffer | string,
filename: string
): Promise<File> {
const stream = new Readable();
stream._read = () => {
null;
};
stream.push(buffer);
stream.push(null);
const ret = new File(app);
ret.filename = filename;
ret.data = stream;
return ret;
}
toDBEntry(): FileDBEntry {
if (!this.filename) {
throw new Error("Missing filename");
}
if (!this.id) {
throw new Error("Missing id");
}
return {
filename: this.filename,
id: this.id,
};
}
async save() {
if (this.id) {
throw new Error(
"This file has already been saved and cannot be edited"
);
}
if (!this.data) {
throw new Error("Please provide file data before saving");
}
if (!this.filename) {
throw new Error("Please provide file data before saving");
}
this.id = UUIDGenerator();
const upload_path = this.app.ConfigManager.get("upload_path");
const upload_path_with_sealious_name = `${upload_path}/${this.id}`;
const writeStream = fs.createWriteStream(
upload_path_with_sealious_name
);
this.data.pipe(writeStream);
await new Promise((resolve, reject) => {
this.data?.on("end", resolve);
this.data?.on("close", resolve);
this.data?.on("error", reject);
});
await this.app.Datastore.insert("files", this.toDBEntry(), {});
return this;
}
}
export class FileFromDB extends File {
filename: string;
getDataPath(): string {
return super.getDataPath() as string;
}
}
export class FileFromPath extends File {
filename: string;
data: ReadStream;
}
diff --git a/src/datastore/datastore.ts b/src/datastore/datastore.ts
index 38887508..4a7ad676 100644
--- a/src/datastore/datastore.ts
+++ b/src/datastore/datastore.ts
@@ -1,256 +1,257 @@
import { MongoClient, Db, Collection as MongoCollection } from "mongodb";
-import { App } from "../main";
-import Collection from "../chip-types/collection";
-import { QueryStage } from "./query";
+import type { App } from "../main";
+import type Collection from "../chip-types/collection";
+import type { QueryStage } from "./query";
import asyncForEach from "../utils/async-foreach";
import QueryStep from "./query-step";
export type OutputOptions = Partial<{
skip: number;
amount: number;
sort: { [field_name: string]: -1 | 1 };
}>;
export default class Datastore {
client: MongoClient;
db: Db;
constructor(public app: App) {
this.app = app;
}
async start(): Promise<void> {
const config = this.app.ConfigManager.get("datastore_mongo") as {
host: string;
port: number;
db_name: string;
};
const url = `mongodb://${config.host}:${config.port}/${config.db_name}`;
this.client = await MongoClient.connect(url, {
useNewUrlParser: true,
useUnifiedTopology: true,
connectTimeoutMS: 1000,
});
if (!this.client) {
return Promise.reject(
"MongoDB was not found, please make sure it's installed. Check https://docs.mongodb.org/manual/tutorial/ for more info."
);
}
this.db = this.client.db(config.db_name);
await this.post_start();
}
async post_start(): Promise<void> {
await asyncForEach(Object.values(this.app.collections), (collection) =>
this.create_index(collection)
);
}
async create_index(collection: Collection): Promise<void> {
const indexes: { [field: string]: number }[] = [];
const text_index: { [field: string]: "text" } = {};
for (const field_name in collection.fields) {
const index_answer = collection.fields[field_name].hasIndex();
if (index_answer === false) {
continue;
}
if (index_answer === "text") {
text_index[field_name] = "text";
} else if (typeof index_answer === "boolean" && index_answer) {
indexes.push({ [field_name]: 1 });
} else if (typeof index_answer === "object") {
for (const [subfield, index] of Object.entries(index_answer)) {
const key = `${field_name}.${subfield as string}`;
if (index === "text") {
text_index[key] = "text";
} else if (index) {
indexes.push({ [key]: 1 });
}
}
}
}
const db_collection = this.db.collection(collection.name);
await asyncForEach(
[
...indexes,
...(Object.keys(text_index).length ? [text_index] : []),
],
async (index) => {
await this.createIndex(collection.name, index).catch(
async (
error: Error & { code?: number; message: string }
) => {
if (error && error.code === 85) {
- const index_name = (error.message.match(
- /name: "([^"]+)"/g
- ) as string[])[1]
+ const index_name = (
+ error.message.match(
+ /name: "([^"]+)"/g
+ ) as string[]
+ )[1]
.replace('name: "', "")
.replace('"', "");
await db_collection.dropIndex(index_name);
return this.createIndex(collection.name, index);
}
throw error;
}
);
}
);
}
find(
collection_name: string,
query: Record<string, any>,
options: Parameters<MongoCollection["find"]>[1] = {},
output_options: OutputOptions = {}
): Promise<Record<string, unknown>[]> {
this.app.Logger.debug2(
"DB",
"find " + collection_name,
{
query,
options,
},
null
);
const cursor = this.db.collection(collection_name).find(query, options);
if (output_options.sort) {
cursor.sort(output_options.sort);
}
if (output_options.skip) {
cursor.skip(output_options.skip);
}
if (output_options.amount) {
cursor.limit(output_options.amount);
}
return cursor.toArray();
}
async aggregate(
collection_name: string,
pipeline: QueryStage[],
_ = {},
output_options: OutputOptions = {}
): Promise<Record<string, any>[]> {
const cursor = this.db.collection(collection_name).aggregate(pipeline);
if (pipeline.find((element) => element instanceof QueryStep)) {
throw new Error(
"Pipeline elements should be simple objects, not QuerySteps. Perhaps you should use .toPipeline()?"
);
}
this.app.Logger.debug2(
"DB",
"Running aggregate",
{
collection_name,
pipeline,
output_options,
},
null
);
if (output_options.sort) {
cursor.sort(output_options.sort);
}
if (output_options.skip) {
cursor.skip(output_options.skip);
}
if (output_options.amount) {
cursor.limit(output_options.amount);
}
const ret = await cursor.toArray();
this.app.Logger.debug3(
"DB",
`Aggregate on collection ${collection_name} returns`,
ret
);
return ret as Record<string, any>[];
}
async insert(
collection_name: string,
to_insert: Record<string, any>,
options?: Parameters<MongoCollection["insertOne"]>[1]
) {
this.app.Logger.debug2("DB", "Running insert", {
collection_name,
to_insert,
options,
});
const result = await this.db
.collection(collection_name)
.insertOne(to_insert, options);
return result.ops[0];
}
update(collection_name: string, query: any, new_value: any) {
this.app.Logger.debug2(
"DB",
"Update",
{
collection_name,
query: query as unknown,
new_value: new_value as unknown,
},
4
);
query = process_query(query);
return this.db.collection(collection_name).updateOne(query, new_value);
}
async remove(collection_name: string, query: any, just_one: boolean) {
this.app.Logger.debug2(
"DB",
"remove",
{
collection_name,
query: query as unknown,
},
3
);
query = process_query(query);
const method = just_one ? "deleteOne" : "deleteMany";
const ret = await this.db.collection(collection_name)[method](query);
return ret;
}
createIndex(
collection_name: string,
index: any,
options?: Parameters<MongoCollection["createIndex"]>[1]
) {
const collection = this.db.collection(collection_name);
return collection.createIndex(index, options);
}
async stop() {
return this.client?.close();
}
}
function process_query(query: Record<string, unknown>) {
if (!query) {
return {};
}
const new_query: Record<string, unknown> = {};
for (const attribute_name in query) {
const value = query[attribute_name];
if (attribute_name == "id") {
new_query[attribute_name] = value;
continue;
}
if (typeof value === "object") {
if (attribute_name[0] === "$") {
new_query[attribute_name] = value;
} else {
for (const i in value) {
- new_query[attribute_name + "." + i] = (value as Record<
- string,
- any
- >)[i];
+ new_query[attribute_name + "." + i] = (
+ value as Record<string, any>
+ )[i];
}
}
} else {
new_query[attribute_name] = query[attribute_name];
}
}
return new_query;
}
diff --git a/src/datastore/negate-stage.ts b/src/datastore/negate-stage.ts
index c7d5ab7c..68161341 100644
--- a/src/datastore/negate-stage.ts
+++ b/src/datastore/negate-stage.ts
@@ -1,28 +1,28 @@
-import QueryStage, { MatchBody } from "./query-stage";
+import type { MatchBody } from "./query-stage";
export default function negate_match(stage: MatchBody) {
const negated_stage: MatchBody = {};
for (const key in stage) {
if (key === "$or") {
negated_stage.$nor = stage.$or;
} else if (key === "$nor") {
negated_stage.$or = stage.$nor;
} else if (key === "$and") {
negated_stage.$or = stage.$and?.map((expression: MatchBody) =>
negate_match(expression)
);
} else {
if ((stage[key] as MatchBody).$not) {
negated_stage[key] = (stage[key] as MatchBody)
.$not as MatchBody;
} else if (typeof stage[key] == "boolean") {
negated_stage[key] = !stage[key];
} else if (typeof stage[key] !== "object") {
negated_stage[key] = { $not: { $eq: stage[key] } };
} else {
negated_stage[key] = { $not: stage[key] };
}
}
}
return negated_stage;
}
diff --git a/src/datastore/query-not.ts b/src/datastore/query-not.ts
index 36528def..fb898a63 100644
--- a/src/datastore/query-not.ts
+++ b/src/datastore/query-not.ts
@@ -1,24 +1,24 @@
import Query, { QueryStage } from "./query";
-import QueryStep from "./query-step";
+import type QueryStep from "./query-step";
export default class Not extends Query {
constructor(query: Query) {
super();
this.addQuery(query);
}
addQuery(query: Query): void {
const steps = query.dump();
this.steps.push(...steps);
}
dump(): QueryStep[] {
return this.steps.map((step) => step.negate());
}
toPipeline(): QueryStage[] {
return this.dump()
.map((step) => step.toPipeline())
.reduce((acc, cur) => [...acc, ...cur], []);
}
}
diff --git a/src/datastore/query-or.ts b/src/datastore/query-or.ts
index cfc82769..f14e01ee 100644
--- a/src/datastore/query-or.ts
+++ b/src/datastore/query-or.ts
@@ -1,58 +1,59 @@
import Query from "./query";
-import QueryStage, { MatchBody } from "./query-stage";
+import type QueryStage from "./query-stage";
+import type { MatchBody } from "./query-stage";
import QueryStep, { Lookup, Match } from "./query-step";
export default class Or extends Query {
lookup_steps: QueryStep[] = [];
constructor(...queries: Query[]) {
super();
for (const query of queries) {
this.addQuery(query);
}
}
addQuery(query: Query): void {
const steps = query.dump();
this.lookup_steps.push(
...(steps.filter((step) => step instanceof Lookup) as Lookup[])
);
const match_stage_bodies = steps
.filter((step) => step instanceof Match)
.map((match: Match) => match.body);
if (match_stage_bodies.length) {
const match_stage: MatchBody =
match_stage_bodies.length > 1
? { $and: match_stage_bodies }
: match_stage_bodies[0];
this.steps.push(new Match(match_stage));
}
}
dump(): QueryStep[] {
return this.lookup_steps.concat(
new Match({ $or: this._getMatchExpressions() })
);
}
toPipeline(): QueryStage[] {
const lookups = this.lookup_steps
.map((step) => step.toPipeline())
.reduce((acc, cur) => acc.concat(cur), []);
return lookups.concat({ $match: { $or: this._getMatchExpressions() } });
}
_getMatchExpressions(): MatchBody[] {
return this.steps
.filter((step) => step instanceof Match)
.map((step) => step.body as MatchBody);
}
prefix(prefix: string): this {
super.prefix(prefix);
this.lookup_steps = this.lookup_steps.map((step) =>
step.prefix(prefix)
);
return this;
}
}
diff --git a/src/datastore/query-stage.ts b/src/datastore/query-stage.ts
index a9e5db9d..e0b8b758 100644
--- a/src/datastore/query-stage.ts
+++ b/src/datastore/query-stage.ts
@@ -1,27 +1,27 @@
-import { ComplexLookupBody, SimpleLookupBody } from "./query-step";
+import type { ComplexLookupBody, SimpleLookupBody } from "./query-step";
export type MatchBody = Partial<{
$not: MatchBody;
$search: any;
$nor: MatchBody[];
$or: MatchBody[];
$and: MatchBody[];
[field: string]: unknown;
}>;
type QueryStage = Partial<{
$match: MatchBody;
$lookup: SimpleLookupBody | ComplexLookupBody;
$unwind: string;
$skip: number;
$limit: number;
$sort: { [field_name: string]: 1 | -1 };
$group: {
_id: string;
[other: string]: any;
};
$count: string;
$unset: string;
}>;
export default QueryStage;
diff --git a/src/datastore/query-step.ts b/src/datastore/query-step.ts
index 5d31c526..c90f1e89 100644
--- a/src/datastore/query-step.ts
+++ b/src/datastore/query-step.ts
@@ -1,335 +1,336 @@
import object_hash from "object-hash";
import transformObject from "../utils/transform-object";
import negate_stage from "./negate-stage";
-import QueryStage, { MatchBody } from "./query-stage";
+import type QueryStage from "./query-stage";
+import type { MatchBody } from "./query-stage";
export default abstract class QueryStep {
body: any;
hash(): string {
return QueryStep.hashBody(this.body);
}
static fromStage(
stage: QueryStage,
unwind = true,
rehash = false
): QueryStep[] {
if (stage.$lookup) {
const clonedStageBody = { ...stage.$lookup };
clonedStageBody.unwind = unwind;
return [Lookup.fromBody(clonedStageBody, rehash)];
} else if (stage.$match) {
return Object.keys(stage.$match).map(
(field) => new Match({ [field]: stage?.$match?.[field] })
);
} else if (stage.$group) {
return [new Group(stage.$group)];
} else if (stage.$unwind) {
return [new Unwind(stage.$unwind)];
}
throw new Error("Unsupported stage: " + JSON.stringify(stage));
}
static hashBody(body: any) {
return object_hash(body, {
algorithm: "md5",
excludeKeys: (key) => key === "as",
});
}
abstract getUsedFields(): string[];
abstract getCost(): number;
abstract negate(): QueryStep;
abstract prefix(prefix: string): QueryStep;
abstract toPipeline(): QueryStage[];
abstract renameField(old_name: string, new_name: string): void;
}
export class Match extends QueryStep {
body: MatchBody;
constructor(body: MatchBody) {
super();
this.body = body;
if (!body) {
throw new Error("no body!");
}
}
toPipeline(): [QueryStage] {
return [{ $match: this.body }];
}
pushStage(pipeline: QueryStage[]): QueryStage[] {
pipeline.push({ $match: this.body });
return pipeline;
}
getUsedFields(): string[] {
return getAllKeys(this.body)
.map((path) => path.split("."))
.reduce((acc, fields) =>
acc.concat(fields.filter((field) => !field.startsWith("$")))
);
}
getCost(): number {
return this.body.$or ? 2 : 0;
}
negate(): Match {
return new Match(negate_stage(this.body as QueryStage));
}
prefix(prefix: string): Match {
const prop_regex = /^[a-z0-9_]/;
const ret: MatchBody = {};
for (const [prop, value] of Object.entries(this.body)) {
const new_prop =
prop_regex.test(prop) && !Array.isArray(value)
? prefix + "." + prop
: prop;
if (prop == "$or" || prop == "$and" || prop == "$nor") {
const new_values = (value as MatchBody[]).map(
(match_body) => new Match(match_body).prefix(prefix).body
);
ret[new_prop] = new_values;
} else if (prop === "$in") {
ret[new_prop] = (value as string[]).map((v) =>
v.replace(/^\$/, "$" + prefix + ".")
);
} else if (value instanceof Object) {
ret[new_prop] = new Match(value as MatchBody).prefix(
prefix
).body;
} else {
if (typeof value === "string") {
ret[new_prop] = value.startsWith("$")
? value.replace("$", "$" + prefix + ".")
: value;
} else {
ret[new_prop] = value;
}
}
}
return new Match(ret);
}
renameField(old_name: string, new_name: string): void {
this.body = transformObject(
this.body,
(prop) => {
if (prop === old_name) {
return new_name;
}
if (prop.split(".")[0] === old_name) {
return [new_name, ...prop.split(".").slice(1)].join(".");
}
return prop;
},
(prop, value) => value
);
}
}
function getAllKeys(obj: any): string[] {
return Object.keys(obj).reduce((acc, key) => {
if (obj[key] instanceof Object) {
acc.push(...getAllKeys(obj[key]));
}
if (!Array.isArray(obj)) {
acc.push(key);
}
return acc;
}, [] as string[]);
}
export type SimpleLookupBodyInput = {
from: string;
localField: string;
foreignField: string;
unwind?: boolean;
as?: string;
};
export type SimpleLookupBody = SimpleLookupBodyInput & { as: string };
export type ComplexLookupBodyInput = {
from: string;
let: Record<string, string>;
pipeline: QueryStage[];
unwind?: boolean;
as?: string;
};
export type ComplexLookupBody = ComplexLookupBodyInput & { as: string };
export type LookupBody = ComplexLookupBody | SimpleLookupBody;
export type LookupBodyInput = ComplexLookupBodyInput | SimpleLookupBodyInput;
export abstract class Lookup extends QueryStep {
abstract getUsedFields(): string[];
body: LookupBody;
unwind: boolean;
constructor(
body: SimpleLookupBodyInput | ComplexLookupBodyInput,
rehash = false
) {
super();
let hash: string = body.as || Lookup.hashBody(body);
if (!body.as || rehash) {
hash = Lookup.hashBody(body);
}
this.body = {
...body,
as: hash,
};
this.unwind = body.unwind || false;
}
static hashBody(body: LookupBodyInput): string {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { as, ...rest } = body;
return QueryStep.hashBody(rest);
}
getCost(): number {
return 8;
}
negate(): QueryStep {
return this;
}
hash(): string {
if (!this.body.as) {
throw new Error(
"Cannot hash a lookup step without an `as` property"
);
}
return this.body.as;
}
static isComplexBody(
body: ComplexLookupBodyInput | SimpleLookupBodyInput
): body is ComplexLookupBodyInput {
return Object.prototype.hasOwnProperty.call(body, "let") as boolean;
}
static fromBody(
body: ComplexLookupBodyInput | SimpleLookupBodyInput,
rehash = false
): Lookup {
if (Lookup.isComplexBody(body)) {
return new ComplexLookup(body, rehash);
} else {
return new SimpleLookup(body, rehash);
}
}
toPipeline(): QueryStage[] {
const ret = { $lookup: { ...this.body } };
delete ret.$lookup.unwind;
return [
ret,
...(this.body.unwind ? [{ $unwind: `$${this.body.as}` }] : []),
];
}
renameField(old_name: string, new_name: string) {
Function.prototype(); //noop
}
}
export class SimpleLookup extends Lookup {
unwind: boolean;
body: SimpleLookupBody;
used_fields: string[];
getUsedFields(): string[] {
return this.body.localField.split(".");
}
prefix(prefix: string) {
return new SimpleLookup({
from: this.body.from,
localField: `${prefix}.${this.body.localField}`,
foreignField: this.body.foreignField,
unwind: this.unwind,
as: `${prefix}.${this.body.as}`,
});
}
}
export class ComplexLookup extends Lookup {
body: ComplexLookupBody;
getUsedFields(): string[] {
return Object.values(this.body.let).map((entry) =>
entry.replace(/\$/g, "")
);
}
prefix(prefix: string): Lookup {
const ret = new ComplexLookup({
from: this.body.from,
let: Object.fromEntries(
Object.entries(this.body.let).map(([key, value]) => [
key,
value.replace("$", "$" + prefix + "."),
])
),
pipeline: this.body.pipeline,
// .map((stage) =>
// QueryStep.fromStage(stage).map((step) =>
// step.prefix(prefix)
// )
// )
// .reduce((acc, cur) => acc.concat(cur))
// .map((step) => step.toPipeline())
// .reduce((acc, cur) => acc.concat(cur)),
as: prefix + "." + this.body.as,
});
return ret;
}
}
abstract class SimpleQueryStep<T> {
abstract getStageName: () => string;
constructor(public body: T) {}
prefix(): SimpleQueryStep<T> {
return this;
}
getCost() {
return 2;
}
toPipeline(): QueryStage[] {
return [{ [this.getStageName()]: this.body }];
}
hash() {
return object_hash(this.body);
}
getUsedFields() {
return [];
}
negate() {
return this;
}
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars
renameField(_: string, __: string): void {}
}
export class Group extends SimpleQueryStep<{ _id: any; [key: string]: any }> {
getStageName = () => "$group";
}
export class Unwind extends SimpleQueryStep<string> {
getStageName = () => "$unwind";
renameField(old_name: string, new_name: string): void {
if ((this.body = "$" + old_name)) {
this.body = "$" + new_name;
}
}
}
diff --git a/src/datastore/query.ts b/src/datastore/query.ts
index 03f75d39..53754b57 100644
--- a/src/datastore/query.ts
+++ b/src/datastore/query.ts
@@ -1,84 +1,84 @@
-import QueryStage from "./query-stage";
+import type QueryStage from "./query-stage";
import {
ComplexLookupBodyInput,
default as QueryStep,
Lookup,
Match,
SimpleLookupBodyInput,
} from "./query-step";
export default class Query {
steps: QueryStep[];
body: any;
constructor() {
this.steps = [];
}
lookup(body: SimpleLookupBodyInput | ComplexLookupBodyInput) {
const lookup_step = Lookup.fromBody(body);
this.steps.push(lookup_step);
return lookup_step.hash();
}
match(body: { [key: string]: unknown }) {
for (const key in body) {
this.steps.push(new Match({ [key]: body[key] }));
}
}
dump() {
return this.steps;
}
toPipeline(): QueryStage[] {
return this.steps
.map((step) => step.toPipeline())
.reduce((acc, cur) => acc.concat(cur), []);
}
static fromSingleMatch(body: any) {
const query = new Query();
query.match(body);
return query;
}
static fromCustomPipeline(stages: QueryStage[], rehash = false) {
const ret = new Query();
const lookup_field_to_hash: { [field_as: string]: string } = {};
for (const stage of stages) {
const query_steps = QueryStep.fromStage(stage, false, rehash);
for (const [old_name, new_name] of Object.entries(
lookup_field_to_hash
)) {
query_steps.forEach((step) =>
step.renameField(old_name, new_name)
);
}
for (const query_step of query_steps) {
if (query_step instanceof Lookup) {
lookup_field_to_hash[stage?.$lookup?.as as string] =
query_step.body.as;
}
}
ret.steps.push(...query_steps);
}
return ret;
}
_isUnwindStage(stages: QueryStage[], i: number) {
if (!stages[i].$lookup) {
return false;
}
return (stages[i + 1]?.$unwind && true) || false;
}
prefix(prefix: string): Query {
this.steps = this.steps.map((step) => step.prefix(prefix));
return this;
}
}
export { default as And } from "./query-and";
export { default as Not } from "./query-not";
export { default as Or } from "./query-or";
export { default as QueryStage } from "./query-stage";
diff --git a/src/email/logger-mailer.ts b/src/email/logger-mailer.ts
index d9b8cc54..5135d338 100644
--- a/src/email/logger-mailer.ts
+++ b/src/email/logger-mailer.ts
@@ -1,15 +1,15 @@
import Mailer from "./mailer";
-import { MessageData } from "./message";
+import type { MessageData } from "./message";
export default class LoggerMailer extends Mailer {
async verify() {
return true;
}
async sendEmail({ to, subject, text }: MessageData) {
this.app.Logger.info("✉ MAIL", "Would send an email here", {
to,
subject,
text,
});
}
}
diff --git a/src/email/mailer.ts b/src/email/mailer.ts
index 1e8ef2d5..12a6cf86 100644
--- a/src/email/mailer.ts
+++ b/src/email/mailer.ts
@@ -1,19 +1,19 @@
-import { App } from "../main";
-import { MessageData } from "./message";
+import type { App } from "../main";
+import type { MessageData } from "./message";
export default abstract class Mailer {
app: App;
abstract verify(): Promise<boolean>;
abstract sendEmail(
message: MessageData & { from_name: string }
): Promise<void>;
async send(message_data: MessageData) {
return this.sendEmail({
...message_data,
from_name: this.app.ConfigManager.get("email").from_name,
});
}
async init(app: App) {
this.app = app;
}
}
diff --git a/src/email/message.ts b/src/email/message.ts
index 1caade86..6dace7cc 100644
--- a/src/email/message.ts
+++ b/src/email/message.ts
@@ -1,26 +1,26 @@
import assert from "assert";
-import App from "../app/app";
+import type App from "../app/app";
export type MessageData = {
to: string;
subject: string;
html: string;
attachments: any[];
text: string;
};
export default class Message {
data: MessageData;
constructor(data: MessageData) {
assert(data.to);
assert(data.subject);
assert(data.html);
assert(
data.attachments === undefined || Array.isArray(data.attachments)
);
this.data = data;
}
async send(app: App) {
return app.mailer.send(this.data);
}
}
diff --git a/src/email/smtp-mailer.ts b/src/email/smtp-mailer.ts
index d0c1d64d..a0e42a7b 100644
--- a/src/email/smtp-mailer.ts
+++ b/src/email/smtp-mailer.ts
@@ -1,66 +1,66 @@
import assert from "assert";
import nodemailer from "nodemailer";
-import { App } from "../main";
+import type { App } from "../main";
import Mailer from "./mailer";
-import { MessageData } from "./message";
+import type { MessageData } from "./message";
export default class SmtpMailer extends Mailer {
mail_config: { from_name: string; from_address: string };
transport: nodemailer.Transporter;
constructor(config: {
host: string;
port: number;
user: string;
password: string;
}) {
super();
assert(typeof config.host == "string");
assert(typeof config.port == "number");
assert(typeof config.user == "string");
assert(typeof config.password == "string");
this.transport = nodemailer.createTransport({
host: config.host,
port: config.port,
auth: {
user: config.user,
pass: config.password,
},
});
}
async verify() {
return this.transport.verify();
}
async init(app: App) {
await super.init(app);
this.mail_config = app.ConfigManager.get("email");
}
async sendEmail({
to,
subject,
text,
html,
from_name,
attachments,
}: MessageData & { from_name: string }) {
return this.transport.sendMail({
from: `${from_name || this.mail_config.from_name} <${
this.mail_config.from_address
}>`,
to,
subject: subject.toString(),
text,
html,
attachments,
});
}
static default_config = {
host: null,
port: null,
user: null,
password: null,
};
}
diff --git a/src/email/templates/simple.ts b/src/email/templates/simple.ts
index fce73e33..978dacd4 100644
--- a/src/email/templates/simple.ts
+++ b/src/email/templates/simple.ts
@@ -1,96 +1,96 @@
import Message from "./../message";
import path from "path";
import mjml2html from "mjml";
import assert from "assert";
-import { App } from "../../main";
+import type { App } from "../../main";
export type Button = { text: string; href: string };
export type SimpleTemplateData = {
text: string;
subject: string;
to: string;
buttons?: Button[];
};
export default async function SimpleTemplate(
app: App,
data: SimpleTemplateData
) {
assert(data.text);
assert(data.subject);
assert(data.to);
assert(data.buttons === undefined || Array.isArray(data.buttons));
if (data.buttons === undefined) {
data.buttons = [];
}
const logo_cid = Math.floor(Math.random() * 10e6).toString();
let html;
if ((app.ConfigManager.get("core") as any).environment === "production") {
html = get_html(app, data, logo_cid);
} else {
html = /* HTML */ `Dummy html text. Enable production mode in app config
to render html each time. This is disabled by default to speed up test
execution time.`;
}
const text = data.text + "\n\n" + buttons_to_text(data.buttons);
return new Message({
to: data.to,
subject: data.subject,
attachments: [
{
filename: path.basename(app.manifest.logo),
path: app.manifest.logo,
cid: logo_cid,
},
],
text,
html,
});
}
function buttons_to_text(buttons: Button[]) {
return buttons
.map((button) => `\t* ${button.text}: ${button.href}`)
.join("\n");
}
function get_html(app: App, data: SimpleTemplateData, logo_cid: string) {
const result = mjml2html(`
<mjml>
<mj-body>
<mj-section>
<mj-column>
<mj-image width="220" src="cid:${logo_cid}"></mj-image>
<mj-divider border-color="${
(app.manifest.colors && app.manifest.colors.primary) ||
"black"
}"></mj-divider>
<mj-text>
<h1>
${data.subject}
</h1>
${data.text}
</mj-text>
${
(data.buttons &&
data.buttons.map(
(button) =>
`<mj-button href="${
button.href
}" font-size="20px" background-color="${
(app.manifest.colors &&
app.manifest.colors.primary) ||
"#0074D9"
}">${button.text}</mj-button>`
)) ||
""
}
</mj-column>
</mj-section>
</mj-body>
</mjml>
`);
return result.html;
}
diff --git a/src/http/error-to-boom.ts b/src/http/error-to-boom.ts
index 9ff70ba5..2f458ccb 100644
--- a/src/http/error-to-boom.ts
+++ b/src/http/error-to-boom.ts
@@ -1,23 +1,23 @@
import Boom from "boom";
-import SealiousError from "../response/errors";
+import type SealiousError from "../response/errors";
const error_code_map = {
validation: 403,
value_exists: 409,
invalid_credentials: 401,
not_found: 404,
permission: 401,
bad_subject: 404,
bad_subject_action: 405,
field_does_not_support_attachments: 405,
};
export default function error_to_boom(error: SealiousError) {
const code = error_code_map[error.type as keyof typeof error_code_map];
const ret = new Boom(error.message, { statusCode: code });
// @ts-ignore;
ret.output.payload.type = error.type;
// @ts-ignore;
ret.output.payload.data = error.data;
return ret;
}
diff --git a/src/http/extract-context.test.ts b/src/http/extract-context.test.ts
index a3e72403..c685b85e 100644
--- a/src/http/extract-context.test.ts
+++ b/src/http/extract-context.test.ts
@@ -1,26 +1,26 @@
import assert from "assert";
import { withRunningApp } from "../test_utils/with-test-app";
import { assertThrowsAsync } from "../test_utils/assert-throws-async";
-import { AxiosError } from "axios";
+import type { AxiosError } from "axios";
describe("Extract context", () => {
it("Behaves correctly when the session cookie is missing", async () =>
withRunningApp(null, async ({ app, rest_api }) => {
const user = await app.collections.users.suCreate({
username: "any",
password: "anyanyany",
});
await rest_api.login({ username: "any", password: "anyanyany" });
await assertThrowsAsync(
() => rest_api.get("/api/v1/collections/users/me"), // cookie left out intentionally
(error: AxiosError) => {
assert.strictEqual(
error?.response?.data?.message,
"You're not logged in!"
);
}
);
}));
});
diff --git a/src/http/extract-context.ts b/src/http/extract-context.ts
index 081636f2..191f710b 100644
--- a/src/http/extract-context.ts
+++ b/src/http/extract-context.ts
@@ -1,46 +1,45 @@
-import { Middleware } from "@koa/router";
-import App from "../app/app";
+import type { Middleware } from "@koa/router";
import Context from "../context";
export default function extract_context(): Middleware {
return async function (ctx, next) {
const config = ctx.$app.ConfigManager.get("www-server");
const cookie_name = config["session-cookie-name"];
let session_id: string | undefined = ctx.cookies.get(cookie_name);
const timestamp = Date.now();
if (ctx.$context) {
await next();
return;
}
if (!session_id) {
ctx.$context = new Context(ctx.$app, timestamp, null, null);
} else {
const sessions = await ctx.$app.collections.sessions
.suList()
.filter({ "session-id": session_id })
.fetch();
let user_id;
if (sessions.empty) {
session_id = undefined;
} else {
user_id = sessions.items[0].get("user") as string;
}
ctx.$app.Logger.debug(
"EXTRACT CONTEXT",
"User for this request is",
user_id
);
ctx.$context = new Context(
ctx.$app,
timestamp,
user_id,
session_id
);
}
await next();
};
}
module.exports = extract_context;
diff --git a/src/http/handle-error.ts b/src/http/handle-error.ts
index 0aa22747..04ebf60c 100644
--- a/src/http/handle-error.ts
+++ b/src/http/handle-error.ts
@@ -1,33 +1,31 @@
-import error_to_boom from "./error-to-boom";
-import { App } from "../main";
import SealiousError from "../response/errors";
-import { Middleware } from "@koa/router";
+import type { Middleware } from "@koa/router";
const error_code_map: { [type: string]: number } = {
validation: 403,
value_exists: 409,
invalid_credentials: 401,
not_found: 404,
permission: 401,
bad_subject: 404,
bad_subject_action: 405,
field_does_not_support_attachments: 405,
};
export default function handleError(): Middleware {
return async function (ctx, next) {
try {
await next();
} catch (error) {
ctx.$app.Logger.error("HTTP ERR", "Responding with error", error);
if (error instanceof SealiousError && error.is_user_fault) {
ctx.status = error_code_map[error.type] || 500;
ctx.body = error.toObject();
} else {
ctx.status = 500;
ctx.body = { message: "Server error" };
console.error(error);
}
}
};
}
diff --git a/src/http/http-to-method-name.ts b/src/http/http-to-method-name.ts
index 7992e42e..d343933f 100644
--- a/src/http/http-to-method-name.ts
+++ b/src/http/http-to-method-name.ts
@@ -1,11 +1,11 @@
-import { ActionName } from "../action";
+import type { ActionName } from "../action";
const method_map: { [method: string]: ActionName } = {
GET: "show",
POST: "create",
PATCH: "edit",
PUT: "replace",
DELETE: "delete",
};
export default method_map;
diff --git a/src/http/http.ts b/src/http/http.ts
index e030e999..b11a7dff 100644
--- a/src/http/http.ts
+++ b/src/http/http.ts
@@ -1,53 +1,53 @@
import { Context, default as Koa } from "koa";
import Static from "koa-static";
import Router from "@koa/router";
-import { Server } from "http";
+import type { Server } from "http";
import mount from "koa-mount";
import installQS from "koa-qs";
import handleError from "./handle-error";
-import { App } from "../main";
+import type { App } from "../main";
export default class HttpServer {
name: "www-serer";
private server: Server;
koa: Koa;
router: Router;
config: {
port: number;
"session-cookie-name": string;
"max-payload-bytes": number;
"api-base": string;
};
constructor(public app: App) {
this.koa = new Koa();
installQS(this.koa);
this.koa.context.$app = this.app;
this.router = new Router();
// const rest_url_base = this.config["api-base"];
}
async start() {
this.koa.use(handleError());
this.koa.use(this.router.routes());
this.config = this.app.ConfigManager.get("www-server");
this.server = this.koa.listen(this.config.port);
this.app.Logger.info(
"STARTED",
`App running. URL set in manifest: ${this.app.manifest.base_url}`
);
}
async stop() {
this.server.close();
}
addStaticRoute(url_path: string, local_path: string) {
this.koa.use(mount(url_path, Static(local_path)));
}
}
diff --git a/src/http/match-policy.ts b/src/http/match-policy.ts
index 0647dcb8..f85cd843 100644
--- a/src/http/match-policy.ts
+++ b/src/http/match-policy.ts
@@ -1,18 +1,18 @@
-import { Middleware } from "@koa/router";
-import Policy from "../chip-types/policy";
+import type { Middleware } from "@koa/router";
+import type Policy from "../chip-types/policy";
export default function MatchPolicy(policy: Policy): Middleware {
return async function (ctx, next) {
const result = await policy.check(ctx.$context);
if (!result) {
ctx.body = "Not allowed";
ctx.status = 403;
return;
}
if (!result.allowed) {
ctx.body = result.reason;
ctx.status = 403;
}
if (result.allowed) await next();
};
}
diff --git a/src/http/parse-body.subtest.ts b/src/http/parse-body.subtest.ts
index a328e968..fca64bcb 100644
--- a/src/http/parse-body.subtest.ts
+++ b/src/http/parse-body.subtest.ts
@@ -1,78 +1,80 @@
import assert from "assert";
-import { withRunningApp } from "../test_utils/with-test-app";
-import { assertThrowsAsync } from "../test_utils/assert-throws-async";
+import {
+ TestAppConstructor,
+ withRunningApp,
+} from "../test_utils/with-test-app";
import Field from "../chip-types/field";
import { Collection, FieldTypes } from "../main";
-import { TestAppType } from "../test_utils/test-app";
import asyncRequest from "../test_utils/async-request";
+import { TestApp } from "../test_utils/test-utils";
-function extend(t: TestAppType) {
+function extend(t: TestAppConstructor<TestApp>) {
class ArrayOfObjects extends Field {
typeName = "array-of-objects";
async isProperValue(_: any, new_value: any) {
if (!Array.isArray(new_value)) {
return Field.invalid("It should be array of objects.");
}
for (const value of new_value) {
if (typeof value !== "object") {
return Field.invalid("One of array item isn't object.");
}
}
return Field.valid();
}
}
const complex_data = new (class ComplexData extends Collection {
name = "complex-data";
fields = {
body: new ArrayOfObjects(),
source: new FieldTypes.Image(),
};
})();
const strings = new (class Strings extends Collection {
name = "strings";
fields = {
title: new FieldTypes.Text(),
};
})();
return class extends t {
collections = {
- ...t.BaseCollections,
+ ...TestApp.BaseCollections,
strings,
"complex-data": complex_data,
};
};
}
describe("get-request-body", () => {
it("handles complex data sent as multipart/form-data", async () => {
await withRunningApp(extend, async ({ port }) => {
// PNG file is empty but it doesnt matter for the test
const form_data =
'------------------------------4ebf00fbcf09\r\nContent-Disposition: form-data; name="source"; filename="test.png"\r\nContent-Type: image/png\r\n\r\nPNG\r\n\r\n\r\n------------------------------4ebf00fbcf09\r\nContent-Disposition: form-data; name="body"; filename="blob"\r\nContent-Type: application/json\r\n\r\n[["Foo", {"Bar": "baz"}]]\r\n------------------------------4ebf00fbcf09--\r\n';
const options = {
hostname: "localhost",
port: port,
path: "/api/v1/collections/complex-data",
method: "POST",
headers: {
"Content-Type":
"multipart/form-data; boundary=----------------------------4ebf00fbcf09",
},
};
const { body, source } = (await asyncRequest(
options,
form_data
)) as {
source: Record<string, unknown>;
body: Array<Record<string, unknown>>;
};
assert.strict.deepStrictEqual(body, [["Foo", { Bar: "baz" }]]);
assert.deepStrictEqual(source?.filename, "test.png");
});
});
});
diff --git a/src/http/parse-body.ts b/src/http/parse-body.ts
index 90fe68fe..a5964b7c 100644
--- a/src/http/parse-body.ts
+++ b/src/http/parse-body.ts
@@ -1,48 +1,48 @@
-import { Middleware } from "@koa/router";
+import type { Middleware } from "@koa/router";
import { promises as fs } from "fs";
import koaBody from "koa-body";
import File from "../data-structures/file";
import { ValidationError } from "../response/errors";
export default function parseBody(): Middleware {
const koaParser = koaBody({ multipart: true });
return async (ctx, next) => {
await koaParser(ctx, () => Promise.resolve());
if (!ctx.request.body) {
ctx.request.body = {};
}
const promises: Promise<void>[] = [];
if (ctx.request.files) {
for (const file_name in ctx.request.files) {
const file = ctx.request.files[file_name];
if (Array.isArray(file)) {
throw new ValidationError(
"Multiple files within one field are not supported"
);
}
if (file.type === "application/json" && file.name === "blob") {
promises.push(
fs.readFile(file.path, "utf-8").then((string) => {
ctx.request.body[file_name] = JSON.parse(string);
})
);
} else {
promises.push(
File.fromPath(
ctx.$app,
file.path,
file.name || undefined
).then((sealious_file) => {
ctx.request.body[file_name] = sealious_file;
})
);
}
}
}
await Promise.all(promises);
ctx.$app.Logger.info("REQUEST", "Parsed body", ctx.request.body);
ctx.$body = ctx.request.body;
await next();
};
}
diff --git a/src/http/routes/logo.ts b/src/http/routes/logo.ts
index 33b03a7d..09ae30a1 100644
--- a/src/http/routes/logo.ts
+++ b/src/http/routes/logo.ts
@@ -1,11 +1,11 @@
-import { Middleware } from "@koa/router";
+import type { Middleware } from "@koa/router";
import { basename, dirname } from "path";
import send from "koa-send";
const logo: Middleware = async (ctx) => {
await send(ctx, basename(ctx.$app.manifest.logo), {
root: dirname(ctx.$app.manifest.logo),
});
};
export default logo;
diff --git a/src/http/routes/uploaded-files.test.ts b/src/http/routes/uploaded-files.test.ts
index 38d2a095..ab39855e 100644
--- a/src/http/routes/uploaded-files.test.ts
+++ b/src/http/routes/uploaded-files.test.ts
@@ -1,48 +1,49 @@
import assert from "assert";
import FileField from "../../app/base-chips/field-types/file";
import { Collection } from "../../main";
import asyncRequest from "../../test_utils/async-request";
+import { TestApp } from "../../test_utils/test-app";
import { withRunningApp } from "../../test_utils/with-test-app";
describe("uploaded_files", () => {
it("has a test", () => {
return withRunningApp(
(test_app_type) => {
return class extends test_app_type {
collections = {
- ...test_app_type.BaseCollections,
+ ...TestApp.BaseCollections,
with_file: new (class extends Collection {
fields = {
file: new FileField(),
};
})(),
};
};
},
async ({ port, rest_api }) => {
const form_data =
'------------------------------4ebf00fbcf09\r\nContent-Disposition: form-data; name="file"; filename="test.txt"\r\nContent-Type: text/plain\r\n\r\nI AM A TEST\r\n\r\n\r\n------------------------------4ebf00fbcf09--';
const options = {
hostname: "localhost",
port: port,
path: "/api/v1/collections/with_file",
method: "POST",
headers: {
"Content-Type":
"multipart/form-data; boundary=----------------------------4ebf00fbcf09",
},
};
const data = (await asyncRequest(options, form_data)) as Record<
"file" | "id",
string
>;
const url_regex = new RegExp(
/\/api\/v1\/uploaded-files\/\S*\/test.txt/
);
assert.match(data.file, url_regex);
const response = await rest_api.get(data.file);
assert.strictEqual(response, "I AM A TEST\r\n\r\n");
}
);
});
});
diff --git a/src/http/type-overrides.ts b/src/http/type-overrides.ts
index f64b2a95..c910608a 100644
--- a/src/http/type-overrides.ts
+++ b/src/http/type-overrides.ts
@@ -1,57 +1,56 @@
-import * as Sealious from "../main";
-import Router from "@koa/router";
-import { Socket } from "net";
-import * as url from "url";
+import type * as Sealious from "../main";
+import type { Socket } from "net";
+import type * as url from "url";
// adding this so properties `$app` and `$context` of `ctx` are known
declare module "koa" {
interface BaseContext {
$context: Sealious.Context;
$app: Sealious.App;
$body: Record<string, unknown>;
}
}
type Query = Record<string, unknown>;
//shamelessly copied the declarations from @types/koa. Changed here is only the
//`query` parameter type, again to help with linting
declare module "koa" {
interface ContextDelegatedRequest {
header: any;
headers: any;
url: string;
origin: string;
href: string;
method: string;
path: string;
query: Query;
querystring: string;
search: string;
host: string;
hostname: string;
URL: url.URL;
fresh: boolean;
stale: boolean;
idempotent: boolean;
socket: Socket;
protocol: string;
secure: boolean;
ip: string;
ips: string[];
subdomains: string[];
accepts(): string[] | boolean;
accepts(...types: string[]): string | boolean;
accepts(types: string[]): string | boolean;
acceptsEncodings(): string[] | boolean;
acceptsEncodings(...encodings: string[]): string | boolean;
acceptsEncodings(encodings: string[]): string | boolean;
acceptsCharsets(): string[] | boolean;
acceptsCharsets(...charsets: string[]): string | boolean;
acceptsCharsets(charsets: string[]): string | boolean;
acceptsLanguages(): string[] | boolean;
acceptsLanguages(...langs: string[]): string | boolean;
acceptsLanguages(langs: string[]): string | boolean;
get(field: string): string;
}
}
diff --git a/src/main.ts b/src/main.ts
index 0cb6291c..1bc46236 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,35 +1,36 @@
export { ActionName } from "./action";
-export { default as App } from "./app/app";
+export { default as Policy, PolicyClass } from "./chip-types/policy";
+export * as Policies from "./app/policy-types/policy-types";
+export { default as Collection } from "./chip-types/collection";
+export { default as Field } from "./chip-types/field";
export * as FieldTypes from "./app/base-chips/field-types/field-types";
+export { default as App } from "./app/app";
export * as SpecialFilters from "./app/base-chips/special_filters/special-filters";
export { default as Collections } from "./app/collections/collections";
export { default as Config } from "./app/config";
export { default as ConfigManager } from "./app/config-manager";
export { EventDescription } from "./app/delegate-listener";
export { default as Logger } from "./app/logger";
export { default as Manifest } from "./app/manifest";
export { default as MetadataFactory } from "./app/metadata";
-export * as Policies from "./app/policy-types/policy-types";
export { default as CalculatedField } from "./chip-types/calculated-field";
-export { default as Collection } from "./chip-types/collection";
export { default as CollectionItem } from "./chip-types/collection-item";
export * from "./chip-types/collection-item-body";
export * from "./chip-types/field";
-export { default as Field } from "./chip-types/field";
export { default as ItemList, ItemListResult } from "./chip-types/item-list";
-export { default as Policy, PolicyClass } from "./chip-types/policy";
export { default as SpecialFilter } from "./chip-types/special-filter";
export { default as Context, SuperContext } from "./context";
export { default as File } from "./data-structures/file";
export { AllowAll } from "./datastore/allow-all";
export { default as DenyAll } from "./datastore/deny-all";
export { default as Query } from "./datastore/query";
export { default as QueryTypes } from "./datastore/query-types";
export { default as LoggerMailer } from "./email/logger-mailer";
export { default as SMTPMailer } from "./email/smtp-mailer";
export * as EmailTemplates from "./email/templates/templates";
export { default as HttpServer } from "./http/http";
export { default as Middlewares } from "./http/middlewares";
export { default as i18nFactory } from "./i18n/i18n";
export * as Errors from "./response/errors";
export * as TestUtils from "./test_utils/test-utils";
+export * as Queries from "./datastore/query";
diff --git a/src/response/errors.ts b/src/response/errors.ts
index fb0c2904..fae99413 100644
--- a/src/response/errors.ts
+++ b/src/response/errors.ts
@@ -1,197 +1,197 @@
-import { ItemFields } from "../chip-types/collection-item-body";
-import { Collection } from "../main";
+import type { ItemFields } from "../chip-types/collection-item-body";
+import type { Collection } from "../main";
export type ErrorParams = {
is_user_fault: boolean;
type: string;
is_developer_fault: boolean;
data: any;
};
export interface ErrorLikeObject {
message: string;
type: string;
data: any;
}
export default class SealiousError<
DataShape = Record<string, unknown>
> extends Error {
is_user_fault: boolean;
data: DataShape;
is_developer_fault: boolean;
sealious_error = true;
type: string;
message: string;
constructor(message: string, _params?: ErrorParams, data?: any) {
super(message);
this.message = message;
const params = _params || ({} as ErrorParams);
this.is_user_fault = params?.is_user_fault || false;
this.type = params.type === undefined ? "error" : params.type;
this.data = data || params.data || {};
this.is_developer_fault =
params.is_developer_fault === undefined
? false
: params.is_developer_fault;
}
toObject(): ErrorLikeObject {
return {
message: this.message,
type: this.type,
data: this.data,
};
}
}
export class ValidationError extends SealiousError {
constructor(message: string, params: Partial<ErrorParams> = {}) {
super(message, {
data: params,
is_user_fault: true,
type: "validation",
is_developer_fault: false,
});
}
}
export class ValueExists extends SealiousError {
constructor(message: string, params?: any) {
super(message, {
...params,
is_user_fault: true,
type: "value_exists",
});
}
}
export class InvalidCredentials extends SealiousError {
constructor(message: string, params?: any) {
super(message, {
...params,
is_user_fault: true,
type: "invalid_credentials",
});
}
}
export class NotFound extends SealiousError {
constructor(message: string, params?: any) {
super(message, {
...params,
is_user_fault: true,
type: "not_found",
});
}
}
export class DeveloperError extends SealiousError {
constructor(message: string, params?: any) {
super(message, {
...params,
is_user_fault: false,
is_developer_fault: true,
type: "dev_error",
});
}
}
export class BadContext extends SealiousError {
constructor(message: string, params?: any) {
super(message, {
...params,
is_user_fault: true,
type: "permission",
});
}
}
export class ServerError extends SealiousError {
constructor(message: string, params?: any) {
super(message, {
...params,
is_user_fault: false,
is_developer_fault: false,
type: "server_error",
});
}
}
export class BadSubjectPath extends SealiousError {
constructor(message: string, params?: any) {
super(message, {
...params,
is_user_fault: true,
type: "bad_subject",
});
}
}
export class BadSubjectAction extends SealiousError {
constructor(message: string, params?: any) {
super(message, {
...params,
is_user_fault: true,
type: "bad_subject_action",
});
}
}
export class FieldDoesNotSupportAttachments extends SealiousError {
constructor(message: string, params?: any) {
super(message, {
...params,
is_user_fault: true,
type: "field_does_not_support_attachments",
});
}
}
export class FieldsError<C extends Collection> extends SealiousError<{
collection: C;
field_messages: { [field in keyof ItemFields<C>]: { message: string } };
other_messages: string[];
}> {
constructor(
collection: C,
public field_messages: {
[index: string]: { message: string } | undefined;
},
public other_messages: string[] = []
) {
super("Invalid field values", {
is_user_fault: true,
is_developer_fault: false,
type: "validation",
data: {
collection: collection.name,
field_messages,
other_messages,
},
});
}
hasErrors(): boolean {
return Object.keys(this.field_messages).length > 0;
}
getSimpleMessages(): Partial<{ [field in keyof ItemFields<C>]: string }> {
return Object.fromEntries(
- Object.entries(this.data.field_messages).map(
- ([field_name, { message }]) => [field_name, message]
- )
+ Object.entries(
+ this.data.field_messages as Record<string, { message: string }>
+ ).map(([field_name, { message }]) => [field_name, message])
) as Partial<{ [field in keyof ItemFields<C>]: string }>;
}
static isFieldsError<C extends Collection>(
collection: C,
e: unknown
): e is FieldsError<C> {
return e instanceof FieldsError && e.data.collection == collection.name;
}
getErrorForField(field_name: keyof ItemFields<C>): string {
return this.data.field_messages?.[field_name]?.message || "";
}
}
diff --git a/src/response/response.ts b/src/response/response.ts
index d00a9326..099dd59a 100644
--- a/src/response/response.ts
+++ b/src/response/response.ts
@@ -1,30 +1,30 @@
-import SealiousError from "./errors";
+import type SealiousError from "./errors";
class Response {
status: "error" | "success";
type: string;
status_message: string;
data: any;
constructor(
data: any,
is_error: boolean,
type: string,
status_message: string
) {
this.status = is_error ? "error" : "success";
this.type = type || "response";
this.status_message = status_message || "ok";
this.data = data || {};
}
static fromError(sealious_error: SealiousError) {
return {
data: sealious_error.data || {},
is_error: true,
type: sealious_error.type,
status_message: sealious_error.message,
message: sealious_error.message,
};
}
}
module.exports = Response;
diff --git a/src/test_utils/database-clear.ts b/src/test_utils/database-clear.ts
index dc8102f7..120745b9 100644
--- a/src/test_utils/database-clear.ts
+++ b/src/test_utils/database-clear.ts
@@ -1,20 +1,20 @@
-import { App } from "../main";
+import type { App } from "../main";
export async function databaseClear(app: App) {
if (app.Datastore.db) {
app.Logger.info("TEST APP", "Clearing the database...");
for (const collection_name in app.collections) {
// eslint-disable-next-line no-await-in-loop
await app.Datastore.remove(
collection_name,
{},
"just_one" && false
);
}
await app.Datastore.remove(
app.Metadata.db_collection_name,
{},
"just_one" && false
);
}
}
diff --git a/src/test_utils/mailcatcher.ts b/src/test_utils/mailcatcher.ts
index fd4ef5d6..6ba3ebb3 100644
--- a/src/test_utils/mailcatcher.ts
+++ b/src/test_utils/mailcatcher.ts
@@ -1,35 +1,35 @@
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import axios from "axios";
-import App from "../app/app";
+import type App from "../app/app";
import asyncForEach from "../utils/async-foreach";
export type MailcatcherMessage = {
recipients: string[];
subject: string;
id: number;
sender: string;
};
export default class MailcatcherAPI {
constructor(public smtp_api_url: string, private app: App) {}
async getMessages() {
const app_address = this.app.ConfigManager.get("email").from_address;
const all_messages = (await axios.get(`${this.smtp_api_url}/messages`))
.data as MailcatcherMessage[];
return all_messages.filter(
(message) => message.sender == `<${app_address}>`
);
}
async getMessageById(id: number) {
return (await axios.get(`${this.smtp_api_url}/messages/${id}.html`))
.data as string;
}
async deleteAllInstanceEmails() {
const messages = await this.getMessages();
await asyncForEach(messages, async (m) => {
await axios.delete(`${this.smtp_api_url}/messages/${m.id}`);
});
}
}
diff --git a/src/test_utils/test-app.ts b/src/test_utils/test-app.ts
index e3cdc899..e27e9206 100644
--- a/src/test_utils/test-app.ts
+++ b/src/test_utils/test-app.ts
@@ -1,95 +1,85 @@
/* eslint-disable */
import locreq_curry from "locreq";
const locreq = locreq_curry(__dirname);
import { App, SMTPMailer } from "../main";
-import { Environment } from "../app/config";
-import { LoggerLevel } from "../app/logger";
+import type { Environment } from "../app/config";
+import type { LoggerLevel } from "../app/logger";
import LoggerMailer from "../email/logger-mailer";
-export const get_test_app = ({
- env,
- port,
- base_url,
- uniq_id,
-}: {
- env: Environment;
- port: number;
- base_url: string;
- uniq_id: string;
-}) => {
- return class TestApp extends App {
- clear_database_on_stop: boolean = true;
- collections = { ...App.BaseCollections };
- config = {
+export class TestApp extends App {
+ clear_database_on_stop: boolean = true;
+ collections = { ...App.BaseCollections };
+ constructor(
+ uniq_id: string,
+ env: Environment,
+ port: number,
+ base_url: string,
+ public config = {
upload_path: "/tmp",
datastore_mongo: {
host: process.env.SEALIOUS_DB_HOST || "127.0.0.1",
password: "sealious-test",
port: parseInt(process.env.SEALIOUS_DB_PORT || "20722"),
db_name: "sealious-test",
},
email: {
from_name: "Sealious test app",
from_address: `sealious-${uniq_id}@example.com`,
},
core: { environment: env },
app: { version: "0.0.0-test" },
logger: {
level: (process.env.SEALIOUS_DEBUG || "none") as LoggerLevel,
},
"www-server": {
port,
},
password_hash: {
iterations: 1,
},
- };
- manifest = {
+ },
+ public manifest = {
name: "testing app",
logo: locreq.resolve("src/assets/logo.png"),
default_language: "pl",
version: "0.0.0-test",
base_url,
colors: {
primary: "#4d394b",
},
admin_email: "admin@example.com",
- };
+ },
+ public mailer = env == "production"
+ ? new SMTPMailer({
+ host: process.env.SEALIOUS_SMTP_HOST || "127.0.0.1",
+ port: parseInt(process.env.SEALIOUS_SMTP_PORT || "1825"),
+ user: "any",
+ password: "any",
+ })
+ : new LoggerMailer()
+ ) {
+ super();
+ }
- mailer =
- env == "production"
- ? new SMTPMailer({
- host: process.env.SEALIOUS_SMTP_HOST || "127.0.0.1",
- port: parseInt(
- process.env.SEALIOUS_SMTP_PORT || "1825"
- ),
- user: "any",
- password: "any",
- })
- : new LoggerMailer();
-
- async start() {
- this.on("stopping", async () => {
- if (this.clear_database_on_stop && this.Datastore.db) {
- this.Logger.info("TEST APP", "Clearing the database...");
- for (const collection_name in this.collections) {
- await this.Datastore.remove(
- collection_name,
- {},
- "just_one" && false
- );
- }
+ async start() {
+ this.on("stopping", async () => {
+ if (this.clear_database_on_stop && this.Datastore.db) {
+ this.Logger.info("TEST APP", "Clearing the database...");
+ for (const collection_name in this.collections) {
await this.Datastore.remove(
- this.Metadata.db_collection_name,
+ collection_name,
{},
"just_one" && false
);
}
- });
-
- await super.start();
- }
- };
-};
+ await this.Datastore.remove(
+ this.Metadata.db_collection_name,
+ {},
+ "just_one" && false
+ );
+ }
+ });
-export type TestAppType = ReturnType<typeof get_test_app>;
+ await super.start();
+ }
+}
diff --git a/src/test_utils/with-test-app.ts b/src/test_utils/with-test-app.ts
index 475882d2..5ec419ad 100644
--- a/src/test_utils/with-test-app.ts
+++ b/src/test_utils/with-test-app.ts
@@ -1,117 +1,120 @@
import { v4 as uuid } from "uuid";
import getPort from "get-port";
-import { Environment } from "../app/config";
-import { App } from "../main";
-import mailcatcher from "./mailcatcher";
+import type { Environment } from "../app/config";
import MockRestApi from "./rest-api";
-import { get_test_app, TestAppType } from "./test-app";
import MailcatcherAPI from "./mailcatcher";
+import { TestApp } from "./test-app";
-type TestCallback = (params: CallbackParams) => Promise<any>;
+export type TestAppConstructor<T extends TestApp = TestApp> = new (
+ uniq_id: string,
+ env: Environment,
+ port: number,
+ base_url: string
+) => T;
+
+type CallbackParams<FinalTestAppType extends TestApp> = {
+ app: FinalTestAppType;
+ base_url: string;
+ smtp_api_url: string;
+ rest_api: MockRestApi;
+ port: number;
+ mail_api: MailcatcherAPI;
+ app_class: TestAppConstructor<TestApp>;
+ uniq_id: string;
+ env: Environment;
+};
-type extendFn = null | ((app_class: TestAppType) => TestAppType);
+type TestCallback<FinalTestAppType extends TestApp> = (
+ params: CallbackParams<FinalTestAppType>
+) => Promise<any>;
+
+type extendFn<FinalTestAppType extends TestApp> =
+ | null
+ | ((
+ app_class: TestAppConstructor<TestApp>
+ ) => TestAppConstructor<FinalTestAppType>);
const test_collections: { [collection: string]: string } = {};
-export async function withStoppedApp(
- extend_fn: extendFn,
- cb: TestCallback,
+export async function withStoppedApp<FinalTestAppType extends TestApp>(
+ extend_fn: extendFn<FinalTestAppType>,
+ cb: TestCallback<FinalTestAppType>,
test_collection?: string // tests with the same collection get assigned the same db id
): Promise<any> {
await withTestApp(
"auto_start" && false,
"dev",
extend_fn,
cb,
test_collection
);
}
-export async function withRunningApp(
- extend_fn: extendFn,
- cb: TestCallback,
+export async function withRunningApp<FinalTestAppType extends TestApp>(
+ extend_fn: extendFn<FinalTestAppType>,
+ cb: TestCallback<FinalTestAppType>,
test_collection?: string // tests with the same collection get assigned the same db id
): Promise<any> {
await withTestApp(
"auto_start" && true,
"dev",
extend_fn,
cb,
test_collection
);
}
function getAppID(test_collection?: string) {
let uniq_id;
if (test_collection) {
if (!test_collections[test_collection]) {
test_collections[test_collection] = uuid();
}
uniq_id = test_collections[test_collection];
} else {
uniq_id = uuid();
}
return uniq_id;
}
-type CallbackParams = {
- app: App;
- base_url: string;
- smtp_api_url: string;
- rest_api: MockRestApi;
- port: number;
-
- mail_api: MailcatcherAPI;
-
- app_class: TestAppType;
-};
-
-export async function withTestApp(
+export async function withTestApp<FinalTestAppType extends TestApp>(
auto_start: boolean,
env: Environment,
- extend_fn: extendFn,
- fn: (params: CallbackParams) => Promise<unknown>,
+ extend_fn: extendFn<FinalTestAppType>,
+ fn: (params: CallbackParams<FinalTestAppType>) => Promise<unknown>,
test_collection?: string
) {
const port = await getPort();
const base_url = `http://127.0.0.1:${port}`;
const smtp_api_url = `http://${
process.env.SEALIOUS_SMTP_HOST || "127.0.0.1"
}:1088`;
- const TestApp = get_test_app({
- env,
- port,
- base_url,
- uniq_id: getAppID(test_collection),
- });
- let modified_app_class;
- if (extend_fn) {
- modified_app_class = extend_fn(TestApp);
- } else {
- modified_app_class = TestApp;
- }
+ const constructor = extend_fn ? extend_fn(TestApp) : TestApp;
+ const uniq_id = getAppID(test_collection);
+ const test_app = new constructor(uniq_id, env, port, base_url);
- const app = new modified_app_class();
if (auto_start) {
- await app.start();
+ await test_app.start();
}
try {
await fn({
- app: app as App,
+ app: test_app as FinalTestAppType,
port,
- app_class: modified_app_class,
+ app_class: constructor,
+ env,
base_url,
+ uniq_id,
smtp_api_url,
- mail_api: new MailcatcherAPI(smtp_api_url, app),
+ mail_api: new MailcatcherAPI(smtp_api_url, test_app),
rest_api: new MockRestApi(base_url),
});
} catch (e) {
console.error(e);
throw e;
} finally {
- if (app.status !== "stopped") {
- await app.stop();
+ if (test_app.status !== "stopped") {
+ await test_app.stop();
}
}
}
diff --git a/tsconfig.json b/tsconfig.json
index 064e696f..2ca1a8fb 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,20 +1,21 @@
{
"compilerOptions": {
"module": "commonjs",
"moduleResolution": "node",
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"target": "ES2020",
"declaration": true,
"esModuleInterop": true,
"lib": ["es6", "esnext"],
"outDir": "lib",
"checkJs": true,
"allowJs": true,
"declarationDir": "@types",
"resolveJsonModule": true,
- "sourceMap": true
+ "sourceMap": true,
+ "importsNotUsedAsValues": "error"
},
"include": ["src/**/*"]
}

File Metadata

Mime Type
text/x-diff
Expires
Fri, Jan 24, 15:15 (1 d, 8 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
66/d5/5f8e0fa0527193570989a73a50c7
Default Alt Text
(847 KB)

Event Timeline