diff --git a/.github/workflows/ci-test-happner-cluster.yml b/.github/workflows/ci-test-happner-cluster.yml index f1cbf545a..fb625026c 100644 --- a/.github/workflows/ci-test-happner-cluster.yml +++ b/.github/workflows/ci-test-happner-cluster.yml @@ -38,6 +38,7 @@ jobs: - run: npm run lint --package_name=happner-cluster - run: npm run-script test-cover --workspace=happner-cluster + - run: npm run-script test-browser --workspace=happner-cluster - name: Generate coverage branch uses: team-tenacious/monorepo-coverage@main diff --git a/.gitignore b/.gitignore index 1b3389629..6668a2ac0 100644 --- a/.gitignore +++ b/.gitignore @@ -48,7 +48,7 @@ packages/happn-3/test/browser/browser-client-02.js !packages/happn-db-provider-mongo/test/__fixtures/data/*.nedb packages/happner-cluster/test/stress/logs/*.log +packages/happner-client/test/example.com.cert +packages/happner-client/test/example.com.key temp/* - -node_modules-no-leak diff --git a/RELEASES.md b/RELEASES.md index a809d1f27..4f4d2481d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -89,3 +89,14 @@ happner-client: 12.2.8 redis-lru-cache: 1.0.12 happner-cluster: 12.1.9 happn-cluster: 12.0.12 + +1.5.0 2022-08-07 +---------------- +- TEN-31: on behalf of +happn-3: 13.2.0 +happner-2: 12.2.0 +happner-client: 12.3.0 +happner-cluster: 12.2.0 +happn-cluster: 12.0.13 +happn-db-provider-elasticsearch: 1.0.13 +happn-db-provider-mongo: 1.0.13 diff --git a/bin/pre-publish.js b/bin/pre-publish.js index 3c432b9ff..0dca6f873 100644 --- a/bin/pre-publish.js +++ b/bin/pre-publish.js @@ -26,8 +26,11 @@ Promise.all( console.log('fetched data from npm'); packagesMetaData = metaData.map((metaDataItem) => { let localPackage = workspacePackages.find((item) => item.name === metaDataItem.data.name); + if (!localPackage) return null; + console.log('scanning package: ', metaDataItem.data.name); const newVersion = localPackage.version; - const lastVersion = metaDataItem.data['dist-tags'].latest; + const lastVersion = getLatestNonPrereleaseVersion(metaDataItem.data['versions']); + console.log(`highest current version:${lastVersion}, local version: ${newVersion}`); const isPrerelease = newVersion.match(/^([0-9]\d*)\.([0-9]\d*)\.([0-9]\d*)$/) == null; return { publishOrder: getPackagePublishOrder(localPackage.name), @@ -48,7 +51,7 @@ Promise.all( releasesUpToDate: checkReleasesUpToDate(localPackage), possibleOnlyInTests: checkOnlyInTests(localPackage), }; - }); + }).filter((item) => item !== null); console.log('fetching master package...'); return require('axios').default.get( `https://raw.githubusercontent.com/happner/happner-suite/master/package.json` @@ -62,6 +65,49 @@ Promise.all( throw e; }); +function getVersionObject(versionString) { + const split = versionString.split('.'); + const versionObject= { + versionString, + major: parseInt(split[0]), + minor: parseInt(split[1]), + patch: isNaN(split[2]) ? split[2] : parseInt(split[2]), + }; + versionObject.isPrerelease = isNaN(versionObject.patch); + return versionObject; +} + +function getLatestNonPrereleaseVersion(versions) { + const nonPrereleaseVersions = Object.keys(versions) + .map(versionString => getVersionObject(versionString)) + .filter(versionObject => { + return versionObject.isPrerelease === false; + }); + + nonPrereleaseVersions.sort((versionObjectA, versionObjectB) => { + if (versionObjectA.major > versionObjectB.major) { + return 1; + } + if (versionObjectB.major > versionObjectA.major) { + return -1; + } + if (versionObjectA.minor > versionObjectB.minor) { + return 1; + } + if (versionObjectB.minor > versionObjectA.minor) { + return -1; + } + if (versionObjectA.patch > versionObjectB.patch) { + return 1; + } + if (versionObjectB.patch > versionObjectA.patch) { + return -1; + } + return 0; + }); + return nonPrereleaseVersions.pop().versionString; +} + function verifyPublish(packagesMetaData, masterPackage) { let issues = [], successes = []; diff --git a/package-lock.json b/package-lock.json index 59675dd03..d4a5ef5a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,14 @@ { "name": "happner-suite", - "version": "1.4.0", + "version": "1.5.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "happner-suite", - "version": "1.4.0", + "version": "1.5.0", "workspaces": [ + "packages/demos", "packages/happn-3", "packages/happn-db-provider-elasticsearch", "packages/happn-db-provider-loki", @@ -28,6 +29,7 @@ ], "dependencies": { "axios": "^0.26.0", + "cd": "^0.3.3", "ws": "6.1.4" }, "devDependencies": { @@ -75,7 +77,7 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.18.8", + "version": "7.18.13", "dev": true, "license": "MIT", "engines": { @@ -83,20 +85,20 @@ } }, "node_modules/@babel/core": { - "version": "7.18.6", + "version": "7.18.13", "dev": true, "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.6", - "@babel/helper-compilation-targets": "^7.18.6", - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helpers": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6", + "@babel/generator": "^7.18.13", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helpers": "^7.18.9", + "@babel/parser": "^7.18.13", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.13", + "@babel/types": "^7.18.13", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -111,6 +113,14 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "1.8.0", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, "node_modules/@babel/core/node_modules/json5": { "version": "2.2.1", "dev": true, @@ -122,6 +132,11 @@ "node": ">=6" } }, + "node_modules/@babel/core/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, "node_modules/@babel/core/node_modules/semver": { "version": "6.3.0", "dev": true, @@ -131,11 +146,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.18.7", + "version": "7.18.13", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.18.7", + "@babel/types": "^7.18.13", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" }, @@ -144,11 +159,11 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.18.6", + "version": "7.18.9", "dev": true, "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.18.6", + "@babel/compat-data": "^7.18.8", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.20.2", "semver": "^6.3.0" @@ -169,7 +184,7 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.6", + "version": "7.18.9", "dev": true, "license": "MIT", "engines": { @@ -177,12 +192,12 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.18.6", + "version": "7.18.9", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -211,18 +226,18 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.18.8", + "version": "7.18.9", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.18.6", "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.8", - "@babel/types": "^7.18.8" + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -250,6 +265,14 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-string-parser": { + "version": "7.18.10", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-validator-identifier": { "version": "7.18.6", "dev": true, @@ -267,13 +290,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.18.6", + "version": "7.18.9", "dev": true, "license": "MIT", "dependencies": { "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" }, "engines": { "node": ">=6.9.0" @@ -293,7 +316,7 @@ } }, "node_modules/@babel/parser": { - "version": "7.18.8", + "version": "7.18.13", "dev": true, "license": "MIT", "bin": { @@ -304,31 +327,31 @@ } }, "node_modules/@babel/template": { - "version": "7.18.6", + "version": "7.18.10", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.18.8", + "version": "7.18.13", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.7", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", + "@babel/generator": "^7.18.13", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.8", - "@babel/types": "^7.18.8", + "@babel/parser": "^7.18.13", + "@babel/types": "^7.18.13", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -337,10 +360,11 @@ } }, "node_modules/@babel/types": { - "version": "7.18.8", + "version": "7.18.13", "dev": true, "license": "MIT", "dependencies": { + "@babel/helper-string-parser": "^7.18.10", "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" }, @@ -381,7 +405,7 @@ } }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.16.0", + "version": "13.17.0", "dev": true, "license": "MIT", "dependencies": { @@ -435,70 +459,6 @@ "node": ">=6" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "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", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "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", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-try": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/path-exists": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { "version": "5.0.0", "dev": true, @@ -554,7 +514,7 @@ "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.14", + "version": "0.3.15", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", @@ -617,7 +577,7 @@ } }, "node_modules/@redis/client": { - "version": "1.2.0", + "version": "1.3.0", "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.0", @@ -643,7 +603,7 @@ } }, "node_modules/@redis/search": { - "version": "1.0.6", + "version": "1.1.0", "license": "MIT", "peerDependencies": { "@redis/client": "^1.0.0" @@ -683,7 +643,7 @@ } }, "node_modules/@sinonjs/text-encoding": { - "version": "0.7.1", + "version": "0.7.2", "dev": true, "license": "(Unlicense OR Apache-2.0)" }, @@ -719,7 +679,7 @@ "peer": true }, "node_modules/@types/node": { - "version": "18.0.3", + "version": "18.7.13", "license": "MIT" }, "node_modules/@types/webidl-conversions": { @@ -1370,11 +1330,6 @@ "node": ">= 0.10" } }, - "node_modules/backo2": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, "node_modules/balanced-match": { "version": "1.0.2", "license": "MIT" @@ -1433,11 +1388,11 @@ "license": "MIT" }, "node_modules/base64id": { - "version": "1.0.0", + "version": "2.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4.0" + "node": "^4.5.0 || >= 5.9" } }, "node_modules/bcrypt-pbkdf": { @@ -1539,6 +1494,22 @@ "lodash": "=3.10.1" } }, + "node_modules/bitcore-lib/node_modules/bn.js": { + "version": "2.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/bitcore-lib/node_modules/elliptic": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^2.0.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, "node_modules/bitcore-lib/node_modules/inherits": { "version": "2.0.1", "dev": true, @@ -1569,8 +1540,7 @@ "license": "MIT" }, "node_modules/bn.js": { - "version": "2.0.4", - "dev": true, + "version": "5.2.1", "license": "MIT" }, "node_modules/body": { @@ -1612,24 +1582,19 @@ "version": "2.0.0", "license": "MIT" }, - "node_modules/body/node_modules/bytes": { - "version": "1.0.0" - }, - "node_modules/body/node_modules/raw-body": { - "version": "1.1.7", + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.4.3", "license": "MIT", "dependencies": { - "bytes": "1", - "string_decoder": "0.10" + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.8" } }, - "node_modules/body/node_modules/string_decoder": { - "version": "0.10.31", - "license": "MIT" - }, "node_modules/boom": { "version": "2.10.1", "dev": true, @@ -1689,37 +1654,19 @@ "browser-pack": "bin/cmd.js" } }, - "node_modules/browser-pack/node_modules/jsonparse": { - "version": "1.3.1", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/browser-pack/node_modules/JSONStream": { - "version": "1.3.5", - "dev": true, - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, "node_modules/browser-resolve": { - "version": "2.0.0", + "version": "1.11.3", "dev": true, "license": "MIT", "dependencies": { - "resolve": "^1.17.0" + "resolve": "1.1.7" } }, + "node_modules/browser-resolve/node_modules/resolve": { + "version": "1.1.7", + "dev": true, + "license": "MIT" + }, "node_modules/browser-stdout": { "version": "1.3.1", "dev": true, @@ -1735,15 +1682,15 @@ } }, "node_modules/browserify": { - "version": "16.5.2", + "version": "16.2.3", "dev": true, "license": "MIT", "dependencies": { "assert": "^1.4.0", "browser-pack": "^6.0.1", - "browser-resolve": "^2.0.0", + "browser-resolve": "^1.11.0", "browserify-zlib": "~0.2.0", - "buffer": "~5.2.1", + "buffer": "^5.0.2", "cached-path-relative": "^1.0.0", "concat-stream": "^1.6.0", "console-browserify": "^1.1.0", @@ -1762,8 +1709,8 @@ "insert-module-globals": "^7.0.0", "JSONStream": "^1.0.3", "labeled-stream-splicer": "^2.0.0", - "mkdirp-classic": "^0.5.2", - "module-deps": "^6.2.3", + "mkdirp": "^0.5.0", + "module-deps": "^6.0.0", "os-browserify": "~0.3.0", "parents": "^1.0.1", "path-browserify": "~0.0.0", @@ -1776,7 +1723,7 @@ "shasum": "^1.0.0", "shell-quote": "^1.6.1", "stream-browserify": "^2.0.0", - "stream-http": "^3.0.0", + "stream-http": "^2.0.0", "string_decoder": "^1.1.1", "subarg": "^1.0.0", "syntax-error": "^1.1.1", @@ -1834,10 +1781,6 @@ "randombytes": "^2.0.1" } }, - "node_modules/browserify-rsa/node_modules/bn.js": { - "version": "5.2.1", - "license": "MIT" - }, "node_modules/browserify-sign": { "version": "4.2.1", "license": "ISC", @@ -1853,27 +1796,6 @@ "safe-buffer": "^5.2.0" } }, - "node_modules/browserify-sign/node_modules/bn.js": { - "version": "5.2.1", - "license": "MIT" - }, - "node_modules/browserify-sign/node_modules/elliptic": { - "version": "6.5.4", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/browserify-sign/node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "license": "MIT" - }, "node_modules/browserify-sign/node_modules/readable-stream": { "version": "3.6.0", "license": "MIT", @@ -1886,24 +1808,6 @@ "node": ">= 6" } }, - "node_modules/browserify-sign/node_modules/safe-buffer": { - "version": "5.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/browserify-zlib": { "version": "0.2.0", "dev": true, @@ -1912,45 +1816,13 @@ "pako": "~1.0.5" } }, - "node_modules/browserify/node_modules/buffer": { - "version": "5.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "node_modules/browserify/node_modules/jsonparse": { - "version": "1.3.1", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/browserify/node_modules/JSONStream": { - "version": "1.3.5", - "dev": true, - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, "node_modules/browserify/node_modules/punycode": { "version": "1.4.1", "dev": true, "license": "MIT" }, "node_modules/browserslist": { - "version": "4.21.2", + "version": "4.21.3", "dev": true, "funding": [ { @@ -1964,10 +1836,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001366", - "electron-to-chromium": "^1.4.188", + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.4" + "update-browserslist-db": "^1.0.5" }, "bin": { "browserslist": "cli.js" @@ -1981,7 +1853,7 @@ "dev": true }, "node_modules/bson": { - "version": "4.6.5", + "version": "4.7.0", "license": "Apache-2.0", "dependencies": { "buffer": "^5.6.0" @@ -2012,20 +1884,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/buffer-alloc": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "node_modules/buffer-alloc-unsafe": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, "node_modules/buffer-compare": { "version": "1.0.0", "dev": true @@ -2038,11 +1896,6 @@ "node": ">=0.4.0" } }, - "node_modules/buffer-fill": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/buffer-from": { "version": "1.1.2", "license": "MIT" @@ -2106,3388 +1959,2953 @@ "node": ">=10.12.0" } }, - "node_modules/c8/node_modules/ansi-regex": { - "version": "4.1.1", + "node_modules/c8/node_modules/camelcase": { + "version": "5.3.1", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/c8/node_modules/camelcase": { - "version": "5.3.1", + "node_modules/c8/node_modules/decamelize": { + "version": "1.2.0", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/c8/node_modules/cliui": { - "version": "5.0.0", + "node_modules/c8/node_modules/foreground-child": { + "version": "2.0.0", "dev": true, "license": "ISC", "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/c8/node_modules/emoji-regex": { - "version": "7.0.3", - "dev": true, - "license": "MIT" - }, - "node_modules/c8/node_modules/find-up": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=8" + "node": ">=8.0.0" } }, - "node_modules/c8/node_modules/get-caller-file": { - "version": "2.0.5", + "node_modules/c8/node_modules/yargs-parser": { + "version": "14.0.0", "dev": true, "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, - "node_modules/c8/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", + "node_modules/cache-base": { + "version": "1.0.1", "dev": true, "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/c8/node_modules/istanbul-lib-coverage": { - "version": "2.0.5", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=6" - } - }, - "node_modules/c8/node_modules/istanbul-lib-report": { - "version": "2.0.8", - "dev": true, - "license": "BSD-3-Clause", "dependencies": { - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "supports-color": "^6.1.0" + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/c8/node_modules/istanbul-reports": { - "version": "2.2.7", + "node_modules/cached-path-relative": { + "version": "1.1.0", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0" - }, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/c8/node_modules/load-json-file": { + "node_modules/caching-transform": { "version": "4.0.0", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/c8/node_modules/load-json-file/node_modules/pify": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/c8/node_modules/locate-path": { - "version": "5.0.0", + "node_modules/caching-transform/node_modules/make-dir": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "semver": "^6.0.0" }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/c8/node_modules/make-dir": { - "version": "2.1.0", + "node_modules/caching-transform/node_modules/semver": { + "version": "6.3.0", "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "engines": { - "node": ">=6" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/c8/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/call-bind": { + "version": "1.0.2", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/c8/node_modules/p-locate": { - "version": "4.1.0", + "node_modules/callsite": { + "version": "1.0.0", "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/c8/node_modules/p-try": { - "version": "2.2.0", + "node_modules/callsites": { + "version": "3.1.0", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/c8/node_modules/parse-json": { - "version": "4.0.0", - "dev": true, + "node_modules/camel-case": { + "version": "1.2.2", "license": "MIT", "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - }, - "engines": { - "node": ">=4" + "sentence-case": "^1.1.1", + "upper-case": "^1.1.1" } }, - "node_modules/c8/node_modules/path-exists": { - "version": "4.0.0", + "node_modules/camelcase": { + "version": "6.3.0", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/c8/node_modules/path-type": { - "version": "3.0.0", + "node_modules/caniuse-lite": { + "version": "1.0.30001384", "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ], + "license": "CC-BY-4.0" }, - "node_modules/c8/node_modules/path-type/node_modules/pify": { - "version": "3.0.0", + "node_modules/capture-stdout": { + "version": "1.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": "^8.1.2" } }, - "node_modules/c8/node_modules/pify": { - "version": "4.0.1", + "node_modules/caseless": { + "version": "0.12.0", "dev": true, - "license": "MIT", + "license": "Apache-2.0" + }, + "node_modules/cd": { + "version": "0.3.3", "engines": { - "node": ">=6" + "node": "*" } }, - "node_modules/c8/node_modules/read-pkg": { - "version": "3.0.0", + "node_modules/center-align": { + "version": "0.1.3", "dev": true, "license": "MIT", "dependencies": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/c8/node_modules/read-pkg-up": { - "version": "4.0.0", + "node_modules/chai": { + "version": "4.3.6", "dev": true, "license": "MIT", "dependencies": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/c8/node_modules/read-pkg-up/node_modules/find-up": { - "version": "3.0.0", + "node_modules/chai-as-promised": { + "version": "7.1.1", "dev": true, - "license": "MIT", + "license": "WTFPL", "dependencies": { - "locate-path": "^3.0.0" + "check-error": "^1.0.2" }, - "engines": { - "node": ">=6" + "peerDependencies": { + "chai": ">= 2.1.2 < 5" } }, - "node_modules/c8/node_modules/read-pkg-up/node_modules/locate-path": { - "version": "3.0.0", + "node_modules/chai-match": { + "version": "1.1.1", "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } + "license": "MIT" }, - "node_modules/c8/node_modules/read-pkg-up/node_modules/p-locate": { - "version": "3.0.0", + "node_modules/chalk": { + "version": "2.4.2", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, - "engines": { - "node": ">=6" - } - }, - "node_modules/c8/node_modules/read-pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "dev": true, - "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/c8/node_modules/require-main-filename": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/c8/node_modules/semver": { - "version": "5.7.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/c8/node_modules/string-width": { - "version": "3.1.0", - "dev": true, + "node_modules/change-case": { + "version": "2.3.0", "license": "MIT", "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, + "camel-case": "^1.1.1", + "constant-case": "^1.1.0", + "dot-case": "^1.1.0", + "is-lower-case": "^1.1.0", + "is-upper-case": "^1.1.0", + "lower-case": "^1.1.1", + "lower-case-first": "^1.0.0", + "param-case": "^1.1.0", + "pascal-case": "^1.1.0", + "path-case": "^1.1.0", + "sentence-case": "^1.1.1", + "snake-case": "^1.1.0", + "swap-case": "^1.1.0", + "title-case": "^1.1.0", + "upper-case": "^1.1.1", + "upper-case-first": "^1.1.0" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "license": "BSD-3-Clause", "engines": { - "node": ">=6" + "node": "*" } }, - "node_modules/c8/node_modules/strip-ansi": { - "version": "5.2.0", + "node_modules/check-error": { + "version": "1.0.2", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, "engines": { - "node": ">=6" + "node": "*" } }, - "node_modules/c8/node_modules/supports-color": { - "version": "6.1.0", + "node_modules/chokidar": { + "version": "2.1.8", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" }, - "engines": { - "node": ">=6" + "optionalDependencies": { + "fsevents": "^1.2.7" } }, - "node_modules/c8/node_modules/test-exclude": { - "version": "5.2.3", + "node_modules/chokidar/node_modules/glob-parent": { + "version": "3.1.0", "dev": true, "license": "ISC", "dependencies": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/chokidar/node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/c8/node_modules/which-module": { - "version": "2.0.0", - "dev": true, - "license": "ISC" + "node_modules/cipher-base": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } }, - "node_modules/c8/node_modules/wrap-ansi": { - "version": "5.1.0", + "node_modules/class-utils": { + "version": "0.3.6", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/c8/node_modules/y18n": { - "version": "4.0.3", + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/c8/node_modules/yargs": { - "version": "14.2.3", + "node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", "dev": true, "license": "MIT", "dependencies": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.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": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/c8/node_modules/yargs-parser": { - "version": "14.0.0", + "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/c8/node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", + "node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^3.0.0" + "kind-of": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/c8/node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", + "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/c8/node_modules/yargs/node_modules/p-locate": { - "version": "3.0.0", + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.0.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/c8/node_modules/yargs/node_modules/path-exists": { - "version": "3.0.0", + "node_modules/clean-stack": { + "version": "2.2.0", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/c8/node_modules/yargs/node_modules/yargs-parser": { - "version": "15.0.3", + "node_modules/cliui": { + "version": "5.0.0", "dev": true, "license": "ISC", "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" } }, - "node_modules/cache-base": { - "version": "1.0.1", + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.1", "dev": true, "license": "MIT", - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/cached-path-relative": { - "version": "1.1.0", + "node_modules/cliui/node_modules/emoji-regex": { + "version": "7.0.3", "dev": true, "license": "MIT" }, - "node_modules/caching-transform": { - "version": "4.0.0", + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", "dev": true, "license": "MIT", - "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": ">=4" } }, - "node_modules/call-bind": { - "version": "1.0.2", + "node_modules/cliui/node_modules/string-width": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsite": { - "version": "1.0.0", - "dev": true, "engines": { - "node": "*" + "node": ">=6" } }, - "node_modules/callsites": { - "version": "3.1.0", + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", "dev": true, "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, "engines": { "node": ">=6" } }, - "node_modules/camel-case": { - "version": "1.2.2", + "node_modules/clone": { + "version": "2.1.2", "license": "MIT", - "dependencies": { - "sentence-case": "^1.1.1", - "upper-case": "^1.1.1" + "engines": { + "node": ">=0.8" } }, - "node_modules/camelcase": { - "version": "3.0.0", + "node_modules/clone-buffer": { + "version": "1.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001366", + "node_modules/clone-stats": { + "version": "1.0.0", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ], - "license": "CC-BY-4.0" + "license": "MIT" }, - "node_modules/capture-stdout": { - "version": "1.0.0", + "node_modules/cloneable-readable": { + "version": "1.1.3", "dev": true, "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "node_modules/cluster-key-slot": { + "version": "1.1.0", + "license": "APACHE-2.0", "engines": { - "node": "^8.1.2" + "node": ">=0.10.0" } }, - "node_modules/caseless": { - "version": "0.12.0", + "node_modules/co": { + "version": "4.6.0", "dev": true, - "license": "Apache-2.0" + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } }, - "node_modules/center-align": { - "version": "0.1.3", + "node_modules/code-point-at": { + "version": "1.1.0", "dev": true, "license": "MIT", - "dependencies": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/chai": { - "version": "4.3.6", + "node_modules/collection-map": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/chai-as-promised": { - "version": "7.1.1", + "node_modules/collection-visit": { + "version": "1.0.0", "dev": true, - "license": "WTFPL", + "license": "MIT", "dependencies": { - "check-error": "^1.0.2" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" }, - "peerDependencies": { - "chai": ">= 2.1.2 < 5" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/chai-match": { - "version": "1.1.1", - "dev": true, - "license": "MIT" + "node_modules/color": { + "version": "0.8.0", + "license": "MIT", + "dependencies": { + "color-convert": "^0.5.0", + "color-string": "^0.3.0" + } }, - "node_modules/chalk": { - "version": "2.4.2", - "dev": true, + "node_modules/color-convert": { + "version": "1.9.3", "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" + "color-name": "1.1.3" } }, - "node_modules/change-case": { - "version": "2.3.0", + "node_modules/color-name": { + "version": "1.1.3", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "0.3.0", "license": "MIT", "dependencies": { - "camel-case": "^1.1.1", - "constant-case": "^1.1.0", - "dot-case": "^1.1.0", - "is-lower-case": "^1.1.0", - "is-upper-case": "^1.1.0", - "lower-case": "^1.1.1", - "lower-case-first": "^1.0.0", - "param-case": "^1.1.0", - "pascal-case": "^1.1.0", - "path-case": "^1.1.0", - "sentence-case": "^1.1.1", - "snake-case": "^1.1.0", - "swap-case": "^1.1.0", - "title-case": "^1.1.0", - "upper-case": "^1.1.1", - "upper-case-first": "^1.1.0" + "color-name": "^1.0.0" } }, - "node_modules/charenc": { - "version": "0.0.2", - "license": "BSD-3-Clause", - "engines": { - "node": "*" + "node_modules/color-support": { + "version": "1.1.3", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" } }, - "node_modules/check-error": { - "version": "1.0.2", + "node_modules/color/node_modules/color-convert": { + "version": "0.5.3" + }, + "node_modules/colornames": { + "version": "0.0.2", + "license": "MIT" + }, + "node_modules/colors": { + "version": "1.4.0", "dev": true, "license": "MIT", "engines": { - "node": "*" + "node": ">=0.1.90" } }, - "node_modules/chokidar": { - "version": "2.1.8", - "dev": true, + "node_modules/colorspace": { + "version": "1.0.1", "license": "MIT", "dependencies": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - }, - "optionalDependencies": { - "fsevents": "^1.2.7" + "color": "0.8.x", + "text-hex": "0.0.x" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "3.1.0", + "node_modules/combine-lists": { + "version": "1.0.1", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "lodash": "^4.5.0" } }, - "node_modules/chokidar/node_modules/glob-parent/node_modules/is-glob": { - "version": "3.1.0", + "node_modules/combine-source-map": { + "version": "0.8.0", "dev": true, "license": "MIT", "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" + "convert-source-map": "~1.1.0", + "inline-source-map": "~0.6.0", + "lodash.memoize": "~3.0.3", + "source-map": "~0.5.3" } }, - "node_modules/cipher-base": { - "version": "1.0.4", + "node_modules/combined-stream": { + "version": "1.0.8", + "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" } }, - "node_modules/circular-json": { - "version": "0.5.9", + "node_modules/commander": { + "version": "2.20.3", + "license": "MIT" + }, + "node_modules/commondir": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/component-emitter": { + "version": "1.2.1", "dev": true, "license": "MIT" }, - "node_modules/class-utils": { - "version": "0.3.6", + "node_modules/component-inherit": { + "version": "0.0.3", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "1.6.2", "dev": true, + "engines": [ + "node >= 0.8" + ], "license": "MIT", "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", + "node_modules/concat-with-sourcemaps": { + "version": "1.1.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" + "source-map": "^0.6.1" } }, - "node_modules/class-utils/node_modules/is-accessor-descriptor": { - "version": "0.1.6", + "node_modules/concat-with-sourcemaps/node_modules/source-map": { + "version": "0.6.1", "dev": true, - "license": "MIT", - "dependencies": { - "kind-of": "^3.0.2" - }, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", + "node_modules/condenseify": { + "version": "1.1.2", "dev": true, "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" + "pumpify": "~1.4.0", + "split2": "~2.2.0", + "through2": "~2.0.1" } }, - "node_modules/class-utils/node_modules/is-data-descriptor": { - "version": "0.1.4", + "node_modules/condenseify/node_modules/pumpify": { + "version": "1.4.0", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" + "duplexify": "^3.5.3", + "inherits": "^2.0.3", + "pump": "^2.0.0" } }, - "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "dev": true, + "node_modules/connect": { + "version": "3.7.0", "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10.0" } }, - "node_modules/class-utils/node_modules/is-descriptor": { - "version": "0.1.6", - "dev": true, - "license": "MIT", + "node_modules/connect-cookies": { + "version": "0.0.0", "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" + "cookies": "~0.3.8", + "keygrip": "~1.0.0" } }, - "node_modules/clean-stack": { - "version": "2.2.0", - "dev": true, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui": { - "version": "3.2.0", - "dev": true, - "license": "ISC", "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "ms": "2.0.0" } }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/connected": { + "version": "0.0.2", + "license": "MIT" + }, + "node_modules/connection-parse": { + "version": "0.0.7", + "license": "MIT" + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "dev": true + }, + "node_modules/constant-case": { + "version": "1.1.2", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "snake-case": "^1.1.0", + "upper-case": "^1.1.1" } }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "node_modules/constants-browserify": { "version": "1.0.0", "dev": true, + "license": "MIT" + }, + "node_modules/content-type": { + "version": "1.0.4", "license": "MIT", - "dependencies": { - "number-is-nan": "^1.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/cliui/node_modules/string-width": { - "version": "1.0.2", + "node_modules/continuable-cache": { + "version": "0.3.1" + }, + "node_modules/convert-source-map": { + "version": "1.1.3", "dev": true, - "license": "MIT", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "3.0.1", + "node_modules/cookie": { + "version": "0.4.2", "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/clone": { - "version": "2.1.2", - "license": "MIT", + "node_modules/cookies": { + "version": "0.3.8", "engines": { - "node": ">=0.8" + "node": ">= 0.6.0" } }, - "node_modules/clone-buffer": { - "version": "1.0.0", + "node_modules/copy-descriptor": { + "version": "0.1.1", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/clone-stats": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/cloneable-readable": { - "version": "1.1.3", + "node_modules/copy-props": { + "version": "2.0.5", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" + "each-props": "^1.3.2", + "is-plain-object": "^5.0.0" } }, - "node_modules/cluster-key-slot": { - "version": "1.1.0", - "license": "APACHE-2.0", - "engines": { - "node": ">=0.10.0" - } + "node_modules/core-js": { + "version": "2.6.12", + "dev": true, + "hasInstallScript": true, + "license": "MIT" }, - "node_modules/co": { - "version": "4.6.0", + "node_modules/core-util-is": { + "version": "1.0.3", "dev": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } + "license": "MIT" }, - "node_modules/code-point-at": { - "version": "1.1.0", + "node_modules/cors": { + "version": "2.8.5", "dev": true, "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/collection-map": { - "version": "1.0.0", + "node_modules/coverage": { + "version": "0.4.1", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "c8": "^5.0.1", + "foreground-child": "^1.5.6", + "normalize-package-data": "^2.5.0", + "slash": "^3.0.0", + "test-exclude": "^5.2.3", + "which": "^1.3.1", + "yargs-parser": "^13.1.1" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "coverage": "index.js" } }, - "node_modules/collection-visit": { - "version": "1.0.0", + "node_modules/coverage/node_modules/which": { + "version": "1.3.1", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "isexe": "^2.0.0" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "which": "bin/which" } }, - "node_modules/color": { - "version": "0.8.0", - "license": "MIT", + "node_modules/coveralls": { + "version": "3.1.1", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "color-convert": "^0.5.0", - "color-string": "^0.3.0" + "js-yaml": "^3.13.1", + "lcov-parse": "^1.0.0", + "log-driver": "^1.2.7", + "minimist": "^1.2.5", + "request": "^2.88.2" + }, + "bin": { + "coveralls": "bin/coveralls.js" + }, + "engines": { + "node": ">=6" } }, - "node_modules/color-convert": { - "version": "1.9.3", + "node_modules/create-ecdh": { + "version": "4.0.4", "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" } }, - "node_modules/color-name": { - "version": "1.1.3", + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", "license": "MIT" }, - "node_modules/color-string": { - "version": "0.3.0", + "node_modules/create-hash": { + "version": "1.2.0", "license": "MIT", "dependencies": { - "color-name": "^1.0.0" + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" } }, - "node_modules/color-support": { - "version": "1.1.3", - "dev": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/color/node_modules/color-convert": { - "version": "0.5.3" - }, - "node_modules/colornames": { - "version": "0.0.2", - "license": "MIT" - }, - "node_modules/colors": { - "version": "1.4.0", - "dev": true, + "node_modules/create-hmac": { + "version": "1.1.7", "license": "MIT", - "engines": { - "node": ">=0.1.90" + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, - "node_modules/colorspace": { - "version": "1.0.1", + "node_modules/create-server": { + "version": "1.0.2", "license": "MIT", "dependencies": { - "color": "0.8.x", - "text-hex": "0.0.x" + "connected": "~0.0.2" } }, - "node_modules/combine-lists": { - "version": "1.0.1", + "node_modules/cross-spawn": { + "version": "7.0.3", "dev": true, "license": "MIT", "dependencies": { - "lodash": "^4.5.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/combine-source-map": { - "version": "0.8.0", - "dev": true, - "license": "MIT", - "dependencies": { - "convert-source-map": "~1.1.0", - "inline-source-map": "~0.6.0", - "lodash.memoize": "~3.0.3", - "source-map": "~0.5.3" + "node_modules/crypt": { + "version": "0.0.2", + "license": "BSD-3-Clause", + "engines": { + "node": "*" } }, - "node_modules/combine-source-map/node_modules/convert-source-map": { - "version": "1.1.3", + "node_modules/cryptiles": { + "version": "2.0.5", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "dependencies": { + "boom": "2.x.x" + }, + "engines": { + "node": ">=0.10.40" + } }, - "node_modules/combined-stream": { - "version": "1.0.8", - "dev": true, + "node_modules/crypto-browserify": { + "version": "3.12.0", "license": "MIT", "dependencies": { - "delayed-stream": "~1.0.0" + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" }, "engines": { - "node": ">= 0.8" + "node": "*" } }, - "node_modules/commander": { - "version": "2.20.3", - "license": "MIT" + "node_modules/custom-env": { + "version": "2.0.1", + "license": "ISC", + "dependencies": { + "dotenv": "*", + "dotenv-expand": "^5.0.0" + } }, - "node_modules/commondir": { + "node_modules/custom-event": { "version": "1.0.1", "dev": true, "license": "MIT" }, - "node_modules/component-bind": { - "version": "1.0.0", - "dev": true + "node_modules/d": { + "version": "1.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } }, - "node_modules/component-emitter": { - "version": "1.3.0", + "node_modules/dash-ast": { + "version": "1.0.0", "dev": true, - "license": "MIT" + "license": "Apache-2.0" }, - "node_modules/component-inherit": { - "version": "0.0.3", - "dev": true + "node_modules/dashdash": { + "version": "1.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } }, - "node_modules/concat-map": { - "version": "0.0.1", - "license": "MIT" + "node_modules/date-format": { + "version": "4.0.13", + "license": "MIT", + "engines": { + "node": ">=4.0" + } }, - "node_modules/concat-stream": { - "version": "1.6.2", + "node_modules/dateformat": { + "version": "2.2.0", "dev": true, - "engines": [ - "node >= 0.8" - ], + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.4", "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/concat-with-sourcemaps": { - "version": "1.1.0", + "node_modules/decamelize": { + "version": "4.0.0", "dev": true, - "license": "ISC", - "dependencies": { - "source-map": "^0.6.1" + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/concat-with-sourcemaps/node_modules/source-map": { - "version": "0.6.1", + "node_modules/decode-uri-component": { + "version": "0.2.0", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.10" } }, - "node_modules/condenseify": { - "version": "1.1.2", + "node_modules/deep-copy": { + "version": "1.4.2", "dev": true, "license": "MIT", - "dependencies": { - "pumpify": "~1.4.0", - "split2": "~2.2.0", - "through2": "~2.0.1" + "engines": { + "node": ">=4.0.0" } }, - "node_modules/condenseify/node_modules/pumpify": { - "version": "1.4.0", + "node_modules/deep-eql": { + "version": "3.0.1", "dev": true, "license": "MIT", "dependencies": { - "duplexify": "^3.5.3", - "inherits": "^2.0.3", - "pump": "^2.0.0" + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=0.12" } }, - "node_modules/connect": { - "version": "3.7.0", + "node_modules/deep-equal": { + "version": "1.1.1", + "dev": true, "license": "MIT", "dependencies": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" }, - "engines": { - "node": ">= 0.10.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/connect-cookies": { - "version": "0.0.0", + "node_modules/deep-is": { + "version": "0.1.4", + "license": "MIT" + }, + "node_modules/default-compare": { + "version": "1.0.0", + "dev": true, + "license": "MIT", "dependencies": { - "cookies": "~0.3.8", - "keygrip": "~1.0.0" + "kind-of": "^5.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/connect/node_modules/debug": { - "version": "2.6.9", + "node_modules/default-require-extensions": { + "version": "3.0.0", + "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/connect/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/connected": { - "version": "0.0.2", - "license": "MIT" - }, - "node_modules/connection-parse": { - "version": "0.0.7", - "license": "MIT" - }, - "node_modules/console-browserify": { - "version": "1.2.0", - "dev": true - }, - "node_modules/constant-case": { - "version": "1.1.2", - "license": "MIT", - "dependencies": { - "snake-case": "^1.1.0", - "upper-case": "^1.1.1" - } - }, - "node_modules/constants-browserify": { - "version": "1.0.0", + "node_modules/default-require-extensions/node_modules/strip-bom": { + "version": "4.0.0", "dev": true, - "license": "MIT" - }, - "node_modules/content-type": { - "version": "1.0.4", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/continuable-cache": { - "version": "0.3.1" - }, - "node_modules/convert-source-map": { - "version": "1.8.0", + "node_modules/default-resolution": { + "version": "2.0.0", "dev": true, "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.1" + "engines": { + "node": ">= 0.10" } }, - "node_modules/cookie": { - "version": "0.3.1", + "node_modules/define-properties": { + "version": "1.1.4", "dev": true, "license": "MIT", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cookies": { - "version": "0.3.8", - "engines": { - "node": ">= 0.6.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/copy-descriptor": { - "version": "0.1.1", + "node_modules/define-property": { + "version": "2.0.2", "dev": true, "license": "MIT", + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/copy-props": { - "version": "2.0.5", + "node_modules/defined": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", "dev": true, "license": "MIT", - "dependencies": { - "each-props": "^1.3.2", - "is-plain-object": "^5.0.0" + "engines": { + "node": ">=0.4.0" } }, - "node_modules/core-js": { - "version": "2.6.12", + "node_modules/demolish": { + "version": "1.0.2", "dev": true, - "hasInstallScript": true, "license": "MIT" }, - "node_modules/core-util-is": { - "version": "1.0.3", - "dev": true, - "license": "MIT" + "node_modules/denque": { + "version": "2.1.0", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } }, - "node_modules/cors": { - "version": "2.8.5", + "node_modules/depd": { + "version": "1.1.2", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/deps-sort": { + "version": "2.0.1", "dev": true, "license": "MIT", "dependencies": { - "object-assign": "^4", - "vary": "^1" + "JSONStream": "^1.0.3", + "shasum-object": "^1.0.0", + "subarg": "^1.0.0", + "through2": "^2.0.0" }, - "engines": { - "node": ">= 0.10" + "bin": { + "deps-sort": "bin/cmd.js" } }, - "node_modules/coverage": { - "version": "0.4.1", + "node_modules/derequire": { + "version": "2.0.6", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "c8": "^5.0.1", - "foreground-child": "^1.5.6", - "normalize-package-data": "^2.5.0", - "slash": "^3.0.0", - "test-exclude": "^5.2.3", - "which": "^1.3.1", - "yargs-parser": "^13.1.1" + "acorn": "^4.0.3", + "concat-stream": "^1.4.6", + "escope": "^3.6.0", + "through2": "^2.0.0", + "yargs": "^6.5.0" }, "bin": { - "coverage": "index.js" + "derequire": "bin/cmd.js" } }, - "node_modules/coverage/node_modules/camelcase": { - "version": "5.3.1", + "node_modules/derequire/node_modules/acorn": { + "version": "4.0.13", "dev": true, "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, "engines": { - "node": ">=6" + "node": ">=0.4.0" } }, - "node_modules/coverage/node_modules/cross-spawn": { - "version": "4.0.2", + "node_modules/derequire/node_modules/ansi-regex": { + "version": "2.1.1", "dev": true, "license": "MIT", - "dependencies": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/find-up": { + "node_modules/derequire/node_modules/camelcase": { "version": "3.0.0", "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/foreground-child": { - "version": "1.5.6", + "node_modules/derequire/node_modules/cliui": { + "version": "3.2.0", "dev": true, "license": "ISC", "dependencies": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" } }, - "node_modules/coverage/node_modules/load-json-file": { - "version": "4.0.0", + "node_modules/derequire/node_modules/decamelize": { + "version": "1.2.0", "dev": true, "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/locate-path": { - "version": "3.0.0", + "node_modules/derequire/node_modules/find-up": { + "version": "1.1.2", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/lru-cache": { - "version": "4.1.5", + "node_modules/derequire/node_modules/get-caller-file": { + "version": "1.0.3", "dev": true, - "license": "ISC", - "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } + "license": "ISC" }, - "node_modules/coverage/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/derequire/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "number-is-nan": "^1.0.0" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/p-locate": { - "version": "3.0.0", + "node_modules/derequire/node_modules/load-json-file": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/p-try": { + "node_modules/derequire/node_modules/parse-json": { "version": "2.2.0", "dev": true, "license": "MIT", + "dependencies": { + "error-ex": "^1.2.0" + }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/parse-json": { - "version": "4.0.0", + "node_modules/derequire/node_modules/path-exists": { + "version": "2.1.0", "dev": true, "license": "MIT", "dependencies": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "pinkie-promise": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/path-type": { - "version": "3.0.0", + "node_modules/derequire/node_modules/path-type": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "pify": "^3.0.0" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/pify": { - "version": "3.0.0", + "node_modules/derequire/node_modules/pify": { + "version": "2.3.0", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/read-pkg": { - "version": "3.0.0", + "node_modules/derequire/node_modules/read-pkg": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "load-json-file": "^4.0.0", + "load-json-file": "^1.0.0", "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "path-type": "^1.0.0" }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/read-pkg-up": { - "version": "4.0.0", + "node_modules/derequire/node_modules/read-pkg-up": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/require-main-filename": { - "version": "2.0.0", + "node_modules/derequire/node_modules/require-main-filename": { + "version": "1.0.1", "dev": true, "license": "ISC" }, - "node_modules/coverage/node_modules/test-exclude": { - "version": "5.2.3", + "node_modules/derequire/node_modules/string-width": { + "version": "1.0.2", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/which": { - "version": "1.3.1", + "node_modules/derequire/node_modules/strip-ansi": { + "version": "3.0.1", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" + "ansi-regex": "^2.0.0" }, - "bin": { - "which": "bin/which" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/coverage/node_modules/yallist": { - "version": "2.1.2", - "dev": true, - "license": "ISC" - }, - "node_modules/coverage/node_modules/yargs-parser": { - "version": "13.1.2", + "node_modules/derequire/node_modules/strip-bom": { + "version": "2.0.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/coveralls": { - "version": "3.1.1", + "node_modules/derequire/node_modules/which-module": { + "version": "1.0.0", "dev": true, - "license": "BSD-2-Clause", + "license": "ISC" + }, + "node_modules/derequire/node_modules/wrap-ansi": { + "version": "2.1.0", + "dev": true, + "license": "MIT", "dependencies": { - "js-yaml": "^3.13.1", - "lcov-parse": "^1.0.0", - "log-driver": "^1.2.7", - "minimist": "^1.2.5", - "request": "^2.88.2" - }, - "bin": { - "coveralls": "bin/coveralls.js" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/create-ecdh": { - "version": "4.0.4", + "node_modules/derequire/node_modules/y18n": { + "version": "3.2.2", + "dev": true, + "license": "ISC" + }, + "node_modules/derequire/node_modules/yargs": { + "version": "6.6.0", + "dev": true, "license": "MIT", "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^4.2.0" } }, - "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.0", - "license": "MIT" - }, - "node_modules/create-ecdh/node_modules/elliptic": { - "version": "6.5.4", - "license": "MIT", + "node_modules/derequire/node_modules/yargs-parser": { + "version": "4.2.1", + "dev": true, + "license": "ISC", "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" + "camelcase": "^3.0.0" } }, - "node_modules/create-hash": { - "version": "1.2.0", + "node_modules/des.js": { + "version": "1.0.1", "license": "MIT", "dependencies": { - "cipher-base": "^1.0.1", "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" + "minimalistic-assert": "^1.0.0" } }, - "node_modules/create-hmac": { - "version": "1.1.7", + "node_modules/destroy": { + "version": "1.2.0", "license": "MIT", - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/create-server": { - "version": "1.0.2", + "node_modules/detect-file": { + "version": "1.0.0", + "dev": true, "license": "MIT", - "dependencies": { - "connected": "~0.0.2" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", + "node_modules/detective": { + "version": "5.2.1", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "detective": "bin/detective.js" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/crypt": { - "version": "0.0.2", - "license": "BSD-3-Clause", - "engines": { - "node": "*" + "node": ">=0.8.0" } }, - "node_modules/cryptiles": { - "version": "2.0.5", + "node_modules/deumdify": { + "version": "1.2.8", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "boom": "2.x.x" + "escodegen": "~2.0.0", + "esprima": "~4.0.0", + "estraverse": "~5.2.0", + "through2": "~4.0.2" }, + "peerDependencies": { + "browserify": "9 - 17" + } + }, + "node_modules/deumdify/node_modules/estraverse": { + "version": "5.2.0", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=0.10.40" + "node": ">=4.0" } }, - "node_modules/crypto-browserify": { - "version": "3.11.0", + "node_modules/deumdify/node_modules/readable-stream": { + "version": "3.6.0", "dev": true, "license": "MIT", "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": "*" + "node": ">= 6" } }, - "node_modules/custom-env": { - "version": "2.0.1", - "license": "ISC", + "node_modules/deumdify/node_modules/through2": { + "version": "4.0.2", + "dev": true, + "license": "MIT", "dependencies": { - "dotenv": "*", - "dotenv-expand": "^5.0.0" + "readable-stream": "3" } }, - "node_modules/custom-event": { + "node_modules/dev-null": { + "version": "0.1.1", + "license": "MIT" + }, + "node_modules/dface": { "version": "1.0.1", + "license": "MIT" + }, + "node_modules/di": { + "version": "0.0.1", "dev": true, "license": "MIT" }, - "node_modules/d": { + "node_modules/diagnostics": { "version": "1.0.1", - "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" + "colorspace": "1.0.x", + "enabled": "1.0.x", + "kuler": "0.0.x" } }, - "node_modules/dash-ast": { - "version": "1.0.0", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/dashdash": { - "version": "1.14.1", + "node_modules/diff": { + "version": "1.4.0", "dev": true, - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - }, "engines": { - "node": ">=0.10" + "node": ">=0.3.1" } }, - "node_modules/date-format": { - "version": "4.0.11", + "node_modules/diffie-hellman": { + "version": "5.0.3", "license": "MIT", - "engines": { - "node": ">=4.0" + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" } }, - "node_modules/dateformat": { - "version": "2.2.0", - "dev": true, - "license": "MIT", + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "license": "MIT" + }, + "node_modules/diskspace": { + "version": "0.1.7", "engines": { "node": "*" } }, - "node_modules/debug": { - "version": "4.3.4", - "license": "MIT", + "node_modules/doctrine": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "ms": "2.1.2" + "esutils": "^2.0.2" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=6.0.0" } }, - "node_modules/decamelize": { - "version": "1.2.0", + "node_modules/dom-serialize": { + "version": "2.2.1", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" } }, - "node_modules/decode-uri-component": { - "version": "0.2.0", + "node_modules/domain-browser": { + "version": "1.2.0", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10" + "node": ">=0.4", + "npm": ">=1.2" } }, - "node_modules/deep-copy": { - "version": "1.4.2", - "dev": true, + "node_modules/dot-case": { + "version": "1.1.2", "license": "MIT", - "engines": { - "node": ">=4.0.0" + "dependencies": { + "sentence-case": "^1.1.2" } }, - "node_modules/deep-eql": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "type-detect": "^4.0.0" - }, + "node_modules/dotenv": { + "version": "16.0.1", + "license": "BSD-2-Clause", "engines": { - "node": ">=0.12" + "node": ">=12" } }, - "node_modules/deep-equal": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", - "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/dotenv-expand": { + "version": "5.1.0", + "license": "BSD-2-Clause" }, - "node_modules/deep-is": { - "version": "0.1.4", + "node_modules/double-ended-queue": { + "version": "2.1.0-0", "license": "MIT" }, - "node_modules/default-compare": { - "version": "1.0.0", + "node_modules/duplexer2": { + "version": "0.1.4", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "kind-of": "^5.0.2" - }, - "engines": { - "node": ">=0.10.0" + "readable-stream": "^2.0.2" } }, - "node_modules/default-require-extensions": { - "version": "3.0.0", + "node_modules/duplexify": { + "version": "3.7.1", "dev": true, "license": "MIT", "dependencies": { - "strip-bom": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/default-require-extensions/node_modules/strip-bom": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/default-resolution": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.10" + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" } }, - "node_modules/define-properties": { - "version": "1.1.4", + "node_modules/each-props": { + "version": "1.3.2", "dev": true, "license": "MIT", "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" } }, - "node_modules/define-property": { - "version": "2.0.2", + "node_modules/each-props/node_modules/is-plain-object": { + "version": "2.0.4", "dev": true, "license": "MIT", "dependencies": { - "is-descriptor": "^1.0.2", "isobject": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/defined": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/delayed-stream": { - "version": "1.0.0", + "node_modules/ecc-jsbn": { + "version": "0.1.2", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.4.0" + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" } }, - "node_modules/demolish": { - "version": "1.0.2", - "dev": true, + "node_modules/ee-first": { + "version": "1.1.1", "license": "MIT" }, - "node_modules/denque": { - "version": "2.0.1", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" - } - }, - "node_modules/depd": { - "version": "1.1.2", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/deps-sort": { - "version": "2.0.1", + "node_modules/ejson": { + "version": "2.1.2", "dev": true, "license": "MIT", "dependencies": { - "JSONStream": "^1.0.3", - "shasum-object": "^1.0.0", - "subarg": "^1.0.0", - "through2": "^2.0.0" - }, - "bin": { - "deps-sort": "bin/cmd.js" + "underscore": "1.8.x" } }, - "node_modules/deps-sort/node_modules/jsonparse": { - "version": "1.3.1", + "node_modules/ejson/node_modules/underscore": { + "version": "1.8.3", "dev": true, - "engines": [ - "node >= 0.2.0" - ], "license": "MIT" }, - "node_modules/deps-sort/node_modules/JSONStream": { - "version": "1.3.5", - "dev": true, - "license": "(MIT OR Apache-2.0)", + "node_modules/elasticsearch": { + "version": "13.3.1", + "license": "Apache-2.0", "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" + "agentkeepalive": "^2.2.0", + "chalk": "^1.0.0", + "lodash": "2.4.2", + "lodash.get": "^4.4.2", + "lodash.isempty": "^4.4.0", + "lodash.trimend": "^4.5.1" }, "engines": { - "node": "*" + "node": ">=0.8" } }, - "node_modules/derequire": { - "version": "2.0.6", - "dev": true, + "node_modules/elasticsearch/node_modules/agentkeepalive": { + "version": "2.2.0", "license": "MIT", - "dependencies": { - "acorn": "^4.0.3", - "concat-stream": "^1.4.6", - "escope": "^3.6.0", - "through2": "^2.0.0", - "yargs": "^6.5.0" - }, - "bin": { - "derequire": "bin/cmd.js" + "engines": { + "node": ">= 0.10.0" } }, - "node_modules/derequire/node_modules/acorn": { - "version": "4.0.13", - "dev": true, + "node_modules/elasticsearch/node_modules/ansi-regex": { + "version": "2.1.1", "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/derequire/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, + "node_modules/elasticsearch/node_modules/ansi-styles": { + "version": "2.2.1", "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/derequire/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "dev": true, + "node_modules/elasticsearch/node_modules/chalk": { + "version": "1.1.3", "license": "MIT", "dependencies": { - "number-is-nan": "^1.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/derequire/node_modules/string-width": { - "version": "1.0.2", - "dev": true, + "node_modules/elasticsearch/node_modules/lodash": { + "version": "2.4.2", + "engines": [ + "node", + "rhino" + ], + "license": "MIT" + }, + "node_modules/elasticsearch/node_modules/strip-ansi": { + "version": "3.0.1", "license": "MIT", "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "ansi-regex": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/derequire/node_modules/strip-ansi": { - "version": "3.0.1", - "dev": true, + "node_modules/elasticsearch/node_modules/supports-color": { + "version": "2.0.0", "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8.0" } }, - "node_modules/derequire/node_modules/yargs": { - "version": "6.6.0", + "node_modules/electron-to-chromium": { + "version": "1.4.233", "dev": true, + "license": "ISC" + }, + "node_modules/elliptic": { + "version": "6.5.4", "license": "MIT", "dependencies": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^4.2.0" + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" } }, - "node_modules/derequire/node_modules/yargs-parser": { - "version": "4.2.1", + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "license": "MIT" + }, + "node_modules/emdee": { + "version": "0.0.3", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "camelcase": "^3.0.0" + "colors": "^1.1.2", + "debug": "^2.2.0", + "underscore.string": "^3.2.2", + "wordwrap": "^1.0.0" } }, - "node_modules/des.js": { - "version": "1.0.1", + "node_modules/emdee/node_modules/debug": { + "version": "2.6.9", + "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "ms": "2.0.0" } }, - "node_modules/destroy": { - "version": "1.2.0", + "node_modules/emdee/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/emits": { + "version": "3.0.0", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/enabled": { + "version": "1.0.2", "license": "MIT", - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "dependencies": { + "env-variable": "0.0.x" } }, - "node_modules/detect-file": { - "version": "1.0.0", - "dev": true, + "node_modules/encodeurl": { + "version": "1.0.2", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/detective": { - "version": "5.2.1", + "node_modules/end-of-stream": { + "version": "1.4.4", "dev": true, "license": "MIT", "dependencies": { - "acorn-node": "^1.8.2", - "defined": "^1.0.0", - "minimist": "^1.2.6" - }, - "bin": { - "detective": "bin/detective.js" - }, - "engines": { - "node": ">=0.8.0" + "once": "^1.4.0" } }, - "node_modules/deumdify": { - "version": "1.2.8", + "node_modules/engine.io": { + "version": "6.2.0", "dev": true, "license": "MIT", "dependencies": { - "escodegen": "~2.0.0", - "esprima": "~4.0.0", - "estraverse": "~5.2.0", - "through2": "~4.0.2" + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" }, - "peerDependencies": { - "browserify": "9 - 17" - } - }, - "node_modules/deumdify/node_modules/estraverse": { - "version": "5.2.0", - "dev": true, - "license": "BSD-2-Clause", "engines": { - "node": ">=4.0" + "node": ">=10.0.0" } }, - "node_modules/deumdify/node_modules/readable-stream": { - "version": "3.6.0", + "node_modules/engine.io-client": { + "version": "3.3.3", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "component-emitter": "1.2.1", + "component-inherit": "0.0.3", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.1", + "has-cors": "1.1.0", + "indexof": "0.0.1", + "parseqs": "0.0.5", + "parseuri": "0.0.5", + "ws": "~6.1.0", + "xmlhttprequest-ssl": "~1.6.3", + "yeast": "0.1.2" } }, - "node_modules/deumdify/node_modules/through2": { - "version": "4.0.2", + "node_modules/engine.io-client/node_modules/debug": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "readable-stream": "3" + "ms": "2.0.0" } }, - "node_modules/dev-null": { - "version": "0.1.1", - "license": "MIT" - }, - "node_modules/dface": { - "version": "1.0.1", - "license": "MIT" - }, - "node_modules/di": { - "version": "0.0.1", + "node_modules/engine.io-client/node_modules/ms": { + "version": "2.0.0", "dev": true, "license": "MIT" }, - "node_modules/diagnostics": { - "version": "1.0.1", + "node_modules/engine.io-parser": { + "version": "2.1.3", + "dev": true, "license": "MIT", "dependencies": { - "colorspace": "1.0.x", - "enabled": "1.0.x", - "kuler": "0.0.x" + "after": "0.8.2", + "arraybuffer.slice": "~0.0.7", + "base64-arraybuffer": "0.1.5", + "blob": "0.0.5", + "has-binary2": "~1.0.2" } }, - "node_modules/diff": { - "version": "5.0.0", + "node_modules/engine.io/node_modules/engine.io-parser": { + "version": "5.0.4", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">=0.3.1" + "node": ">=10.0.0" } }, - "node_modules/diffie-hellman": { - "version": "5.0.3", + "node_modules/engine.io/node_modules/ws": { + "version": "8.2.3", + "dev": true, "license": "MIT", - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.0", - "license": "MIT" - }, - "node_modules/diskspace": { - "version": "0.1.7", "engines": { - "node": "*" + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/doctrine": { - "version": "3.0.0", + "node_modules/enquirer": { + "version": "2.3.6", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "ansi-colors": "^4.1.1" }, "engines": { - "node": ">=6.0.0" + "node": ">=8.6" } }, - "node_modules/dom-serialize": { - "version": "2.2.1", + "node_modules/ent": { + "version": "2.2.0", "dev": true, - "license": "MIT", - "dependencies": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" - } + "license": "MIT" }, - "node_modules/domain-browser": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4", - "npm": ">=1.2" - } - }, - "node_modules/dot-case": { - "version": "1.1.2", - "license": "MIT", - "dependencies": { - "sentence-case": "^1.1.2" - } - }, - "node_modules/dotenv": { - "version": "16.0.1", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/dotenv-expand": { - "version": "5.1.0", - "license": "BSD-2-Clause" - }, - "node_modules/double-ended-queue": { - "version": "2.1.0-0", + "node_modules/env-variable": { + "version": "0.0.6", "license": "MIT" }, - "node_modules/duplexer2": { - "version": "0.1.4", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexify": { - "version": "3.7.1", - "dev": true, - "license": "MIT", + "node_modules/error": { + "version": "7.2.1", "dependencies": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" + "string-template": "~0.2.1" } }, - "node_modules/each-props": { + "node_modules/error-ex": { "version": "1.3.2", "dev": true, "license": "MIT", "dependencies": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" + "is-arrayish": "^0.2.1" } }, - "node_modules/each-props/node_modules/is-plain-object": { - "version": "2.0.4", + "node_modules/es-abstract": { + "version": "1.20.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "isobject": "^3.0.1" + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "regexp.prototype.flags": "^1.4.3", + "string.prototype.trimend": "^1.0.5", + "string.prototype.trimstart": "^1.0.5", + "unbox-primitive": "^1.0.2" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", + "node_modules/es-shim-unscopables": { + "version": "1.0.0", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "has": "^1.0.3" } }, - "node_modules/ee-first": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/ejson": { - "version": "2.1.2", + "node_modules/es-to-primitive": { + "version": "1.2.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "underscore": "1.8.x" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/ejson/node_modules/underscore": { - "version": "1.8.3", + "node_modules/es5-ext": { + "version": "0.10.62", "dev": true, - "license": "MIT" - }, - "node_modules/elasticsearch": { - "version": "13.3.1", - "license": "Apache-2.0", + "hasInstallScript": true, + "license": "ISC", "dependencies": { - "agentkeepalive": "^2.2.0", - "chalk": "^1.0.0", - "lodash": "2.4.2", - "lodash.get": "^4.4.2", - "lodash.isempty": "^4.4.0", - "lodash.trimend": "^4.5.1" + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" }, "engines": { - "node": ">=0.8" - } - }, - "node_modules/elasticsearch/node_modules/agentkeepalive": { - "version": "2.2.0", - "license": "MIT", - "engines": { - "node": ">= 0.10.0" + "node": ">=0.10" } }, - "node_modules/elasticsearch/node_modules/ansi-regex": { - "version": "2.1.1", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "node_modules/es6-error": { + "version": "4.1.1", + "dev": true, + "license": "MIT" }, - "node_modules/elasticsearch/node_modules/ansi-styles": { - "version": "2.2.1", + "node_modules/es6-iterator": { + "version": "2.0.3", + "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" } }, - "node_modules/elasticsearch/node_modules/chalk": { - "version": "1.1.3", + "node_modules/es6-map": { + "version": "0.1.5", + "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" } }, - "node_modules/elasticsearch/node_modules/lodash": { - "version": "2.4.2", - "engines": [ - "node", - "rhino" - ], + "node_modules/es6-promisify": { + "version": "6.1.1", "license": "MIT" }, - "node_modules/elasticsearch/node_modules/strip-ansi": { - "version": "3.0.1", - "license": "MIT", + "node_modules/es6-set": { + "version": "0.1.6", + "dev": true, + "license": "ISC", "dependencies": { - "ansi-regex": "^2.0.0" + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "es6-iterator": "~2.0.3", + "es6-symbol": "^3.1.3", + "event-emitter": "^0.3.5", + "type": "^2.7.2" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/elasticsearch/node_modules/supports-color": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">=0.8.0" + "node": ">=0.12" } }, - "node_modules/electron-to-chromium": { - "version": "1.4.188", + "node_modules/es6-set/node_modules/type": { + "version": "2.7.2", "dev": true, "license": "ISC" }, - "node_modules/elliptic": { - "version": "3.0.3", + "node_modules/es6-symbol": { + "version": "3.1.3", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "bn.js": "^2.0.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "inherits": "^2.0.1" + "d": "^1.0.1", + "ext": "^1.1.2" } }, - "node_modules/emdee": { - "version": "0.0.3", + "node_modules/es6-weak-map": { + "version": "2.0.3", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "colors": "^1.1.2", - "debug": "^2.2.0", - "underscore.string": "^3.2.2", - "wordwrap": "^1.0.0" + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" } }, - "node_modules/emdee/node_modules/debug": { - "version": "2.6.9", + "node_modules/escalade": { + "version": "3.1.1", "dev": true, "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=6" } }, - "node_modules/emdee/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/emdee/node_modules/wordwrap": { - "version": "1.0.0", - "dev": true, + "node_modules/escape-html": { + "version": "1.0.3", "license": "MIT" }, - "node_modules/emits": { - "version": "3.0.0", - "license": "MIT" + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } }, - "node_modules/emoji-regex": { - "version": "8.0.0", + "node_modules/escodegen": { + "version": "2.0.0", "dev": true, - "license": "MIT" - }, - "node_modules/enabled": { - "version": "1.0.2", - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "env-variable": "0.0.x" + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/encodeurl": { - "version": "1.0.2", - "license": "MIT", + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">= 0.8" + "node": ">=4.0" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", "dev": true, "license": "MIT", "dependencies": { - "once": "^1.4.0" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/engine.io": { - "version": "3.3.2", + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~6.1.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/engine.io-client": { - "version": "3.3.3", + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", "dev": true, - "license": "MIT", - "dependencies": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.6.3", - "yeast": "0.1.2" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/engine.io-client/node_modules/component-emitter": { - "version": "1.2.1", + "node_modules/escodegen/node_modules/source-map": { + "version": "0.6.1", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/engine.io-client/node_modules/debug": { - "version": "3.1.0", + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/engine.io-client/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/engine.io-parser": { - "version": "2.1.3", + "node_modules/escope": { + "version": "3.6.0", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/engine.io/node_modules/debug": { - "version": "3.1.0", + "node_modules/eslint": { + "version": "7.32.0", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "@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/engine.io/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/enquirer": { - "version": "2.3.6", + "node_modules/eslint-config-prettier": { + "version": "6.15.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-colors": "^4.1.1" + "get-stdin": "^6.0.0" }, - "engines": { - "node": ">=8.6" + "bin": { + "eslint-config-prettier-check": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=3.14.1" } }, - "node_modules/ent": { - "version": "2.2.0", + "node_modules/eslint-config-standard": { + "version": "16.0.3", "dev": true, - "license": "MIT" - }, - "node_modules/env-variable": { - "version": "0.0.6", - "license": "MIT" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "peerDependencies": { + "eslint": "^7.12.1", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^4.2.1 || ^5.0.0" + } }, - "node_modules/error": { - "version": "7.2.1", + "node_modules/eslint-import-resolver-node": { + "version": "0.3.6", + "dev": true, + "license": "MIT", + "peer": true, "dependencies": { - "string-template": "~0.2.1" + "debug": "^3.2.7", + "resolve": "^1.20.0" } }, - "node_modules/error-ex": { - "version": "1.3.2", + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "is-arrayish": "^0.2.1" + "ms": "^2.1.1" } }, - "node_modules/es-abstract": { - "version": "1.20.1", + "node_modules/eslint-module-utils": { + "version": "2.7.4", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.1", - "get-symbol-description": "^1.0.0", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "regexp.prototype.flags": "^1.4.3", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" + "debug": "^3.2.7" }, "engines": { - "node": ">= 0.4" + "node": ">=4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "has": "^1.0.3" + "ms": "^2.1.1" } }, - "node_modules/es-to-primitive": { - "version": "1.2.1", + "node_modules/eslint-plugin-es": { + "version": "3.0.1", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=8.10.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" } }, - "node_modules/es5-ext": { - "version": "0.10.61", + "node_modules/eslint-plugin-import": { + "version": "2.26.0", "dev": true, - "hasInstallScript": true, - "license": "ISC", + "license": "MIT", + "peer": true, "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" + "array-includes": "^3.1.4", + "array.prototype.flat": "^1.2.5", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.7.3", + "has": "^1.0.3", + "is-core-module": "^2.8.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.5", + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" }, "engines": { - "node": ">=0.10" + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, - "node_modules/es6-error": { - "version": "4.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/es6-iterator": { - "version": "2.0.3", + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "2.6.9", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" + "ms": "2.0.0" } }, - "node_modules/es6-map": { - "version": "0.1.5", + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "peer": true, "dependencies": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/es6-promisify": { - "version": "6.1.1", - "license": "MIT" - }, - "node_modules/es6-set": { - "version": "0.1.5", + "node_modules/eslint-plugin-import/node_modules/ms": { + "version": "2.0.0", "dev": true, "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - } + "peer": true }, - "node_modules/es6-set/node_modules/es6-symbol": { - "version": "3.1.1", + "node_modules/eslint-plugin-node": { + "version": "11.1.0", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" + "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/es6-symbol": { - "version": "3.1.3", + "node_modules/eslint-plugin-node/node_modules/ignore": { + "version": "5.2.0", "dev": true, - "license": "ISC", - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 4" } }, - "node_modules/es6-weak-map": { - "version": "2.0.3", + "node_modules/eslint-plugin-node/node_modules/semver": { + "version": "6.3.0", "dev": true, "license": "ISC", - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" + "peer": true, + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/escalade": { - "version": "3.1.1", + "node_modules/eslint-plugin-prettier": { + "version": "3.4.1", "dev": true, "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, "engines": { - "node": ">=6" + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=5.0.0", + "prettier": ">=1.13.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } } }, - "node_modules/escape-html": { - "version": "1.0.3", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "license": "MIT", + "node_modules/eslint-plugin-promise": { + "version": "5.2.0", + "dev": true, + "license": "ISC", + "peer": true, "engines": { - "node": ">=0.8.0" + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0" } }, - "node_modules/escodegen": { - "version": "2.0.0", + "node_modules/eslint-scope": { + "version": "5.1.1", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^1.1.0" }, "engines": { - "node": ">=6.0" + "node": ">=6" }, - "optionalDependencies": { - "source-map": "~0.6.1" + "funding": { + "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/escodegen/node_modules/estraverse": { - "version": "5.3.0", + "node_modules/eslint-visitor-keys": { + "version": "1.3.0", "dev": true, - "license": "BSD-2-Clause", + "license": "Apache-2.0", "engines": { - "node": ">=4.0" + "node": ">=4" } }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", + "node_modules/eslint/node_modules/@babel/code-frame": { + "version": "7.12.11", "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" + "@babel/highlight": "^7.10.4" } }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, "license": "MIT", "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", "dev": true, "license": "MIT", "dependencies": { - "prelude-ls": "~1.1.2" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/escope": { - "version": "3.6.0", + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "es6-map": "^0.1.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.4.0" + "node": ">=7.0.0" } }, - "node_modules/eslint": { - "version": "7.32.0", + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", "dev": true, "license": "MIT", - "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" + "node": ">=10" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-config-prettier": { - "version": "6.15.0", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.17.0", "dev": true, "license": "MIT", "dependencies": { - "get-stdin": "^6.0.0" + "type-fest": "^0.20.2" }, - "bin": { - "eslint-config-prettier-check": "bin/cli.js" + "engines": { + "node": ">=8" }, - "peerDependencies": { - "eslint": ">=3.14.1" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-config-standard": { - "version": "16.0.3", + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", "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" - } - ], "license": "MIT", - "peerDependencies": { - "eslint": "^7.12.1", - "eslint-plugin-import": "^2.22.1", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^4.2.1 || ^5.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.6", + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "debug": "^3.2.7", - "resolve": "^1.20.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", + "node_modules/espree": { + "version": "7.3.1", "dev": true, - "license": "MIT", - "peer": true, + "license": "BSD-2-Clause", "dependencies": { - "ms": "^2.1.1" + "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/eslint-module-utils": { - "version": "2.7.3", + "node_modules/esprima": { + "version": "4.0.1", "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "debug": "^3.2.7", - "find-up": "^2.1.0" + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { "node": ">=4" } }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", + "node_modules/esquery": { + "version": "1.4.0", "dev": true, - "license": "MIT", - "peer": true, + "license": "BSD-3-Clause", "dependencies": { - "ms": "^2.1.1" + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/eslint-plugin-es": { - "version": "3.0.1", + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" + "node": ">=4.0" } }, - "node_modules/eslint-plugin-import": { - "version": "2.26.0", + "node_modules/esrecurse": { + "version": "4.3.0", "dev": true, - "license": "MIT", - "peer": true, + "license": "BSD-2-Clause", "dependencies": { - "array-includes": "^3.1.4", - "array.prototype.flat": "^1.2.5", - "debug": "^2.6.9", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.6", - "eslint-module-utils": "^2.7.3", - "has": "^1.0.3", - "is-core-module": "^2.8.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.5", - "resolve": "^1.22.0", - "tsconfig-paths": "^3.14.1" + "estraverse": "^5.2.0" }, "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "node": ">=4.0" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "2.6.9", + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ms": "2.0.0" + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" } }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", + "node_modules/estraverse": { + "version": "4.3.0", "dev": true, - "license": "Apache-2.0", - "peer": true, - "dependencies": { - "esutils": "^2.0.2" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">=0.10.0" + "node": ">=4.0" } }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.0.0", + "node_modules/esutils": { + "version": "2.0.3", "dev": true, - "license": "MIT", - "peer": true + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/eslint-plugin-node": { - "version": "11.1.0", - "dev": true, + "node_modules/etag": { + "version": "1.8.1", "license": "MIT", - "peer": 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": ">= 0.6" } }, - "node_modules/eslint-plugin-node/node_modules/ignore": { - "version": "5.2.0", + "node_modules/event-emitter": { + "version": "0.3.5", "dev": true, "license": "MIT", - "peer": true, - "engines": { - "node": ">= 4" + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" } }, - "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "6.3.0", + "node_modules/event-lite": { + "version": "0.1.2", "dev": true, - "license": "ISC", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } + "license": "MIT" }, - "node_modules/eslint-plugin-prettier": { - "version": "3.4.1", + "node_modules/eventemitter3": { + "version": "1.2.0", + "license": "MIT" + }, + "node_modules/events": { + "version": "2.1.0", "dev": true, "license": "MIT", - "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": ">=0.4.x" } }, - "node_modules/eslint-plugin-promise": { - "version": "5.2.0", + "node_modules/eventsource": { + "version": "1.1.2", "dev": true, - "license": "ISC", - "peer": true, + "license": "MIT", "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.0.0" + "node": ">=0.12.0" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" } }, - "node_modules/eslint-utils": { - "version": "2.1.0", + "node_modules/exec-time": { + "version": "0.0.2", + "dev": true + }, + "node_modules/expand-braces": { + "version": "0.1.2", "dev": true, "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^1.1.0" + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" }, "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" + "node": ">=0.10.0" } }, - "node_modules/eslint-visitor-keys": { - "version": "1.3.0", + "node_modules/expand-braces/node_modules/array-slice": { + "version": "0.2.3", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/@babel/code-frame": { - "version": "7.12.11", + "node_modules/expand-braces/node_modules/array-unique": { + "version": "0.2.1", "dev": true, "license": "MIT", - "dependencies": { - "@babel/highlight": "^7.10.4" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/expand-braces/node_modules/braces": { + "version": "0.1.5", "dev": true, - "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "expand-range": "^0.1.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", + "node_modules/expand-brackets": { + "version": "2.1.4", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", + "node_modules/expand-brackets/node_modules/debug": { + "version": "2.6.9", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" + "ms": "2.0.0" } }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "is-descriptor": "^0.1.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "2.1.0", + "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.16.0", + "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", + "node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", "dev": true, "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/espree": { - "version": "7.3.1", + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=0.10.0" } }, - "node_modules/esprima": { - "version": "4.0.1", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/etag": { - "version": "1.8.1", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/event-emitter": { - "version": "0.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "node_modules/event-lite": { - "version": "0.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/eventemitter3": { - "version": "1.2.0", - "license": "MIT" - }, - "node_modules/events": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.x" - } - }, - "node_modules/eventsource": { - "version": "1.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "license": "MIT", - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/exec-time": { - "version": "0.0.2", - "dev": true - }, - "node_modules/expand-braces": { - "version": "0.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-braces/node_modules/array-slice": { - "version": "0.2.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-braces/node_modules/array-unique": { - "version": "0.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-braces/node_modules/braces": { - "version": "0.1.5", - "dev": true, - "dependencies": { - "expand-range": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "dev": true, - "license": "MIT", - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "dev": true, - "license": "MIT", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor": { - "version": "0.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.6", - "dev": true, - "license": "MIT", - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/ms": { - "version": "2.0.0", + "node_modules/expand-brackets/node_modules/ms": { + "version": "2.0.0", "dev": true, "license": "MIT" }, @@ -5558,7 +4976,7 @@ } }, "node_modules/ext/node_modules/type": { - "version": "2.6.0", + "version": "2.7.2", "dev": true, "license": "ISC" }, @@ -5750,17 +5168,39 @@ "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, - "node_modules/find-up": { - "version": "2.1.0", + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "3.1.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "locate-path": "^2.0.0" + "semver": "^6.0.0" }, "engines": { - "node": ">=4" - } + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } }, "node_modules/findup-sync": { "version": "3.0.0", @@ -5831,7 +5271,7 @@ } }, "node_modules/flatted": { - "version": "3.2.6", + "version": "3.2.7", "license": "ISC" }, "node_modules/flush-write-stream": { @@ -5881,17 +5321,48 @@ } }, "node_modules/foreground-child": { - "version": "2.0.0", + "version": "1.5.6", "dev": true, "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + } + }, + "node_modules/foreground-child/node_modules/cross-spawn": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "node_modules/foreground-child/node_modules/lru-cache": { + "version": "4.1.5", + "dev": true, + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/foreground-child/node_modules/which": { + "version": "1.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" }, - "engines": { - "node": ">=8.0.0" + "bin": { + "which": "bin/which" } }, + "node_modules/foreground-child/node_modules/yallist": { + "version": "2.1.2", + "dev": true, + "license": "ISC" + }, "node_modules/forever-agent": { "version": "0.6.1", "dev": true, @@ -5956,15 +5427,25 @@ "license": "MIT" }, "node_modules/fs-extra": { - "version": "10.1.0", + "version": "0.24.0", + "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/fs-extra/node_modules/rimraf": { + "version": "2.7.1", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" }, - "engines": { - "node": ">=12" + "bin": { + "rimraf": "bin.js" } }, "node_modules/fs-mkdirp-stream": { @@ -6074,9 +5555,12 @@ "license": "Apache-2.0" }, "node_modules/get-caller-file": { - "version": "1.0.3", + "version": "2.0.5", "dev": true, - "license": "ISC" + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } }, "node_modules/get-func-name": { "version": "2.0.0", @@ -6296,12 +5780,9 @@ "license": "ISC" }, "node_modules/growl": { - "version": "1.10.5", + "version": "1.9.2", "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.x" - } + "license": "MIT" }, "node_modules/gulp": { "version": "4.0.2", @@ -6362,178 +5843,407 @@ "node": ">=0.10.0" } }, - "node_modules/gulp-header": { - "version": "2.0.9", + "node_modules/gulp-cli/node_modules/ansi-regex": { + "version": "2.1.1", "dev": true, "license": "MIT", - "dependencies": { - "concat-with-sourcemaps": "^1.1.0", - "lodash.template": "^4.5.0", - "map-stream": "0.0.7", - "through2": "^2.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/gulp-uglify-es": { - "version": "2.0.0", + "node_modules/gulp-cli/node_modules/camelcase": { + "version": "3.0.0", "dev": true, "license": "MIT", - "dependencies": { - "o-stream": "^0.2.2", - "plugin-error": "^1.0.1", - "terser": "^4.3.9", - "vinyl": "^2.2.0", - "vinyl-sourcemaps-apply": "^0.2.1" - } - }, - "node_modules/gulp-uglify-es/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, - "node_modules/gulp-uglify-es/node_modules/terser": { - "version": "4.8.1", + "node_modules/gulp-cli/node_modules/cliui": { + "version": "3.2.0", "dev": true, - "license": "BSD-2-Clause", + "license": "ISC", "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=6.0.0" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" } }, - "node_modules/gulp-util": { - "version": "3.0.8", + "node_modules/gulp-cli/node_modules/decamelize": { + "version": "1.2.0", "dev": true, "license": "MIT", - "dependencies": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, "engines": { - "node": ">=0.10" + "node": ">=0.10.0" } }, - "node_modules/gulp-util/node_modules/ansi-regex": { - "version": "2.1.1", + "node_modules/gulp-cli/node_modules/find-up": { + "version": "1.1.2", "dev": true, "license": "MIT", + "dependencies": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/gulp-util/node_modules/ansi-styles": { - "version": "2.2.1", + "node_modules/gulp-cli/node_modules/get-caller-file": { + "version": "1.0.3", + "dev": true, + "license": "ISC" + }, + "node_modules/gulp-cli/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", "dev": true, "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/gulp-util/node_modules/chalk": { - "version": "1.1.3", + "node_modules/gulp-cli/node_modules/load-json-file": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/gulp-util/node_modules/clone": { - "version": "1.0.4", + "node_modules/gulp-cli/node_modules/parse-json": { + "version": "2.2.0", "dev": true, "license": "MIT", + "dependencies": { + "error-ex": "^1.2.0" + }, "engines": { - "node": ">=0.8" + "node": ">=0.10.0" } }, - "node_modules/gulp-util/node_modules/clone-stats": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/gulp-util/node_modules/lodash.template": { - "version": "3.6.2", + "node_modules/gulp-cli/node_modules/path-exists": { + "version": "2.1.0", "dev": true, "license": "MIT", "dependencies": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/gulp-util/node_modules/lodash.templatesettings": { - "version": "3.1.1", + "node_modules/gulp-cli/node_modules/path-type": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/gulp-util/node_modules/object-assign": { - "version": "3.0.0", + "node_modules/gulp-cli/node_modules/pify": { + "version": "2.3.0", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/gulp-util/node_modules/replace-ext": { - "version": "0.0.1", + "node_modules/gulp-cli/node_modules/read-pkg": { + "version": "1.1.0", "dev": true, + "license": "MIT", + "dependencies": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=0.10.0" } }, - "node_modules/gulp-util/node_modules/strip-ansi": { - "version": "3.0.1", + "node_modules/gulp-cli/node_modules/read-pkg-up": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^2.0.0" + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/gulp-util/node_modules/supports-color": { - "version": "2.0.0", + "node_modules/gulp-cli/node_modules/require-main-filename": { + "version": "1.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/gulp-cli/node_modules/string-width": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/strip-bom": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-utf8": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/which-module": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/gulp-cli/node_modules/wrap-ansi": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-cli/node_modules/y18n": { + "version": "3.2.2", + "dev": true, + "license": "ISC" + }, + "node_modules/gulp-cli/node_modules/yargs": { + "version": "7.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "node_modules/gulp-cli/node_modules/yargs-parser": { + "version": "5.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + }, + "node_modules/gulp-header": { + "version": "2.0.9", + "dev": true, + "license": "MIT", + "dependencies": { + "concat-with-sourcemaps": "^1.1.0", + "lodash.template": "^4.5.0", + "map-stream": "0.0.7", + "through2": "^2.0.0" + } + }, + "node_modules/gulp-uglify-es": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "o-stream": "^0.2.2", + "plugin-error": "^1.0.1", + "terser": "^4.3.9", + "vinyl": "^2.2.0", + "vinyl-sourcemaps-apply": "^0.2.1" + } + }, + "node_modules/gulp-uglify-es/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-uglify-es/node_modules/terser": { + "version": "4.8.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/gulp-util": { + "version": "3.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/gulp-util/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-util/node_modules/ansi-styles": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-util/node_modules/chalk": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-util/node_modules/clone": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/gulp-util/node_modules/clone-stats": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/gulp-util/node_modules/lodash.template": { + "version": "3.6.2", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "node_modules/gulp-util/node_modules/lodash.templatesettings": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "node_modules/gulp-util/node_modules/object-assign": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-util/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-util/node_modules/supports-color": { + "version": "2.0.0", "dev": true, "license": "MIT", "engines": { @@ -6732,17 +6442,37 @@ "node": ">=0.10.0" } }, - "node_modules/happn/node_modules/happn-logger": { - "version": "0.0.2", + "node_modules/happn/node_modules/crypto-browserify": { + "version": "3.11.0", "dev": true, "license": "MIT", "dependencies": { - "log4js": "^0.6.29" - } - }, - "node_modules/happn/node_modules/happn-nedb": { - "version": "1.9.1", - "dev": true, + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/happn/node_modules/happn-logger": { + "version": "0.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "log4js": "^0.6.29" + } + }, + "node_modules/happn/node_modules/happn-nedb": { + "version": "1.9.1", + "dev": true, "license": "SEE LICENSE IN LICENSE", "dependencies": { "async": "^3.2.0", @@ -6777,6 +6507,33 @@ "pbkdf2": "3.0.4" } }, + "node_modules/happn/node_modules/isarray": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/happn/node_modules/jsonparse": { + "version": "0.0.5", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/happn/node_modules/JSONStream": { + "version": "0.10.0", + "dev": true, + "dependencies": { + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "index.js" + }, + "engines": { + "node": "*" + } + }, "node_modules/happn/node_modules/jwt-simple": { "version": "0.2.0", "dev": true, @@ -6784,6 +6541,18 @@ "node": ">= 0.4.0" } }, + "node_modules/happn/node_modules/log4js": { + "version": "0.6.38", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "readable-stream": "~1.0.2", + "semver": "~4.3.3" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/happn/node_modules/lru-cache": { "version": "4.1.5", "dev": true, @@ -6798,6 +6567,14 @@ "dev": true, "license": "MIT" }, + "node_modules/happn/node_modules/pbkdf2": { + "version": "3.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "create-hmac": "^1.1.2" + } + }, "node_modules/happn/node_modules/pem": { "version": "1.11.2", "dev": true, @@ -6811,6 +6588,30 @@ "node": ">=4.0.0" } }, + "node_modules/happn/node_modules/readable-stream": { + "version": "1.0.34", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/happn/node_modules/semver": { + "version": "4.3.6", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/happn/node_modules/string_decoder": { + "version": "0.10.31", + "dev": true, + "license": "MIT" + }, "node_modules/happn/node_modules/which": { "version": "1.3.1", "dev": true, @@ -6879,6 +6680,10 @@ "resolved": "packages/happner-cluster", "link": true }, + "node_modules/happner-demos": { + "resolved": "packages/demos", + "link": true + }, "node_modules/happner-hyperid": { "version": "2.0.0", "dependencies": { @@ -6924,36 +6729,6 @@ "dev": true, "license": "MIT" }, - "node_modules/happner-serial-mocha/node_modules/commander": { - "version": "2.3.0", - "dev": true, - "engines": { - "node": ">= 0.6.x" - } - }, - "node_modules/happner-serial-mocha/node_modules/debug": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "0.7.1" - } - }, - "node_modules/happner-serial-mocha/node_modules/diff": { - "version": "1.4.0", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/happner-serial-mocha/node_modules/escape-string-regexp": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/happner-serial-mocha/node_modules/fs-extra": { "version": "1.0.0", "dev": true, @@ -6964,103 +6739,6 @@ "klaw": "^1.0.0" } }, - "node_modules/happner-serial-mocha/node_modules/glob": { - "version": "3.2.11", - "dev": true, - "license": "BSD", - "dependencies": { - "inherits": "2", - "minimatch": "0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/happner-serial-mocha/node_modules/growl": { - "version": "1.9.2", - "dev": true, - "license": "MIT" - }, - "node_modules/happner-serial-mocha/node_modules/jsonfile": { - "version": "2.4.0", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/happner-serial-mocha/node_modules/lru-cache": { - "version": "2.7.3", - "dev": true, - "license": "ISC" - }, - "node_modules/happner-serial-mocha/node_modules/minimatch": { - "version": "0.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "lru-cache": "2", - "sigmund": "~1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/happner-serial-mocha/node_modules/mkdirp": { - "version": "0.5.1", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "0.0.8" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/happner-serial-mocha/node_modules/mkdirp/node_modules/minimist": { - "version": "0.0.8", - "dev": true, - "license": "MIT" - }, - "node_modules/happner-serial-mocha/node_modules/mocha": { - "version": "2.5.3", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "2.3.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.2", - "glob": "3.2.11", - "growl": "1.9.2", - "jade": "0.26.3", - "mkdirp": "0.5.1", - "supports-color": "1.2.0", - "to-iso-string": "0.0.2" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 0.8.x" - } - }, - "node_modules/happner-serial-mocha/node_modules/ms": { - "version": "0.7.1", - "dev": true - }, - "node_modules/happner-serial-mocha/node_modules/supports-color": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "bin": { - "supports-color": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/happner-terminal": { "version": "0.0.8", "dev": true, @@ -7093,24 +6771,6 @@ "klaw": "^1.0.0" } }, - "node_modules/happner-terminal/node_modules/jsonfile": { - "version": "2.4.0", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/happner-terminal/node_modules/keypress": { - "version": "0.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/happner-terminal/node_modules/wordwrap": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/happner-test-modules": { "version": "1.0.2", "dev": true, @@ -7152,6 +6812,31 @@ "node": ">=0.10.0" } }, + "node_modules/happner/node_modules/core-util-is": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/happner/node_modules/crypto-browserify": { + "version": "3.11.0", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/happner/node_modules/form-data": { "version": "2.1.4", "dev": true, @@ -7165,17 +6850,6 @@ "node": ">= 0.12" } }, - "node_modules/happner/node_modules/fs-extra": { - "version": "0.24.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, "node_modules/happner/node_modules/glob": { "version": "5.0.15", "dev": true, @@ -7305,6 +6979,11 @@ "npm": ">=1.3.7" } }, + "node_modules/happner/node_modules/isarray": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, "node_modules/happner/node_modules/json-stable-stringify": { "version": "1.0.1", "dev": true, @@ -7313,12 +6992,26 @@ "jsonify": "~0.0.0" } }, - "node_modules/happner/node_modules/jsonfile": { - "version": "2.4.0", + "node_modules/happner/node_modules/jsonparse": { + "version": "0.0.5", "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/happner/node_modules/JSONStream": { + "version": "0.10.0", + "dev": true, + "dependencies": { + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "index.js" + }, + "engines": { + "node": "*" } }, "node_modules/happner/node_modules/jsprim": { @@ -7350,6 +7043,18 @@ "node": ">= 0.4.0" } }, + "node_modules/happner/node_modules/log4js": { + "version": "0.6.38", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "readable-stream": "~1.0.2", + "semver": "~4.3.3" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/happner/node_modules/lru-cache": { "version": "4.1.5", "dev": true, @@ -7377,6 +7082,14 @@ "node": "*" } }, + "node_modules/happner/node_modules/pbkdf2": { + "version": "3.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "create-hmac": "^1.1.2" + } + }, "node_modules/happner/node_modules/performance-now": { "version": "0.2.0", "dev": true, @@ -7395,6 +7108,17 @@ "node": ">=0.6" } }, + "node_modules/happner/node_modules/readable-stream": { + "version": "1.0.34", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, "node_modules/happner/node_modules/request": { "version": "2.81.0", "dev": true, @@ -7427,35 +7151,18 @@ "node": ">= 4" } }, - "node_modules/happner/node_modules/rimraf": { - "version": "2.7.1", + "node_modules/happner/node_modules/semver": { + "version": "4.3.6", "dev": true, "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, "bin": { - "rimraf": "bin.js" + "semver": "bin/semver" } }, - "node_modules/happner/node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", + "node_modules/happner/node_modules/string_decoder": { + "version": "0.10.31", "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } + "license": "MIT" }, "node_modules/happner/node_modules/tough-cookie": { "version": "2.3.4", @@ -7468,6 +7175,27 @@ "node": ">=0.8" } }, + "node_modules/happner/node_modules/verror": { + "version": "1.10.0", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/happner/node_modules/verror/node_modules/assert-plus": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/happner/node_modules/ws": { "version": "1.1.5", "dev": true, @@ -7547,11 +7275,6 @@ "isarray": "2.0.1" } }, - "node_modules/has-binary2/node_modules/isarray": { - "version": "2.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/has-cors": { "version": "1.1.0", "dev": true, @@ -7672,24 +7395,6 @@ "node": ">= 6" } }, - "node_modules/hash-base/node_modules/safe-buffer": { - "version": "5.2.1", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/hash.js": { "version": "1.1.7", "license": "MIT", @@ -7883,6 +7588,11 @@ "npm": ">=1.3.7" } }, + "node_modules/http-signature/node_modules/core-util-is": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, "node_modules/http-signature/node_modules/jsprim": { "version": "1.4.2", "dev": true, @@ -7897,6 +7607,19 @@ "node": ">=0.6.0" } }, + "node_modules/http-signature/node_modules/verror": { + "version": "1.10.0", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "node_modules/https-browserify": { "version": "1.0.0", "dev": true, @@ -8029,29 +7752,6 @@ "insert-module-globals": "bin/cmd.js" } }, - "node_modules/insert-module-globals/node_modules/jsonparse": { - "version": "1.3.1", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/insert-module-globals/node_modules/JSONStream": { - "version": "1.3.5", - "dev": true, - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, "node_modules/int64-buffer": { "version": "0.1.10", "dev": true, @@ -8097,13 +7797,15 @@ }, "node_modules/ip": { "version": "1.1.8", + "dev": true, "license": "MIT" }, "node_modules/ip-regex": { - "version": "2.1.0", + "version": "4.3.0", + "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/is-absolute": { @@ -8213,7 +7915,7 @@ } }, "node_modules/is-core-module": { - "version": "2.9.0", + "version": "2.10.0", "dev": true, "license": "MIT", "dependencies": { @@ -8323,14 +8025,6 @@ "node": ">=8" } }, - "node_modules/is-ip/node_modules/ip-regex": { - "version": "4.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-lower-case": { "version": "1.1.3", "license": "MIT", @@ -8514,17 +8208,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-upper-case": { "version": "1.1.2", "license": "MIT", @@ -8581,20 +8264,27 @@ "node": ">=v0.10.0" } }, + "node_modules/is2/node_modules/ip-regex": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/isarray": { - "version": "1.0.0", + "version": "2.0.1", "dev": true, "license": "MIT" }, "node_modules/isbinaryfile": { - "version": "3.0.3", + "version": "4.0.10", "dev": true, "license": "MIT", - "dependencies": { - "buffer-alloc": "^1.2.0" - }, "engines": { - "node": ">=0.6.0" + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" } }, "node_modules/isexe": { @@ -8615,11 +8305,11 @@ "license": "MIT" }, "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", + "version": "2.0.5", "dev": true, "license": "BSD-3-Clause", "engines": { - "node": ">=8" + "node": ">=6" } }, "node_modules/istanbul-lib-hook": { @@ -8648,6 +8338,14 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-instrument/node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, "node_modules/istanbul-lib-instrument/node_modules/semver": { "version": "6.3.0", "dev": true, @@ -8672,6 +8370,14 @@ "node": ">=8" } }, + "node_modules/istanbul-lib-processinfo/node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, "node_modules/istanbul-lib-processinfo/node_modules/uuid": { "version": "8.3.2", "dev": true, @@ -8681,35 +8387,27 @@ } }, "node_modules/istanbul-lib-report": { - "version": "3.0.0", + "version": "2.0.8", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" }, "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "node": ">=6" } }, "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", + "version": "6.1.0", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" } }, "node_modules/istanbul-lib-source-maps": { @@ -8725,6 +8423,14 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-source-maps/node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, "node_modules/istanbul-lib-source-maps/node_modules/source-map": { "version": "0.6.1", "dev": true, @@ -8734,15 +8440,14 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.4", + "version": "2.2.7", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "html-escaper": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=6" } }, "node_modules/jade": { @@ -8875,11 +8580,9 @@ } }, "node_modules/jsonfile": { - "version": "6.1.0", + "version": "2.4.0", + "dev": true, "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -8893,7 +8596,7 @@ "version": "1.1.5" }, "node_modules/jsonparse": { - "version": "0.0.5", + "version": "1.3.1", "dev": true, "engines": [ "node >= 0.2.0" @@ -8901,14 +8604,15 @@ "license": "MIT" }, "node_modules/JSONStream": { - "version": "0.10.0", + "version": "1.3.5", "dev": true, + "license": "(MIT OR Apache-2.0)", "dependencies": { - "jsonparse": "0.0.5", + "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" }, "bin": { - "JSONStream": "index.js" + "JSONStream": "bin.js" }, "engines": { "node": "*" @@ -8928,6 +8632,24 @@ "verror": "1.10.0" } }, + "node_modules/jsprim/node_modules/core-util-is": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/jsprim/node_modules/verror": { + "version": "1.10.0", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, "node_modules/just-debounce": { "version": "1.1.0", "dev": true, @@ -8946,44 +8668,40 @@ } }, "node_modules/karma": { - "version": "3.1.4", + "version": "6.4.0", "dev": true, "license": "MIT", "dependencies": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "chokidar": "^2.0.3", - "colors": "^1.1.0", - "combine-lists": "^1.0.0", - "connect": "^3.6.0", - "core-js": "^2.2.0", + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", - "flatted": "^2.0.0", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^4.17.5", - "log4js": "^3.0.0", - "mime": "^2.3.1", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", - "socket.io": "2.1.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", "source-map": "^0.6.1", - "tmp": "0.0.33", - "useragent": "2.3.0" + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" }, "bin": { "karma": "bin/karma" }, "engines": { - "node": ">= 6" + "node": ">= 10" } }, "node_modules/karma-chai": { @@ -9030,6 +8748,80 @@ "node": ">=10.0.0" } }, + "node_modules/karma-coverage/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/karma-coverage/node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/karma-coverage/node_modules/istanbul-lib-report": { + "version": "3.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/karma-coverage/node_modules/istanbul-reports": { + "version": "3.1.5", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/karma-coverage/node_modules/make-dir": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/karma-coverage/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/karma-coverage/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/karma-mocha": { "version": "2.0.1", "dev": true, @@ -9070,116 +8862,249 @@ "node": ">=4" } }, - "node_modules/karma/node_modules/bluebird": { - "version": "3.7.2", - "dev": true, - "license": "MIT" - }, - "node_modules/karma/node_modules/date-format": { - "version": "1.2.0", + "node_modules/karma/node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=4.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/karma/node_modules/debug": { - "version": "3.2.7", + "node_modules/karma/node_modules/anymatch": { + "version": "3.1.2", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "ms": "^2.1.1" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/karma/node_modules/flatted": { - "version": "2.0.2", + "node_modules/karma/node_modules/binary-extensions": { + "version": "2.2.0", "dev": true, - "license": "ISC" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/karma/node_modules/log4js": { - "version": "3.0.6", + "node_modules/karma/node_modules/braces": { + "version": "3.0.2", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "rfdc": "^1.1.2", - "streamroller": "0.7.0" + "fill-range": "^7.0.1" }, "engines": { - "node": ">=6.0" + "node": ">=8" } }, - "node_modules/karma/node_modules/mime": { - "version": "2.6.0", + "node_modules/karma/node_modules/chokidar": { + "version": "3.5.3", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "license": "MIT", - "bin": { - "mime": "cli.js" + "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": ">=4.0.0" + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/karma/node_modules/rimraf": { - "version": "2.7.1", + "node_modules/karma/node_modules/cliui": { + "version": "7.0.4", "dev": true, "license": "ISC", "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/karma/node_modules/source-map": { - "version": "0.6.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/karma/node_modules/streamroller": { - "version": "0.7.0", + "node_modules/karma/node_modules/color-convert": { + "version": "2.0.1", "dev": true, "license": "MIT", "dependencies": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/keygrip": { - "version": "1.0.3", - "license": "MIT", - "engines": { - "node": ">= 0.6" + "node": ">=7.0.0" } }, - "node_modules/keypress": { - "version": "0.1.0", + "node_modules/karma/node_modules/color-name": { + "version": "1.1.4", "dev": true, "license": "MIT" }, - "node_modules/kind-of": { - "version": "5.1.0", + "node_modules/karma/node_modules/fill-range": { + "version": "7.0.1", "dev": true, "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/klaw": { - "version": "1.3.1", + "node_modules/karma/node_modules/fsevents": { + "version": "2.3.2", "dev": true, "license": "MIT", - "optionalDependencies": { + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/karma/node_modules/is-binary-path": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/karma/node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/karma/node_modules/readdirp": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/karma/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/karma/node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/karma/node_modules/wrap-ansi": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "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/karma/node_modules/y18n": { + "version": "5.0.8", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/karma/node_modules/yargs": { + "version": "16.2.0", + "dev": true, + "license": "MIT", + "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/karma/node_modules/yargs-parser": { + "version": "20.2.9", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/keygrip": { + "version": "1.0.3", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/keypress": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/kind-of": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "optionalDependencies": { "graceful-fs": "^4.1.9" } }, @@ -9318,29 +9243,25 @@ "license": "MIT" }, "node_modules/load-json-file": { - "version": "1.1.0", + "version": "4.0.0", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/load-json-file/node_modules/strip-bom": { - "version": "2.0.0", + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", "dev": true, "license": "MIT", - "dependencies": { - "is-utf8": "^0.2.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, "node_modules/localforage": { @@ -9351,16 +9272,14 @@ } }, "node_modules/locate-path": { - "version": "2.0.0", + "version": "5.0.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "^4.1.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/lodash": { @@ -9529,46 +9448,19 @@ } }, "node_modules/log4js": { - "version": "0.6.38", - "dev": true, + "version": "6.6.1", "license": "Apache-2.0", "dependencies": { - "readable-stream": "~1.0.2", - "semver": "~4.3.3" + "date-format": "^4.0.13", + "debug": "^4.3.4", + "flatted": "^3.2.6", + "rfdc": "^1.3.0", + "streamroller": "^3.1.2" }, "engines": { - "node": ">=0.8" - } - }, - "node_modules/log4js/node_modules/isarray": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/log4js/node_modules/readable-stream": { - "version": "1.0.34", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/log4js/node_modules/semver": { - "version": "4.3.6", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" + "node": ">=8.0" } }, - "node_modules/log4js/node_modules/string_decoder": { - "version": "0.10.31", - "dev": true, - "license": "MIT" - }, "node_modules/lokijs": { "version": "1.5.12", "license": "MIT" @@ -9616,25 +9508,23 @@ } }, "node_modules/make-dir": { - "version": "3.1.0", + "version": "2.1.0", "dev": true, "license": "MIT", "dependencies": { - "semver": "^6.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", + "version": "5.7.1", "dev": true, "license": "ISC", "bin": { - "semver": "bin/semver.js" + "semver": "bin/semver" } }, "node_modules/make-iterator": { @@ -9845,13 +9735,14 @@ "license": "MIT" }, "node_modules/mime": { - "version": "1.6.0", + "version": "2.6.0", + "dev": true, "license": "MIT", "bin": { "mime": "cli.js" }, "engines": { - "node": ">=4" + "node": ">=4.0.0" } }, "node_modules/mime-db": { @@ -9937,5583 +9828,5797 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "dev": true, - "license": "MIT" - }, "node_modules/mocha": { - "version": "9.2.2", + "version": "2.5.3", "dev": true, "license": "MIT", "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "4.2.1", - "ms": "2.1.3", - "nanoid": "3.3.1", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.11", + "growl": "1.9.2", + "jade": "0.26.3", + "mkdirp": "0.5.1", + "supports-color": "1.2.0", + "to-iso-string": "0.0.2" }, "bin": { "_mocha": "bin/_mocha", "mocha": "bin/mocha" }, "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" + "node": ">= 0.8.x" } }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", + "node_modules/mocha/node_modules/commander": { + "version": "2.3.0", "dev": true, - "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 0.6.x" } }, - "node_modules/mocha/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/mocha/node_modules/debug": { + "version": "2.2.0", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, + "ms": "0.7.1" + } + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "1.0.2", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=0.8.0" } }, - "node_modules/mocha/node_modules/anymatch": { - "version": "3.1.2", + "node_modules/mocha/node_modules/glob": { + "version": "3.2.11", "dev": true, - "license": "ISC", + "license": "BSD", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "inherits": "2", + "minimatch": "0.3" }, "engines": { - "node": ">= 8" + "node": "*" } }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", + "node_modules/mocha/node_modules/lru-cache": { + "version": "2.7.3", "dev": true, - "license": "Python-2.0" + "license": "ISC" }, - "node_modules/mocha/node_modules/binary-extensions": { - "version": "2.2.0", + "node_modules/mocha/node_modules/minimatch": { + "version": "0.3.0", "dev": true, "license": "MIT", + "dependencies": { + "lru-cache": "2", + "sigmund": "~1.0.0" + }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/mocha/node_modules/braces": { - "version": "3.0.2", + "node_modules/mocha/node_modules/minimist": { + "version": "0.0.8", + "dev": true, + "license": "MIT" + }, + "node_modules/mocha/node_modules/mkdirp": { + "version": "0.5.1", "dev": true, "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "minimist": "0.0.8" }, - "engines": { - "node": ">=8" + "bin": { + "mkdirp": "bin/cmd.js" } }, - "node_modules/mocha/node_modules/chalk": { - "version": "4.1.2", + "node_modules/mocha/node_modules/ms": { + "version": "0.7.1", + "dev": true + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "1.2.0", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "bin": { + "supports-color": "cli.js" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/mock-fs": { + "version": "5.1.4", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=12.0.0" } }, - "node_modules/mocha/node_modules/chokidar": { - "version": "3.5.3", + "node_modules/module-deps": { + "version": "6.2.3", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], "license": "MIT", "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" + "browser-resolve": "^2.0.0", + "cached-path-relative": "^1.0.2", + "concat-stream": "~1.6.0", + "defined": "^1.0.0", + "detective": "^5.2.0", + "duplexer2": "^0.1.2", + "inherits": "^2.0.1", + "JSONStream": "^1.0.3", + "parents": "^1.0.0", + "readable-stream": "^2.0.2", + "resolve": "^1.4.0", + "stream-combiner2": "^1.1.1", + "subarg": "^1.0.0", + "through2": "^2.0.0", + "xtend": "^4.0.0" }, - "engines": { - "node": ">= 8.10.0" + "bin": { + "module-deps": "bin/cmd.js" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/mocha/node_modules/cliui": { - "version": "7.0.4", + "node_modules/module-deps/node_modules/browser-resolve": { + "version": "2.0.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "resolve": "^1.17.0" } }, - "node_modules/mocha/node_modules/color-convert": { - "version": "2.0.1", + "node_modules/moment": { + "version": "2.29.4", "dev": true, "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/mongodb": { + "version": "4.9.0", + "license": "Apache-2.0", "dependencies": { - "color-name": "~1.1.4" + "bson": "^4.7.0", + "denque": "^2.1.0", + "mongodb-connection-string-url": "^2.5.3", + "socks": "^2.7.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=12.9.0" + }, + "optionalDependencies": { + "saslprep": "^1.0.3" } }, - "node_modules/mocha/node_modules/color-name": { - "version": "1.1.4", - "dev": true, + "node_modules/mongodb-connection-string-url": { + "version": "2.5.3", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/ms": { + "version": "2.1.2", "license": "MIT" }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.3", + "node_modules/msgpack-lite": { + "version": "0.1.26", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" + "event-lite": "^0.1.1", + "ieee754": "^1.1.8", + "int64-buffer": "^0.1.9", + "isarray": "^1.0.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "bin": { + "msgpack": "bin/msgpack" } }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", + "node_modules/msgpack-lite/node_modules/isarray": { + "version": "1.0.0", "dev": true, "license": "MIT" }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", + "node_modules/multipipe": { + "version": "0.1.2", "dev": true, "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dependencies": { + "duplexer2": "0.0.2" } }, - "node_modules/mocha/node_modules/fill-range": { - "version": "7.0.1", + "node_modules/multipipe/node_modules/duplexer2": { + "version": "0.0.2", "dev": true, - "license": "MIT", + "license": "BSD", "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" + "readable-stream": "~1.1.9" } }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", + "node_modules/multipipe/node_modules/isarray": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/multipipe/node_modules/readable-stream": { + "version": "1.1.14", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "node_modules/mocha/node_modules/fsevents": { - "version": "2.3.2", + "node_modules/multipipe/node_modules/string_decoder": { + "version": "0.10.31", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } + "license": "MIT" }, - "node_modules/mocha/node_modules/get-caller-file": { - "version": "2.0.5", + "node_modules/mute-stdout": { + "version": "1.0.1", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">= 0.10" } }, - "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", + "node_modules/nan": { + "version": "2.16.0", "dev": true, - "license": "ISC", - "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" + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.1.32", + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", + "node_modules/nanomatch": { + "version": "1.2.13", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/is-binary-path": { - "version": "2.1.0", + "node_modules/nanomatch/node_modules/extend-shallow": { + "version": "3.0.2", "dev": true, "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/is-number": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", + "node_modules/nanomatch/node_modules/is-extendable": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^5.0.0" + "is-plain-object": "^2.0.4" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/log-symbols": { - "version": "4.1.0", + "node_modules/nanomatch/node_modules/is-plain-object": { + "version": "2.0.4", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" + "isobject": "^3.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/minimatch": { - "version": "4.2.1", + "node_modules/nanomatch/node_modules/kind-of": { + "version": "6.0.3", "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", + "node_modules/natural-compare": { + "version": "1.4.0", "dev": true, "license": "MIT" }, - "node_modules/mocha/node_modules/nanoid": { - "version": "3.3.1", + "node_modules/negotiator": { + "version": "0.6.3", "dev": true, "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">= 0.6" } }, - "node_modules/mocha/node_modules/p-limit": { - "version": "3.1.0", + "node_modules/next-tick": { + "version": "1.1.0", "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "ISC" }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", + "node_modules/nise": { + "version": "5.1.1", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": ">=5", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" } }, - "node_modules/mocha/node_modules/path-exists": { - "version": "4.0.0", + "node_modules/node-preload": { + "version": "0.2.1", "dev": true, "license": "MIT", + "dependencies": { + "process-on-spawn": "^1.0.0" + }, "engines": { "node": ">=8" } }, - "node_modules/mocha/node_modules/readdirp": { - "version": "3.6.0", - "dev": true, - "license": "MIT", + "node_modules/node-redis-pubsub": { + "version": "1.0.3", "dependencies": { - "picomatch": "^2.2.1" + "redis": "^2.7.1" }, "engines": { - "node": ">=8.10.0" + "node": "*" } }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "dev": true, + "node_modules/node-redis-pubsub/node_modules/redis": { + "version": "2.8.0", "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "double-ended-queue": "^2.1.0-0", + "redis-commands": "^1.2.0", + "redis-parser": "^2.6.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/to-regex-range": { - "version": "5.0.1", - "dev": true, + "node_modules/node-redis-pubsub/node_modules/redis-parser": { + "version": "2.6.0", "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, "engines": { - "node": ">=8.0" + "node": ">=0.10.0" } }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "7.0.0", + "node_modules/node-releases": { + "version": "2.0.6", "dev": true, - "license": "MIT", - "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" - } + "license": "MIT" }, - "node_modules/mocha/node_modules/y18n": { - "version": "5.0.8", + "node_modules/node-uuid": { + "version": "1.4.8", "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" + "bin": { + "uuid": "bin/uuid" } }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", + "node_modules/normalize-package-data": { + "version": "2.5.0", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "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" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", "dev": true, "license": "ISC", - "engines": { - "node": ">=10" + "bin": { + "semver": "bin/semver" } }, - "node_modules/mock-fs": { - "version": "5.1.2", + "node_modules/normalize-path": { + "version": "3.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=12.0.0" + "node": ">=0.10.0" } }, - "node_modules/module-deps": { - "version": "6.2.3", + "node_modules/now-and-later": { + "version": "2.0.1", "dev": true, "license": "MIT", "dependencies": { - "browser-resolve": "^2.0.0", - "cached-path-relative": "^1.0.2", - "concat-stream": "~1.6.0", - "defined": "^1.0.0", - "detective": "^5.2.0", - "duplexer2": "^0.1.2", - "inherits": "^2.0.1", - "JSONStream": "^1.0.3", - "parents": "^1.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.4.0", - "stream-combiner2": "^1.1.1", - "subarg": "^1.0.0", - "through2": "^2.0.0", - "xtend": "^4.0.0" - }, - "bin": { - "module-deps": "bin/cmd.js" + "once": "^1.3.2" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.10" } }, - "node_modules/module-deps/node_modules/jsonparse": { - "version": "1.3.1", + "node_modules/npm-programmatic": { + "version": "0.0.12", + "dev": true, + "license": "ISC", + "dependencies": { + "bluebird": "^3.4.1" + } + }, + "node_modules/npm-programmatic/node_modules/bluebird": { + "version": "3.7.2", "dev": true, - "engines": [ - "node >= 0.2.0" - ], "license": "MIT" }, - "node_modules/module-deps/node_modules/JSONStream": { - "version": "1.3.5", + "node_modules/number-is-nan": { + "version": "1.0.1", "dev": true, - "license": "(MIT OR Apache-2.0)", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc": { + "version": "15.1.0", + "dev": true, + "license": "ISC", "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" + "@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": { - "JSONStream": "bin.js" + "nyc": "bin/nyc.js" }, "engines": { - "node": "*" + "node": ">=8.9" } }, - "node_modules/moment": { - "version": "2.29.4", + "node_modules/nyc/node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/mongodb": { - "version": "4.8.0", - "license": "Apache-2.0", "dependencies": { - "bson": "^4.6.5", - "denque": "^2.0.1", - "mongodb-connection-string-url": "^2.5.2", - "socks": "^2.6.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=12.9.0" + "node": ">=8" }, - "optionalDependencies": { - "saslprep": "^1.0.3" - } - }, - "node_modules/mongodb-connection-string-url": { - "version": "2.5.2", - "license": "Apache-2.0", - "dependencies": { - "@types/whatwg-url": "^8.2.1", - "whatwg-url": "^11.0.0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ms": { - "version": "2.1.2", - "license": "MIT" - }, - "node_modules/msgpack-lite": { - "version": "0.1.26", + "node_modules/nyc/node_modules/camelcase": { + "version": "5.3.1", "dev": true, "license": "MIT", - "dependencies": { - "event-lite": "^0.1.1", - "ieee754": "^1.1.8", - "int64-buffer": "^0.1.9", - "isarray": "^1.0.0" - }, - "bin": { - "msgpack": "bin/msgpack" + "engines": { + "node": ">=6" } }, - "node_modules/multipipe": { - "version": "0.1.2", + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "duplexer2": "0.0.2" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, - "node_modules/multipipe/node_modules/duplexer2": { - "version": "0.0.2", + "node_modules/nyc/node_modules/color-convert": { + "version": "2.0.1", "dev": true, - "license": "BSD", + "license": "MIT", "dependencies": { - "readable-stream": "~1.1.9" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/multipipe/node_modules/isarray": { - "version": "0.0.1", + "node_modules/nyc/node_modules/color-name": { + "version": "1.1.4", "dev": true, "license": "MIT" }, - "node_modules/multipipe/node_modules/readable-stream": { - "version": "1.1.14", + "node_modules/nyc/node_modules/convert-source-map": { + "version": "1.8.0", "dev": true, "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "safe-buffer": "~5.1.1" } }, - "node_modules/multipipe/node_modules/string_decoder": { - "version": "0.10.31", + "node_modules/nyc/node_modules/decamelize": { + "version": "1.2.0", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/mute-stdout": { - "version": "1.0.1", + "node_modules/nyc/node_modules/foreground-child": { + "version": "2.0.0", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, "engines": { - "node": ">= 0.10" + "node": ">=8.0.0" } }, - "node_modules/nan": { - "version": "2.16.0", + "node_modules/nyc/node_modules/has-flag": { + "version": "4.0.0", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "node_modules/nanoid": { - "version": "2.1.11", + "node_modules/nyc/node_modules/istanbul-lib-coverage": { + "version": "3.2.0", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } }, - "node_modules/nanomatch": { - "version": "1.2.13", + "node_modules/nyc/node_modules/istanbul-lib-instrument": { + "version": "4.0.3", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/nanomatch/node_modules/extend-shallow": { - "version": "3.0.2", + "node_modules/nyc/node_modules/istanbul-lib-report": { + "version": "3.0.0", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/nanomatch/node_modules/is-extendable": { - "version": "1.0.1", + "node_modules/nyc/node_modules/istanbul-reports": { + "version": "3.1.5", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "is-plain-object": "^2.0.4" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/nanomatch/node_modules/is-plain-object": { - "version": "2.0.4", + "node_modules/nyc/node_modules/make-dir": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "semver": "^6.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/nanomatch/node_modules/kind-of": { - "version": "6.0.3", + "node_modules/nyc/node_modules/resolve-from": { + "version": "5.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/natural-compare": { - "version": "1.4.0", + "node_modules/nyc/node_modules/safe-buffer": { + "version": "5.1.2", "dev": true, "license": "MIT" }, - "node_modules/negotiator": { - "version": "0.6.3", + "node_modules/nyc/node_modules/semver": { + "version": "6.3.0", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/next-tick": { - "version": "1.1.0", - "dev": true, - "license": "ISC" - }, - "node_modules/nise": { - "version": "5.1.1", + "node_modules/nyc/node_modules/supports-color": { + "version": "7.2.0", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": ">=5", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "path-to-regexp": "^1.7.0" + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/node-preload": { - "version": "0.2.1", + "node_modules/nyc/node_modules/test-exclude": { + "version": "6.0.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "process-on-spawn": "^1.0.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "engines": { "node": ">=8" } }, - "node_modules/node-redis-pubsub": { - "version": "1.0.3", + "node_modules/nyc/node_modules/wrap-ansi": { + "version": "6.2.0", + "dev": true, + "license": "MIT", "dependencies": { - "redis": "^2.7.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/node-redis-pubsub/node_modules/redis": { - "version": "2.8.0", + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "dev": true, "license": "MIT", "dependencies": { - "double-ended-queue": "^2.1.0-0", - "redis-commands": "^1.2.0", - "redis-parser": "^2.6.0" + "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": ">=0.10.0" + "node": ">=8" } }, - "node_modules/node-redis-pubsub/node_modules/redis-parser": { - "version": "2.6.0", - "license": "MIT", + "node_modules/nyc/node_modules/yargs-parser": { + "version": "18.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/node-releases": { - "version": "2.0.6", + "node_modules/o-stream": { + "version": "0.2.2", "dev": true, "license": "MIT" }, - "node_modules/node-uuid": { - "version": "1.4.8", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", + "node_modules/oauth-sign": { + "version": "0.9.0", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" + "license": "Apache-2.0", + "engines": { + "node": "*" } }, - "node_modules/normalize-path": { - "version": "3.0.0", + "node_modules/object-assign": { + "version": "4.1.1", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/now-and-later": { - "version": "2.0.1", + "node_modules/object-copy": { + "version": "0.1.0", "dev": true, "license": "MIT", "dependencies": { - "once": "^1.3.2" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/npm-programmatic": { - "version": "0.0.12", + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "bluebird": "^3.4.1" + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/npm-programmatic/node_modules/bluebird": { - "version": "3.7.2", - "dev": true, - "license": "MIT" - }, - "node_modules/number-is-nan": { - "version": "1.0.1", + "node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", "dev": true, "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/nyc": { - "version": "15.1.0", + "node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", "dev": true, - "license": "ISC", + "license": "MIT", "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" + "kind-of": "^3.0.2" }, "engines": { - "node": ">=8.9" + "node": ">=0.10.0" } }, - "node_modules/nyc/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=0.10.0" } }, - "node_modules/nyc/node_modules/camelcase": { - "version": "5.3.1", + "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", "dev": true, "license": "MIT", "engines": { - "node": ">=6" - } - }, - "node_modules/nyc/node_modules/cliui": { - "version": "6.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" + "node": ">=0.10.0" } }, - "node_modules/nyc/node_modules/color-convert": { - "version": "2.0.1", + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">=7.0.0" + "node": ">=0.10.0" } }, - "node_modules/nyc/node_modules/color-name": { - "version": "1.1.4", + "node_modules/object-inspect": { + "version": "1.12.2", "dev": true, - "license": "MIT" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/nyc/node_modules/find-up": { - "version": "4.1.0", + "node_modules/object-is": { + "version": "1.1.5", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" }, "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/get-caller-file": { - "version": "2.0.5", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/nyc/node_modules/istanbul-lib-instrument": { - "version": "4.0.3", + "node_modules/object-keys": { + "version": "1.1.1", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/nyc/node_modules/locate-path": { - "version": "5.0.0", + "node_modules/object-visit": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "isobject": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/nyc/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/object.assign": { + "version": "4.1.4", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/nyc/node_modules/p-locate": { - "version": "4.1.0", + "node_modules/object.defaults": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" - }, + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/nyc/node_modules/p-try": { - "version": "2.2.0", + "node_modules/object.map": { + "version": "1.0.1", "dev": true, "license": "MIT", + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/nyc/node_modules/path-exists": { - "version": "4.0.0", + "node_modules/object.pick": { + "version": "1.3.0", "dev": true, "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/nyc/node_modules/require-main-filename": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/nyc/node_modules/resolve-from": { - "version": "5.0.0", + "node_modules/object.reduce": { + "version": "1.0.1", "dev": true, "license": "MIT", + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/semver": { - "version": "6.3.0", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node": ">=0.10.0" } }, - "node_modules/nyc/node_modules/which-module": { - "version": "2.0.0", - "dev": true, - "license": "ISC" - }, - "node_modules/nyc/node_modules/wrap-ansi": { - "version": "6.2.0", + "node_modules/object.values": { + "version": "1.1.5", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.1" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/nyc/node_modules/y18n": { - "version": "4.0.3", - "dev": true, - "license": "ISC" - }, - "node_modules/nyc/node_modules/yargs": { - "version": "15.4.1", - "dev": true, + "node_modules/on-finished": { + "version": "2.3.0", "license": "MIT", "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" + "ee-first": "1.1.1" }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/nyc/node_modules/yargs-parser": { - "version": "18.1.3", - "dev": true, + "node_modules/once": { + "version": "1.4.0", "license": "ISC", "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" + "wrappy": "1" } }, - "node_modules/o-stream": { - "version": "0.2.2", + "node_modules/one-time": { + "version": "0.0.4", "dev": true, "license": "MIT" }, - "node_modules/oauth-sign": { - "version": "0.9.0", + "node_modules/optimist": { + "version": "0.6.1", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "*" + "license": "MIT/X11", + "dependencies": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" } }, - "node_modules/object-assign": { - "version": "4.1.1", + "node_modules/optimist/node_modules/minimist": { + "version": "0.0.10", + "dev": true, + "license": "MIT" + }, + "node_modules/optimist/node_modules/wordwrap": { + "version": "0.0.3", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.4.0" } }, - "node_modules/object-component": { - "version": "0.0.3", - "dev": true - }, - "node_modules/object-copy": { - "version": "0.1.0", + "node_modules/optionator": { + "version": "0.9.1", "dev": true, "license": "MIT", "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", + "node_modules/options": { + "version": "0.0.6", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ordered-read-streams": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "is-descriptor": "^0.1.0" - }, + "readable-stream": "^2.0.1" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/os-homedir": { + "version": "1.0.2", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/object-copy/node_modules/is-accessor-descriptor": { - "version": "0.1.6", + "node_modules/os-locale": { + "version": "1.4.0", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" + "lcid": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/object-copy/node_modules/is-data-descriptor": { - "version": "0.1.4", - "dev": true, + "node_modules/os-tmpdir": { + "version": "1.0.2", "license": "MIT", - "dependencies": { - "kind-of": "^3.0.2" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/object-copy/node_modules/is-descriptor": { - "version": "0.1.6", + "node_modules/p-limit": { + "version": "2.3.0", "dev": true, "license": "MIT", "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "p-try": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", + "node_modules/p-locate": { + "version": "4.1.0", "dev": true, "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", + "node_modules/p-map": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" + "aggregate-error": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/object-inspect": { - "version": "1.12.2", + "node_modules/p-try": { + "version": "2.2.0", "dev": true, "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6" } }, - "node_modules/object-is": { - "version": "1.1.5", + "node_modules/package-hash": { + "version": "4.0.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/object-keys": { - "version": "1.1.1", + "node_modules/pako": { + "version": "1.0.11", "dev": true, + "license": "(MIT AND Zlib)" + }, + "node_modules/param-case": { + "version": "1.1.2", "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "sentence-case": "^1.1.2" } }, - "node_modules/object-visit": { + "node_modules/parent-module": { "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.0" + "callsites": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/object.assign": { - "version": "4.1.2", + "node_modules/parents": { + "version": "1.0.1", "dev": true, "license": "MIT", "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" + "path-platform": "~0.11.15" } }, - "node_modules/object.defaults": { - "version": "1.1.0", + "node_modules/parse-asn1": { + "version": "5.1.6", + "license": "ISC", + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", "dev": true, "license": "MIT", "dependencies": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8" } }, - "node_modules/object.map": { - "version": "1.0.1", + "node_modules/parse-json": { + "version": "4.0.0", "dev": true, "license": "MIT", "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/object.pick": { - "version": "1.3.0", + "node_modules/parse-mongo-url": { + "version": "1.1.1", + "license": "Apache 2.0" + }, + "node_modules/parse-node-version": { + "version": "1.0.1", "dev": true, "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/object.reduce": { - "version": "1.0.1", + "node_modules/parse-passwd": { + "version": "1.0.0", "dev": true, "license": "MIT", - "dependencies": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/object.values": { - "version": "1.1.5", + "node_modules/parseqs": { + "version": "0.0.5", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "better-assert": "~1.0.0" } }, - "node_modules/on-finished": { - "version": "2.3.0", + "node_modules/parseuri": { + "version": "0.0.5", + "dev": true, "license": "MIT", "dependencies": { - "ee-first": "1.1.1" - }, + "better-assert": "~1.0.0" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "license": "MIT", "engines": { "node": ">= 0.8" } }, - "node_modules/once": { - "version": "1.4.0", - "license": "ISC", + "node_modules/pascal-case": { + "version": "1.1.2", + "license": "MIT", "dependencies": { - "wrappy": "1" + "camel-case": "^1.1.1", + "upper-case-first": "^1.1.0" } }, - "node_modules/one-time": { - "version": "0.0.4", + "node_modules/pascalcase": { + "version": "0.1.1", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/optimist": { - "version": "0.6.1", + "node_modules/path-browserify": { + "version": "0.0.1", "dev": true, - "license": "MIT/X11", + "license": "MIT" + }, + "node_modules/path-case": { + "version": "1.1.2", + "license": "MIT", "dependencies": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" + "sentence-case": "^1.1.2" } }, - "node_modules/optimist/node_modules/minimist": { - "version": "0.0.10", + "node_modules/path-dirname": { + "version": "1.0.2", "dev": true, "license": "MIT" }, - "node_modules/optionator": { - "version": "0.9.1", + "node_modules/path-exists": { + "version": "4.0.0", "dev": true, "license": "MIT", - "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": ">=8" } }, - "node_modules/options": { - "version": "0.0.6", - "dev": true, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "license": "MIT", "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/ordered-read-streams": { - "version": "1.0.1", + "node_modules/path-key": { + "version": "3.1.1", "dev": true, "license": "MIT", - "dependencies": { - "readable-stream": "^2.0.1" + "engines": { + "node": ">=8" } }, - "node_modules/os-browserify": { - "version": "0.3.0", + "node_modules/path-parse": { + "version": "1.0.7", "dev": true, "license": "MIT" }, - "node_modules/os-homedir": { - "version": "1.0.2", + "node_modules/path-platform": { + "version": "0.11.15", + "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, - "node_modules/os-locale": { - "version": "1.4.0", + "node_modules/path-root": { + "version": "0.1.1", "dev": true, "license": "MIT", "dependencies": { - "lcid": "^1.0.0" + "path-root-regex": "^0.1.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/os-tmpdir": { - "version": "1.0.2", + "node_modules/path-root-regex": { + "version": "0.1.2", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/p-limit": { - "version": "1.3.0", + "node_modules/path-to-regexp": { + "version": "1.8.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" + "isarray": "0.0.1" } }, - "node_modules/p-locate": { - "version": "2.0.0", + "node_modules/path-to-regexp/node_modules/isarray": { + "version": "0.0.1", "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } + "license": "MIT" }, - "node_modules/p-map": { + "node_modules/path-type": { "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "aggregate-error": "^3.0.0" + "pify": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/p-try": { - "version": "1.0.0", + "node_modules/path-type/node_modules/pify": { + "version": "3.0.0", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=4" } }, - "node_modules/package-hash": { - "version": "4.0.0", + "node_modules/pathval": { + "version": "1.1.1", "dev": true, - "license": "ISC", - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/pako": { - "version": "1.0.11", - "dev": true, - "license": "(MIT AND Zlib)" - }, - "node_modules/param-case": { - "version": "1.1.2", + "node_modules/pbkdf2": { + "version": "3.1.2", "license": "MIT", "dependencies": { - "sentence-case": "^1.1.2" + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" } }, - "node_modules/parent-module": { - "version": "1.0.1", - "dev": true, + "node_modules/pem": { + "version": "1.14.6", "license": "MIT", "dependencies": { - "callsites": "^3.0.0" + "es6-promisify": "^6.0.0", + "md5": "^2.2.1", + "os-tmpdir": "^1.0.1", + "which": "^2.0.2" }, "engines": { - "node": ">=6" + "node": ">=6.0.0" } }, - "node_modules/parents": { - "version": "1.0.1", + "node_modules/performance-now": { + "version": "2.1.0", "dev": true, - "license": "MIT", - "dependencies": { - "path-platform": "~0.11.15" - } + "license": "MIT" }, - "node_modules/parse-asn1": { - "version": "5.1.6", - "license": "ISC", - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } + "node_modules/picocolors": { + "version": "1.0.0", + "dev": true, + "license": "ISC" }, - "node_modules/parse-filepath": { - "version": "1.0.2", + "node_modules/picomatch": { + "version": "2.3.1", "dev": true, "license": "MIT", - "dependencies": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - }, "engines": { - "node": ">=0.8" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/parse-json": { - "version": "2.2.0", + "node_modules/pify": { + "version": "4.0.1", "dev": true, "license": "MIT", - "dependencies": { - "error-ex": "^1.2.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/parse-mongo-url": { - "version": "1.1.1", - "license": "Apache 2.0" - }, - "node_modules/parse-node-version": { - "version": "1.0.1", + "node_modules/pinkie": { + "version": "2.0.4", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/parse-passwd": { - "version": "1.0.0", + "node_modules/pinkie-promise": { + "version": "2.0.1", "dev": true, "license": "MIT", + "dependencies": { + "pinkie": "^2.0.0" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/parseqs": { - "version": "0.0.5", + "node_modules/pkg-dir": { + "version": "4.2.0", "dev": true, "license": "MIT", "dependencies": { - "better-assert": "~1.0.0" + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "node_modules/parseuri": { - "version": "0.0.5", + "node_modules/plugin-error": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "better-assert": "~1.0.0" + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, + "engines": { + "node": ">= 0.10" } }, - "node_modules/parseurl": { - "version": "1.3.3", + "node_modules/plugin-error/node_modules/ansi-colors": { + "version": "1.1.0", + "dev": true, "license": "MIT", + "dependencies": { + "ansi-wrap": "^0.1.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/pascal-case": { - "version": "1.1.2", + "node_modules/plugin-error/node_modules/extend-shallow": { + "version": "3.0.2", + "dev": true, "license": "MIT", "dependencies": { - "camel-case": "^1.1.1", - "upper-case-first": "^1.1.0" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/pascalcase": { - "version": "0.1.1", + "node_modules/plugin-error/node_modules/is-extendable": { + "version": "1.0.1", "dev": true, "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/path-browserify": { - "version": "0.0.1", + "node_modules/plugin-error/node_modules/is-plain-object": { + "version": "2.0.4", "dev": true, - "license": "MIT" - }, - "node_modules/path-case": { - "version": "1.1.2", "license": "MIT", "dependencies": { - "sentence-case": "^1.1.2" + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/path-dirname": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/path-exists": { - "version": "3.0.0", + "node_modules/posix-character-classes": { + "version": "0.1.1", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", + "node_modules/predefine": { + "version": "0.1.3", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "extendible": "0.1.x" } }, - "node_modules/path-key": { - "version": "3.1.1", + "node_modules/prelude-ls": { + "version": "1.2.1", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "dev": true, - "license": "MIT" - }, - "node_modules/path-platform": { - "version": "0.11.15", + "node_modules/prettier": { + "version": "2.7.1", "dev": true, "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, "engines": { - "node": ">= 0.8.0" + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/path-root": { - "version": "0.1.1", + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "path-root-regex": "^0.1.0" + "fast-diff": "^1.1.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/path-root-regex": { - "version": "0.1.2", + "node_modules/pretty-hrtime": { + "version": "1.0.3", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/path-to-regexp": { - "version": "1.8.0", - "dev": true, + "node_modules/primus": { + "version": "7.3.5", "license": "MIT", "dependencies": { - "isarray": "0.0.1" + "access-control": "~1.0.0", + "asyncemit": "~3.0.1", + "create-server": "~1.0.1", + "diagnostics": "~2.0.0", + "eventemitter3": "~4.0.0", + "forwarded-for": "~1.1.0", + "fusing": "~1.0.0", + "nanoid": "~3.1.10", + "setheader": "~1.0.2", + "ultron": "~1.1.0" } }, - "node_modules/path-to-regexp/node_modules/isarray": { - "version": "0.0.1", + "node_modules/primus-msgpack": { + "version": "1.0.2", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "msgpack-lite": "0.1.26" + } }, - "node_modules/path-type": { - "version": "1.1.0", - "dev": true, + "node_modules/primus/node_modules/color": { + "version": "3.2.1", "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "color-convert": "^1.9.3", + "color-string": "^1.6.0" } }, - "node_modules/pathval": { - "version": "1.1.1", - "dev": true, + "node_modules/primus/node_modules/color-string": { + "version": "1.9.1", "license": "MIT", - "engines": { - "node": "*" + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "node_modules/pbkdf2": { - "version": "3.0.4", + "node_modules/primus/node_modules/colornames": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/primus/node_modules/colorspace": { + "version": "1.1.4", "license": "MIT", "dependencies": { - "create-hmac": "^1.1.2" + "color": "^3.1.3", + "text-hex": "1.0.x" } }, - "node_modules/pem": { - "version": "1.14.6", + "node_modules/primus/node_modules/diagnostics": { + "version": "2.0.2", "license": "MIT", "dependencies": { - "es6-promisify": "^6.0.0", - "md5": "^2.2.1", - "os-tmpdir": "^1.0.1", - "which": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0", + "storage-engine": "3.0.x" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "dev": true, + "node_modules/primus/node_modules/enabled": { + "version": "2.0.0", "license": "MIT" }, - "node_modules/picocolors": { - "version": "1.0.0", - "dev": true, - "license": "ISC" + "node_modules/primus/node_modules/eventemitter3": { + "version": "4.0.7", + "license": "MIT" }, - "node_modules/picomatch": { - "version": "2.3.1", - "dev": true, + "node_modules/primus/node_modules/forwarded-for": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/primus/node_modules/kuler": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/primus/node_modules/setheader": { + "version": "1.0.2", "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "dependencies": { + "diagnostics": "1.x.x" } }, - "node_modules/pify": { - "version": "2.3.0", - "dev": true, + "node_modules/primus/node_modules/setheader/node_modules/diagnostics": { + "version": "1.1.1", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" } }, - "node_modules/pinkie": { - "version": "2.0.4", - "dev": true, + "node_modules/primus/node_modules/setheader/node_modules/enabled": { + "version": "1.0.2", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "env-variable": "0.0.x" } }, - "node_modules/pinkie-promise": { - "version": "2.0.1", - "dev": true, + "node_modules/primus/node_modules/setheader/node_modules/kuler": { + "version": "1.0.1", "license": "MIT", "dependencies": { - "pinkie": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" + "colornames": "^1.1.1" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", + "node_modules/primus/node_modules/text-hex": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/primus/node_modules/ultron": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/proc-stats": { + "version": "0.0.4", + "license": "MIT" + }, + "node_modules/process": { + "version": "0.11.10", "dev": true, "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.6.0" } }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", + "node_modules/process-nextick-args": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/process-on-spawn": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "fromentries": "^1.2.0" }, "engines": { "node": ">=8" } }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", + "node_modules/progress": { + "version": "2.0.3", "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, "engines": { - "node": ">=8" + "node": ">=0.4.0" } }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/pseudomap": { + "version": "1.0.2", "dev": true, + "license": "ISC" + }, + "node_modules/psl": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/public-encrypt": { + "version": "4.0.3", "license": "MIT", "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" } }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "license": "MIT" + }, + "node_modules/pump": { + "version": "2.0.1", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "node_modules/pkg-dir/node_modules/p-try": { - "version": "2.2.0", + "node_modules/pumpify": { + "version": "1.5.1", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" } }, - "node_modules/pkg-dir/node_modules/path-exists": { - "version": "4.0.0", - "dev": true, + "node_modules/punycode": { + "version": "2.1.1", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/plugin-error": { - "version": "1.0.1", + "node_modules/qjobs": { + "version": "1.2.0", "dev": true, "license": "MIT", - "dependencies": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, "engines": { - "node": ">= 0.10" + "node": ">=0.9" } }, - "node_modules/plugin-error/node_modules/ansi-colors": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-wrap": "^0.1.0" - }, + "node_modules/qs": { + "version": "6.9.7", + "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/plugin-error/node_modules/extend-shallow": { - "version": "3.0.2", + "node_modules/querystring": { + "version": "0.2.0", "dev": true, - "license": "MIT", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">=0.4.x" } }, - "node_modules/plugin-error/node_modules/is-extendable": { - "version": "1.0.1", + "node_modules/querystring-es3": { + "version": "0.2.1", "dev": true, - "license": "MIT", - "dependencies": { - "is-plain-object": "^2.0.4" - }, "engines": { - "node": ">=0.10.0" + "node": ">=0.4.x" } }, - "node_modules/plugin-error/node_modules/is-plain-object": { - "version": "2.0.4", + "node_modules/querystringify": { + "version": "2.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/randexp": { + "version": "0.3.4", "dev": true, - "license": "MIT", "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" + "ret": "0.1.x" } }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "dev": true, + "node_modules/randombytes": { + "version": "2.1.0", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "safe-buffer": "^5.1.0" } }, - "node_modules/predefine": { - "version": "0.1.3", + "node_modules/randomfill": { + "version": "1.0.4", "license": "MIT", "dependencies": { - "extendible": "0.1.x" + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, - "node_modules/prelude-ls": { + "node_modules/range-parser": { "version": "1.2.1", - "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">= 0.6" } }, - "node_modules/prettier": { - "version": "2.7.1", - "dev": true, + "node_modules/raw-body": { + "version": "1.1.7", "license": "MIT", - "bin": { - "prettier": "bin-prettier.js" + "dependencies": { + "bytes": "1", + "string_decoder": "0.10" }, "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">= 0.8.0" } }, - "node_modules/prettier-linter-helpers": { - "version": "1.0.0", - "dev": true, + "node_modules/raw-body/node_modules/bytes": { + "version": "1.0.0" + }, + "node_modules/raw-body/node_modules/string_decoder": { + "version": "0.10.31", + "license": "MIT" + }, + "node_modules/read-only-stream": { + "version": "2.0.0", + "dev": true, "license": "MIT", "dependencies": { - "fast-diff": "^1.1.2" - }, - "engines": { - "node": ">=6.0.0" + "readable-stream": "^2.0.2" } }, - "node_modules/pretty-hrtime": { - "version": "1.0.3", + "node_modules/read-pkg": { + "version": "3.0.0", "dev": true, "license": "MIT", + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, "engines": { - "node": ">= 0.8" + "node": ">=4" } }, - "node_modules/primus": { - "version": "7.3.5", + "node_modules/read-pkg-up": { + "version": "4.0.0", + "dev": true, "license": "MIT", "dependencies": { - "access-control": "~1.0.0", - "asyncemit": "~3.0.1", - "create-server": "~1.0.1", - "diagnostics": "~2.0.0", - "eventemitter3": "~4.0.0", - "forwarded-for": "~1.1.0", - "fusing": "~1.0.0", - "nanoid": "~3.1.10", - "setheader": "~1.0.2", - "ultron": "~1.1.0" + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/primus-msgpack": { - "version": "1.0.2", + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "msgpack-lite": "0.1.26" + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/primus/node_modules/color": { - "version": "3.2.1", + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^1.9.3", - "color-string": "^1.6.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/primus/node_modules/color-string": { - "version": "1.9.1", + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "dev": true, "license": "MIT", "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/primus/node_modules/colornames": { - "version": "1.1.1", - "license": "MIT" - }, - "node_modules/primus/node_modules/colorspace": { - "version": "1.1.4", + "node_modules/read-pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "dev": true, "license": "MIT", - "dependencies": { - "color": "^3.1.3", - "text-hex": "1.0.x" + "engines": { + "node": ">=4" } }, - "node_modules/primus/node_modules/diagnostics": { - "version": "2.0.2", + "node_modules/readable-stream": { + "version": "2.3.7", + "dev": true, "license": "MIT", "dependencies": { - "colorspace": "1.1.x", - "enabled": "2.0.x", - "kuler": "^2.0.0", - "storage-engine": "3.0.x" + "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/primus/node_modules/enabled": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/primus/node_modules/eventemitter3": { - "version": "4.0.7", - "license": "MIT" - }, - "node_modules/primus/node_modules/forwarded-for": { - "version": "1.1.0", + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "dev": true, "license": "MIT" }, - "node_modules/primus/node_modules/kuler": { - "version": "2.0.0", + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, "license": "MIT" }, - "node_modules/primus/node_modules/nanoid": { - "version": "3.1.32", + "node_modules/readable-stream/node_modules/string_decoder": { + "version": "1.1.1", + "dev": true, "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "dependencies": { + "safe-buffer": "~5.1.0" } }, - "node_modules/primus/node_modules/setheader": { - "version": "1.0.2", + "node_modules/readdirp": { + "version": "2.2.1", + "dev": true, "license": "MIT", "dependencies": { - "diagnostics": "1.x.x" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" } }, - "node_modules/primus/node_modules/setheader/node_modules/diagnostics": { - "version": "1.1.1", - "license": "MIT", + "node_modules/rechoir": { + "version": "0.6.2", + "dev": true, "dependencies": { - "colorspace": "1.1.x", - "enabled": "1.0.x", - "kuler": "1.0.x" + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" } }, - "node_modules/primus/node_modules/setheader/node_modules/enabled": { - "version": "1.0.2", + "node_modules/recovery": { + "version": "0.2.6", + "dev": true, "license": "MIT", "dependencies": { - "env-variable": "0.0.x" + "demolish": "1.0.x", + "eventemitter3": "1.1.x", + "millisecond": "0.1.x", + "one-time": "0.0.x", + "tick-tock": "1.0.x" } }, - "node_modules/primus/node_modules/setheader/node_modules/kuler": { - "version": "1.0.1", + "node_modules/recovery/node_modules/eventemitter3": { + "version": "1.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/redis": { + "version": "4.3.0", "license": "MIT", + "workspaces": [ + "./packages/*" + ], "dependencies": { - "colornames": "^1.1.1" + "@redis/bloom": "1.0.2", + "@redis/client": "1.3.0", + "@redis/graph": "1.0.1", + "@redis/json": "1.0.3", + "@redis/search": "1.1.0", + "@redis/time-series": "1.0.3" } }, - "node_modules/primus/node_modules/text-hex": { - "version": "1.0.0", + "node_modules/redis-commands": { + "version": "1.7.0", "license": "MIT" }, - "node_modules/primus/node_modules/ultron": { - "version": "1.1.1", - "license": "MIT" + "node_modules/redis-errors": { + "version": "1.2.0", + "license": "MIT", + "engines": { + "node": ">=4" + } }, - "node_modules/proc-stats": { - "version": "0.0.4", - "license": "MIT" + "node_modules/redis-lru-cache": { + "resolved": "packages/redis-lru-cache", + "link": true }, - "node_modules/process": { - "version": "0.11.10", - "dev": true, + "node_modules/redis-parser": { + "version": "3.0.0", "license": "MIT", + "dependencies": { + "redis-errors": "^1.0.0" + }, "engines": { - "node": ">= 0.6.0" + "node": ">=4" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/process-on-spawn": { - "version": "1.0.0", + "node_modules/regex-not": { + "version": "1.0.2", "dev": true, "license": "MIT", "dependencies": { - "fromentries": "^1.2.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/progress": { - "version": "2.0.3", + "node_modules/regex-not/node_modules/extend-shallow": { + "version": "3.0.2", "dev": true, "license": "MIT", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, "engines": { - "node": ">=0.4.0" + "node": ">=0.10.0" } }, - "node_modules/pseudomap": { - "version": "1.0.2", + "node_modules/regex-not/node_modules/is-extendable": { + "version": "1.0.1", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/psl": { - "version": "1.9.0", + "node_modules/regex-not/node_modules/is-plain-object": { + "version": "2.0.4", "dev": true, - "license": "MIT" - }, - "node_modules/public-encrypt": { - "version": "4.0.3", "license": "MIT", "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "license": "MIT" - }, - "node_modules/pump": { - "version": "2.0.1", + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", "dev": true, "license": "MIT", "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/pumpify": { - "version": "1.5.1", + "node_modules/regexpp": { + "version": "3.2.0", "dev": true, "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "dev": true, + "license": "ISC", "dependencies": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" } }, - "node_modules/punycode": { - "version": "2.1.1", + "node_modules/remove-bom-buffer": { + "version": "3.0.0", + "dev": true, "license": "MIT", + "dependencies": { + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" + }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, - "node_modules/qjobs": { + "node_modules/remove-bom-stream": { "version": "1.2.0", "dev": true, "license": "MIT", + "dependencies": { + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" + }, "engines": { - "node": ">=0.9" + "node": ">= 0.10" } }, - "node_modules/qs": { - "version": "6.9.7", - "license": "BSD-3-Clause", + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "dev": true, + "license": "ISC" + }, + "node_modules/repeat-element": { + "version": "1.1.4", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/querystring": { - "version": "0.2.0", + "node_modules/repeat-string": { + "version": "1.6.1", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.4.x" + "node": ">=0.10" } }, - "node_modules/querystring-es3": { - "version": "0.2.1", - "dev": true, + "node_modules/repl": { + "version": "0.1.3", "engines": { - "node": ">=0.4.x" + "node": ">= 0.4.0" } }, - "node_modules/querystringify": { - "version": "2.1.1", - "dev": true, - "license": "MIT" + "node_modules/repl.history": { + "version": "0.1.4", + "license": "MIT", + "bin": { + "repl.history": "bin/repl.history" + } }, - "node_modules/randexp": { - "version": "0.3.4", + "node_modules/replace-ext": { + "version": "0.0.1", "dev": true, - "dependencies": { - "ret": "0.1.x" + "engines": { + "node": ">= 0.4" } }, - "node_modules/randombytes": { - "version": "2.1.0", + "node_modules/replace-homedir": { + "version": "1.0.0", + "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "^5.1.0" + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" } }, - "node_modules/randomfill": { - "version": "1.0.4", - "license": "MIT", + "node_modules/request": { + "version": "2.88.2", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" } }, - "node_modules/range-parser": { - "version": "1.2.1", + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/raw-body": { - "version": "2.4.3", + "node_modules/require-from-string": { + "version": "2.0.2", + "dev": true, "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, "engines": { - "node": ">= 0.8" + "node": ">=0.10.0" } }, - "node_modules/read-only-stream": { + "node_modules/require-main-filename": { "version": "2.0.0", "dev": true, + "license": "ISC" + }, + "node_modules/require-self": { + "version": "0.2.3", + "dev": true, "license": "MIT", - "dependencies": { - "readable-stream": "^2.0.2" + "bin": { + "require-self": "bin/require-self" } }, - "node_modules/read-pkg": { - "version": "1.1.0", + "node_modules/requires-port": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.1", "dev": true, "license": "MIT", "dependencies": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" }, - "engines": { - "node": ">=0.10.0" + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/read-pkg-up": { + "node_modules/resolve-dir": { "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "1.1.2", + "node_modules/resolve-from": { + "version": "4.0.0", "dev": true, "license": "MIT", - "dependencies": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "2.1.0", + "node_modules/resolve-options": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "pinkie-promise": "^2.0.0" + "value-or-function": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/readable-stream": { - "version": "2.3.7", + "node_modules/resolve-url": { + "version": "0.2.1", "dev": true, - "license": "MIT", - "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" - } + "license": "MIT" }, - "node_modules/readdirp": { - "version": "2.2.1", + "node_modules/restler": { + "version": "3.4.0", "dev": true, "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" + "iconv-lite": "0.2.11", + "qs": "1.2.0", + "xml2js": "0.4.0", + "yaml": "0.2.3" }, "engines": { - "node": ">=0.10" + "node": ">= 0.10.x" } }, - "node_modules/rechoir": { - "version": "0.6.2", + "node_modules/restler/node_modules/iconv-lite": { + "version": "0.2.11", "dev": true, - "dependencies": { - "resolve": "^1.1.6" - }, + "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=0.4.0" } }, - "node_modules/recovery": { - "version": "0.2.6", - "dev": true, - "license": "MIT", - "dependencies": { - "demolish": "1.0.x", - "eventemitter3": "1.1.x", - "millisecond": "0.1.x", - "one-time": "0.0.x", - "tick-tock": "1.0.x" - } + "node_modules/restler/node_modules/qs": { + "version": "1.2.0", + "dev": true }, - "node_modules/recovery/node_modules/eventemitter3": { - "version": "1.1.1", + "node_modules/ret": { + "version": "0.1.15", "dev": true, - "license": "MIT" - }, - "node_modules/redis": { - "version": "4.2.0", "license": "MIT", - "workspaces": [ - "./packages/*" - ], - "dependencies": { - "@redis/bloom": "1.0.2", - "@redis/client": "1.2.0", - "@redis/graph": "1.0.1", - "@redis/json": "1.0.3", - "@redis/search": "1.0.6", - "@redis/time-series": "1.0.3" + "engines": { + "node": ">=0.12" } }, - "node_modules/redis-commands": { - "version": "1.7.0", + "node_modules/rfdc": { + "version": "1.3.0", "license": "MIT" }, - "node_modules/redis-errors": { - "version": "1.2.0", + "node_modules/right-align": { + "version": "0.1.3", + "dev": true, "license": "MIT", + "dependencies": { + "align-text": "^0.1.1" + }, "engines": { - "node": ">=4" + "node": ">=0.10.0" } }, - "node_modules/redis-lru-cache": { - "resolved": "packages/redis-lru-cache", - "link": true + "node_modules/rimraf": { + "version": "3.0.2", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } }, - "node_modules/redis-parser": { - "version": "3.0.0", + "node_modules/ripemd160": { + "version": "2.0.2", "license": "MIT", "dependencies": { - "redis-errors": "^1.0.0" - }, - "engines": { - "node": ">=4" + "hash-base": "^3.0.0", + "inherits": "^2.0.1" } }, - "node_modules/regex-not": { - "version": "1.0.2", + "node_modules/rocambole": { + "version": "0.7.0", "dev": true, "license": "MIT", "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" + "esprima": "^2.1" } }, - "node_modules/regex-not/node_modules/extend-shallow": { - "version": "3.0.2", + "node_modules/rocambole-node-remove": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "rocambole-token": "^1.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/regex-not/node_modules/is-extendable": { - "version": "1.0.1", + "node_modules/rocambole-token": { + "version": "1.2.1", "dev": true, - "license": "MIT", - "dependencies": { - "is-plain-object": "^2.0.4" + "license": "MIT" + }, + "node_modules/rocambole/node_modules/esprima": { + "version": "2.7.3", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/regex-not/node_modules/is-plain-object": { - "version": "2.0.4", + "node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-json-parse": { + "version": "1.0.1" + }, + "node_modules/safe-regex": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" + "ret": "~0.1.10" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "dev": true, + "node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/saslprep": { + "version": "1.0.3", "license": "MIT", + "optional": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "sparse-bitfield": "^3.0.3" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=6" } }, - "node_modules/regexpp": { - "version": "3.2.0", + "node_modules/sax": { + "version": "0.5.8", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } + "license": "BSD" }, - "node_modules/release-zalgo": { - "version": "1.0.0", + "node_modules/semver": { + "version": "7.3.7", "dev": true, "license": "ISC", "dependencies": { - "es6-error": "^4.0.1" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/remove-bom-buffer": { - "version": "3.0.0", + "node_modules/semver-greatest-satisfied-range": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" + "sver-compat": "^1.5.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/remove-bom-stream": { - "version": "1.2.0", - "dev": true, + "node_modules/send": { + "version": "0.18.0", "license": "MIT", "dependencies": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" }, "engines": { - "node": ">= 0.10" + "node": ">= 0.8.0" } }, - "node_modules/remove-trailing-separator": { - "version": "1.1.0", - "dev": true, - "license": "ISC" - }, - "node_modules/repeat-element": { - "version": "1.1.4", - "dev": true, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "ms": "2.0.0" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "dev": true, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/send/node_modules/depd": { + "version": "2.0.0", "license": "MIT", "engines": { - "node": ">=0.10" + "node": ">= 0.8" } }, - "node_modules/repl": { - "version": "0.1.3", + "node_modules/send/node_modules/http-errors": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, "engines": { - "node": ">= 0.4.0" + "node": ">= 0.8" } }, - "node_modules/repl.history": { - "version": "0.1.4", + "node_modules/send/node_modules/mime": { + "version": "1.6.0", "license": "MIT", "bin": { - "repl.history": "bin/repl.history" + "mime": "cli.js" + }, + "engines": { + "node": ">=4" } }, - "node_modules/replace-ext": { - "version": "1.0.1", - "dev": true, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "license": "MIT" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, "engines": { - "node": ">= 0.10" + "node": ">= 0.8" } }, - "node_modules/replace-homedir": { - "version": "1.0.0", - "dev": true, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", "license": "MIT", - "dependencies": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - }, "engines": { - "node": ">= 0.10" + "node": ">= 0.8" } }, - "node_modules/request": { - "version": "2.88.2", - "dev": true, - "license": "Apache-2.0", + "node_modules/sentence-case": { + "version": "1.1.3", + "license": "MIT", "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" + "lower-case": "^1.1.1" } }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", + "node_modules/serialize-javascript": { + "version": "6.0.0", "dev": true, "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "1.15.0", + "license": "MIT", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, "engines": { - "node": ">=0.6" + "node": ">= 0.8.0" } }, - "node_modules/require-directory": { - "version": "2.1.1", + "node_modules/set-blocking": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/set-value": { + "version": "2.0.1", "dev": true, "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", + "node_modules/set-value/node_modules/is-plain-object": { + "version": "2.0.4", "dev": true, "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "1.0.1", + "node_modules/setheader": { + "version": "0.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "0.7.x" + } + }, + "node_modules/setheader/node_modules/debug": { + "version": "0.7.4", "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", "license": "ISC" }, - "node_modules/require-self": { - "version": "0.2.3", + "node_modules/sha.js": { + "version": "2.4.11", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shasum": { + "version": "1.0.2", "dev": true, "license": "MIT", - "bin": { - "require-self": "bin/require-self" + "dependencies": { + "json-stable-stringify": "~0.0.0", + "sha.js": "~2.4.4" } }, - "node_modules/requires-port": { + "node_modules/shasum-object": { "version": "1.0.0", - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.1", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "fast-safe-stringify": "^2.0.7" } }, - "node_modules/resolve-dir": { - "version": "1.0.1", + "node_modules/shebang-command": { + "version": "2.0.0", "dev": true, "license": "MIT", "dependencies": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "shebang-regex": "^3.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/resolve-from": { - "version": "4.0.0", + "node_modules/shebang-regex": { + "version": "3.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/resolve-options": { - "version": "1.1.0", + "node_modules/shell-quote": { + "version": "1.7.3", + "dev": true, + "license": "MIT" + }, + "node_modules/shortid": { + "version": "2.2.16", "dev": true, "license": "MIT", "dependencies": { - "value-or-function": "^3.0.0" - }, - "engines": { - "node": ">= 0.10" + "nanoid": "^2.1.0" } }, - "node_modules/resolve-url": { - "version": "0.2.1", + "node_modules/shortid/node_modules/nanoid": { + "version": "2.1.11", "dev": true, "license": "MIT" }, - "node_modules/restler": { - "version": "3.4.0", + "node_modules/should": { + "version": "13.2.3", "dev": true, "license": "MIT", "dependencies": { - "iconv-lite": "0.2.11", - "qs": "1.2.0", - "xml2js": "0.4.0", - "yaml": "0.2.3" - }, - "engines": { - "node": ">= 0.10.x" + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" } }, - "node_modules/restler/node_modules/iconv-lite": { - "version": "0.2.11", + "node_modules/should-equal": { + "version": "2.0.0", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.4.0" + "dependencies": { + "should-type": "^1.4.0" } }, - "node_modules/restler/node_modules/qs": { - "version": "1.2.0", - "dev": true - }, - "node_modules/ret": { - "version": "0.1.15", + "node_modules/should-format": { + "version": "3.0.3", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.12" + "dependencies": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" } }, - "node_modules/rfdc": { - "version": "1.3.0", + "node_modules/should-type": { + "version": "1.4.0", + "dev": true, "license": "MIT" }, - "node_modules/right-align": { - "version": "0.1.3", + "node_modules/should-type-adaptors": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "align-text": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "license": "MIT", - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "should-type": "^1.3.0", + "should-util": "^1.0.0" } }, - "node_modules/rocambole": { - "version": "0.7.0", + "node_modules/should-util": { + "version": "1.0.1", "dev": true, - "license": "MIT", - "dependencies": { - "esprima": "^2.1" - } + "license": "MIT" }, - "node_modules/rocambole-node-remove": { - "version": "3.0.0", + "node_modules/side-channel": { + "version": "1.0.4", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "rocambole-token": "^1.1.0" + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" }, - "engines": { - "node": ">=6" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/rocambole-token": { - "version": "1.2.1", + "node_modules/sift": { + "version": "3.3.12", "dev": true, "license": "MIT" }, - "node_modules/rocambole/node_modules/esprima": { - "version": "2.7.3", + "node_modules/siginfo": { + "version": "2.0.0", "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } + "license": "ISC" }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "license": "MIT" + "node_modules/sigmund": { + "version": "1.0.1", + "dev": true, + "license": "ISC" }, - "node_modules/safe-json-parse": { - "version": "1.0.1" + "node_modules/signal-exit": { + "version": "3.0.7", + "dev": true, + "license": "ISC" }, - "node_modules/safe-regex": { - "version": "1.1.0", + "node_modules/simple-concat": { + "version": "1.0.1", "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" + } + ], + "license": "MIT" + }, + "node_modules/simple-lru-cache": { + "version": "0.0.2" + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", "license": "MIT", "dependencies": { - "ret": "~0.1.10" + "is-arrayish": "^0.3.1" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", "license": "MIT" }, - "node_modules/saslprep": { - "version": "1.0.3", - "license": "MIT", - "optional": true, + "node_modules/sinon": { + "version": "12.0.1", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "sparse-bitfield": "^3.0.3" + "@sinonjs/commons": "^1.8.3", + "@sinonjs/fake-timers": "^8.1.0", + "@sinonjs/samsam": "^6.0.2", + "diff": "^5.0.0", + "nise": "^5.1.0", + "supports-color": "^7.2.0" }, - "engines": { - "node": ">=6" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" } }, - "node_modules/sax": { - "version": "0.5.8", + "node_modules/sinon-chai": { + "version": "3.7.0", "dev": true, - "license": "BSD" + "license": "(BSD-2-Clause OR WTFPL)", + "peerDependencies": { + "chai": "^4.0.0", + "sinon": ">=4.0.0" + } }, - "node_modules/semver": { - "version": "7.3.7", + "node_modules/sinon/node_modules/diff": { + "version": "5.1.0", "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">=10" + "node": ">=0.3.1" } }, - "node_modules/semver-greatest-satisfied-range": { - "version": "1.1.0", + "node_modules/sinon/node_modules/has-flag": { + "version": "4.0.0", "dev": true, "license": "MIT", - "dependencies": { - "sver-compat": "^1.5.0" - }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "node_modules/send": { - "version": "0.18.0", + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, "license": "MIT", "dependencies": { - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "mime": "1.6.0", - "ms": "2.1.3", - "on-finished": "2.4.1", - "range-parser": "~1.2.1", - "statuses": "2.0.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "node": ">=8" } }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/send/node_modules/depd": { - "version": "2.0.0", + "node_modules/slash": { + "version": "3.0.0", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=8" } }, - "node_modules/send/node_modules/http-errors": { - "version": "2.0.0", + "node_modules/slice-ansi": { + "version": "4.0.0", + "dev": true, "license": "MIT", "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/send/node_modules/ms": { - "version": "2.1.3", - "license": "MIT" - }, - "node_modules/send/node_modules/on-finished": { - "version": "2.4.1", + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, "license": "MIT", "dependencies": { - "ee-first": "1.1.1" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.8" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/send/node_modules/statuses": { + "node_modules/slice-ansi/node_modules/color-convert": { "version": "2.0.1", + "dev": true, "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">= 0.8" + "node": ">=7.0.0" } }, - "node_modules/sentence-case": { - "version": "1.1.3", - "license": "MIT", - "dependencies": { - "lower-case": "^1.1.1" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.0", + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } + "license": "MIT" }, - "node_modules/serve-static": { - "version": "1.15.0", + "node_modules/smart-buffer": { + "version": "4.2.0", "license": "MIT", - "dependencies": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.18.0" - }, "engines": { - "node": ">= 0.8.0" + "node": ">= 6.0.0", + "npm": ">= 3.0.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "dev": true, - "license": "ISC" + "node_modules/snake-case": { + "version": "1.1.2", + "license": "MIT", + "dependencies": { + "sentence-case": "^1.1.2" + } }, - "node_modules/set-value": { - "version": "2.0.1", + "node_modules/snapdragon": { + "version": "0.8.2", "dev": true, "license": "MIT", "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/set-value/node_modules/is-plain-object": { - "version": "2.0.4", + "node_modules/snapdragon-node": { + "version": "2.1.1", "dev": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/setheader": { - "version": "0.0.4", + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "debug": "0.7.x" - } - }, - "node_modules/setheader/node_modules/debug": { - "version": "0.7.4", - "dev": true, + "is-descriptor": "^1.0.0" + }, "engines": { - "node": "*" + "node": ">=0.10.0" } }, - "node_modules/setprototypeof": { - "version": "1.2.0", - "license": "ISC" - }, - "node_modules/sha.js": { - "version": "2.4.11", - "license": "(MIT AND BSD-3-Clause)", + "node_modules/snapdragon-util": { + "version": "3.0.1", + "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "kind-of": "^3.2.0" }, - "bin": { - "sha.js": "bin.js" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/shasum": { - "version": "1.0.2", + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", "dev": true, "license": "MIT", "dependencies": { - "json-stable-stringify": "~0.0.0", - "sha.js": "~2.4.4" + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/shasum-object": { - "version": "1.0.0", + "node_modules/snapdragon/node_modules/debug": { + "version": "2.6.9", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "fast-safe-stringify": "^2.0.7" + "ms": "2.0.0" } }, - "node_modules/shebang-command": { - "version": "2.0.0", + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", "dev": true, "license": "MIT", "dependencies": { - "shebang-regex": "^3.0.0" + "is-descriptor": "^0.1.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/shebang-regex": { - "version": "3.0.0", + "node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", "dev": true, "license": "MIT", + "dependencies": { + "kind-of": "^3.0.2" + }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/shell-quote": { - "version": "1.7.3", - "dev": true, - "license": "MIT" - }, - "node_modules/shortid": { - "version": "2.2.16", + "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", "dev": true, "license": "MIT", "dependencies": { - "nanoid": "^2.1.0" + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/should": { - "version": "13.2.3", + "node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", "dev": true, "license": "MIT", "dependencies": { - "should-equal": "^2.0.0", - "should-format": "^3.0.3", - "should-type": "^1.4.0", - "should-type-adaptors": "^1.0.1", - "should-util": "^1.0.0" + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/should-equal": { - "version": "2.0.0", + "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", "dev": true, "license": "MIT", "dependencies": { - "should-type": "^1.4.0" + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/should-format": { - "version": "3.0.3", + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", "dev": true, "license": "MIT", "dependencies": { - "should-type": "^1.3.0", - "should-type-adaptors": "^1.0.1" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/should-type": { - "version": "1.4.0", + "node_modules/snapdragon/node_modules/ms": { + "version": "2.0.0", "dev": true, "license": "MIT" }, - "node_modules/should-type-adaptors": { - "version": "1.1.0", + "node_modules/sntp": { + "version": "1.0.9", + "dev": true, + "dependencies": { + "hoek": "2.x.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/socket.io": { + "version": "4.5.1", "dev": true, "license": "MIT", "dependencies": { - "should-type": "^1.3.0", - "should-util": "^1.0.0" + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.2.0", + "socket.io-adapter": "~2.4.0", + "socket.io-parser": "~4.0.4" + }, + "engines": { + "node": ">=10.0.0" } }, - "node_modules/should-util": { - "version": "1.0.1", + "node_modules/socket.io-adapter": { + "version": "2.4.0", "dev": true, "license": "MIT" }, - "node_modules/side-channel": { - "version": "1.0.4", + "node_modules/socket.io-parser": { + "version": "4.0.5", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10.0.0" } }, - "node_modules/sift": { - "version": "3.3.12", + "node_modules/socket.io-parser/node_modules/component-emitter": { + "version": "1.3.0", "dev": true, "license": "MIT" }, - "node_modules/siginfo": { - "version": "2.0.0", + "node_modules/sockjs": { + "version": "0.3.24", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } }, - "node_modules/sigmund": { - "version": "1.0.1", + "node_modules/sockjs-client": { + "version": "1.3.0", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "debug": "^3.2.5", + "eventsource": "^1.0.7", + "faye-websocket": "~0.11.1", + "inherits": "^2.0.3", + "json3": "^3.3.2", + "url-parse": "^1.4.3" + } }, - "node_modules/signal-exit": { - "version": "3.0.7", + "node_modules/sockjs-client/node_modules/debug": { + "version": "3.2.7", "dev": true, - "license": "ISC" + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } }, - "node_modules/simple-concat": { - "version": "1.0.1", + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", "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" - } - ], - "license": "MIT" - }, - "node_modules/simple-lru-cache": { - "version": "0.0.2" + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } }, - "node_modules/simple-swizzle": { - "version": "0.2.2", + "node_modules/socks": { + "version": "2.7.0", "license": "MIT", "dependencies": { - "is-arrayish": "^0.3.1" + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" } }, - "node_modules/simple-swizzle/node_modules/is-arrayish": { - "version": "0.3.2", + "node_modules/socks/node_modules/ip": { + "version": "2.0.0", "license": "MIT" }, - "node_modules/sinon": { - "version": "12.0.1", + "node_modules/source-map": { + "version": "0.5.7", "dev": true, "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.8.3", - "@sinonjs/fake-timers": "^8.1.0", - "@sinonjs/samsam": "^6.0.2", - "diff": "^5.0.0", - "nise": "^5.1.0", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/sinon-chai": { - "version": "3.7.0", + "node_modules/source-map-resolve": { + "version": "0.5.3", "dev": true, - "license": "(BSD-2-Clause OR WTFPL)", - "peerDependencies": { - "chai": "^4.0.0", - "sinon": ">=4.0.0" + "license": "MIT", + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, - "node_modules/sinon/node_modules/has-flag": { - "version": "4.0.0", - "dev": true, + "node_modules/source-map-support": { + "version": "0.5.21", "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "license": "BSD-3-Clause", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", + "node_modules/source-map-url": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/sparkles": { + "version": "1.0.1", "dev": true, "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.10" } }, - "node_modules/slash": { - "version": "3.0.0", - "dev": true, + "node_modules/sparse-bitfield": { + "version": "3.0.3", "license": "MIT", - "engines": { - "node": ">=8" + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" } }, - "node_modules/slice-ansi": { - "version": "4.0.0", + "node_modules/spawn-wrap": { + "version": "2.0.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "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": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" + "node": ">=8" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", + "node_modules/spawn-wrap/node_modules/foreground-child": { + "version": "2.0.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "color-convert": "^2.0.1" + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=8.0.0" } }, - "node_modules/slice-ansi/node_modules/color-convert": { - "version": "2.0.1", + "node_modules/spawn-wrap/node_modules/make-dir": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "semver": "^6.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/slice-ansi/node_modules/color-name": { - "version": "1.1.4", + "node_modules/spawn-wrap/node_modules/semver": { + "version": "6.3.0", "dev": true, - "license": "MIT" - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" } }, - "node_modules/snake-case": { - "version": "1.1.2", - "license": "MIT", + "node_modules/spdx-correct": { + "version": "3.1.1", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "sentence-case": "^1.1.2" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/snapdragon": { - "version": "0.8.2", + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", "dev": true, "license": "MIT", "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, - "node_modules/snapdragon-node": { - "version": "2.1.1", + "node_modules/spdx-license-ids": { + "version": "3.0.12", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/split-string": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "extend-shallow": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", "dev": true, "license": "MIT", "dependencies": { - "is-descriptor": "^1.0.0" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon-util": { - "version": "3.0.1", + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^3.2.0" + "is-plain-object": "^2.0.4" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", + "node_modules/split-string/node_modules/is-plain-object": { + "version": "2.0.4", "dev": true, "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" + "isobject": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon/node_modules/debug": { - "version": "2.6.9", + "node_modules/split2": { + "version": "2.2.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "ms": "2.0.0" + "through2": "^2.0.2" } }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", + "node_modules/sprintf-js": { + "version": "1.0.3", "dev": true, - "license": "MIT", - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } + "license": "BSD-3-Clause" }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor": { - "version": "0.1.6", + "node_modules/sshpk": { + "version": "1.17.0", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" - }, + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", + "node_modules/stack-trace": { + "version": "0.0.10", "dev": true, "license": "MIT", - "dependencies": { - "is-buffer": "^1.1.5" - }, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "node_modules/snapdragon/node_modules/is-data-descriptor": { - "version": "0.1.4", + "node_modules/stackback": { + "version": "0.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/static-extend": { + "version": "0.1.2", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", "dev": true, "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" + "is-descriptor": "^0.1.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon/node_modules/is-descriptor": { + "node_modules/static-extend/node_modules/is-accessor-descriptor": { "version": "0.1.6", "dev": true, "license": "MIT", "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "kind-of": "^3.0.2" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/snapdragon/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/sntp": { - "version": "1.0.9", + "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", "dev": true, + "license": "MIT", "dependencies": { - "hoek": "2.x.x" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">=0.8.0" + "node": ">=0.10.0" } }, - "node_modules/socket.io": { - "version": "2.1.1", + "node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", "dev": true, "license": "MIT", "dependencies": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/socket.io-adapter": { - "version": "1.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/socket.io-client": { - "version": "2.1.1", + "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", "dev": true, "license": "MIT", "dependencies": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", - "to-array": "0.1.4" + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/socket.io-client/node_modules/component-emitter": { - "version": "1.2.1", - "dev": true, - "license": "MIT" - }, - "node_modules/socket.io-client/node_modules/debug": { - "version": "3.1.0", + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/socket.io-client/node_modules/engine.io-client": { - "version": "3.2.1", - "dev": true, + "node_modules/statuses": { + "version": "1.5.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/storage-engine": { + "version": "3.0.7", + "hasInstallScript": true, "license": "MIT", "dependencies": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" + "enabled": "^2.0.0", + "eventemitter3": "^4.0.0" } }, - "node_modules/socket.io-client/node_modules/ms": { + "node_modules/storage-engine/node_modules/enabled": { "version": "2.0.0", - "dev": true, "license": "MIT" }, - "node_modules/socket.io-client/node_modules/ultron": { - "version": "1.1.1", - "dev": true, + "node_modules/storage-engine/node_modules/eventemitter3": { + "version": "4.0.7", "license": "MIT" }, - "node_modules/socket.io-client/node_modules/ws": { - "version": "3.3.3", + "node_modules/stream-browserify": { + "version": "2.0.2", "dev": true, "license": "MIT", "dependencies": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, - "node_modules/socket.io-client/node_modules/xmlhttprequest-ssl": { - "version": "1.5.5", - "dev": true, - "engines": { - "node": ">=0.4.0" + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" } }, - "node_modules/socket.io-parser": { - "version": "3.2.0", + "node_modules/stream-combiner2": { + "version": "1.1.1", "dev": true, "license": "MIT", "dependencies": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" } }, - "node_modules/socket.io-parser/node_modules/component-emitter": { - "version": "1.2.1", + "node_modules/stream-exhaust": { + "version": "1.0.2", "dev": true, "license": "MIT" }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "3.1.0", + "node_modules/stream-http": { + "version": "2.8.3", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" } }, - "node_modules/socket.io-parser/node_modules/isarray": { - "version": "2.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/socket.io-parser/node_modules/ms": { - "version": "2.0.0", + "node_modules/stream-shift": { + "version": "1.0.1", "dev": true, "license": "MIT" }, - "node_modules/socket.io/node_modules/debug": { - "version": "3.1.0", + "node_modules/stream-splicer": { + "version": "2.0.1", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" } }, - "node_modules/socket.io/node_modules/engine.io": { - "version": "3.2.1", - "dev": true, + "node_modules/streamroller": { + "version": "3.1.2", "license": "MIT", "dependencies": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" + "date-format": "^4.0.13", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" } }, - "node_modules/socket.io/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/socket.io/node_modules/ultron": { - "version": "1.1.1", - "dev": true, - "license": "MIT" - }, - "node_modules/socket.io/node_modules/ws": { - "version": "3.3.3", - "dev": true, + "node_modules/streamroller/node_modules/fs-extra": { + "version": "8.1.0", "license": "MIT", "dependencies": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" } }, - "node_modules/sockjs": { - "version": "0.3.24", - "dev": true, + "node_modules/streamroller/node_modules/jsonfile": { + "version": "4.0.0", "license": "MIT", - "dependencies": { - "faye-websocket": "^0.11.3", - "uuid": "^8.3.2", - "websocket-driver": "^0.7.4" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/sockjs-client": { + "node_modules/string_decoder": { "version": "1.3.0", - "dev": true, "license": "MIT", "dependencies": { - "debug": "^3.2.5", - "eventsource": "^1.0.7", - "faye-websocket": "~0.11.1", - "inherits": "^2.0.3", - "json3": "^3.3.2", - "url-parse": "^1.4.3" + "safe-buffer": "~5.2.0" } }, - "node_modules/sockjs-client/node_modules/debug": { - "version": "3.2.7", + "node_modules/string-template": { + "version": "0.2.1" + }, + "node_modules/string-width": { + "version": "4.2.3", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/sockjs/node_modules/uuid": { - "version": "8.3.2", + "node_modules/string.prototype.trimend": { + "version": "1.0.5", "dev": true, "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" + "peer": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/socks": { - "version": "2.6.2", + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "ip": "^1.1.5", - "smart-buffer": "^4.2.0" + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" }, - "engines": { - "node": ">= 10.13.0", - "npm": ">= 3.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/source-map": { - "version": "0.5.7", + "node_modules/stringstream": { + "version": "0.0.6", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/source-map-resolve": { - "version": "0.5.3", + "node_modules/strip-ansi": { + "version": "6.0.1", "dev": true, "license": "MIT", "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" } }, - "node_modules/source-map-support": { - "version": "0.5.21", + "node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/source-map": { - "version": "0.6.1", - "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/source-map-url": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "node_modules/sparkles": { - "version": "1.0.1", + "node_modules/strip-json-comments": { + "version": "3.1.1", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/sparse-bitfield": { - "version": "3.0.3", + "node_modules/subarg": { + "version": "1.0.0", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { - "memory-pager": "^1.0.2" + "minimist": "^1.1.0" } }, - "node_modules/spawn-wrap": { - "version": "2.0.0", + "node_modules/supports-color": { + "version": "5.5.0", "dev": true, - "license": "ISC", + "license": "MIT", "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" + "has-flag": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/spdx-correct": { - "version": "3.1.1", + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", + "node_modules/sver-compat": { + "version": "1.5.0", "dev": true, "license": "MIT", "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" } }, - "node_modules/spdx-license-ids": { - "version": "3.0.11", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/split-string": { - "version": "3.1.0", - "dev": true, + "node_modules/swap-case": { + "version": "1.1.2", "license": "MIT", "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" + "lower-case": "^1.1.1", + "upper-case": "^1.1.1" } }, - "node_modules/split-string/node_modules/extend-shallow": { - "version": "3.0.2", + "node_modules/syntax-error": { + "version": "1.4.0", "dev": true, "license": "MIT", "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" + "acorn-node": "^1.2.0" } }, - "node_modules/split-string/node_modules/is-extendable": { - "version": "1.0.1", + "node_modules/table": { + "version": "6.8.0", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "is-plain-object": "^2.0.4" + "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": ">=0.10.0" + "node": ">=10.0.0" } }, - "node_modules/split-string/node_modules/is-plain-object": { - "version": "2.0.4", + "node_modules/table/node_modules/ajv": { + "version": "8.11.0", "dev": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=0.10.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/split2": { - "version": "2.2.0", + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", "dev": true, - "license": "ISC", - "dependencies": { - "through2": "^2.0.2" - } + "license": "MIT" }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "dev": true, - "license": "BSD-3-Clause" + "node_modules/tame-search": { + "resolved": "packages/tame-search", + "link": true }, - "node_modules/sshpk": { - "version": "1.17.0", - "dev": true, - "license": "MIT", + "node_modules/terser": { + "version": "5.15.0", + "license": "BSD-2-Clause", "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" }, "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" + "terser": "bin/terser" }, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" + "node": ">=10" } }, - "node_modules/stackback": { - "version": "0.0.2", - "dev": true, - "license": "MIT" - }, - "node_modules/static-extend": { - "version": "0.1.2", - "dev": true, + "node_modules/terser/node_modules/acorn": { + "version": "8.8.0", "license": "MIT", - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.4.0" } }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", + "node_modules/test-exclude": { + "version": "5.2.3", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "is-descriptor": "^0.1.0" + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/static-extend/node_modules/is-accessor-descriptor": { - "version": "0.1.6", + "node_modules/text-hex": { + "version": "0.0.0", + "license": "MIT" + }, + "node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/through": { + "version": "2.3.8", + "dev": true, + "license": "MIT" + }, + "node_modules/through2": { + "version": "2.0.5", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", + "node_modules/through2-filter": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" + "through2": "~2.0.0", + "xtend": "~4.0.0" } }, - "node_modules/static-extend/node_modules/is-data-descriptor": { - "version": "0.1.4", + "node_modules/tick-tock": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" + "millisecond": "0.1.x" } }, - "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", + "node_modules/time-stamp": { + "version": "1.1.0", "dev": true, "license": "MIT", - "dependencies": { - "is-buffer": "^1.1.5" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/static-extend/node_modules/is-descriptor": { - "version": "0.1.6", + "node_modules/timers-browserify": { + "version": "1.4.2", "dev": true, - "license": "MIT", "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "process": "~0.11.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.6.0" } }, - "node_modules/statuses": { - "version": "1.5.0", + "node_modules/title-case": { + "version": "1.1.2", "license": "MIT", - "engines": { - "node": ">= 0.6" + "dependencies": { + "sentence-case": "^1.1.1", + "upper-case": "^1.0.3" } }, - "node_modules/storage-engine": { - "version": "3.0.7", - "hasInstallScript": true, + "node_modules/tmp": { + "version": "0.2.1", + "dev": true, "license": "MIT", "dependencies": { - "enabled": "^2.0.0", - "eventemitter3": "^4.0.0" + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" } }, - "node_modules/storage-engine/node_modules/enabled": { - "version": "2.0.0", - "license": "MIT" - }, - "node_modules/storage-engine/node_modules/eventemitter3": { - "version": "4.0.7", - "license": "MIT" - }, - "node_modules/stream-browserify": { + "node_modules/to-absolute-glob": { "version": "2.0.2", "dev": true, "license": "MIT", "dependencies": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/stream-combiner2": { - "version": "1.1.1", + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", "dev": true, "license": "MIT", - "dependencies": { - "duplexer2": "~0.1.0", - "readable-stream": "^2.0.2" + "engines": { + "node": ">=4" } }, - "node_modules/stream-exhaust": { - "version": "1.0.2", + "node_modules/to-iso-string": { + "version": "0.0.2", "dev": true, "license": "MIT" }, - "node_modules/stream-http": { - "version": "3.2.0", + "node_modules/to-object-path": { + "version": "0.3.0", "dev": true, "license": "MIT", "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/stream-http/node_modules/readable-stream": { - "version": "3.6.0", + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "is-buffer": "^1.1.5" }, "engines": { - "node": ">= 6" + "node": ">=0.10.0" } }, - "node_modules/stream-shift": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, - "node_modules/stream-splicer": { - "version": "2.0.1", + "node_modules/to-regex": { + "version": "3.0.2", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/streamroller": { - "version": "3.1.1", + "node_modules/to-regex-range": { + "version": "2.1.1", + "dev": true, "license": "MIT", "dependencies": { - "date-format": "^4.0.10", - "debug": "^4.3.4", - "fs-extra": "^10.1.0" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" }, "engines": { - "node": ">=8.0" + "node": ">=0.10.0" } }, - "node_modules/string_decoder": { - "version": "1.1.1", + "node_modules/to-regex/node_modules/extend-shallow": { + "version": "3.0.2", + "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "~5.1.0" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/string-template": { - "version": "0.2.1" - }, - "node_modules/string-width": { - "version": "4.2.3", + "node_modules/to-regex/node_modules/is-extendable": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "is-plain-object": "^2.0.4" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.5", + "node_modules/to-regex/node_modules/is-plain-object": { + "version": "2.0.4", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "isobject": "^3.0.1" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.5", + "node_modules/to-through": { + "version": "2.0.0", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.19.5" + "through2": "^2.0.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.10" } }, - "node_modules/stringstream": { - "version": "0.0.6", - "dev": true, - "license": "MIT" + "node_modules/toidentifier": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.6" + } }, - "node_modules/strip-ansi": { - "version": "6.0.1", + "node_modules/tough-cookie": { + "version": "2.5.0", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "ansi-regex": "^5.0.1" + "psl": "^1.1.28", + "punycode": "^2.1.1" }, "engines": { - "node": ">=8" + "node": ">=0.8" } }, - "node_modules/strip-bom": { + "node_modules/tr46": { "version": "3.0.0", - "dev": true, "license": "MIT", + "dependencies": { + "punycode": "^2.1.1" + }, "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", + "node_modules/traverse": { + "version": "0.6.6", + "license": "MIT" + }, + "node_modules/tree-kill": { + "version": "1.2.2", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bin": { + "tree-kill": "cli.js" } }, - "node_modules/subarg": { - "version": "1.0.0", + "node_modules/tsconfig-paths": { + "version": "3.14.1", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "minimist": "^1.1.0" + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, - "node_modules/supports-color": { - "version": "5.5.0", + "node_modules/tty-browserify": { + "version": "0.0.1", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "has-flag": "^3.0.0" + "safe-buffer": "^5.0.1" }, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", + "node_modules/tweetnacl": { + "version": "0.14.5", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "Unlicense" }, - "node_modules/sver-compat": { - "version": "1.5.0", + "node_modules/type": { + "version": "1.2.0", "dev": true, - "license": "MIT", - "dependencies": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } + "license": "ISC" }, - "node_modules/swap-case": { - "version": "1.1.2", + "node_modules/type-check": { + "version": "0.4.0", + "dev": true, "license": "MIT", "dependencies": { - "lower-case": "^1.1.1", - "upper-case": "^1.1.1" + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" } }, - "node_modules/syntax-error": { - "version": "1.4.0", + "node_modules/type-detect": { + "version": "4.0.8", "dev": true, "license": "MIT", - "dependencies": { - "acorn-node": "^1.2.0" + "engines": { + "node": ">=4" } }, - "node_modules/table": { - "version": "6.8.0", + "node_modules/type-fest": { + "version": "0.20.2", "dev": true, - "license": "BSD-3-Clause", - "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" - }, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=10.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/table/node_modules/ajv": { - "version": "8.11.0", - "dev": true, + "node_modules/type-is": { + "version": "1.6.18", "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "media-typer": "0.3.0", + "mime-types": "~2.1.24" }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "engines": { + "node": ">= 0.6" } }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", + "node_modules/typedarray": { + "version": "0.0.6", "dev": true, "license": "MIT" }, - "node_modules/tame-search": { - "resolved": "packages/tame-search", - "link": true - }, - "node_modules/terser": { - "version": "5.14.2", - "license": "BSD-2-Clause", + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/source-map": "^0.3.2", - "acorn": "^8.5.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" + "is-typedarray": "^1.0.0" } }, - "node_modules/terser/node_modules/acorn": { - "version": "8.7.1", + "node_modules/ua-parser-js": { + "version": "0.7.31", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, "engines": { - "node": ">=0.4.0" + "node": "*" } }, - "node_modules/test-exclude": { - "version": "6.0.0", - "dev": true, - "license": "ISC", + "node_modules/uglify-es": { + "version": "3.3.9", + "license": "BSD-2-Clause", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "commander": "~2.13.0", + "source-map": "~0.6.1" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" }, "engines": { - "node": ">=8" + "node": ">=0.8.0" } }, - "node_modules/text-hex": { - "version": "0.0.0", - "license": "MIT" - }, - "node_modules/text-table": { - "version": "0.2.0", - "dev": true, + "node_modules/uglify-es/node_modules/commander": { + "version": "2.13.0", "license": "MIT" }, - "node_modules/through": { - "version": "2.3.8", - "dev": true, - "license": "MIT" + "node_modules/uglify-es/node_modules/source-map": { + "version": "0.6.1", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } }, - "node_modules/through2": { - "version": "2.0.5", + "node_modules/uglify-js": { + "version": "2.8.29", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" + "source-map": "~0.5.1", + "yargs": "~3.10.0" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + }, + "optionalDependencies": { + "uglify-to-browserify": "~1.0.0" } }, - "node_modules/through2-filter": { - "version": "3.0.0", + "node_modules/uglify-js/node_modules/camelcase": { + "version": "1.2.1", "dev": true, "license": "MIT", - "dependencies": { - "through2": "~2.0.0", - "xtend": "~4.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/tick-tock": { - "version": "1.0.0", + "node_modules/uglify-js/node_modules/cliui": { + "version": "2.1.0", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "millisecond": "0.1.x" + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" } }, - "node_modules/time-stamp": { - "version": "1.1.0", + "node_modules/uglify-js/node_modules/decamelize": { + "version": "1.2.0", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/timers-browserify": { - "version": "1.4.2", + "node_modules/uglify-js/node_modules/wordwrap": { + "version": "0.0.2", "dev": true, - "dependencies": { - "process": "~0.11.0" - }, + "license": "MIT/X11", "engines": { - "node": ">=0.6.0" + "node": ">=0.4.0" } }, - "node_modules/title-case": { - "version": "1.1.2", + "node_modules/uglify-js/node_modules/yargs": { + "version": "3.10.0", + "dev": true, "license": "MIT", "dependencies": { - "sentence-case": "^1.1.1", - "upper-case": "^1.0.3" + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" } }, - "node_modules/tmp": { - "version": "0.0.33", + "node_modules/uglify-to-browserify": { + "version": "1.0.2", "dev": true, "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } + "optional": true }, - "node_modules/to-absolute-glob": { - "version": "2.0.2", + "node_modules/ultron": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/umd": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "bin": { + "umd": "bin/cli.js" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "node_modules/to-array": { - "version": "0.1.4", - "dev": true - }, - "node_modules/to-arraybuffer": { - "version": "1.0.1", + "node_modules/undeclared-identifiers": { + "version": "1.1.3", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "acorn-node": "^1.3.0", + "dash-ast": "^1.0.0", + "get-assigned-identifiers": "^1.2.0", + "simple-concat": "^1.0.0", + "xtend": "^4.0.1" + }, + "bin": { + "undeclared-identifiers": "bin.js" + } + }, + "node_modules/underscore": { + "version": "1.13.4", "license": "MIT" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", + "node_modules/underscore.deep": { + "version": "0.5.3", + "license": "BSD", + "engines": { + "node": ">=0.10.x" + }, + "peerDependencies": { + "underscore": "1.x" + } + }, + "node_modules/underscore.string": { + "version": "3.3.6", "dev": true, "license": "MIT", + "dependencies": { + "sprintf-js": "^1.1.1", + "util-deprecate": "^1.0.2" + }, "engines": { - "node": ">=4" + "node": "*" } }, - "node_modules/to-iso-string": { - "version": "0.0.2", + "node_modules/underscore.string/node_modules/sprintf-js": { + "version": "1.1.2", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause" }, - "node_modules/to-object-path": { - "version": "0.3.0", + "node_modules/undertaker": { + "version": "1.3.0", "dev": true, "license": "MIT", "dependencies": { - "kind-of": "^3.0.2" + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "fast-levenshtein": "^1.0.0", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", + "node_modules/undertaker-registry": { + "version": "1.0.1", "dev": true, "license": "MIT", - "dependencies": { - "is-buffer": "^1.1.5" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.10" } }, - "node_modules/to-regex": { - "version": "3.0.2", + "node_modules/undertaker/node_modules/fast-levenshtein": { + "version": "1.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/union-value": { + "version": "1.0.1", "dev": true, "license": "MIT", "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/to-regex-range": { - "version": "2.1.1", + "node_modules/unique-stream": { + "version": "2.3.1", "dev": true, "license": "MIT", "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, + "json-stable-stringify-without-jsonify": "^1.0.1", + "through2-filter": "^3.0.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 4.0.0" } }, - "node_modules/to-regex/node_modules/extend-shallow": { - "version": "3.0.2", - "dev": true, + "node_modules/unpipe": { + "version": "1.0.0", "license": "MIT", - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8" } }, - "node_modules/to-regex/node_modules/is-extendable": { - "version": "1.0.1", + "node_modules/unset-value": { + "version": "1.0.0", "dev": true, "license": "MIT", "dependencies": { - "is-plain-object": "^2.0.4" + "has-value": "^0.3.1", + "isobject": "^3.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/to-regex/node_modules/is-plain-object": { - "version": "2.0.4", + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", "dev": true, "license": "MIT", "dependencies": { - "isobject": "^3.0.1" + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/to-through": { - "version": "2.0.0", + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", "dev": true, "license": "MIT", "dependencies": { - "through2": "^2.0.3" + "isarray": "1.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/toidentifier": { - "version": "1.0.1", + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "dev": true, "license": "MIT", "engines": { - "node": ">=0.6" + "node": ">=0.10.0" } }, - "node_modules/tough-cookie": { - "version": "2.5.0", + "node_modules/unset-value/node_modules/isarray": { + "version": "1.0.0", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, + "license": "MIT" + }, + "node_modules/upath": { + "version": "1.2.0", + "dev": true, + "license": "MIT", "engines": { - "node": ">=0.8" + "node": ">=4", + "yarn": "*" } }, - "node_modules/tr46": { - "version": "3.0.0", + "node_modules/update-browserslist-db": { + "version": "1.0.5", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], "license": "MIT", "dependencies": { - "punycode": "^2.1.1" + "escalade": "^3.1.1", + "picocolors": "^1.0.0" }, - "engines": { - "node": ">=12" + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/traverse": { - "version": "0.6.6", + "node_modules/upper-case": { + "version": "1.1.3", "license": "MIT" }, - "node_modules/tree-kill": { - "version": "1.2.2", - "dev": true, + "node_modules/upper-case-first": { + "version": "1.1.2", "license": "MIT", - "bin": { - "tree-kill": "cli.js" + "dependencies": { + "upper-case": "^1.1.1" } }, - "node_modules/tsconfig-paths": { - "version": "3.14.1", + "node_modules/uri-js": { + "version": "4.4.1", "dev": true, - "license": "MIT", - "peer": true, + "license": "BSD-2-Clause", "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "punycode": "^2.1.0" } }, - "node_modules/tty-browserify": { - "version": "0.0.1", + "node_modules/urix": { + "version": "0.1.0", "dev": true, "license": "MIT" }, - "node_modules/tunnel-agent": { - "version": "0.6.0", + "node_modules/url": { + "version": "0.11.0", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" + "punycode": "1.3.2", + "querystring": "0.2.0" } }, - "node_modules/tweetnacl": { - "version": "0.14.5", + "node_modules/url-parse": { + "version": "1.4.7", "dev": true, - "license": "Unlicense" + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } }, - "node_modules/type": { - "version": "1.2.0", + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/type-check": { - "version": "0.4.0", + "node_modules/use": { + "version": "3.1.1", "dev": true, "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/user-home": { + "version": "2.0.0", + "license": "MIT", "dependencies": { - "prelude-ls": "^1.2.1" + "os-homedir": "^1.0.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">=0.10.0" } }, - "node_modules/type-detect": { - "version": "4.0.8", + "node_modules/useragent": { + "version": "2.3.0", "dev": true, "license": "MIT", - "engines": { - "node": ">=4" + "dependencies": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" } }, - "node_modules/type-fest": { - "version": "0.20.2", + "node_modules/useragent/node_modules/lru-cache": { + "version": "4.1.5", "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, - "node_modules/type-is": { - "version": "1.6.18", + "node_modules/useragent/node_modules/tmp": { + "version": "0.0.33", + "dev": true, "license": "MIT", "dependencies": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" + "os-tmpdir": "~1.0.2" }, "engines": { - "node": ">= 0.6" + "node": ">=0.6.0" } }, - "node_modules/typedarray": { - "version": "0.0.6", + "node_modules/useragent/node_modules/yallist": { + "version": "2.1.2", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", + "node_modules/util": { + "version": "0.10.4", "dev": true, "license": "MIT", "dependencies": { - "is-typedarray": "^1.0.0" + "inherits": "2.0.3" } }, - "node_modules/ua-parser-js": { - "version": "0.7.31", + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/ua-parser-js" - }, - { - "type": "paypal", - "url": "https://paypal.me/faisalman" - } - ], + "license": "ISC" + }, + "node_modules/utils-merge": { + "version": "1.0.1", "license": "MIT", "engines": { - "node": "*" + "node": ">= 0.4.0" } }, - "node_modules/uglify-es": { - "version": "3.3.9", - "license": "BSD-2-Clause", - "dependencies": { - "commander": "~2.13.0", - "source-map": "~0.6.1" - }, + "node_modules/uuid": { + "version": "3.4.0", + "license": "MIT", "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" + "uuid": "bin/uuid" } }, - "node_modules/uglify-es/node_modules/commander": { - "version": "2.13.0", - "license": "MIT" - }, - "node_modules/uglify-es/node_modules/source-map": { - "version": "0.6.1", - "license": "BSD-3-Clause", + "node_modules/uws": { + "version": "10.148.1", + "dev": true, + "license": "Zlib", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/uglify-js": { - "version": "2.8.29", + "node_modules/v8-compile-cache": { + "version": "2.3.0", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "3.2.6", + "dev": true, + "license": "ISC", "dependencies": { - "source-map": "~0.5.1", - "yargs": "~3.10.0" - }, - "bin": { - "uglifyjs": "bin/uglifyjs" + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0", + "source-map": "^0.7.3" }, "engines": { - "node": ">=0.8.0" - }, - "optionalDependencies": { - "uglify-to-browserify": "~1.0.0" + "node": ">=10.10.0" } }, - "node_modules/uglify-js/node_modules/camelcase": { - "version": "1.2.1", + "node_modules/v8-to-istanbul/node_modules/convert-source-map": { + "version": "1.8.0", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "safe-buffer": "~5.1.1" } }, - "node_modules/uglify-js/node_modules/cliui": { - "version": "2.1.0", + "node_modules/v8-to-istanbul/node_modules/safe-buffer": { + "version": "5.1.2", "dev": true, - "license": "ISC", - "dependencies": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } + "license": "MIT" }, - "node_modules/uglify-js/node_modules/wordwrap": { - "version": "0.0.2", + "node_modules/v8-to-istanbul/node_modules/source-map": { + "version": "0.7.4", "dev": true, - "license": "MIT/X11", + "license": "BSD-3-Clause", "engines": { - "node": ">=0.4.0" + "node": ">= 8" } }, - "node_modules/uglify-js/node_modules/yargs": { - "version": "3.10.0", + "node_modules/v8flags": { + "version": "3.2.0", "dev": true, "license": "MIT", "dependencies": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" } }, - "node_modules/uglify-to-browserify": { - "version": "1.0.2", + "node_modules/validate-npm-package-license": { + "version": "3.0.4", "dev": true, - "license": "MIT", - "optional": true + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } }, - "node_modules/ultron": { - "version": "1.0.2", + "node_modules/value-or-function": { + "version": "3.0.0", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.10" + } }, - "node_modules/umd": { - "version": "3.0.3", - "dev": true, + "node_modules/vary": { + "version": "1.1.2", "license": "MIT", - "bin": { - "umd": "bin/cli.js" + "engines": { + "node": ">= 0.8" } }, - "node_modules/unbox-primitive": { - "version": "1.0.2", + "node_modules/verror": { + "version": "1.10.1", "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=0.6.0" } }, - "node_modules/unc-path-regex": { - "version": "0.1.2", + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, - "node_modules/undeclared-identifiers": { - "version": "1.1.3", + "node_modules/vinyl": { + "version": "2.2.1", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "acorn-node": "^1.3.0", - "dash-ast": "^1.0.0", - "get-assigned-identifiers": "^1.2.0", - "simple-concat": "^1.0.0", - "xtend": "^4.0.1" + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" }, - "bin": { - "undeclared-identifiers": "bin.js" + "engines": { + "node": ">= 0.10" } }, - "node_modules/underscore": { - "version": "1.13.4", - "license": "MIT" - }, - "node_modules/underscore.deep": { - "version": "0.5.3", - "license": "BSD", - "engines": { - "node": ">=0.10.x" - }, - "peerDependencies": { - "underscore": "1.x" + "node_modules/vinyl-buffer": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^1.2.1", + "through2": "^2.0.3" } }, - "node_modules/underscore.string": { - "version": "3.3.6", + "node_modules/vinyl-fs": { + "version": "3.0.3", "dev": true, "license": "MIT", "dependencies": { - "sprintf-js": "^1.1.1", - "util-deprecate": "^1.0.2" + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" }, "engines": { - "node": "*" + "node": ">= 0.10" } }, - "node_modules/underscore.string/node_modules/sprintf-js": { - "version": "1.1.2", + "node_modules/vinyl-source-stream": { + "version": "2.0.0", "dev": true, - "license": "BSD-3-Clause" + "license": "MIT", + "dependencies": { + "through2": "^2.0.3", + "vinyl": "^2.1.0" + } }, - "node_modules/undertaker": { - "version": "1.3.0", + "node_modules/vinyl-sourcemap": { + "version": "1.1.0", "dev": true, "license": "MIT", "dependencies": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "fast-levenshtein": "^1.0.0", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" }, "engines": { "node": ">= 0.10" } }, - "node_modules/undertaker-registry": { - "version": "1.0.1", + "node_modules/vinyl-sourcemap/node_modules/convert-source-map": { + "version": "1.8.0", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.10" + "dependencies": { + "safe-buffer": "~5.1.1" } }, - "node_modules/undertaker/node_modules/fast-levenshtein": { - "version": "1.1.4", - "dev": true, - "license": "MIT" - }, - "node_modules/union-value": { - "version": "1.0.1", + "node_modules/vinyl-sourcemap/node_modules/normalize-path": { + "version": "2.1.1", "dev": true, "license": "MIT", "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" + "remove-trailing-separator": "^1.0.1" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/unique-stream": { - "version": "2.3.1", + "node_modules/vinyl-sourcemap/node_modules/safe-buffer": { + "version": "5.1.2", "dev": true, - "license": "MIT", + "license": "MIT" + }, + "node_modules/vinyl-sourcemaps-apply": { + "version": "0.2.1", + "dev": true, + "license": "ISC", "dependencies": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" + "source-map": "^0.5.1" } }, - "node_modules/universalify": { - "version": "2.0.0", + "node_modules/vinyl/node_modules/replace-ext": { + "version": "1.0.1", + "dev": true, "license": "MIT", "engines": { - "node": ">= 10.0.0" + "node": ">= 0.10" } }, - "node_modules/unpipe": { - "version": "1.0.0", - "license": "MIT", - "engines": { - "node": ">= 0.8" - } + "node_modules/vm-browserify": { + "version": "1.1.2", + "dev": true, + "license": "MIT" }, - "node_modules/unset-value": { - "version": "1.0.0", + "node_modules/void-elements": { + "version": "2.0.1", "dev": true, "license": "MIT", - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, "engines": { "node": ">=0.10.0" } }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "license": "BSD-2-Clause", "engines": { - "node": ">=0.10.0" + "node": ">=12" } }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", + "node_modules/websocket-driver": { + "version": "0.7.4", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "isarray": "1.0.0" + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=0.8.0" } }, - "node_modules/unset-value/node_modules/has-values": { + "node_modules/websocket-extensions": { "version": "0.1.4", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=0.10.0" + "node": ">=0.8.0" } }, - "node_modules/upath": { - "version": "1.2.0", - "dev": true, + "node_modules/whatwg-url": { + "version": "11.0.0", "license": "MIT", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, "engines": { - "node": ">=4", - "yarn": "*" + "node": ">=12" } }, - "node_modules/update-browserslist-db": { - "version": "1.0.4", + "node_modules/when": { + "version": "3.7.8", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "license": "MIT", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "license": "ISC", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "isexe": "^2.0.0" }, "bin": { - "browserslist-lint": "cli.js" + "node-which": "bin/node-which" }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/upper-case": { - "version": "1.1.3", - "license": "MIT" - }, - "node_modules/upper-case-first": { - "version": "1.1.2", - "license": "MIT", - "dependencies": { - "upper-case": "^1.1.1" + "engines": { + "node": ">= 8" } }, - "node_modules/uri-js": { - "version": "4.4.1", + "node_modules/which-boxed-primitive": { + "version": "1.0.2", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", + "peer": true, "dependencies": { - "punycode": "^2.1.0" + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/urix": { - "version": "0.1.0", + "node_modules/which-module": { + "version": "2.0.0", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/url": { - "version": "0.11.0", + "node_modules/why-is-node-running": { + "version": "2.2.2", "dev": true, "license": "MIT", "dependencies": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" } }, - "node_modules/url-parse": { - "version": "1.4.7", + "node_modules/window-size": { + "version": "0.1.0", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", "dev": true, "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/url/node_modules/punycode": { - "version": "1.3.2", + "node_modules/wordwrap": { + "version": "1.0.0", "dev": true, "license": "MIT" }, - "node_modules/use": { - "version": "3.1.1", + "node_modules/workerpool": { + "version": "6.2.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/user-home": { + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/emoji-regex": { + "version": "7.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { "version": "2.0.0", + "dev": true, "license": "MIT", - "dependencies": { - "os-homedir": "^1.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, - "node_modules/useragent": { - "version": "2.3.0", + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "lru-cache": "4.1.x", - "tmp": "0.0.x" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/useragent/node_modules/lru-cache": { - "version": "4.1.5", + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/useragent/node_modules/yallist": { - "version": "2.1.2", - "dev": true, + "node_modules/wrappy": { + "version": "1.0.2", "license": "ISC" }, - "node_modules/util": { - "version": "0.10.4", + "node_modules/write-file-atomic": { + "version": "3.0.3", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "inherits": "2.0.3" + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "license": "MIT" + "node_modules/ws": { + "version": "6.1.4", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } }, - "node_modules/util/node_modules/inherits": { - "version": "2.0.3", + "node_modules/xml2js": { + "version": "0.4.0", "dev": true, - "license": "ISC" + "dependencies": { + "sax": "0.5.x", + "xmlbuilder": ">=0.4.2" + } }, - "node_modules/utils-merge": { - "version": "1.0.1", + "node_modules/xmlbuilder": { + "version": "15.1.1", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4.0" + "node": ">=8.0" } }, - "node_modules/uuid": { - "version": "3.4.0", - "license": "MIT", - "bin": { - "uuid": "bin/uuid" + "node_modules/xmlhttprequest-ssl": { + "version": "1.6.3", + "dev": true, + "engines": { + "node": ">=0.4.0" } }, - "node_modules/uws": { - "version": "10.148.1", + "node_modules/xtend": { + "version": "4.0.2", "dev": true, - "license": "Zlib", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.4" } }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", + "node_modules/y18n": { + "version": "4.0.3", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/v8-to-istanbul": { - "version": "3.2.6", + "node_modules/yallist": { + "version": "4.0.0", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "0.2.3", + "dev": true + }, + "node_modules/yargs": { + "version": "14.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.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": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", "dev": true, "license": "ISC", "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "engines": { - "node": ">=10.10.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.4", + "node_modules/yargs-parser/node_modules/camelcase": { + "version": "5.3.1", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "engines": { - "node": ">= 8" + "node": ">=6" } }, - "node_modules/v8flags": { - "version": "3.2.0", + "node_modules/yargs-parser/node_modules/decamelize": { + "version": "1.2.0", "dev": true, "license": "MIT", - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", + "node_modules/yargs-unparser": { + "version": "2.0.0", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" } }, - "node_modules/value-or-function": { - "version": "3.0.0", + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.1", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.10" + "node": ">=6" } }, - "node_modules/vary": { - "version": "1.1.2", + "node_modules/yargs/node_modules/camelcase": { + "version": "5.3.1", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8" + "node": ">=6" } }, - "node_modules/verror": { - "version": "1.10.0", + "node_modules/yargs/node_modules/decamelize": { + "version": "1.2.0", "dev": true, - "engines": [ - "node >=0.6.0" - ], "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "engines": { + "node": ">=0.10.0" } }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", + "node_modules/yargs/node_modules/emoji-regex": { + "version": "7.0.3", "dev": true, "license": "MIT" }, - "node_modules/vinyl": { - "version": "2.2.1", + "node_modules/yargs/node_modules/find-up": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "locate-path": "^3.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=6" } }, - "node_modules/vinyl-buffer": { - "version": "1.0.1", + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", "dev": true, "license": "MIT", - "dependencies": { - "bl": "^1.2.1", - "through2": "^2.0.3" + "engines": { + "node": ">=4" } }, - "node_modules/vinyl-fs": { - "version": "3.0.3", + "node_modules/yargs/node_modules/locate-path": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" }, "engines": { - "node": ">= 0.10" + "node": ">=6" } }, - "node_modules/vinyl-source-stream": { - "version": "2.0.0", + "node_modules/yargs/node_modules/p-locate": { + "version": "3.0.0", "dev": true, "license": "MIT", "dependencies": { - "through2": "^2.0.3", - "vinyl": "^2.1.0" + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" } }, - "node_modules/vinyl-sourcemap": { - "version": "1.1.0", + "node_modules/yargs/node_modules/path-exists": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" }, "engines": { - "node": ">= 0.10" + "node": ">=6" } }, - "node_modules/vinyl-sourcemap/node_modules/normalize-path": { - "version": "2.1.1", + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", "dev": true, "license": "MIT", "dependencies": { - "remove-trailing-separator": "^1.0.1" + "ansi-regex": "^4.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/vinyl-sourcemaps-apply": { - "version": "0.2.1", + "node_modules/yargs/node_modules/yargs-parser": { + "version": "15.0.3", "dev": true, "license": "ISC", "dependencies": { - "source-map": "^0.5.1" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } }, - "node_modules/vm-browserify": { - "version": "1.1.2", + "node_modules/yeast": { + "version": "0.1.2", "dev": true, "license": "MIT" }, - "node_modules/void-elements": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" + "packages/demos": { + "name": "happner-demos", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "happn-commons-test": "^1.1.0", + "happner-cluster": "^12.2.0" } }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "dev": true, - "license": "Apache-2.0", + "packages/happn-3": { + "version": "13.2.0", + "license": "MIT", "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "body-parser": "1.19.2", + "connect": "^3.7.0", + "connect-cookies": "^0.0.0", + "dev-null": "^0.1.1", + "happn-commons": "^1.1.0", + "happn-db-provider-loki": "^1.0.7", + "happn-logger": "^2.1.1", + "happn-password-hash-and-salt": "^1.2.0", + "happn-primus-wrapper": "^8.0.2", + "happn-tcp-port-used": "^1.0.3", + "happn-util-crypto": "^3.0.5", + "homedir": "^0.6.0", + "hsts": "^2.1.0", + "jsonpack": "^1.1.5", + "jwt-simple": "^0.5.5", + "long-timeout": "^0.1.1", + "lru-cache": "^5.1.1", + "md5": "^2.2.1", + "ms": "^2.1.1", + "pem": "^1.14.1", + "serve-static": "^1.14.2", + "tame-search": "^3.0.5", + "terser": "^5.10.0", + "traverse": "^0.6.6", + "user-home": "^2.0.0" }, - "engines": { - "node": ">=0.8.0" + "devDependencies": { + "byline": "5.0.0", + "capture-stdout": "^1.0.0", + "commander": "^4.1.0", + "debug": "4.1.1", + "gulp": "^4.0.2", + "happn": "^2.21.3", + "happn-cluster": "^12.0.13", + "happn-commons-test": "^1.1.0", + "happn-db-provider-elasticsearch": "^1.0.13", + "happn-db-provider-mongo": "^1.0.13", + "happn-random-activity-generator": "0.2.1", + "jsprim": "^2.0.0", + "mongodb": "^4.1.3", + "npm-programmatic": "0.0.12", + "request": "^2.88.2", + "require-self": "^0.2.1" } }, - "node_modules/websocket-extensions": { - "version": "0.1.4", + "packages/happn-3/node_modules/commander": { + "version": "4.1.1", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/whatwg-url": { - "version": "11.0.0", "license": "MIT", - "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" - }, "engines": { - "node": ">=12" + "node": ">= 6" } }, - "node_modules/when": { - "version": "3.7.8", + "packages/happn-3/node_modules/debug": { + "version": "4.1.1", "dev": true, - "license": "MIT" - }, - "node_modules/which": { - "version": "2.0.2", - "license": "ISC", + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" + "ms": "^2.1.1" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "peer": true, + "packages/happn-3/node_modules/lru-cache": { + "version": "5.1.1", + "license": "ISC", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "yallist": "^3.0.2" } }, - "node_modules/which-module": { - "version": "1.0.0", - "dev": true, + "packages/happn-3/node_modules/yallist": { + "version": "3.1.1", "license": "ISC" }, - "node_modules/why-is-node-running": { - "version": "2.2.2", - "dev": true, + "packages/happn-cluster": { + "version": "12.0.13", "license": "MIT", "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" + "bluebird": "^3.7.2", + "clone": "^1.0.2", + "dface": "1.0.1", + "happn-3": "^13.2.0", + "happn-commons": "^1.1.0", + "happn-db-provider-mongo": "^1.0.13", + "happn-swim": "^1.0.3", + "http-proxy": "^1.18.1", + "mongodb": "^4.1.4" }, - "engines": { - "node": ">=8" + "devDependencies": { + "capture-stdout": "^1.0.0", + "happn-commons-test": "^1.1.0", + "happn-random-activity-generator": "0.2.1", + "happner-serial-mocha": "1.3.0", + "ip": "^1.1.5", + "request": "^2.81.0" } }, - "node_modules/window-size": { - "version": "0.1.0", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } + "packages/happn-cluster/node_modules/bluebird": { + "version": "3.7.2", + "license": "MIT" }, - "node_modules/word-wrap": { - "version": "1.2.3", - "dev": true, + "packages/happn-cluster/node_modules/clone": { + "version": "1.0.4", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.8" } }, - "node_modules/wordwrap": { - "version": "0.0.3", + "packages/happn-commons": { + "version": "1.1.0", + "license": "ISC", + "dependencies": { + "async": "^3.2.2", + "custom-env": "^2.0.1", + "fast-clone": "^1.5.13", + "fs-extra": "^10.0.0", + "happn-sillyname": "^0.1.1", + "happner-hyperid": "^2.0.0", + "lodash": "^4.17.21", + "lru-cache": "^7.3.1", + "nanoid": "^3.1.30", + "rimraf": "^3.0.2", + "sift": "^15.0.0", + "uuid": "^3.3.2" + } + }, + "packages/happn-commons-test": { + "version": "1.1.0", + "license": "ISC", + "devDependencies": { + "assert": "^2.0.0", + "await-delay": "^1.0.0", + "axios": "^0.25.0", + "callsites": "^3.1.0", + "chai": "^4.3.4", + "chai-as-promised": "^7.1.1", + "chai-match": "^1.1.1", + "coverage": "^0.4.1", + "coveralls": "^3.1.1", + "expect.js": "^0.3.1", + "expose-gc": "^1.0.0", + "gulp": "^4.0.2", + "happn-commons": "^1.1.0", + "happner-hyperid": "^2.0.0", + "heapdump": "^0.3.15", + "http-proxy": "^1.18.1", + "karma": "^6.3.9", + "karma-chai": "^0.1.0", + "karma-chrome-launcher": "^3.1.0", + "karma-coverage": "^2.1.0", + "karma-mocha": "^2.0.1", + "karma-mocha-reporter": "^2.2.5", + "mocha": "^9.1.3", + "mock-fs": "^5.1.2", + "moment": "^2.29.1", + "nyc": "^15.1.0", + "request": "^2.88.2", + "semver": "^7.3.5", + "should": "^13.2.3", + "sinon": "^12.0.1", + "sinon-chai": "^3.7.0", + "when": "^3.7.8", + "why-is-node-running": "^2.2.0" + } + }, + "packages/happn-commons-test/node_modules/ansi-colors": { + "version": "4.1.1", "dev": true, "license": "MIT", "engines": { - "node": ">=0.4.0" + "node": ">=6" } }, - "node_modules/workerpool": { - "version": "6.2.0", + "packages/happn-commons-test/node_modules/ansi-styles": { + "version": "4.3.0", "dev": true, - "license": "Apache-2.0" + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } }, - "node_modules/wrap-ansi": { - "version": "2.1.0", + "packages/happn-commons-test/node_modules/anymatch": { + "version": "3.1.2", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "2.1.1", + "packages/happn-commons-test/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "packages/happn-commons-test/node_modules/assert": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "es6-object-assign": "^1.1.0", + "is-nan": "^1.2.1", + "object-is": "^1.0.1", + "util": "^0.12.0" + } + }, + "packages/happn-commons-test/node_modules/axios": { + "version": "0.25.0", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.7" + } + }, + "packages/happn-commons-test/node_modules/binary-extensions": { + "version": "2.2.0", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", + "packages/happn-commons-test/node_modules/braces": { + "version": "3.0.2", "dev": true, "license": "MIT", "dependencies": { - "number-is-nan": "^1.0.0" + "fill-range": "^7.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "1.0.2", + "packages/happn-commons-test/node_modules/chalk": { + "version": "4.1.2", "dev": true, "license": "MIT", "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "3.0.1", + "packages/happn-commons-test/node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^2.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "license": "ISC" + "packages/happn-commons-test/node_modules/chokidar": { + "version": "3.5.3", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "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/write-file-atomic": { - "version": "3.0.3", + "packages/happn-commons-test/node_modules/cliui": { + "version": "7.0.4", "dev": true, "license": "ISC", "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "node_modules/ws": { - "version": "6.1.4", + "packages/happn-commons-test/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, "license": "MIT", "dependencies": { - "async-limiter": "~1.0.0" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/xml2js": { - "version": "0.4.0", + "packages/happn-commons-test/node_modules/color-name": { + "version": "1.1.4", "dev": true, - "dependencies": { - "sax": "0.5.x", - "xmlbuilder": ">=0.4.2" - } + "license": "MIT" }, - "node_modules/xmlbuilder": { - "version": "15.1.1", + "packages/happn-commons-test/node_modules/debug": { + "version": "4.3.3", "dev": true, "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, "engines": { - "node": ">=8.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/xmlhttprequest-ssl": { - "version": "1.6.3", + "packages/happn-commons-test/node_modules/diff": { + "version": "5.0.0", "dev": true, + "license": "BSD-3-Clause", "engines": { - "node": ">=0.4.0" + "node": ">=0.3.1" } }, - "node_modules/xtend": { - "version": "4.0.2", + "packages/happn-commons-test/node_modules/escape-string-regexp": { + "version": "4.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=0.4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/y18n": { - "version": "3.2.2", + "packages/happn-commons-test/node_modules/fill-range": { + "version": "7.0.1", "dev": true, - "license": "ISC" - }, - "node_modules/yallist": { - "version": "4.0.0", - "license": "ISC" - }, - "node_modules/yaml": { - "version": "0.2.3", - "dev": true + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } }, - "node_modules/yargs": { - "version": "7.1.2", + "packages/happn-commons-test/node_modules/find-up": { + "version": "5.0.0", "dev": true, "license": "MIT", "dependencies": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yargs-parser": { - "version": "5.0.1", + "packages/happn-commons-test/node_modules/fsevents": { + "version": "2.3.2", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "packages/happn-commons-test/node_modules/glob": { + "version": "7.2.0", "dev": true, "license": "ISC", "dependencies": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" + "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/yargs-unparser": { - "version": "2.0.0", + "packages/happn-commons-test/node_modules/growl": { + "version": "1.10.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.x" + } + }, + "packages/happn-commons-test/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "packages/happn-commons-test/node_modules/is-binary-path": { + "version": "2.1.0", "dev": true, "license": "MIT", "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" + "binary-extensions": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=8" } }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", + "packages/happn-commons-test/node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "packages/happn-commons-test/node_modules/js-yaml": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "packages/happn-commons-test/node_modules/locate-path": { + "version": "6.0.0", "dev": true, "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, "engines": { "node": ">=10" }, @@ -15521,10 +15626,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yargs-unparser/node_modules/decamelize": { - "version": "4.0.0", + "packages/happn-commons-test/node_modules/log-symbols": { + "version": "4.1.0", "dev": true, "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, "engines": { "node": ">=10" }, @@ -15532,58 +15641,96 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "2.1.1", + "packages/happn-commons-test/node_modules/mocha": { + "version": "9.2.2", "dev": true, "license": "MIT", + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" } }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "1.0.0", + "packages/happn-commons-test/node_modules/mocha/node_modules/minimatch": { + "version": "4.2.1", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "number-is-nan": "^1.0.0" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" } }, - "node_modules/yargs/node_modules/string-width": { - "version": "1.0.2", + "packages/happn-commons-test/node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "packages/happn-commons-test/node_modules/nanoid": { + "version": "3.3.1", "dev": true, "license": "MIT", - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=0.10.0" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "3.0.1", + "packages/happn-commons-test/node_modules/p-limit": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "ansi-regex": "^2.0.0" + "yocto-queue": "^0.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yeast": { - "version": "0.1.2", - "dev": true, - "license": "MIT" - }, - "node_modules/yocto-queue": { - "version": "0.1.0", + "packages/happn-commons-test/node_modules/p-locate": { + "version": "5.0.0", "dev": true, "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, "engines": { "node": ">=10" }, @@ -15591,1039 +15738,544 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/happn-3": { - "version": "13.1.4", + "packages/happn-commons-test/node_modules/readdirp": { + "version": "3.6.0", + "dev": true, "license": "MIT", "dependencies": { - "body-parser": "1.19.2", - "connect": "^3.7.0", - "connect-cookies": "^0.0.0", - "dev-null": "^0.1.1", - "happn-commons": "^1.1.0", - "happn-db-provider-loki": "^1.0.7", - "happn-logger": "^2.1.1", - "happn-password-hash-and-salt": "^1.2.0", - "happn-primus-wrapper": "^8.0.2", - "happn-tcp-port-used": "^1.0.3", - "happn-util-crypto": "^3.0.5", - "homedir": "^0.6.0", - "hsts": "^2.1.0", - "jsonpack": "^1.1.5", - "jwt-simple": "^0.5.5", - "long-timeout": "^0.1.1", - "lru-cache": "^5.1.1", - "md5": "^2.2.1", - "ms": "^2.1.1", - "pem": "^1.14.1", - "serve-static": "^1.14.2", - "tame-search": "^3.0.5", - "terser": "^5.10.0", - "traverse": "^0.6.6", - "user-home": "^2.0.0" + "picomatch": "^2.2.1" }, - "devDependencies": { - "byline": "5.0.0", - "capture-stdout": "^1.0.0", - "commander": "^4.1.0", - "debug": "4.1.1", - "gulp": "^4.0.2", - "happn": "^2.21.3", - "happn-cluster": "^12.0.12", - "happn-commons-test": "^1.1.0", - "happn-db-provider-elasticsearch": "^1.0.12", - "happn-db-provider-mongo": "^1.0.12", - "happn-random-activity-generator": "0.2.1", - "jsprim": "^2.0.0", - "mongodb": "^4.1.3", - "npm-programmatic": "0.0.12", - "request": "^2.88.2", - "require-self": "^0.2.1" + "engines": { + "node": ">=8.10.0" } }, - "packages/happn-3/node_modules/commander": { - "version": "4.1.1", + "packages/happn-commons-test/node_modules/supports-color": { + "version": "8.1.1", "dev": true, "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "packages/happn-3/node_modules/debug": { - "version": "4.1.1", + "packages/happn-commons-test/node_modules/to-regex-range": { + "version": "5.0.1", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" } }, - "packages/happn-3/node_modules/lru-cache": { - "version": "5.1.1", - "license": "ISC", + "packages/happn-commons-test/node_modules/util": { + "version": "0.12.4", + "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^3.0.2" - } - }, - "packages/happn-3/node_modules/yallist": { - "version": "3.1.1", - "license": "ISC" - }, - "packages/happn-cluster": { - "version": "12.0.12", - "license": "MIT", - "dependencies": { - "bluebird": "^3.7.2", - "clone": "^1.0.2", - "dface": "1.0.1", - "happn-3": "^13.1.4", - "happn-commons": "^1.1.0", - "happn-db-provider-mongo": "^1.0.12", - "happn-swim": "^1.0.3", - "http-proxy": "^1.18.1", - "mongodb": "^4.1.4" - }, - "devDependencies": { - "capture-stdout": "^1.0.0", - "happn-commons-test": "^1.1.0", - "happn-random-activity-generator": "0.2.1", - "happner-serial-mocha": "1.3.0", - "ip": "^1.1.5", - "request": "^2.81.0" - } - }, - "packages/happn-cluster/node_modules/bluebird": { - "version": "3.7.2", - "license": "MIT" - }, - "packages/happn-cluster/node_modules/clone": { - "version": "1.0.4", - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "packages/happn-commons": { - "version": "1.1.0", - "license": "ISC", - "dependencies": { - "async": "^3.2.2", - "custom-env": "^2.0.1", - "fast-clone": "^1.5.13", - "fs-extra": "^10.0.0", - "happn-sillyname": "^0.1.1", - "happner-hyperid": "^2.0.0", - "lodash": "^4.17.21", - "lru-cache": "^7.3.1", - "nanoid": "^3.1.30", - "rimraf": "^3.0.2", - "sift": "^15.0.0", - "uuid": "^3.3.2" - } - }, - "packages/happn-commons-test": { - "version": "1.1.0", - "license": "ISC", - "devDependencies": { - "assert": "^2.0.0", - "await-delay": "^1.0.0", - "axios": "^0.25.0", - "callsites": "^3.1.0", - "chai": "^4.3.4", - "chai-as-promised": "^7.1.1", - "chai-match": "^1.1.1", - "coverage": "^0.4.1", - "coveralls": "^3.1.1", - "expect.js": "^0.3.1", - "expose-gc": "^1.0.0", - "gulp": "^4.0.2", - "happn-commons": "^1.1.0", - "happner-hyperid": "^2.0.0", - "heapdump": "^0.3.15", - "http-proxy": "^1.18.1", - "karma": "^6.3.9", - "karma-chai": "^0.1.0", - "karma-chrome-launcher": "^3.1.0", - "karma-coverage": "^2.1.0", - "karma-mocha": "^2.0.1", - "karma-mocha-reporter": "^2.2.5", - "mocha": "^9.1.3", - "mock-fs": "^5.1.2", - "moment": "^2.29.1", - "nyc": "^15.1.0", - "request": "^2.88.2", - "semver": "^7.3.5", - "should": "^13.2.3", - "sinon": "^12.0.1", - "sinon-chai": "^3.7.0", - "when": "^3.7.8", - "why-is-node-running": "^2.2.0" + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "safe-buffer": "^5.1.2", + "which-typed-array": "^1.1.2" } }, - "packages/happn-commons-test/node_modules/ansi-styles": { - "version": "4.3.0", + "packages/happn-commons-test/node_modules/wrap-ansi": { + "version": "7.0.0", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "packages/happn-commons-test/node_modules/anymatch": { - "version": "3.1.2", + "packages/happn-commons-test/node_modules/y18n": { + "version": "5.0.8", "dev": true, "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, "engines": { - "node": ">= 8" - } - }, - "packages/happn-commons-test/node_modules/assert": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "es6-object-assign": "^1.1.0", - "is-nan": "^1.2.1", - "object-is": "^1.0.1", - "util": "^0.12.0" + "node": ">=10" } }, - "packages/happn-commons-test/node_modules/axios": { - "version": "0.25.0", + "packages/happn-commons-test/node_modules/yargs": { + "version": "16.2.0", "dev": true, "license": "MIT", "dependencies": { - "follow-redirects": "^1.14.7" - } - }, - "packages/happn-commons-test/node_modules/base64id": { - "version": "2.0.0", - "dev": true, - "license": "MIT", + "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": "^4.5.0 || >= 5.9" + "node": ">=10" } }, - "packages/happn-commons-test/node_modules/binary-extensions": { - "version": "2.2.0", + "packages/happn-commons-test/node_modules/yargs-parser": { + "version": "20.2.4", "dev": true, - "license": "MIT", + "license": "ISC", "engines": { - "node": ">=8" + "node": ">=10" } }, - "packages/happn-commons-test/node_modules/braces": { - "version": "3.0.2", - "dev": true, + "packages/happn-commons/node_modules/async": { + "version": "3.2.3", + "license": "MIT" + }, + "packages/happn-commons/node_modules/fs-extra": { + "version": "10.1.0", "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=12" } }, - "packages/happn-commons-test/node_modules/chokidar": { - "version": "3.5.3", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "packages/happn-commons/node_modules/jsonfile": { + "version": "6.1.0", "license": "MIT", "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" + "universalify": "^2.0.0" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "graceful-fs": "^4.1.6" } }, - "packages/happn-commons-test/node_modules/cliui": { - "version": "7.0.4", - "dev": true, + "packages/happn-commons/node_modules/lru-cache": { + "version": "7.8.1", "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "engines": { + "node": ">=12" } }, - "packages/happn-commons-test/node_modules/color-convert": { - "version": "2.0.1", - "dev": true, + "packages/happn-commons/node_modules/nanoid": { + "version": "3.3.4", "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" + "bin": { + "nanoid": "bin/nanoid.cjs" }, "engines": { - "node": ">=7.0.0" + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "packages/happn-commons-test/node_modules/color-name": { - "version": "1.1.4", - "dev": true, + "packages/happn-commons/node_modules/sift": { + "version": "15.1.3", "license": "MIT" }, - "packages/happn-commons-test/node_modules/cookie": { - "version": "0.4.2", - "dev": true, + "packages/happn-commons/node_modules/universalify": { + "version": "2.0.0", "license": "MIT", "engines": { - "node": ">= 0.6" + "node": ">= 10.0.0" } }, - "packages/happn-commons-test/node_modules/engine.io": { - "version": "6.2.0", - "dev": true, - "license": "MIT", + "packages/happn-db-provider-elasticsearch": { + "version": "1.0.13", "dependencies": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" + "agentkeepalive": "^3.3.0", + "bluebird": "2.10.2", + "elasticsearch": "^13.2.0", + "extract-values": "^0.1.2", + "happn-commons": "^1.1.0", + "happn-logger": "^2.1.1", + "micromustache": "^5.2.0", + "redis-lru-cache": "^1.0.13", + "traverse": "0.6.6" }, - "engines": { - "node": ">=10.0.0" + "devDependencies": { + "happn-3": "^13.2.0", + "happn-commons-test": "^1.1.0", + "json-from-schema": "1.10.0" } }, - "packages/happn-commons-test/node_modules/engine.io-parser": { - "version": "5.0.4", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" + "packages/happn-db-provider-elasticsearch/node_modules/bluebird": { + "version": "2.10.2", + "license": "MIT" + }, + "packages/happn-db-provider-loki": { + "version": "1.0.7", + "license": "ISC", + "dependencies": { + "happn-commons": "^1.1.0", + "lokijs": "^1.5.12" + }, + "devDependencies": { + "happn-commons-test": "^1.1.0" } }, - "packages/happn-commons-test/node_modules/fill-range": { - "version": "7.0.1", - "dev": true, - "license": "MIT", + "packages/happn-db-provider-mongo": { + "version": "1.0.13", "dependencies": { - "to-regex-range": "^5.0.1" + "happn-commons": "^1.1.0", + "mongodb": "^4.4.0", + "parse-mongo-url": "^1.1.1" }, - "engines": { - "node": ">=8" + "devDependencies": { + "byline": "^5.0.0", + "gulp": "^3.9.0", + "happn-3": "^13.2.0", + "happn-commons-test": "^1.1.0" } }, - "packages/happn-commons-test/node_modules/fsevents": { - "version": "2.3.2", + "packages/happn-db-provider-mongo/node_modules/ansi-regex": { + "version": "2.1.1", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=0.10.0" } }, - "packages/happn-commons-test/node_modules/get-caller-file": { - "version": "2.0.5", + "packages/happn-db-provider-mongo/node_modules/ansi-styles": { + "version": "2.2.1", "dev": true, - "license": "ISC", + "license": "MIT", "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=0.10.0" } }, - "packages/happn-commons-test/node_modules/is-binary-path": { - "version": "2.1.0", + "packages/happn-db-provider-mongo/node_modules/chalk": { + "version": "1.1.3", "dev": true, "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "packages/happn-commons-test/node_modules/is-number": { - "version": "7.0.0", + "packages/happn-db-provider-mongo/node_modules/clone": { + "version": "0.2.0", "dev": true, "license": "MIT", "engines": { - "node": ">=0.12.0" + "node": "*" } }, - "packages/happn-commons-test/node_modules/isbinaryfile": { - "version": "4.0.10", + "packages/happn-db-provider-mongo/node_modules/clone-stats": { + "version": "0.0.1", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } + "license": "MIT" }, - "packages/happn-commons-test/node_modules/karma": { - "version": "6.4.0", + "packages/happn-db-provider-mongo/node_modules/findup-sync": { + "version": "2.0.0", "dev": true, "license": "MIT", "dependencies": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.4.1", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" - }, - "bin": { - "karma": "bin/karma" + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" }, "engines": { - "node": ">= 10" + "node": ">= 0.10" } }, - "packages/happn-commons-test/node_modules/log4js": { - "version": "6.6.0", + "packages/happn-db-provider-mongo/node_modules/glob": { + "version": "4.5.3", "dev": true, - "license": "Apache-2.0", + "license": "ISC", "dependencies": { - "date-format": "^4.0.11", - "debug": "^4.3.4", - "flatted": "^3.2.5", - "rfdc": "^1.3.0", - "streamroller": "^3.1.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" }, "engines": { - "node": ">=8.0" + "node": "*" } }, - "packages/happn-commons-test/node_modules/mime": { - "version": "2.6.0", + "packages/happn-db-provider-mongo/node_modules/glob-stream": { + "version": "3.1.18", "dev": true, - "license": "MIT", - "bin": { - "mime": "cli.js" + "dependencies": { + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" }, "engines": { - "node": ">=4.0.0" + "node": ">= 0.9" } }, - "packages/happn-commons-test/node_modules/readdirp": { - "version": "3.6.0", + "packages/happn-db-provider-mongo/node_modules/glob-watcher": { + "version": "0.0.6", "dev": true, - "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "gaze": "^0.5.1" }, "engines": { - "node": ">=8.10.0" + "node": ">= 0.9" } }, - "packages/happn-commons-test/node_modules/socket.io": { - "version": "4.5.1", + "packages/happn-db-provider-mongo/node_modules/graceful-fs": { + "version": "3.0.12", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.2.0", - "socket.io-adapter": "~2.4.0", - "socket.io-parser": "~4.0.4" + "natives": "^1.1.3" }, "engines": { - "node": ">=10.0.0" + "node": ">=0.4.0" } }, - "packages/happn-commons-test/node_modules/socket.io-adapter": { - "version": "2.4.0", - "dev": true, - "license": "MIT" - }, - "packages/happn-commons-test/node_modules/socket.io-parser": { - "version": "4.0.5", + "packages/happn-db-provider-mongo/node_modules/gulp": { + "version": "3.9.1", "dev": true, "license": "MIT", "dependencies": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" + }, + "bin": { + "gulp": "bin/gulp.js" }, "engines": { - "node": ">=10.0.0" + "node": ">= 0.9" } }, - "packages/happn-commons-test/node_modules/source-map": { - "version": "0.6.1", + "packages/happn-db-provider-mongo/node_modules/is-glob": { + "version": "3.1.0", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.0" + }, "engines": { "node": ">=0.10.0" } }, - "packages/happn-commons-test/node_modules/tmp": { - "version": "0.2.1", + "packages/happn-db-provider-mongo/node_modules/is-plain-object": { + "version": "2.0.4", "dev": true, "license": "MIT", "dependencies": { - "rimraf": "^3.0.0" + "isobject": "^3.0.1" }, "engines": { - "node": ">=8.17.0" + "node": ">=0.10.0" } }, - "packages/happn-commons-test/node_modules/to-regex-range": { - "version": "5.0.1", + "packages/happn-db-provider-mongo/node_modules/isarray": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "packages/happn-db-provider-mongo/node_modules/liftoff": { + "version": "2.5.0", "dev": true, "license": "MIT", "dependencies": { - "is-number": "^7.0.0" + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" }, "engines": { - "node": ">=8.0" + "node": ">= 0.8" } }, - "packages/happn-commons-test/node_modules/util": { - "version": "0.12.4", + "packages/happn-db-provider-mongo/node_modules/minimatch": { + "version": "2.0.10", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "inherits": "^2.0.3", - "is-arguments": "^1.0.4", - "is-generator-function": "^1.0.7", - "is-typed-array": "^1.1.3", - "safe-buffer": "^5.1.2", - "which-typed-array": "^1.1.2" + "brace-expansion": "^1.0.0" + }, + "engines": { + "node": "*" } }, - "packages/happn-commons-test/node_modules/wrap-ansi": { - "version": "7.0.0", + "packages/happn-db-provider-mongo/node_modules/ordered-read-streams": { + "version": "0.1.0", + "dev": true, + "license": "MIT" + }, + "packages/happn-db-provider-mongo/node_modules/readable-stream": { + "version": "1.0.34", "dev": true, "license": "MIT", "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" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "packages/happn-commons-test/node_modules/ws": { - "version": "8.2.3", + "packages/happn-db-provider-mongo/node_modules/semver": { + "version": "4.3.6", "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "packages/happn-commons-test/node_modules/y18n": { - "version": "5.0.8", + "packages/happn-db-provider-mongo/node_modules/string_decoder": { + "version": "0.10.31", "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } + "license": "MIT" }, - "packages/happn-commons-test/node_modules/yargs": { - "version": "16.2.0", + "packages/happn-db-provider-mongo/node_modules/strip-ansi": { + "version": "3.0.1", "dev": true, "license": "MIT", "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" + "ansi-regex": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=0.10.0" } }, - "packages/happn-commons-test/node_modules/yargs-parser": { - "version": "20.2.9", + "packages/happn-db-provider-mongo/node_modules/strip-bom": { + "version": "1.0.0", "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "packages/happn-commons/node_modules/async": { - "version": "3.2.3", - "license": "MIT" - }, - "packages/happn-commons/node_modules/lru-cache": { - "version": "7.8.1", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "packages/happn-commons/node_modules/nanoid": { - "version": "3.3.4", "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "packages/happn-commons/node_modules/sift": { - "version": "15.1.3", - "license": "MIT" - }, - "packages/happn-db-provider-elasticsearch": { - "version": "1.0.12", - "dependencies": { - "agentkeepalive": "^3.3.0", - "bluebird": "2.10.2", - "elasticsearch": "^13.2.0", - "extract-values": "^0.1.2", - "happn-commons": "^1.1.0", - "happn-logger": "^2.1.1", - "micromustache": "^5.2.0", - "redis-lru-cache": "^1.0.12", - "traverse": "0.6.6" - }, - "devDependencies": { - "happn-3": "^13.1.4", - "happn-commons-test": "^1.1.0", - "json-from-schema": "1.10.0" - } - }, - "packages/happn-db-provider-elasticsearch/node_modules/bluebird": { - "version": "2.10.2", - "license": "MIT" - }, - "packages/happn-db-provider-loki": { - "version": "1.0.7", - "license": "ISC", "dependencies": { - "happn-commons": "^1.1.0", - "lokijs": "^1.5.12" + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" }, - "devDependencies": { - "happn-commons-test": "^1.1.0" - } - }, - "packages/happn-db-provider-mongo": { - "version": "1.0.12", - "dependencies": { - "happn-commons": "^1.1.0", - "mongodb": "^4.4.0", - "parse-mongo-url": "^1.1.1" + "bin": { + "strip-bom": "cli.js" }, - "devDependencies": { - "byline": "^5.0.0", - "gulp": "^3.9.0", - "happn-3": "^13.1.4", - "happn-commons-test": "^1.1.0" - } - }, - "packages/happn-db-provider-mongo/node_modules/ansi-regex": { - "version": "2.1.1", - "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } }, - "packages/happn-db-provider-mongo/node_modules/ansi-styles": { - "version": "2.2.1", + "packages/happn-db-provider-mongo/node_modules/supports-color": { + "version": "2.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.8.0" } }, - "packages/happn-db-provider-mongo/node_modules/chalk": { - "version": "1.1.3", + "packages/happn-db-provider-mongo/node_modules/through2": { + "version": "0.6.5", "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "packages/happn-db-provider-mongo/node_modules/clone": { - "version": "0.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" } }, - "packages/happn-db-provider-mongo/node_modules/clone-stats": { - "version": "0.0.1", + "packages/happn-db-provider-mongo/node_modules/unique-stream": { + "version": "1.0.0", "dev": true, - "license": "MIT" + "license": "BSD" }, - "packages/happn-db-provider-mongo/node_modules/findup-sync": { - "version": "2.0.0", + "packages/happn-db-provider-mongo/node_modules/user-home": { + "version": "1.1.1", "dev": true, "license": "MIT", - "dependencies": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" + "bin": { + "user-home": "cli.js" }, "engines": { - "node": ">= 0.10" + "node": ">=0.10.0" } }, - "packages/happn-db-provider-mongo/node_modules/glob": { - "version": "4.5.3", + "packages/happn-db-provider-mongo/node_modules/v8flags": { + "version": "2.1.1", "dev": true, - "license": "ISC", "dependencies": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" + "user-home": "^1.1.1" }, "engines": { - "node": "*" + "node": ">= 0.10.0" } }, - "packages/happn-db-provider-mongo/node_modules/glob-stream": { - "version": "3.1.18", + "packages/happn-db-provider-mongo/node_modules/vinyl": { + "version": "0.4.6", "dev": true, "dependencies": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" + "clone": "^0.2.0", + "clone-stats": "^0.0.1" }, "engines": { "node": ">= 0.9" } }, - "packages/happn-db-provider-mongo/node_modules/glob-watcher": { - "version": "0.0.6", + "packages/happn-db-provider-mongo/node_modules/vinyl-fs": { + "version": "0.3.14", "dev": true, "dependencies": { - "gaze": "^0.5.1" + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" }, "engines": { - "node": ">= 0.9" + "node": ">= 0.10" } }, - "packages/happn-db-provider-mongo/node_modules/graceful-fs": { - "version": "3.0.12", - "dev": true, + "packages/happn-db-provider-nedb": { + "version": "1.0.6", "license": "ISC", "dependencies": { - "natives": "^1.1.3" + "happn-commons": "^1.1.0", + "happn-nedb": "^2.0.5" }, - "engines": { - "node": ">=0.4.0" + "devDependencies": { + "happn-commons-test": "^1.1.0" } }, - "packages/happn-db-provider-mongo/node_modules/gulp": { - "version": "3.9.1", - "dev": true, + "packages/happn-logger": { + "version": "2.1.1", "license": "MIT", "dependencies": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" - }, - "bin": { - "gulp": "bin/gulp.js" - }, - "engines": { - "node": ">= 0.9" - } - }, - "packages/happn-db-provider-mongo/node_modules/is-glob": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "packages/happn-db-provider-mongo/node_modules/is-plain-object": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "packages/happn-db-provider-mongo/node_modules/isarray": { - "version": "0.0.1", - "dev": true, - "license": "MIT" - }, - "packages/happn-db-provider-mongo/node_modules/liftoff": { - "version": "2.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">= 0.8" - } - }, - "packages/happn-db-provider-mongo/node_modules/minimatch": { - "version": "2.0.10", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "packages/happn-db-provider-mongo/node_modules/ordered-read-streams": { - "version": "0.1.0", - "dev": true, - "license": "MIT" - }, - "packages/happn-db-provider-mongo/node_modules/readable-stream": { - "version": "1.0.34", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "packages/happn-db-provider-mongo/node_modules/semver": { - "version": "4.3.6", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "packages/happn-db-provider-mongo/node_modules/string_decoder": { - "version": "0.10.31", - "dev": true, - "license": "MIT" - }, - "packages/happn-db-provider-mongo/node_modules/strip-ansi": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "packages/happn-db-provider-mongo/node_modules/strip-bom": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "first-chunk-stream": "^1.0.0", - "is-utf8": "^0.2.0" - }, - "bin": { - "strip-bom": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "packages/happn-db-provider-mongo/node_modules/supports-color": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "packages/happn-db-provider-mongo/node_modules/through2": { - "version": "0.6.5", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - }, - "packages/happn-db-provider-mongo/node_modules/unique-stream": { - "version": "1.0.0", - "dev": true, - "license": "BSD" - }, - "packages/happn-db-provider-mongo/node_modules/user-home": { - "version": "1.1.1", - "dev": true, - "license": "MIT", - "bin": { - "user-home": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "packages/happn-db-provider-mongo/node_modules/v8flags": { - "version": "2.1.1", - "dev": true, - "dependencies": { - "user-home": "^1.1.1" - }, - "engines": { - "node": ">= 0.10.0" - } - }, - "packages/happn-db-provider-mongo/node_modules/vinyl": { - "version": "0.4.6", - "dev": true, - "dependencies": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" - }, - "engines": { - "node": ">= 0.9" - } - }, - "packages/happn-db-provider-mongo/node_modules/vinyl-fs": { - "version": "0.3.14", - "dev": true, - "dependencies": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" - }, - "engines": { - "node": ">= 0.10" - } - }, - "packages/happn-db-provider-nedb": { - "version": "1.0.6", - "license": "ISC", - "dependencies": { - "happn-commons": "^1.1.0", - "happn-nedb": "^2.0.5" - }, - "devDependencies": { - "happn-commons-test": "^1.1.0" - } - }, - "packages/happn-logger": { - "version": "2.1.1", - "license": "MIT", - "dependencies": { - "log4js": "^6.3.0" + "log4js": "^6.3.0" }, "devDependencies": { "capture-stdout": "^1.0.0", "happn-commons-test": "^1.1.0" } }, - "packages/happn-logger/node_modules/log4js": { - "version": "6.6.0", - "license": "Apache-2.0", - "dependencies": { - "date-format": "^4.0.11", - "debug": "^4.3.4", - "flatted": "^3.2.5", - "rfdc": "^1.3.0", - "streamroller": "^3.1.1" - }, - "engines": { - "node": ">=8.0" - } - }, "packages/happn-nedb": { "version": "2.0.5", "license": "SEE LICENSE IN LICENSE", @@ -16656,6 +16308,11 @@ "node": ">= 0.6.x" } }, + "packages/happn-nedb/node_modules/keypress": { + "version": "0.1.0", + "dev": true, + "license": "MIT" + }, "packages/happn-nedb/node_modules/request": { "version": "2.9.203", "dev": true, @@ -16702,107 +16359,45 @@ "yeast": "~0.1.2" } }, - "packages/happn-primus-wrapper/node_modules/browser-resolve": { - "version": "1.11.3", + "packages/happn-primus-wrapper/node_modules/base64id": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "packages/happn-primus-wrapper/node_modules/chai": { + "version": "4.1.2", "dev": true, "license": "MIT", "dependencies": { - "resolve": "1.1.7" + "assertion-error": "^1.0.1", + "check-error": "^1.0.1", + "deep-eql": "^3.0.0", + "get-func-name": "^2.0.0", + "pathval": "^1.0.0", + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=4" } }, - "packages/happn-primus-wrapper/node_modules/browserify": { - "version": "16.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "assert": "^1.4.0", - "browser-pack": "^6.0.1", - "browser-resolve": "^1.11.0", - "browserify-zlib": "~0.2.0", - "buffer": "^5.0.2", - "cached-path-relative": "^1.0.0", - "concat-stream": "^1.6.0", - "console-browserify": "^1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "^3.0.0", - "defined": "^1.0.0", - "deps-sort": "^2.0.0", - "domain-browser": "^1.2.0", - "duplexer2": "~0.1.2", - "events": "^2.0.0", - "glob": "^7.1.0", - "has": "^1.0.0", - "htmlescape": "^1.1.0", - "https-browserify": "^1.0.0", - "inherits": "~2.0.1", - "insert-module-globals": "^7.0.0", - "JSONStream": "^1.0.3", - "labeled-stream-splicer": "^2.0.0", - "mkdirp": "^0.5.0", - "module-deps": "^6.0.0", - "os-browserify": "~0.3.0", - "parents": "^1.0.1", - "path-browserify": "~0.0.0", - "process": "~0.11.0", - "punycode": "^1.3.2", - "querystring-es3": "~0.2.0", - "read-only-stream": "^2.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.4", - "shasum": "^1.0.0", - "shell-quote": "^1.6.1", - "stream-browserify": "^2.0.0", - "stream-http": "^2.0.0", - "string_decoder": "^1.1.1", - "subarg": "^1.0.0", - "syntax-error": "^1.1.1", - "through2": "^2.0.0", - "timers-browserify": "^1.0.1", - "tty-browserify": "0.0.1", - "url": "~0.11.0", - "util": "~0.10.1", - "vm-browserify": "^1.0.0", - "xtend": "^4.0.0" - }, - "bin": { - "browserify": "bin/cmd.js" - }, - "engines": { - "node": ">= 0.8" - } - }, - "packages/happn-primus-wrapper/node_modules/browserify/node_modules/through2": { - "version": "2.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "packages/happn-primus-wrapper/node_modules/chai": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^1.0.1", - "check-error": "^1.0.1", - "deep-eql": "^3.0.0", - "get-func-name": "^2.0.0", - "pathval": "^1.0.0", - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "packages/happn-primus-wrapper/node_modules/commander": { - "version": "2.15.1", - "dev": true, - "license": "MIT" - }, - "packages/happn-primus-wrapper/node_modules/debug": { - "version": "3.1.0", + "packages/happn-primus-wrapper/node_modules/commander": { + "version": "2.15.1", + "dev": true, + "license": "MIT" + }, + "packages/happn-primus-wrapper/node_modules/cookie": { + "version": "0.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "packages/happn-primus-wrapper/node_modules/debug": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { @@ -16817,6 +16412,19 @@ "node": ">=0.3.1" } }, + "packages/happn-primus-wrapper/node_modules/engine.io": { + "version": "3.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~6.1.0" + } + }, "packages/happn-primus-wrapper/node_modules/glob": { "version": "7.1.2", "dev": true, @@ -16833,35 +16441,20 @@ "node": "*" } }, - "packages/happn-primus-wrapper/node_modules/he": { - "version": "1.1.1", + "packages/happn-primus-wrapper/node_modules/growl": { + "version": "1.10.5", "dev": true, "license": "MIT", - "bin": { - "he": "bin/he" + "engines": { + "node": ">=4.x" } }, - "packages/happn-primus-wrapper/node_modules/jsonparse": { - "version": "1.3.1", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "packages/happn-primus-wrapper/node_modules/JSONStream": { - "version": "1.3.5", + "packages/happn-primus-wrapper/node_modules/he": { + "version": "1.1.1", "dev": true, - "license": "(MIT OR Apache-2.0)", - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, + "license": "MIT", "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" + "he": "bin/he" } }, "packages/happn-primus-wrapper/node_modules/minimatch": { @@ -16921,28 +16514,6 @@ "dev": true, "license": "MIT" }, - "packages/happn-primus-wrapper/node_modules/punycode": { - "version": "1.4.1", - "dev": true, - "license": "MIT" - }, - "packages/happn-primus-wrapper/node_modules/resolve": { - "version": "1.1.7", - "dev": true, - "license": "MIT" - }, - "packages/happn-primus-wrapper/node_modules/stream-http": { - "version": "2.8.3", - "dev": true, - "license": "MIT", - "dependencies": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, "packages/happn-primus-wrapper/node_modules/supports-color": { "version": "5.4.0", "dev": true, @@ -16989,303 +16560,536 @@ "vinyl-source-stream": "^2.0.0" } }, - "packages/happn-util-crypto/node_modules/crypto-browserify": { - "version": "3.12.0", + "packages/happn-util-crypto/node_modules/base64id": { + "version": "1.0.0", + "dev": true, "license": "MIT", - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, "engines": { - "node": "*" + "node": ">= 0.4.0" } }, - "packages/happn-util-crypto/node_modules/karma-chrome-launcher": { - "version": "2.2.0", + "packages/happn-util-crypto/node_modules/bluebird": { + "version": "3.7.2", "dev": true, - "license": "MIT", - "dependencies": { - "fs-access": "^1.0.0", - "which": "^1.2.1" - } + "license": "MIT" }, - "packages/happn-util-crypto/node_modules/karma-mocha": { - "version": "1.3.0", + "packages/happn-util-crypto/node_modules/cookie": { + "version": "0.3.1", "dev": true, "license": "MIT", - "dependencies": { - "minimist": "1.2.0" + "engines": { + "node": ">= 0.6" } }, - "packages/happn-util-crypto/node_modules/minimist": { + "packages/happn-util-crypto/node_modules/date-format": { "version": "1.2.0", "dev": true, - "license": "MIT" - }, - "packages/happn-util-crypto/node_modules/which": { - "version": "1.3.1", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "packages/happner-2": { - "version": "12.1.9", "license": "MIT", - "dependencies": { - "body": "5.1.0", - "change-case": "2.3.0", - "commander": "2.9.0", - "diskspace": "0.1.7", - "happn-3": "^13.1.4", - "happn-commons": "^1.1.0", - "happn-logger": "^2.1.1", - "happn-sillyname": "^0.1.1", - "happner-client": "^12.2.8", - "happner-semver": "^1.0.1", - "homedir": "0.6.0", - "later": "1.2.0", - "md5": "2.0.0", - "merge": "^2.1.1", - "proc-stats": "0.0.4", - "repl": "^0.1.3", - "repl.history": "^0.1.4", - "uglify-es": "^3.3.9" - }, - "bin": { - "happner": "bin/happner" - }, - "devDependencies": { - "address": "^1.1.2", - "happn-commons-test": "^1.1.0", - "happn-db-provider-mongo": "^1.0.12", - "happner": "1.33.4", - "happner-test-modules": "^1.0.2", - "is-ip": "^3.1.0", - "restler": "3.4.0", - "serve-static": "1.10.0", - "tree-kill": "^1.2.1" + "engines": { + "node": ">=4.0" } }, - "packages/happner-2/node_modules/commander": { - "version": "2.9.0", + "packages/happn-util-crypto/node_modules/debug": { + "version": "3.2.7", + "dev": true, "license": "MIT", "dependencies": { - "graceful-readlink": ">= 1.0.0" - }, - "engines": { - "node": ">= 0.6.x" + "ms": "^2.1.1" } }, - "packages/happner-2/node_modules/debug": { - "version": "2.2.0", + "packages/happn-util-crypto/node_modules/engine.io": { + "version": "3.2.1", "dev": true, "license": "MIT", "dependencies": { - "ms": "0.7.1" + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" } }, - "packages/happner-2/node_modules/depd": { - "version": "1.0.1", + "packages/happn-util-crypto/node_modules/engine.io/node_modules/debug": { + "version": "3.1.0", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.6" + "dependencies": { + "ms": "2.0.0" } }, - "packages/happner-2/node_modules/destroy": { - "version": "1.0.3", + "packages/happn-util-crypto/node_modules/engine.io/node_modules/ms": { + "version": "2.0.0", "dev": true, "license": "MIT" }, - "packages/happner-2/node_modules/escape-html": { - "version": "1.0.2", + "packages/happn-util-crypto/node_modules/flatted": { + "version": "2.0.2", "dev": true, - "license": "MIT" + "license": "ISC" }, - "packages/happner-2/node_modules/etag": { - "version": "1.7.0", + "packages/happn-util-crypto/node_modules/isbinaryfile": { + "version": "3.0.3", "dev": true, "license": "MIT", + "dependencies": { + "buffer-alloc": "^1.2.0" + }, "engines": { - "node": ">= 0.6" + "node": ">=0.6.0" } }, - "packages/happner-2/node_modules/fresh": { - "version": "0.3.0", + "packages/happn-util-crypto/node_modules/karma": { + "version": "3.1.4", "dev": true, "license": "MIT", + "dependencies": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^2.0.3", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "flatted": "^2.0.0", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.5", + "log4js": "^3.0.0", + "mime": "^2.3.1", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.1.1", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.3.0" + }, + "bin": { + "karma": "bin/karma" + }, "engines": { - "node": ">= 0.6" + "node": ">= 6" } }, - "packages/happner-2/node_modules/http-errors": { - "version": "1.3.1", + "packages/happn-util-crypto/node_modules/karma-chrome-launcher": { + "version": "2.2.0", "dev": true, "license": "MIT", "dependencies": { - "inherits": "~2.0.1", - "statuses": "1" + "fs-access": "^1.0.0", + "which": "^1.2.1" + } + }, + "packages/happn-util-crypto/node_modules/karma-mocha": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "1.2.0" + } + }, + "packages/happn-util-crypto/node_modules/log4js": { + "version": "3.0.6", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "circular-json": "^0.5.5", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "rfdc": "^1.1.2", + "streamroller": "0.7.0" }, "engines": { - "node": ">= 0.6" + "node": ">=6.0" } }, - "packages/happner-2/node_modules/is-buffer": { - "version": "1.0.2", + "packages/happn-util-crypto/node_modules/minimist": { + "version": "1.2.0", + "dev": true, "license": "MIT" }, - "packages/happner-2/node_modules/md5": { - "version": "2.0.0", - "license": "BSD-3-Clause", + "packages/happn-util-crypto/node_modules/rimraf": { + "version": "2.7.1", + "dev": true, + "license": "ISC", "dependencies": { - "charenc": "~ 0.0.1", - "crypt": "~ 0.0.1", - "is-buffer": "~ 1.0.2" + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" } }, - "packages/happner-2/node_modules/mime": { - "version": "1.3.4", + "packages/happn-util-crypto/node_modules/safe-buffer": { + "version": "5.1.2", "dev": true, - "bin": { - "mime": "cli.js" + "license": "MIT" + }, + "packages/happn-util-crypto/node_modules/socket.io": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" } }, - "packages/happner-2/node_modules/ms": { - "version": "0.7.1", - "dev": true + "packages/happn-util-crypto/node_modules/socket.io-adapter": { + "version": "1.1.2", + "dev": true, + "license": "MIT" }, - "packages/happner-2/node_modules/range-parser": { - "version": "1.0.3", + "packages/happn-util-crypto/node_modules/socket.io-parser": { + "version": "3.2.0", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.6" + "dependencies": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" } }, - "packages/happner-2/node_modules/send": { - "version": "0.13.0", + "packages/happn-util-crypto/node_modules/socket.io-parser/node_modules/debug": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "debug": "~2.2.0", - "depd": "~1.0.1", - "destroy": "1.0.3", - "escape-html": "1.0.2", - "etag": "~1.7.0", - "fresh": "0.3.0", - "http-errors": "~1.3.1", - "mime": "1.3.4", - "ms": "0.7.1", - "on-finished": "~2.3.0", - "range-parser": "~1.0.2", - "statuses": "~1.2.1" - }, - "engines": { - "node": ">= 0.8.0" + "ms": "2.0.0" } }, - "packages/happner-2/node_modules/serve-static": { - "version": "1.10.0", + "packages/happn-util-crypto/node_modules/socket.io-parser/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "packages/happn-util-crypto/node_modules/socket.io/node_modules/debug": { + "version": "3.1.0", "dev": true, "license": "MIT", "dependencies": { - "escape-html": "1.0.2", - "parseurl": "~1.3.0", - "send": "0.13.0" - }, - "engines": { - "node": ">= 0.8.0" + "ms": "2.0.0" } }, - "packages/happner-2/node_modules/statuses": { - "version": "1.2.1", + "packages/happn-util-crypto/node_modules/socket.io/node_modules/ms": { + "version": "2.0.0", "dev": true, "license": "MIT" }, - "packages/happner-client": { - "version": "12.2.8", + "packages/happn-util-crypto/node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "packages/happn-util-crypto/node_modules/streamroller": { + "version": "0.7.0", + "dev": true, "license": "MIT", "dependencies": { - "happn-3": "^13.1.4", - "happn-commons": "^1.1.0", - "happner-semver": "^1.0.1" + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" }, - "devDependencies": { - "happn-commons-test": "^1.1.0", - "happner-2": "^12.1.9" + "engines": { + "node": ">=0.12.0" } }, - "packages/happner-cluster": { - "version": "12.1.9", + "packages/happn-util-crypto/node_modules/tmp": { + "version": "0.0.33", + "dev": true, "license": "MIT", "dependencies": { - "bluebird": "^3.5.0", - "happn-cluster": "^12.0.12", - "happn-commons": "^1.1.0", - "happner-2": "^12.1.9", - "happner-client": "^12.2.8", - "hashring": "^3.2.0", - "http-proxy": "1.18.1", - "semver": "^5.3.0" + "os-tmpdir": "~1.0.2" }, - "devDependencies": { - "array-unique": "^0.3.2", - "happn-commons-test": "^1.1.0", - "intercept-stdout": "^0.1.2", - "restler": "^3.4.0" + "engines": { + "node": ">=0.6.0" } }, - "packages/happner-cluster/node_modules/bluebird": { - "version": "3.7.2", + "packages/happn-util-crypto/node_modules/ultron": { + "version": "1.1.1", + "dev": true, "license": "MIT" }, - "packages/happner-cluster/node_modules/semver": { - "version": "5.7.1", + "packages/happn-util-crypto/node_modules/which": { + "version": "1.3.1", + "dev": true, "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, "bin": { - "semver": "bin/semver" + "which": "bin/which" } }, - "packages/redis-lru-cache": { - "version": "1.0.12", + "packages/happn-util-crypto/node_modules/ws": { + "version": "3.3.3", + "dev": true, + "license": "MIT", "dependencies": { - "@node-redis/bloom": "^1.0.1", - "@node-redis/client": "^1.0.3", - "@node-redis/graph": "^1.0.0", - "@node-redis/json": "^1.0.2", - "@node-redis/search": "^1.0.2", - "@node-redis/time-series": "^1.0.1", - "clone": "^2.1.2", - "happn-commons": "^1.1.0", - "node-redis-pubsub": "^1.0.3", - "redis": "^4.0.3" - }, - "devDependencies": { - "happn-commons-test": "^1.1.0", - "happn-db-provider-mongo": "^1.0.12" + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" } }, - "packages/tame-search": { - "version": "3.0.5", + "packages/happner-2": { + "version": "12.2.0", "license": "MIT", "dependencies": { - "happn-commons": "^1.1.0" + "body": "5.1.0", + "change-case": "2.3.0", + "commander": "2.9.0", + "diskspace": "0.1.7", + "happn-3": "^13.2.0", + "happn-commons": "^1.1.0", + "happn-logger": "^2.1.1", + "happn-sillyname": "^0.1.1", + "happner-client": "^12.3.0", + "happner-semver": "^1.0.1", + "homedir": "0.6.0", + "later": "1.2.0", + "md5": "2.0.0", + "merge": "^2.1.1", + "proc-stats": "0.0.4", + "repl": "^0.1.3", + "repl.history": "^0.1.4", + "uglify-es": "^3.3.9" }, - "devDependencies": { + "bin": { + "happner": "bin/happner" + }, + "devDependencies": { + "address": "^1.1.2", + "happn-commons-test": "^1.1.0", + "happn-db-provider-mongo": "^1.0.13", + "happner": "1.33.4", + "happner-test-modules": "^1.0.2", + "is-ip": "^3.1.0", + "restler": "3.4.0", + "serve-static": "1.10.0", + "tree-kill": "^1.2.1" + } + }, + "packages/happner-2/node_modules/commander": { + "version": "2.9.0", + "license": "MIT", + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "packages/happner-2/node_modules/debug": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "0.7.1" + } + }, + "packages/happner-2/node_modules/depd": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "packages/happner-2/node_modules/destroy": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "packages/happner-2/node_modules/escape-html": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "packages/happner-2/node_modules/etag": { + "version": "1.7.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "packages/happner-2/node_modules/fresh": { + "version": "0.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "packages/happner-2/node_modules/http-errors": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.1", + "statuses": "1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "packages/happner-2/node_modules/is-buffer": { + "version": "1.0.2", + "license": "MIT" + }, + "packages/happner-2/node_modules/md5": { + "version": "2.0.0", + "license": "BSD-3-Clause", + "dependencies": { + "charenc": "~ 0.0.1", + "crypt": "~ 0.0.1", + "is-buffer": "~ 1.0.2" + } + }, + "packages/happner-2/node_modules/mime": { + "version": "1.3.4", + "dev": true, + "bin": { + "mime": "cli.js" + } + }, + "packages/happner-2/node_modules/ms": { + "version": "0.7.1", + "dev": true + }, + "packages/happner-2/node_modules/range-parser": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "packages/happner-2/node_modules/send": { + "version": "0.13.0", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "~2.2.0", + "depd": "~1.0.1", + "destroy": "1.0.3", + "escape-html": "1.0.2", + "etag": "~1.7.0", + "fresh": "0.3.0", + "http-errors": "~1.3.1", + "mime": "1.3.4", + "ms": "0.7.1", + "on-finished": "~2.3.0", + "range-parser": "~1.0.2", + "statuses": "~1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "packages/happner-2/node_modules/serve-static": { + "version": "1.10.0", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-html": "1.0.2", + "parseurl": "~1.3.0", + "send": "0.13.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "packages/happner-2/node_modules/statuses": { + "version": "1.2.1", + "dev": true, + "license": "MIT" + }, + "packages/happner-client": { + "version": "12.3.0", + "license": "MIT", + "dependencies": { + "happn-3": "^13.2.0", + "happn-commons": "^1.1.0", + "happner-semver": "^1.0.1" + }, + "devDependencies": { + "happn-commons-test": "^1.1.0", + "happner-2": "^12.2.0" + } + }, + "packages/happner-cluster": { + "version": "12.2.0", + "license": "MIT", + "dependencies": { + "bluebird": "^3.5.0", + "happn-cluster": "^12.0.13", + "happn-commons": "^1.1.0", + "happner-2": "^12.2.0", + "happner-client": "^12.3.0", + "hashring": "^3.2.0", + "http-proxy": "1.18.1", + "semver": "^5.3.0" + }, + "devDependencies": { + "array-unique": "^0.3.2", + "happn-commons-test": "^1.1.0", + "intercept-stdout": "^0.1.2", + "restler": "^3.4.0" + } + }, + "packages/happner-cluster/node_modules/bluebird": { + "version": "3.7.2", + "license": "MIT" + }, + "packages/happner-cluster/node_modules/semver": { + "version": "5.7.1", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "packages/redis-lru-cache": { + "version": "1.0.13", + "dependencies": { + "@node-redis/bloom": "^1.0.1", + "@node-redis/client": "^1.0.3", + "@node-redis/graph": "^1.0.0", + "@node-redis/json": "^1.0.2", + "@node-redis/search": "^1.0.2", + "@node-redis/time-series": "^1.0.1", + "clone": "^2.1.2", + "happn-commons": "^1.1.0", + "node-redis-pubsub": "^1.0.3", + "redis": "^4.0.3" + }, + "devDependencies": { + "happn-commons-test": "^1.1.0", + "happn-db-provider-mongo": "^1.0.13" + } + }, + "packages/tame-search": { + "version": "3.0.5", + "license": "MIT", + "dependencies": { + "happn-commons": "^1.1.0" + }, + "devDependencies": { "happn-commons-test": "^1.1.0" } } @@ -17317,23 +17121,23 @@ } }, "@babel/compat-data": { - "version": "7.18.8", + "version": "7.18.13", "dev": true }, "@babel/core": { - "version": "7.18.6", + "version": "7.18.13", "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.6", - "@babel/helper-compilation-targets": "^7.18.6", - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helpers": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6", + "@babel/generator": "^7.18.13", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helpers": "^7.18.9", + "@babel/parser": "^7.18.13", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.13", + "@babel/types": "^7.18.13", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -17341,10 +17145,21 @@ "semver": "^6.3.0" }, "dependencies": { + "convert-source-map": { + "version": "1.8.0", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, "json5": { "version": "2.2.1", "dev": true }, + "safe-buffer": { + "version": "5.1.2", + "dev": true + }, "semver": { "version": "6.3.0", "dev": true @@ -17352,19 +17167,19 @@ } }, "@babel/generator": { - "version": "7.18.7", + "version": "7.18.13", "dev": true, "requires": { - "@babel/types": "^7.18.7", + "@babel/types": "^7.18.13", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" } }, "@babel/helper-compilation-targets": { - "version": "7.18.6", + "version": "7.18.9", "dev": true, "requires": { - "@babel/compat-data": "^7.18.6", + "@babel/compat-data": "^7.18.8", "@babel/helper-validator-option": "^7.18.6", "browserslist": "^4.20.2", "semver": "^6.3.0" @@ -17377,15 +17192,15 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.18.6", + "version": "7.18.9", "dev": true }, "@babel/helper-function-name": { - "version": "7.18.6", + "version": "7.18.9", "dev": true, "requires": { "@babel/template": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/types": "^7.18.9" } }, "@babel/helper-hoist-variables": { @@ -17403,17 +17218,17 @@ } }, "@babel/helper-module-transforms": { - "version": "7.18.8", + "version": "7.18.9", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-module-imports": "^7.18.6", "@babel/helper-simple-access": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.18.6", "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.8", - "@babel/types": "^7.18.8" + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" } }, "@babel/helper-simple-access": { @@ -17430,6 +17245,10 @@ "@babel/types": "^7.18.6" } }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "dev": true + }, "@babel/helper-validator-identifier": { "version": "7.18.6", "dev": true @@ -17439,12 +17258,12 @@ "dev": true }, "@babel/helpers": { - "version": "7.18.6", + "version": "7.18.9", "dev": true, "requires": { "@babel/template": "^7.18.6", - "@babel/traverse": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" } }, "@babel/highlight": { @@ -17457,38 +17276,39 @@ } }, "@babel/parser": { - "version": "7.18.8", + "version": "7.18.13", "dev": true }, "@babel/template": { - "version": "7.18.6", + "version": "7.18.10", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.6", - "@babel/types": "^7.18.6" + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" } }, "@babel/traverse": { - "version": "7.18.8", + "version": "7.18.13", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.18.7", - "@babel/helper-environment-visitor": "^7.18.6", - "@babel/helper-function-name": "^7.18.6", + "@babel/generator": "^7.18.13", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.18.8", - "@babel/types": "^7.18.8", + "@babel/parser": "^7.18.13", + "@babel/types": "^7.18.13", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.18.8", + "version": "7.18.13", "dev": true, "requires": { + "@babel/helper-string-parser": "^7.18.10", "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" } @@ -17517,7 +17337,7 @@ }, "dependencies": { "globals": { - "version": "13.16.0", + "version": "13.17.0", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -17553,44 +17373,7 @@ "version": "5.3.1", "dev": true }, - "find-up": { - "version": "4.1.0", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "dev": true - }, - "resolve-from": { + "resolve-from": { "version": "5.0.0", "dev": true } @@ -17625,7 +17408,7 @@ "version": "1.4.14" }, "@jridgewell/trace-mapping": { - "version": "0.3.14", + "version": "0.3.15", "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -17665,7 +17448,7 @@ "requires": {} }, "@redis/client": { - "version": "1.2.0", + "version": "1.3.0", "requires": { "cluster-key-slot": "1.1.0", "generic-pool": "3.8.2", @@ -17681,7 +17464,7 @@ "requires": {} }, "@redis/search": { - "version": "1.0.6", + "version": "1.1.0", "requires": {} }, "@redis/time-series": { @@ -17712,7 +17495,7 @@ } }, "@sinonjs/text-encoding": { - "version": "0.7.1", + "version": "0.7.2", "dev": true }, "@types/component-emitter": { @@ -17741,7 +17524,7 @@ "peer": true }, "@types/node": { - "version": "18.0.3" + "version": "18.7.13" }, "@types/webidl-conversions": { "version": "6.1.1" @@ -18181,10 +17964,6 @@ "now-and-later": "^2.0.0" } }, - "backo2": { - "version": "1.0.2", - "dev": true - }, "balanced-match": { "version": "1.0.2" }, @@ -18218,7 +17997,7 @@ "version": "1.5.1" }, "base64id": { - "version": "1.0.0", + "version": "2.0.0", "dev": true }, "bcrypt-pbkdf": { @@ -18300,6 +18079,20 @@ "lodash": "=3.10.1" }, "dependencies": { + "bn.js": { + "version": "2.0.4", + "dev": true + }, + "elliptic": { + "version": "3.0.3", + "dev": true, + "requires": { + "bn.js": "^2.0.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "inherits": "^2.0.1" + } + }, "inherits": { "version": "2.0.1", "dev": true @@ -18327,8 +18120,7 @@ "dev": true }, "bn.js": { - "version": "2.0.4", - "dev": true + "version": "5.2.1" }, "body": { "version": "5.1.0", @@ -18337,21 +18129,6 @@ "error": "^7.0.0", "raw-body": "~1.1.0", "safe-json-parse": "~1.0.1" - }, - "dependencies": { - "bytes": { - "version": "1.0.0" - }, - "raw-body": { - "version": "1.1.7", - "requires": { - "bytes": "1", - "string_decoder": "0.10" - } - }, - "string_decoder": { - "version": "0.10.31" - } } }, "body-parser": { @@ -18377,6 +18154,15 @@ }, "ms": { "version": "2.0.0" + }, + "raw-body": { + "version": "2.4.3", + "requires": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } } } }, @@ -18423,27 +18209,19 @@ "safe-buffer": "^5.1.1", "through2": "^2.0.0", "umd": "^3.0.0" - }, - "dependencies": { - "jsonparse": { - "version": "1.3.1", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - } } }, "browser-resolve": { - "version": "2.0.0", + "version": "1.11.3", "dev": true, "requires": { - "resolve": "^1.17.0" + "resolve": "1.1.7" + }, + "dependencies": { + "resolve": { + "version": "1.1.7", + "dev": true + } } }, "browser-stdout": { @@ -18460,14 +18238,14 @@ } }, "browserify": { - "version": "16.5.2", + "version": "16.2.3", "dev": true, "requires": { "assert": "^1.4.0", "browser-pack": "^6.0.1", - "browser-resolve": "^2.0.0", + "browser-resolve": "^1.11.0", "browserify-zlib": "~0.2.0", - "buffer": "~5.2.1", + "buffer": "^5.0.2", "cached-path-relative": "^1.0.0", "concat-stream": "^1.6.0", "console-browserify": "^1.1.0", @@ -18486,8 +18264,8 @@ "insert-module-globals": "^7.0.0", "JSONStream": "^1.0.3", "labeled-stream-splicer": "^2.0.0", - "mkdirp-classic": "^0.5.2", - "module-deps": "^6.2.3", + "mkdirp": "^0.5.0", + "module-deps": "^6.0.0", "os-browserify": "~0.3.0", "parents": "^1.0.1", "path-browserify": "~0.0.0", @@ -18500,7 +18278,7 @@ "shasum": "^1.0.0", "shell-quote": "^1.6.1", "stream-browserify": "^2.0.0", - "stream-http": "^3.0.0", + "stream-http": "^2.0.0", "string_decoder": "^1.1.1", "subarg": "^1.0.0", "syntax-error": "^1.1.1", @@ -18513,26 +18291,6 @@ "xtend": "^4.0.0" }, "dependencies": { - "buffer": { - "version": "5.2.1", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "jsonparse": { - "version": "1.3.1", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, "punycode": { "version": "1.4.1", "dev": true @@ -18572,11 +18330,6 @@ "requires": { "bn.js": "^5.0.0", "randombytes": "^2.0.1" - }, - "dependencies": { - "bn.js": { - "version": "5.2.1" - } } }, "browserify-sign": { @@ -18593,26 +18346,6 @@ "safe-buffer": "^5.2.0" }, "dependencies": { - "bn.js": { - "version": "5.2.1" - }, - "elliptic": { - "version": "6.5.4", - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0" - } - } - }, "readable-stream": { "version": "3.6.0", "requires": { @@ -18620,9 +18353,6 @@ "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } - }, - "safe-buffer": { - "version": "5.2.1" } } }, @@ -18634,13 +18364,13 @@ } }, "browserslist": { - "version": "4.21.2", + "version": "4.21.3", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001366", - "electron-to-chromium": "^1.4.188", + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.4" + "update-browserslist-db": "^1.0.5" } }, "bs58": { @@ -18648,7 +18378,7 @@ "dev": true }, "bson": { - "version": "4.6.5", + "version": "4.7.0", "requires": { "buffer": "^5.6.0" } @@ -18660,18 +18390,6 @@ "ieee754": "^1.1.13" } }, - "buffer-alloc": { - "version": "1.2.0", - "dev": true, - "requires": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "buffer-alloc-unsafe": { - "version": "1.1.0", - "dev": true - }, "buffer-compare": { "version": "1.0.0", "dev": true @@ -18680,10 +18398,6 @@ "version": "1.0.0", "dev": true }, - "buffer-fill": { - "version": "1.0.0", - "dev": true - }, "buffer-from": { "version": "1.1.2" }, @@ -18726,336 +18440,74 @@ "yargs-parser": "^14.0.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.1", - "dev": true - }, "camelcase": { "version": "5.3.1", "dev": true }, - "cliui": { - "version": "5.0.0", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "emoji-regex": { - "version": "7.0.3", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "get-caller-file": { - "version": "2.0.5", + "decamelize": { + "version": "1.2.0", "dev": true }, - "is-fullwidth-code-point": { + "foreground-child": { "version": "2.0.0", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "2.0.5", - "dev": true - }, - "istanbul-lib-report": { - "version": "2.0.8", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "supports-color": "^6.1.0" - } - }, - "istanbul-reports": { - "version": "2.2.7", - "dev": true, - "requires": { - "html-escaper": "^2.0.0" - } - }, - "load-json-file": { - "version": "4.0.0", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "dev": true - } + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" } }, - "locate-path": { - "version": "5.0.0", + "yargs-parser": { + "version": "14.0.0", "dev": true, "requires": { - "p-locate": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } - }, + } + } + }, + "cache-base": { + "version": "1.0.1", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cached-path-relative": { + "version": "1.1.0", + "dev": true + }, + "caching-transform": { + "version": "4.0.0", + "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": "2.1.0", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "p-limit": { - "version": "2.3.0", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "dev": true - }, - "parse-json": { - "version": "4.0.0", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "path-exists": { - "version": "4.0.0", - "dev": true - }, - "path-type": { - "version": "3.0.0", + "version": "3.1.0", "dev": true, "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "dev": true - } + "semver": "^6.0.0" } }, - "pify": { - "version": "4.0.1", + "semver": { + "version": "6.3.0", "dev": true - }, - "read-pkg": { - "version": "3.0.0", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "4.0.0", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "dev": true - } - } - }, - "require-main-filename": { - "version": "2.0.0", - "dev": true - }, - "semver": { - "version": "5.7.1", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "supports-color": { - "version": "6.1.0", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "test-exclude": { - "version": "5.2.3", - "dev": true, - "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "y18n": { - "version": "4.0.3", - "dev": true - }, - "yargs": { - "version": "14.2.3", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.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": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "dev": true - }, - "yargs-parser": { - "version": "15.0.3", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "yargs-parser": { - "version": "14.0.0", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } }, - "cache-base": { - "version": "1.0.1", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "cached-path-relative": { - "version": "1.1.0", - "dev": true - }, - "caching-transform": { - "version": "4.0.0", - "dev": true, - "requires": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - } - }, "call-bind": { "version": "1.0.2", "dev": true, @@ -19080,11 +18532,11 @@ } }, "camelcase": { - "version": "3.0.0", + "version": "6.3.0", "dev": true }, "caniuse-lite": { - "version": "1.0.30001366", + "version": "1.0.30001384", "dev": true }, "capture-stdout": { @@ -19095,6 +18547,9 @@ "version": "0.12.0", "dev": true }, + "cd": { + "version": "0.3.3" + }, "center-align": { "version": "0.1.3", "dev": true, @@ -19208,10 +18663,6 @@ "safe-buffer": "^5.0.1" } }, - "circular-json": { - "version": "0.5.9", - "dev": true - }, "class-utils": { "version": "0.3.6", "dev": true, @@ -19277,39 +18728,40 @@ "dev": true }, "cliui": { - "version": "3.2.0", + "version": "5.0.0", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", + "version": "4.1.1", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", "dev": true }, "is-fullwidth-code-point": { - "version": "1.0.0", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "2.0.0", + "dev": true }, "string-width": { - "version": "1.0.2", + "version": "3.1.0", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "strip-ansi": { - "version": "3.0.1", + "version": "5.2.0", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^4.1.0" } } } @@ -19422,12 +18874,6 @@ "inline-source-map": "~0.6.0", "lodash.memoize": "~3.0.3", "source-map": "~0.5.3" - }, - "dependencies": { - "convert-source-map": { - "version": "1.1.3", - "dev": true - } } }, "combined-stream": { @@ -19444,12 +18890,8 @@ "version": "1.0.1", "dev": true }, - "component-bind": { - "version": "1.0.0", - "dev": true - }, "component-emitter": { - "version": "1.3.0", + "version": "1.2.1", "dev": true }, "component-inherit": { @@ -19557,14 +18999,11 @@ "version": "0.3.1" }, "convert-source-map": { - "version": "1.8.0", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } + "version": "1.1.3", + "dev": true }, "cookie": { - "version": "0.3.1", + "version": "0.4.2", "dev": true }, "cookies": { @@ -19611,144 +19050,11 @@ "yargs-parser": "^13.1.1" }, "dependencies": { - "camelcase": { - "version": "5.3.1", - "dev": true - }, - "cross-spawn": { - "version": "4.0.2", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "find-up": { - "version": "3.0.0", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "foreground-child": { - "version": "1.5.6", - "dev": true, - "requires": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" - } - }, - "load-json-file": { - "version": "4.0.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lru-cache": { - "version": "4.1.5", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "p-limit": { - "version": "2.3.0", + "which": { + "version": "1.3.1", "dev": true, "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "dev": true - }, - "parse-json": { - "version": "4.0.0", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "path-type": { - "version": "3.0.0", - "dev": true, - "requires": { - "pify": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "dev": true - }, - "read-pkg": { - "version": "3.0.0", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - } - }, - "read-pkg-up": { - "version": "4.0.0", - "dev": true, - "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - } - }, - "require-main-filename": { - "version": "2.0.0", - "dev": true - }, - "test-exclude": { - "version": "5.2.3", - "dev": true, - "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" - } - }, - "which": { - "version": "1.3.1", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "yallist": { - "version": "2.1.2", - "dev": true - }, - "yargs-parser": { - "version": "13.1.2", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "isexe": "^2.0.0" } } } @@ -19773,18 +19079,6 @@ "dependencies": { "bn.js": { "version": "4.12.0" - }, - "elliptic": { - "version": "6.5.4", - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } } } }, @@ -19835,8 +19129,7 @@ } }, "crypto-browserify": { - "version": "3.11.0", - "dev": true, + "version": "3.12.0", "requires": { "browserify-cipher": "^1.0.0", "browserify-sign": "^4.0.0", @@ -19847,7 +19140,8 @@ "inherits": "^2.0.1", "pbkdf2": "^3.0.3", "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0" + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" } }, "custom-env": { @@ -19881,7 +19175,7 @@ } }, "date-format": { - "version": "4.0.11" + "version": "4.0.13" }, "dateformat": { "version": "2.2.0", @@ -19894,7 +19188,7 @@ } }, "decamelize": { - "version": "1.2.0", + "version": "4.0.0", "dev": true }, "decode-uri-component": { @@ -19980,7 +19274,7 @@ "dev": true }, "denque": { - "version": "2.0.1" + "version": "2.1.0" }, "depd": { "version": "1.1.2" @@ -19993,20 +19287,6 @@ "shasum-object": "^1.0.0", "subarg": "^1.0.0", "through2": "^2.0.0" - }, - "dependencies": { - "jsonparse": { - "version": "1.3.1", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - } } }, "derequire": { @@ -20028,6 +19308,35 @@ "version": "2.1.1", "dev": true }, + "camelcase": { + "version": "3.0.0", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "dev": true + }, "is-fullwidth-code-point": { "version": "1.0.0", "dev": true, @@ -20035,6 +19344,65 @@ "number-is-nan": "^1.0.0" } }, + "load-json-file": { + "version": "1.1.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "require-main-filename": { + "version": "1.0.1", + "dev": true + }, "string-width": { "version": "1.0.2", "dev": true, @@ -20051,6 +19419,29 @@ "ansi-regex": "^2.0.0" } }, + "strip-bom": { + "version": "2.0.0", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "which-module": { + "version": "1.0.0", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "y18n": { + "version": "3.2.2", + "dev": true + }, "yargs": { "version": "6.6.0", "dev": true, @@ -20153,7 +19544,7 @@ } }, "diff": { - "version": "5.0.0", + "version": "1.4.0", "dev": true }, "diffie-hellman": { @@ -20311,17 +19702,24 @@ } }, "electron-to-chromium": { - "version": "1.4.188", + "version": "1.4.233", "dev": true }, "elliptic": { - "version": "3.0.3", - "dev": true, + "version": "6.5.4", "requires": { - "bn.js": "^2.0.0", - "brorand": "^1.0.1", + "bn.js": "^4.11.9", + "brorand": "^1.1.0", "hash.js": "^1.0.0", - "inherits": "^2.0.1" + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0" + } } }, "emdee": { @@ -20344,10 +19742,6 @@ "ms": { "version": "2.0.0", "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "dev": true } } }, @@ -20375,27 +19769,29 @@ } }, "engine.io": { - "version": "3.3.2", + "version": "6.2.0", "dev": true, "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~6.1.0" + "base64id": "2.0.0", + "cookie": "~0.4.1", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" }, "dependencies": { - "debug": { - "version": "3.1.0", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", + "engine.io-parser": { + "version": "5.0.4", "dev": true + }, + "ws": { + "version": "8.2.3", + "dev": true, + "requires": {} } } }, @@ -20416,10 +19812,6 @@ "yeast": "0.1.2" }, "dependencies": { - "component-emitter": { - "version": "1.2.1", - "dev": true - }, "debug": { "version": "3.1.0", "dev": true, @@ -20520,7 +19912,7 @@ } }, "es5-ext": { - "version": "0.10.61", + "version": "0.10.62", "dev": true, "requires": { "es6-iterator": "^2.0.3", @@ -20557,24 +19949,21 @@ "version": "6.1.1" }, "es6-set": { - "version": "0.1.5", + "version": "0.1.6", "dev": true, "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "es6-iterator": "~2.0.3", + "es6-symbol": "^3.1.3", + "event-emitter": "^0.3.5", + "type": "^2.7.2" }, "dependencies": { - "es6-symbol": { - "version": "3.1.1", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - } + "type": { + "version": "2.7.2", + "dev": true + } } }, "es6-symbol": { @@ -20756,7 +20145,7 @@ "dev": true }, "globals": { - "version": "13.16.0", + "version": "13.17.0", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -20807,12 +20196,11 @@ } }, "eslint-module-utils": { - "version": "2.7.3", + "version": "2.7.4", "dev": true, "peer": true, "requires": { - "debug": "^3.2.7", - "find-up": "^2.1.0" + "debug": "^3.2.7" }, "dependencies": { "debug": { @@ -21168,7 +20556,7 @@ }, "dependencies": { "type": { - "version": "2.6.0", + "version": "2.7.2", "dev": true } } @@ -21309,14 +20697,27 @@ "commondir": "^1.0.1", "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "dev": true + } } }, "find-up": { - "version": "2.1.0", + "version": "4.1.0", "dev": true, - "peer": true, "requires": { - "locate-path": "^2.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "findup-sync": { @@ -21366,7 +20767,7 @@ } }, "flatted": { - "version": "3.2.6" + "version": "3.2.7" }, "flush-write-stream": { "version": "1.1.1", @@ -21391,11 +20792,40 @@ } }, "foreground-child": { - "version": "2.0.0", + "version": "1.5.6", "dev": true, "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "4.0.2", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "lru-cache": { + "version": "4.1.5", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "which": { + "version": "1.3.1", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "yallist": { + "version": "2.1.2", + "dev": true + } } }, "forever-agent": { @@ -21430,11 +20860,22 @@ "dev": true }, "fs-extra": { - "version": "10.1.0", + "version": "0.24.0", + "dev": true, "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "rimraf": { + "version": "2.7.1", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } } }, "fs-mkdirp-stream": { @@ -21507,7 +20948,7 @@ "dev": true }, "get-caller-file": { - "version": "1.0.3", + "version": "2.0.5", "dev": true }, "get-func-name": { @@ -21659,7 +21100,7 @@ "version": "4.2.10" }, "growl": { - "version": "1.10.5", + "version": "1.9.2", "dev": true }, "gulp": { @@ -21702,6 +21143,171 @@ "requires": { "ansi-wrap": "^0.1.0" } + }, + "ansi-regex": { + "version": "2.1.1", + "dev": true + }, + "camelcase": { + "version": "3.0.0", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-type": { + "version": "1.1.0", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "require-main-filename": { + "version": "1.0.1", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "which-module": { + "version": "1.0.0", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "y18n": { + "version": "3.2.2", + "dev": true + }, + "yargs": { + "version": "7.1.2", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.1" + } + }, + "yargs-parser": { + "version": "5.0.1", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } } } }, @@ -21819,10 +21425,6 @@ "version": "3.0.0", "dev": true }, - "replace-ext": { - "version": "0.0.1", - "dev": true - }, "strip-ansi": { "version": "3.0.1", "dev": true, @@ -21890,6 +21492,22 @@ "version": "4.2.2", "dev": true }, + "crypto-browserify": { + "version": "3.11.0", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0" + } + }, "happn-logger": { "version": "0.0.2", "dev": true, @@ -21933,15 +21551,39 @@ "pbkdf2": "3.0.4" } }, - "jwt-simple": { - "version": "0.2.0", + "isarray": { + "version": "0.0.1", "dev": true }, - "lru-cache": { - "version": "4.1.5", + "jsonparse": { + "version": "0.0.5", + "dev": true + }, + "JSONStream": { + "version": "0.10.0", "dev": true, "requires": { - "pseudomap": "^1.0.2", + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" + } + }, + "jwt-simple": { + "version": "0.2.0", + "dev": true + }, + "log4js": { + "version": "0.6.38", + "dev": true, + "requires": { + "readable-stream": "~1.0.2", + "semver": "~4.3.3" + } + }, + "lru-cache": { + "version": "4.1.5", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, @@ -21949,6 +21591,13 @@ "version": "0.7.3", "dev": true }, + "pbkdf2": { + "version": "3.0.4", + "dev": true, + "requires": { + "create-hmac": "^1.1.2" + } + }, "pem": { "version": "1.11.2", "dev": true, @@ -21959,6 +21608,24 @@ "which": "^1.2.4" } }, + "readable-stream": { + "version": "1.0.34", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "semver": { + "version": "4.3.6", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "dev": true + }, "which": { "version": "1.3.1", "dev": true, @@ -21993,12 +21660,12 @@ "dev-null": "^0.1.1", "gulp": "^4.0.2", "happn": "^2.21.3", - "happn-cluster": "^12.0.12", + "happn-cluster": "^12.0.13", "happn-commons": "^1.1.0", "happn-commons-test": "^1.1.0", - "happn-db-provider-elasticsearch": "^1.0.12", + "happn-db-provider-elasticsearch": "^1.0.13", "happn-db-provider-loki": "^1.0.7", - "happn-db-provider-mongo": "^1.0.12", + "happn-db-provider-mongo": "^1.0.13", "happn-logger": "^2.1.1", "happn-password-hash-and-salt": "^1.2.0", "happn-primus-wrapper": "^8.0.2", @@ -22055,10 +21722,10 @@ "capture-stdout": "^1.0.0", "clone": "^1.0.2", "dface": "1.0.1", - "happn-3": "^13.1.4", + "happn-3": "^13.2.0", "happn-commons": "^1.1.0", "happn-commons-test": "^1.1.0", - "happn-db-provider-mongo": "^1.0.12", + "happn-db-provider-mongo": "^1.0.13", "happn-random-activity-generator": "0.2.1", "happn-swim": "^1.0.3", "happner-serial-mocha": "1.3.0", @@ -22096,6 +21763,21 @@ "async": { "version": "3.2.3" }, + "fs-extra": { + "version": "10.1.0", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, "lru-cache": { "version": "7.8.1" }, @@ -22104,6 +21786,9 @@ }, "sift": { "version": "15.1.3" + }, + "universalify": { + "version": "2.0.0" } } }, @@ -22145,6 +21830,10 @@ "why-is-node-running": "^2.2.0" }, "dependencies": { + "ansi-colors": { + "version": "4.1.1", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "dev": true, @@ -22160,6 +21849,10 @@ "picomatch": "^2.0.4" } }, + "argparse": { + "version": "2.0.1", + "dev": true + }, "assert": { "version": "2.0.0", "dev": true, @@ -22177,10 +21870,6 @@ "follow-redirects": "^1.14.7" } }, - "base64id": { - "version": "2.0.0", - "dev": true - }, "binary-extensions": { "version": "2.2.0", "dev": true @@ -22192,6 +21881,23 @@ "fill-range": "^7.0.1" } }, + "chalk": { + "version": "4.1.2", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "chokidar": { "version": "3.5.3", "dev": true, @@ -22226,28 +21932,19 @@ "version": "1.1.4", "dev": true }, - "cookie": { - "version": "0.4.2", - "dev": true - }, - "engine.io": { - "version": "6.2.0", + "debug": { + "version": "4.3.3", "dev": true, "requires": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.4.1", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" + "ms": "2.1.2" } }, - "engine.io-parser": { - "version": "5.0.4", + "diff": { + "version": "5.0.0", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", "dev": true }, "fill-range": { @@ -22257,13 +21954,37 @@ "to-regex-range": "^5.0.1" } }, + "find-up": { + "version": "5.0.0", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, "fsevents": { "version": "2.3.2", "dev": true, "optional": true }, - "get-caller-file": { - "version": "2.0.5", + "glob": { + "version": "7.2.0", + "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" + } + }, + "growl": { + "version": "1.10.5", + "dev": true + }, + "has-flag": { + "version": "4.0.0", "dev": true }, "is-binary-path": { @@ -22277,96 +21998,101 @@ "version": "7.0.0", "dev": true }, - "isbinaryfile": { - "version": "4.0.10", - "dev": true - }, - "karma": { - "version": "6.4.0", + "js-yaml": { + "version": "4.1.0", "dev": true, "requires": { - "@colors/colors": "1.5.0", - "body-parser": "^1.19.0", - "braces": "^3.0.2", - "chokidar": "^3.5.1", - "connect": "^3.7.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.1", - "glob": "^7.1.7", - "graceful-fs": "^4.2.6", - "http-proxy": "^1.18.1", - "isbinaryfile": "^4.0.8", - "lodash": "^4.17.21", - "log4js": "^6.4.1", - "mime": "^2.5.2", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.5", - "qjobs": "^1.2.0", - "range-parser": "^1.2.1", - "rimraf": "^3.0.2", - "socket.io": "^4.4.1", - "source-map": "^0.6.1", - "tmp": "^0.2.1", - "ua-parser-js": "^0.7.30", - "yargs": "^16.1.1" + "argparse": "^2.0.1" } }, - "log4js": { - "version": "6.6.0", + "locate-path": { + "version": "6.0.0", "dev": true, "requires": { - "date-format": "^4.0.11", - "debug": "^4.3.4", - "flatted": "^3.2.5", - "rfdc": "^1.3.0", - "streamroller": "^3.1.1" + "p-locate": "^5.0.0" } }, - "mime": { - "version": "2.6.0", - "dev": true - }, - "readdirp": { - "version": "3.6.0", + "log-symbols": { + "version": "4.1.0", "dev": true, "requires": { - "picomatch": "^2.2.1" + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" } }, - "socket.io": { - "version": "4.5.1", + "mocha": { + "version": "9.2.2", "dev": true, "requires": { - "accepts": "~1.3.4", - "base64id": "~2.0.0", - "debug": "~4.3.2", - "engine.io": "~6.2.0", - "socket.io-adapter": "~2.4.0", - "socket.io-parser": "~4.0.4" + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "minimatch": { + "version": "4.2.1", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.3", + "dev": true + } } }, - "socket.io-adapter": { - "version": "2.4.0", + "nanoid": { + "version": "3.3.1", "dev": true }, - "socket.io-parser": { - "version": "4.0.5", + "p-limit": { + "version": "3.1.0", "dev": true, "requires": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" + "yocto-queue": "^0.1.0" } }, - "source-map": { - "version": "0.6.1", - "dev": true + "p-locate": { + "version": "5.0.0", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } }, - "tmp": { - "version": "0.2.1", + "readdirp": { + "version": "3.6.0", "dev": true, "requires": { - "rimraf": "^3.0.0" + "picomatch": "^2.2.1" + } + }, + "supports-color": { + "version": "8.1.1", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } }, "to-regex-range": { @@ -22397,11 +22123,6 @@ "strip-ansi": "^6.0.0" } }, - "ws": { - "version": "8.2.3", - "dev": true, - "requires": {} - }, "y18n": { "version": "5.0.8", "dev": true @@ -22420,7 +22141,7 @@ } }, "yargs-parser": { - "version": "20.2.9", + "version": "20.2.4", "dev": true } } @@ -22432,13 +22153,13 @@ "bluebird": "2.10.2", "elasticsearch": "^13.2.0", "extract-values": "^0.1.2", - "happn-3": "^13.1.4", + "happn-3": "^13.2.0", "happn-commons": "^1.1.0", "happn-commons-test": "^1.1.0", "happn-logger": "^2.1.1", "json-from-schema": "1.10.0", "micromustache": "^5.2.0", - "redis-lru-cache": "^1.0.12", + "redis-lru-cache": "^1.0.13", "traverse": "0.6.6" }, "dependencies": { @@ -22460,7 +22181,7 @@ "requires": { "byline": "^5.0.0", "gulp": "^3.9.0", - "happn-3": "^13.1.4", + "happn-3": "^13.2.0", "happn-commons": "^1.1.0", "happn-commons-test": "^1.1.0", "mongodb": "^4.4.0", @@ -22700,18 +22421,6 @@ "capture-stdout": "^1.0.0", "happn-commons-test": "^1.1.0", "log4js": "^6.3.0" - }, - "dependencies": { - "log4js": { - "version": "6.6.0", - "requires": { - "date-format": "^4.0.11", - "debug": "^4.3.4", - "flatted": "^3.2.5", - "rfdc": "^1.3.0", - "streamroller": "^3.1.1" - } - } } }, "happn-nedb": { @@ -22739,6 +22448,10 @@ "keypress": "0.1.x" } }, + "keypress": { + "version": "0.1.0", + "dev": true + }, "request": { "version": "2.9.203", "dev": true @@ -22801,76 +22514,9 @@ "yeast": "~0.1.2" }, "dependencies": { - "browser-resolve": { - "version": "1.11.3", - "dev": true, - "requires": { - "resolve": "1.1.7" - } - }, - "browserify": { - "version": "16.2.3", - "dev": true, - "requires": { - "assert": "^1.4.0", - "browser-pack": "^6.0.1", - "browser-resolve": "^1.11.0", - "browserify-zlib": "~0.2.0", - "buffer": "^5.0.2", - "cached-path-relative": "^1.0.0", - "concat-stream": "^1.6.0", - "console-browserify": "^1.1.0", - "constants-browserify": "~1.0.0", - "crypto-browserify": "^3.0.0", - "defined": "^1.0.0", - "deps-sort": "^2.0.0", - "domain-browser": "^1.2.0", - "duplexer2": "~0.1.2", - "events": "^2.0.0", - "glob": "^7.1.0", - "has": "^1.0.0", - "htmlescape": "^1.1.0", - "https-browserify": "^1.0.0", - "inherits": "~2.0.1", - "insert-module-globals": "^7.0.0", - "JSONStream": "^1.0.3", - "labeled-stream-splicer": "^2.0.0", - "mkdirp": "^0.5.0", - "module-deps": "^6.0.0", - "os-browserify": "~0.3.0", - "parents": "^1.0.1", - "path-browserify": "~0.0.0", - "process": "~0.11.0", - "punycode": "^1.3.2", - "querystring-es3": "~0.2.0", - "read-only-stream": "^2.0.0", - "readable-stream": "^2.0.2", - "resolve": "^1.1.4", - "shasum": "^1.0.0", - "shell-quote": "^1.6.1", - "stream-browserify": "^2.0.0", - "stream-http": "^2.0.0", - "string_decoder": "^1.1.1", - "subarg": "^1.0.0", - "syntax-error": "^1.1.1", - "through2": "^2.0.0", - "timers-browserify": "^1.0.1", - "tty-browserify": "0.0.1", - "url": "~0.11.0", - "util": "~0.10.1", - "vm-browserify": "^1.0.0", - "xtend": "^4.0.0" - }, - "dependencies": { - "through2": { - "version": "2.0.5", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - } - } + "base64id": { + "version": "1.0.0", + "dev": true }, "chai": { "version": "4.1.2", @@ -22888,6 +22534,10 @@ "version": "2.15.1", "dev": true }, + "cookie": { + "version": "0.3.1", + "dev": true + }, "debug": { "version": "3.1.0", "dev": true, @@ -22899,6 +22549,18 @@ "version": "3.5.0", "dev": true }, + "engine.io": { + "version": "3.3.2", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~6.1.0" + } + }, "glob": { "version": "7.1.2", "dev": true, @@ -22911,22 +22573,14 @@ "path-is-absolute": "^1.0.0" } }, - "he": { - "version": "1.1.1", + "growl": { + "version": "1.10.5", "dev": true }, - "jsonparse": { - "version": "1.3.1", + "he": { + "version": "1.1.1", "dev": true }, - "JSONStream": { - "version": "1.3.5", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, "minimatch": { "version": "3.0.4", "dev": true, @@ -22966,25 +22620,6 @@ "version": "2.0.0", "dev": true }, - "punycode": { - "version": "1.4.1", - "dev": true - }, - "resolve": { - "version": "1.1.7", - "dev": true - }, - "stream-http": { - "version": "2.8.3", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, "supports-color": { "version": "5.4.0", "dev": true, @@ -23074,20 +22709,97 @@ "vinyl-source-stream": "^2.0.0" }, "dependencies": { - "crypto-browserify": { - "version": "3.12.0", + "base64id": { + "version": "1.0.0", + "dev": true + }, + "bluebird": { + "version": "3.7.2", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "dev": true + }, + "date-format": { + "version": "1.2.0", + "dev": true + }, + "debug": { + "version": "3.2.7", + "dev": true, "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" + "ms": "^2.1.1" + } + }, + "engine.io": { + "version": "3.2.1", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "base64id": "1.0.0", + "cookie": "0.3.1", + "debug": "~3.1.0", + "engine.io-parser": "~2.1.0", + "ws": "~3.3.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "dev": true + } + } + }, + "flatted": { + "version": "2.0.2", + "dev": true + }, + "isbinaryfile": { + "version": "3.0.3", + "dev": true, + "requires": { + "buffer-alloc": "^1.2.0" + } + }, + "karma": { + "version": "3.1.4", + "dev": true, + "requires": { + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^2.0.3", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "flatted": "^2.0.0", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^4.17.5", + "log4js": "^3.0.0", + "mime": "^2.3.1", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", + "socket.io": "2.1.1", + "source-map": "^0.6.1", + "tmp": "0.0.33", + "useragent": "2.3.0" } }, "karma-chrome-launcher": { @@ -23105,16 +22817,123 @@ "minimist": "1.2.0" } }, + "log4js": { + "version": "3.0.6", + "dev": true, + "requires": { + "circular-json": "^0.5.5", + "date-format": "^1.2.0", + "debug": "^3.1.0", + "rfdc": "^1.1.2", + "streamroller": "0.7.0" + } + }, "minimist": { "version": "1.2.0", "dev": true }, + "rimraf": { + "version": "2.7.1", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "dev": true + }, + "socket.io": { + "version": "2.1.1", + "dev": true, + "requires": { + "debug": "~3.1.0", + "engine.io": "~3.2.0", + "has-binary2": "~1.0.2", + "socket.io-adapter": "~1.1.0", + "socket.io-client": "2.1.1", + "socket.io-parser": "~3.2.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "dev": true + } + } + }, + "socket.io-adapter": { + "version": "1.1.2", + "dev": true + }, + "socket.io-parser": { + "version": "3.2.0", + "dev": true, + "requires": { + "component-emitter": "1.2.1", + "debug": "~3.1.0", + "isarray": "2.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "dev": true + } + } + }, + "source-map": { + "version": "0.6.1", + "dev": true + }, + "streamroller": { + "version": "0.7.0", + "dev": true, + "requires": { + "date-format": "^1.2.0", + "debug": "^3.1.0", + "mkdirp": "^0.5.1", + "readable-stream": "^2.3.0" + } + }, + "tmp": { + "version": "0.0.33", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "ultron": { + "version": "1.1.1", + "dev": true + }, "which": { "version": "1.3.1", "dev": true, "requires": { "isexe": "^2.0.0" } + }, + "ws": { + "version": "3.3.3", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } } } }, @@ -23163,6 +22982,26 @@ "version": "4.2.2", "dev": true }, + "core-util-is": { + "version": "1.0.2", + "dev": true + }, + "crypto-browserify": { + "version": "3.11.0", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0" + } + }, "form-data": { "version": "2.1.4", "dev": true, @@ -23172,16 +23011,6 @@ "mime-types": "^2.1.12" } }, - "fs-extra": { - "version": "0.24.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" - } - }, "glob": { "version": "5.0.15", "dev": true, @@ -23291,6 +23120,10 @@ "sshpk": "^1.7.0" } }, + "isarray": { + "version": "0.0.1", + "dev": true + }, "json-stable-stringify": { "version": "1.0.1", "dev": true, @@ -23298,11 +23131,16 @@ "jsonify": "~0.0.0" } }, - "jsonfile": { - "version": "2.4.0", + "jsonparse": { + "version": "0.0.5", + "dev": true + }, + "JSONStream": { + "version": "0.10.0", "dev": true, "requires": { - "graceful-fs": "^4.1.6" + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" } }, "jsprim": { @@ -23325,6 +23163,14 @@ "version": "0.2.0", "dev": true }, + "log4js": { + "version": "0.6.38", + "dev": true, + "requires": { + "readable-stream": "~1.0.2", + "semver": "~4.3.3" + } + }, "lru-cache": { "version": "4.1.5", "dev": true, @@ -23345,6 +23191,13 @@ "version": "0.8.2", "dev": true }, + "pbkdf2": { + "version": "3.0.4", + "dev": true, + "requires": { + "create-hmac": "^1.1.2" + } + }, "performance-now": { "version": "0.2.0", "dev": true @@ -23357,6 +23210,16 @@ "version": "6.4.1", "dev": true }, + "readable-stream": { + "version": "1.0.34", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, "request": { "version": "2.81.0", "dev": true, @@ -23385,26 +23248,13 @@ "uuid": "^3.0.0" } }, - "rimraf": { - "version": "2.7.1", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } + "semver": { + "version": "4.3.6", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "dev": true }, "tough-cookie": { "version": "2.3.4", @@ -23413,6 +23263,21 @@ "punycode": "^1.4.1" } }, + "verror": { + "version": "1.10.0", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "dev": true + } + } + }, "ws": { "version": "1.1.5", "dev": true, @@ -23435,14 +23300,14 @@ "change-case": "2.3.0", "commander": "2.9.0", "diskspace": "0.1.7", - "happn-3": "^13.1.4", + "happn-3": "^13.2.0", "happn-commons": "^1.1.0", "happn-commons-test": "^1.1.0", - "happn-db-provider-mongo": "^1.0.12", + "happn-db-provider-mongo": "^1.0.13", "happn-logger": "^2.1.1", "happn-sillyname": "^0.1.1", "happner": "1.33.4", - "happner-client": "^12.2.8", + "happner-client": "^12.3.0", "happner-semver": "^1.0.1", "happner-test-modules": "^1.0.2", "homedir": "0.6.0", @@ -23559,10 +23424,10 @@ "happner-client": { "version": "file:packages/happner-client", "requires": { - "happn-3": "^13.1.4", + "happn-3": "^13.2.0", "happn-commons": "^1.1.0", "happn-commons-test": "^1.1.0", - "happner-2": "^12.1.9", + "happner-2": "^12.2.0", "happner-semver": "^1.0.1" } }, @@ -23571,11 +23436,11 @@ "requires": { "array-unique": "^0.3.2", "bluebird": "^3.5.0", - "happn-cluster": "^12.0.12", + "happn-cluster": "^12.0.13", "happn-commons": "^1.1.0", "happn-commons-test": "^1.1.0", - "happner-2": "^12.1.9", - "happner-client": "^12.2.8", + "happner-2": "^12.2.0", + "happner-client": "^12.3.0", "hashring": "^3.2.0", "http-proxy": "1.18.1", "intercept-stdout": "^0.1.2", @@ -23591,7 +23456,14 @@ } } }, - "happner-hyperid": { + "happner-demos": { + "version": "file:packages/demos", + "requires": { + "happn-commons-test": "^1.1.0", + "happner-cluster": "^12.2.0" + } + }, + "happner-hyperid": { "version": "2.0.0", "requires": { "uuid": "2.0.2" @@ -23630,25 +23502,6 @@ "version": "3.7.2", "dev": true }, - "commander": { - "version": "2.3.0", - "dev": true - }, - "debug": { - "version": "2.2.0", - "dev": true, - "requires": { - "ms": "0.7.1" - } - }, - "diff": { - "version": "1.4.0", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.2", - "dev": true - }, "fs-extra": { "version": "1.0.0", "dev": true, @@ -23657,74 +23510,6 @@ "jsonfile": "^2.1.0", "klaw": "^1.0.0" } - }, - "glob": { - "version": "3.2.11", - "dev": true, - "requires": { - "inherits": "2", - "minimatch": "0.3" - } - }, - "growl": { - "version": "1.9.2", - "dev": true - }, - "jsonfile": { - "version": "2.4.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "lru-cache": { - "version": "2.7.3", - "dev": true - }, - "minimatch": { - "version": "0.3.0", - "dev": true, - "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" - } - }, - "mkdirp": { - "version": "0.5.1", - "dev": true, - "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "dev": true - } - } - }, - "mocha": { - "version": "2.5.3", - "dev": true, - "requires": { - "commander": "2.3.0", - "debug": "2.2.0", - "diff": "1.4.0", - "escape-string-regexp": "1.0.2", - "glob": "3.2.11", - "growl": "1.9.2", - "jade": "0.26.3", - "mkdirp": "0.5.1", - "supports-color": "1.2.0", - "to-iso-string": "0.0.2" - } - }, - "ms": { - "version": "0.7.1", - "dev": true - }, - "supports-color": { - "version": "1.2.0", - "dev": true } } }, @@ -23756,21 +23541,6 @@ "jsonfile": "^2.1.0", "klaw": "^1.0.0" } - }, - "jsonfile": { - "version": "2.4.0", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "keypress": { - "version": "0.2.1", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "dev": true } } }, @@ -23821,12 +23591,6 @@ "dev": true, "requires": { "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "dev": true - } } }, "has-cors": { @@ -23903,9 +23667,6 @@ "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } - }, - "safe-buffer": { - "version": "5.2.1" } } }, @@ -24043,6 +23804,10 @@ "sshpk": "^1.7.0" }, "dependencies": { + "core-util-is": { + "version": "1.0.2", + "dev": true + }, "jsprim": { "version": "1.4.2", "dev": true, @@ -24052,6 +23817,15 @@ "json-schema": "0.4.0", "verror": "1.10.0" } + }, + "verror": { + "version": "1.10.0", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } } } }, @@ -24136,20 +23910,6 @@ "through2": "^2.0.0", "undeclared-identifiers": "^1.1.2", "xtend": "^4.0.0" - }, - "dependencies": { - "jsonparse": { - "version": "1.3.1", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - } } }, "int64-buffer": { @@ -24182,10 +23942,12 @@ "dev": true }, "ip": { - "version": "1.1.8" + "version": "1.1.8", + "dev": true }, "ip-regex": { - "version": "2.1.0" + "version": "4.3.0", + "dev": true }, "is-absolute": { "version": "1.0.0", @@ -24253,7 +24015,7 @@ "peer": true }, "is-core-module": { - "version": "2.9.0", + "version": "2.10.0", "dev": true, "requires": { "has": "^1.0.3" @@ -24318,12 +24080,6 @@ "dev": true, "requires": { "ip-regex": "^4.0.0" - }, - "dependencies": { - "ip-regex": { - "version": "4.3.0", - "dev": true - } } }, "is-lower-case": { @@ -24431,10 +24187,6 @@ "unc-path-regex": "^0.1.2" } }, - "is-unicode-supported": { - "version": "0.1.0", - "dev": true - }, "is-upper-case": { "version": "1.1.2", "requires": { @@ -24470,18 +24222,20 @@ "deep-is": "^0.1.3", "ip-regex": "^2.1.0", "is-url": "^1.2.2" + }, + "dependencies": { + "ip-regex": { + "version": "2.1.0" + } } }, "isarray": { - "version": "1.0.0", + "version": "2.0.1", "dev": true }, "isbinaryfile": { - "version": "3.0.3", - "dev": true, - "requires": { - "buffer-alloc": "^1.2.0" - } + "version": "4.0.10", + "dev": true }, "isexe": { "version": "2.0.0" @@ -24495,7 +24249,7 @@ "dev": true }, "istanbul-lib-coverage": { - "version": "3.2.0", + "version": "2.0.5", "dev": true }, "istanbul-lib-hook": { @@ -24516,6 +24270,10 @@ "semver": "^6.3.0" }, "dependencies": { + "istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true + }, "semver": { "version": "6.3.0", "dev": true @@ -24534,6 +24292,10 @@ "uuid": "^8.3.2" }, "dependencies": { + "istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true + }, "uuid": { "version": "8.3.2", "dev": true @@ -24541,23 +24303,19 @@ } }, "istanbul-lib-report": { - "version": "3.0.0", + "version": "2.0.8", "dev": true, "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" }, "dependencies": { - "has-flag": { - "version": "4.0.0", - "dev": true - }, "supports-color": { - "version": "7.2.0", + "version": "6.1.0", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" } } } @@ -24571,6 +24329,10 @@ "source-map": "^0.6.1" }, "dependencies": { + "istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true + }, "source-map": { "version": "0.6.1", "dev": true @@ -24578,11 +24340,10 @@ } }, "istanbul-reports": { - "version": "3.1.4", + "version": "2.2.7", "dev": true, "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "html-escaper": "^2.0.0" } }, "jade": { @@ -24682,10 +24443,10 @@ } }, "jsonfile": { - "version": "6.1.0", + "version": "2.4.0", + "dev": true, "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" + "graceful-fs": "^4.1.6" } }, "jsonify": { @@ -24696,14 +24457,14 @@ "version": "1.1.5" }, "jsonparse": { - "version": "0.0.5", + "version": "1.3.1", "dev": true }, "JSONStream": { - "version": "0.10.0", + "version": "1.3.5", "dev": true, "requires": { - "jsonparse": "0.0.5", + "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" } }, @@ -24715,6 +24476,21 @@ "extsprintf": "1.3.0", "json-schema": "0.4.0", "verror": "1.10.0" + }, + "dependencies": { + "core-util-is": { + "version": "1.0.2", + "dev": true + }, + "verror": { + "version": "1.10.0", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + } } }, "just-debounce": { @@ -24729,93 +24505,165 @@ "version": "0.5.6" }, "karma": { - "version": "3.1.4", + "version": "6.4.0", "dev": true, "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "chokidar": "^2.0.3", - "colors": "^1.1.0", - "combine-lists": "^1.0.0", - "connect": "^3.6.0", - "core-js": "^2.2.0", + "@colors/colors": "1.5.0", + "body-parser": "^1.19.0", + "braces": "^3.0.2", + "chokidar": "^3.5.1", + "connect": "^3.7.0", "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", - "flatted": "^2.0.0", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^4.17.5", - "log4js": "^3.0.0", - "mime": "^2.3.1", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", - "socket.io": "2.1.1", + "dom-serialize": "^2.2.1", + "glob": "^7.1.7", + "graceful-fs": "^4.2.6", + "http-proxy": "^1.18.1", + "isbinaryfile": "^4.0.8", + "lodash": "^4.17.21", + "log4js": "^6.4.1", + "mime": "^2.5.2", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.5", + "qjobs": "^1.2.0", + "range-parser": "^1.2.1", + "rimraf": "^3.0.2", + "socket.io": "^4.4.1", "source-map": "^0.6.1", - "tmp": "0.0.33", - "useragent": "2.3.0" + "tmp": "^0.2.1", + "ua-parser-js": "^0.7.30", + "yargs": "^16.1.1" }, "dependencies": { - "bluebird": { - "version": "3.7.2", - "dev": true + "ansi-styles": { + "version": "4.3.0", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } }, - "date-format": { - "version": "1.2.0", + "anymatch": { + "version": "3.1.2", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", "dev": true }, - "debug": { - "version": "3.2.7", + "braces": { + "version": "3.0.2", "dev": true, "requires": { - "ms": "^2.1.1" + "fill-range": "^7.0.1" } }, - "flatted": { - "version": "2.0.2", + "chokidar": { + "version": "3.5.3", + "dev": true, + "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" + } + }, + "cliui": { + "version": "7.0.4", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", "dev": true }, - "log4js": { - "version": "3.0.6", + "fill-range": { + "version": "7.0.1", "dev": true, "requires": { - "circular-json": "^0.5.5", - "date-format": "^1.2.0", - "debug": "^3.1.0", - "rfdc": "^1.1.2", - "streamroller": "0.7.0" + "to-regex-range": "^5.0.1" } }, - "mime": { - "version": "2.6.0", + "fsevents": { + "version": "2.3.2", + "dev": true, + "optional": true + }, + "is-binary-path": { + "version": "2.1.0", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", "dev": true }, - "rimraf": { - "version": "2.7.1", + "readdirp": { + "version": "3.6.0", "dev": true, "requires": { - "glob": "^7.1.3" + "picomatch": "^2.2.1" } }, "source-map": { "version": "0.6.1", "dev": true }, - "streamroller": { - "version": "0.7.0", + "to-regex-range": { + "version": "5.0.1", "dev": true, "requires": { - "date-format": "^1.2.0", - "debug": "^3.1.0", - "mkdirp": "^0.5.1", - "readable-stream": "^2.3.0" + "is-number": "^7.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "dev": true, + "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.9", + "dev": true } } }, @@ -24850,6 +24698,51 @@ "istanbul-lib-source-maps": "^4.0.1", "istanbul-reports": "^3.0.5", "minimatch": "^3.0.4" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true + }, + "istanbul-lib-report": { + "version": "3.0.0", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-reports": { + "version": "3.1.5", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "make-dir": { + "version": "3.1.0", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "karma-mocha": { @@ -24885,7 +24778,7 @@ "version": "1.0.3" }, "keypress": { - "version": "0.1.0", + "version": "0.2.1", "dev": true }, "kind-of": { @@ -24995,22 +24888,18 @@ "dev": true }, "load-json-file": { - "version": "1.1.0", + "version": "4.0.0", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" }, "dependencies": { - "strip-bom": { - "version": "2.0.0", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } + "pify": { + "version": "3.0.0", + "dev": true } } }, @@ -25021,12 +24910,10 @@ } }, "locate-path": { - "version": "2.0.0", + "version": "5.0.0", "dev": true, - "peer": true, "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "^4.1.0" } }, "lodash": { @@ -25161,35 +25048,13 @@ } }, "log4js": { - "version": "0.6.38", - "dev": true, + "version": "6.6.1", "requires": { - "readable-stream": "~1.0.2", - "semver": "~4.3.3" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "semver": { - "version": "4.3.6", - "dev": true - }, - "string_decoder": { - "version": "0.10.31", - "dev": true - } + "date-format": "^4.0.13", + "debug": "^4.3.4", + "flatted": "^3.2.6", + "rfdc": "^1.3.0", + "streamroller": "^3.1.2" } }, "lokijs": { @@ -25226,14 +25091,15 @@ } }, "make-dir": { - "version": "3.1.0", + "version": "2.1.0", "dev": true, "requires": { - "semver": "^6.0.0" + "pify": "^4.0.1", + "semver": "^5.6.0" }, "dependencies": { "semver": { - "version": "6.3.0", + "version": "5.7.1", "dev": true } } @@ -25387,7 +25253,8 @@ "version": "0.1.2" }, "mime": { - "version": "1.6.0" + "version": "2.6.0", + "dev": true }, "mime-db": { "version": "1.52.0" @@ -25443,312 +25310,80 @@ "minimist": "^1.2.6" } }, - "mkdirp-classic": { - "version": "0.5.3", - "dev": true - }, "mocha": { - "version": "9.2.2", + "version": "2.5.3", "dev": true, "requires": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.3", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "4.2.1", - "ms": "2.1.3", - "nanoid": "3.3.1", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "workerpool": "6.2.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.11", + "growl": "1.9.2", + "jade": "0.26.3", + "mkdirp": "0.5.1", + "supports-color": "1.2.0", + "to-iso-string": "0.0.2" }, "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.2", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "2.0.1", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "dev": true - }, - "braces": { - "version": "3.0.2", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "supports-color": { - "version": "7.2.0", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "chokidar": { - "version": "3.5.3", - "dev": true, - "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" - } - }, - "cliui": { - "version": "7.0.4", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "dev": true - }, - "debug": { - "version": "4.3.3", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "dev": true - } - } - }, - "escape-string-regexp": { - "version": "4.0.0", - "dev": true - }, - "fill-range": { - "version": "7.0.1", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "fsevents": { - "version": "2.3.2", - "dev": true, - "optional": true - }, - "get-caller-file": { - "version": "2.0.5", - "dev": true - }, - "glob": { - "version": "7.2.0", - "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" - }, - "dependencies": { - "minimatch": { - "version": "3.1.2", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "has-flag": { - "version": "4.0.0", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "locate-path": { - "version": "6.0.0", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "log-symbols": { - "version": "4.1.0", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "minimatch": { - "version": "4.2.1", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "ms": { - "version": "2.1.3", - "dev": true - }, - "nanoid": { - "version": "3.3.1", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "dev": true - }, - "readdirp": { - "version": "3.6.0", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } + "commander": { + "version": "2.3.0", + "dev": true }, - "supports-color": { - "version": "8.1.1", + "debug": { + "version": "2.2.0", "dev": true, "requires": { - "has-flag": "^4.0.0" + "ms": "0.7.1" } }, - "to-regex-range": { - "version": "5.0.1", + "escape-string-regexp": { + "version": "1.0.2", + "dev": true + }, + "glob": { + "version": "3.2.11", "dev": true, "requires": { - "is-number": "^7.0.0" + "inherits": "2", + "minimatch": "0.3" } }, - "wrap-ansi": { - "version": "7.0.0", + "lru-cache": { + "version": "2.7.3", + "dev": true + }, + "minimatch": { + "version": "0.3.0", "dev": true, "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "lru-cache": "2", + "sigmund": "~1.0.0" } }, - "y18n": { - "version": "5.0.8", + "minimist": { + "version": "0.0.8", "dev": true }, - "yargs": { - "version": "16.2.0", + "mkdirp": { + "version": "0.5.1", "dev": true, "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" + "minimist": "0.0.8" } }, - "yargs-parser": { - "version": "20.2.4", + "ms": { + "version": "0.7.1", + "dev": true + }, + "supports-color": { + "version": "1.2.0", "dev": true } } }, "mock-fs": { - "version": "5.1.2", + "version": "5.1.4", "dev": true }, "module-deps": { @@ -25772,16 +25407,11 @@ "xtend": "^4.0.0" }, "dependencies": { - "jsonparse": { - "version": "1.3.1", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", + "browser-resolve": { + "version": "2.0.0", "dev": true, "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" + "resolve": "^1.17.0" } } } @@ -25791,17 +25421,17 @@ "dev": true }, "mongodb": { - "version": "4.8.0", + "version": "4.9.0", "requires": { - "bson": "^4.6.5", - "denque": "^2.0.1", - "mongodb-connection-string-url": "^2.5.2", + "bson": "^4.7.0", + "denque": "^2.1.0", + "mongodb-connection-string-url": "^2.5.3", "saslprep": "^1.0.3", - "socks": "^2.6.2" + "socks": "^2.7.0" } }, "mongodb-connection-string-url": { - "version": "2.5.2", + "version": "2.5.3", "requires": { "@types/whatwg-url": "^8.2.1", "whatwg-url": "^11.0.0" @@ -25818,6 +25448,12 @@ "ieee754": "^1.1.8", "int64-buffer": "^0.1.9", "isarray": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "dev": true + } } }, "multipipe": { @@ -25863,8 +25499,7 @@ "dev": true }, "nanoid": { - "version": "2.1.11", - "dev": true + "version": "3.1.32" }, "nanomatch": { "version": "1.2.13", @@ -26076,16 +25711,31 @@ "version": "1.1.4", "dev": true }, - "find-up": { - "version": "4.1.0", + "convert-source-map": { + "version": "1.8.0", "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "safe-buffer": "~5.1.1" } }, - "get-caller-file": { - "version": "2.0.5", + "decamelize": { + "version": "1.2.0", + "dev": true + }, + "foreground-child": { + "version": "2.0.0", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + } + }, + "has-flag": { + "version": "4.0.0", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", "dev": true }, "istanbul-lib-instrument": { @@ -26098,50 +25748,57 @@ "semver": "^6.3.0" } }, - "locate-path": { - "version": "5.0.0", + "istanbul-lib-report": { + "version": "3.0.0", "dev": true, "requires": { - "p-locate": "^4.1.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" } }, - "p-limit": { - "version": "2.3.0", + "istanbul-reports": { + "version": "3.1.5", "dev": true, "requires": { - "p-try": "^2.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" } }, - "p-locate": { - "version": "4.1.0", + "make-dir": { + "version": "3.1.0", "dev": true, "requires": { - "p-limit": "^2.2.0" + "semver": "^6.0.0" } }, - "p-try": { - "version": "2.2.0", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "dev": true - }, "resolve-from": { "version": "5.0.0", "dev": true }, + "safe-buffer": { + "version": "5.1.2", + "dev": true + }, "semver": { "version": "6.3.0", "dev": true }, - "which-module": { - "version": "2.0.0", - "dev": true + "supports-color": { + "version": "7.2.0", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } }, "wrap-ansi": { "version": "6.2.0", @@ -26152,10 +25809,6 @@ "strip-ansi": "^6.0.0" } }, - "y18n": { - "version": "4.0.3", - "dev": true - }, "yargs": { "version": "15.4.1", "dev": true, @@ -26195,10 +25848,6 @@ "version": "4.1.1", "dev": true }, - "object-component": { - "version": "0.0.3", - "dev": true - }, "object-copy": { "version": "0.1.0", "dev": true, @@ -26277,12 +25926,12 @@ } }, "object.assign": { - "version": "4.1.2", + "version": "4.1.4", "dev": true, "requires": { - "call-bind": "^1.0.0", - "define-properties": "^1.1.3", - "has-symbols": "^1.0.1", + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, @@ -26356,6 +26005,10 @@ "minimist": { "version": "0.0.10", "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "dev": true } } }, @@ -26400,19 +26053,17 @@ "version": "1.0.2" }, "p-limit": { - "version": "1.3.0", + "version": "2.3.0", "dev": true, - "peer": true, "requires": { - "p-try": "^1.0.0" + "p-try": "^2.0.0" } }, "p-locate": { - "version": "2.0.0", + "version": "4.1.0", "dev": true, - "peer": true, "requires": { - "p-limit": "^1.1.0" + "p-limit": "^2.2.0" } }, "p-map": { @@ -26423,9 +26074,8 @@ } }, "p-try": { - "version": "1.0.0", - "dev": true, - "peer": true + "version": "2.2.0", + "dev": true }, "package-hash": { "version": "4.0.0", @@ -26481,10 +26131,11 @@ } }, "parse-json": { - "version": "2.2.0", + "version": "4.0.0", "dev": true, "requires": { - "error-ex": "^1.2.0" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, "parse-mongo-url": { @@ -26541,7 +26192,7 @@ "dev": true }, "path-exists": { - "version": "3.0.0", + "version": "4.0.0", "dev": true }, "path-is-absolute": { @@ -26584,12 +26235,16 @@ } }, "path-type": { - "version": "1.1.0", + "version": "3.0.0", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "dev": true + } } }, "pathval": { @@ -26597,9 +26252,13 @@ "dev": true }, "pbkdf2": { - "version": "3.0.4", + "version": "3.1.2", "requires": { - "create-hmac": "^1.1.2" + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" } }, "pem": { @@ -26613,75 +26272,36 @@ }, "performance-now": { "version": "2.1.0", - "dev": true - }, - "picocolors": { - "version": "1.0.0", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "dev": true - }, - "pify": { - "version": "2.3.0", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "4.2.0", - "dev": true, - "requires": { - "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "dev": true - } + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "dev": true + }, + "pify": { + "version": "4.0.1", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "dev": true, + "requires": { + "find-up": "^4.0.0" } }, "plugin-error": { @@ -26814,9 +26434,6 @@ "kuler": { "version": "2.0.0" }, - "nanoid": { - "version": "3.1.32" - }, "setheader": { "version": "1.0.2", "requires": { @@ -26969,12 +26586,18 @@ "version": "1.2.1" }, "raw-body": { - "version": "2.4.3", + "version": "1.1.7", "requires": { - "bytes": "3.1.2", - "http-errors": "1.8.1", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "1", + "string_decoder": "0.10" + }, + "dependencies": { + "bytes": { + "version": "1.0.0" + }, + "string_decoder": { + "version": "0.10.31" + } } }, "read-only-stream": { @@ -26985,36 +26608,47 @@ } }, "read-pkg": { - "version": "1.1.0", + "version": "3.0.0", "dev": true, "requires": { - "load-json-file": "^1.0.0", + "load-json-file": "^4.0.0", "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "path-type": "^3.0.0" } }, "read-pkg-up": { - "version": "1.0.1", + "version": "4.0.0", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" }, "dependencies": { "find-up": { - "version": "1.1.2", + "version": "3.0.0", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "locate-path": "^3.0.0" } }, - "path-exists": { - "version": "2.1.0", + "locate-path": { + "version": "3.0.0", "dev": true, "requires": { - "pinkie-promise": "^2.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" } + }, + "p-locate": { + "version": "3.0.0", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "dev": true } } }, @@ -27029,6 +26663,23 @@ "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "readdirp": { @@ -27065,13 +26716,13 @@ } }, "redis": { - "version": "4.2.0", + "version": "4.3.0", "requires": { "@redis/bloom": "1.0.2", - "@redis/client": "1.2.0", + "@redis/client": "1.3.0", "@redis/graph": "1.0.1", "@redis/json": "1.0.3", - "@redis/search": "1.0.6", + "@redis/search": "1.1.0", "@redis/time-series": "1.0.3" } }, @@ -27093,7 +26744,7 @@ "clone": "^2.1.2", "happn-commons": "^1.1.0", "happn-commons-test": "^1.1.0", - "happn-db-provider-mongo": "^1.0.12", + "happn-db-provider-mongo": "^1.0.13", "node-redis-pubsub": "^1.0.3", "redis": "^4.0.3" } @@ -27192,7 +26843,7 @@ "version": "0.1.4" }, "replace-ext": { - "version": "1.0.1", + "version": "0.0.1", "dev": true }, "replace-homedir": { @@ -27245,7 +26896,7 @@ "dev": true }, "require-main-filename": { - "version": "1.0.1", + "version": "2.0.0", "dev": true }, "require-self": { @@ -27359,7 +27010,7 @@ "dev": true }, "safe-buffer": { - "version": "5.1.2" + "version": "5.2.1" }, "safe-json-parse": { "version": "1.0.1" @@ -27441,6 +27092,9 @@ "toidentifier": "1.0.1" } }, + "mime": { + "version": "1.6.0" + }, "ms": { "version": "2.1.3" }, @@ -27558,6 +27212,12 @@ "dev": true, "requires": { "nanoid": "^2.1.0" + }, + "dependencies": { + "nanoid": { + "version": "2.1.11", + "dev": true + } } }, "should": { @@ -27658,6 +27318,10 @@ "supports-color": "^7.2.0" }, "dependencies": { + "diff": { + "version": "5.1.0", + "dev": true + }, "has-flag": { "version": "4.0.0", "dev": true @@ -27835,156 +27499,32 @@ } }, "socket.io": { - "version": "2.1.1", + "version": "4.5.1", "dev": true, "requires": { - "debug": "~3.1.0", - "engine.io": "~3.2.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.1.1", - "socket.io-parser": "~3.2.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "engine.io": { - "version": "3.2.1", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~3.3.1" - } - }, - "ms": { - "version": "2.0.0", - "dev": true - }, - "ultron": { - "version": "1.1.1", - "dev": true - }, - "ws": { - "version": "3.3.3", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - } + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.2.0", + "socket.io-adapter": "~2.4.0", + "socket.io-parser": "~4.0.4" } }, "socket.io-adapter": { - "version": "1.1.2", + "version": "2.4.0", "dev": true }, - "socket.io-client": { - "version": "2.1.1", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.2.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.2.0", - "to-array": "0.1.4" - }, - "dependencies": { - "component-emitter": { - "version": "1.2.1", - "dev": true - }, - "debug": { - "version": "3.1.0", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "engine.io-client": { - "version": "3.2.1", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~3.3.1", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - } - }, - "ms": { - "version": "2.0.0", - "dev": true - }, - "ultron": { - "version": "1.1.1", - "dev": true - }, - "ws": { - "version": "3.3.3", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "dev": true - } - } - }, "socket.io-parser": { - "version": "3.2.0", + "version": "4.0.5", "dev": true, "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" }, "dependencies": { "component-emitter": { - "version": "1.2.1", - "dev": true - }, - "debug": { - "version": "3.1.0", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "2.0.1", - "dev": true - }, - "ms": { - "version": "2.0.0", + "version": "1.3.0", "dev": true } } @@ -28026,10 +27566,15 @@ } }, "socks": { - "version": "2.6.2", + "version": "2.7.0", "requires": { - "ip": "^1.1.5", + "ip": "^2.0.0", "smart-buffer": "^4.2.0" + }, + "dependencies": { + "ip": { + "version": "2.0.0" + } } }, "source-map": { @@ -28084,6 +27629,27 @@ "rimraf": "^3.0.0", "signal-exit": "^3.0.2", "which": "^2.0.1" + }, + "dependencies": { + "foreground-child": { + "version": "2.0.0", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + } + }, + "make-dir": { + "version": "3.1.0", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "dev": true + } } }, "spdx-correct": { @@ -28107,7 +27673,7 @@ } }, "spdx-license-ids": { - "version": "3.0.11", + "version": "3.0.12", "dev": true }, "split-string": { @@ -28272,24 +27838,14 @@ "dev": true }, "stream-http": { - "version": "3.2.0", + "version": "2.8.3", "dev": true, "requires": { "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "xtend": "^4.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" } }, "stream-shift": { @@ -28305,17 +27861,33 @@ } }, "streamroller": { - "version": "3.1.1", + "version": "3.1.2", "requires": { - "date-format": "^4.0.10", + "date-format": "^4.0.13", "debug": "^4.3.4", - "fs-extra": "^10.1.0" + "fs-extra": "^8.1.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "jsonfile": { + "version": "4.0.0", + "requires": { + "graceful-fs": "^4.1.6" + } + } } }, "string_decoder": { - "version": "1.1.1", + "version": "1.3.0", "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" } }, "string-template": { @@ -28444,7 +28016,7 @@ } }, "terser": { - "version": "5.14.2", + "version": "5.15.0", "requires": { "@jridgewell/source-map": "^0.3.2", "acorn": "^8.5.0", @@ -28453,17 +28025,18 @@ }, "dependencies": { "acorn": { - "version": "8.7.1" + "version": "8.8.0" } } }, "test-exclude": { - "version": "6.0.0", + "version": "5.2.3", "dev": true, "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" } }, "text-hex": { @@ -28519,10 +28092,10 @@ } }, "tmp": { - "version": "0.0.33", + "version": "0.2.1", "dev": true, "requires": { - "os-tmpdir": "~1.0.2" + "rimraf": "^3.0.0" } }, "to-absolute-glob": { @@ -28533,10 +28106,6 @@ "is-negated-glob": "^1.0.0" } }, - "to-array": { - "version": "0.1.4", - "dev": true - }, "to-arraybuffer": { "version": "1.0.1", "dev": true @@ -28742,6 +28311,10 @@ "wordwrap": "0.0.2" } }, + "decamelize": { + "version": "1.2.0", + "dev": true + }, "wordwrap": { "version": "0.0.2", "dev": true @@ -28863,7 +28436,7 @@ } }, "universalify": { - "version": "2.0.0" + "version": "0.1.2" }, "unpipe": { "version": "1.0.0" @@ -28897,6 +28470,10 @@ "has-values": { "version": "0.1.4", "dev": true + }, + "isarray": { + "version": "1.0.0", + "dev": true } } }, @@ -28905,7 +28482,7 @@ "dev": true }, "update-browserslist-db": { - "version": "1.0.4", + "version": "1.0.5", "dev": true, "requires": { "escalade": "^3.1.1", @@ -28980,6 +28557,13 @@ "yallist": "^2.1.2" } }, + "tmp": { + "version": "0.0.33", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "yallist": { "version": "2.1.2", "dev": true @@ -29025,6 +28609,17 @@ "source-map": "^0.7.3" }, "dependencies": { + "convert-source-map": { + "version": "1.8.0", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "dev": true + }, "source-map": { "version": "0.7.4", "dev": true @@ -29054,7 +28649,7 @@ "version": "1.1.2" }, "verror": { - "version": "1.10.0", + "version": "1.10.1", "dev": true, "requires": { "assert-plus": "^1.0.0", @@ -29078,6 +28673,12 @@ "cloneable-readable": "^1.0.0", "remove-trailing-separator": "^1.0.1", "replace-ext": "^1.0.0" + }, + "dependencies": { + "replace-ext": { + "version": "1.0.1", + "dev": true + } } }, "vinyl-buffer": { @@ -29132,12 +28733,23 @@ "vinyl": "^2.0.0" }, "dependencies": { + "convert-source-map": { + "version": "1.8.0", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, "normalize-path": { "version": "2.1.1", "dev": true, "requires": { "remove-trailing-separator": "^1.0.1" } + }, + "safe-buffer": { + "version": "5.1.2", + "dev": true } } }, @@ -29202,7 +28814,7 @@ } }, "which-module": { - "version": "1.0.0", + "version": "2.0.0", "dev": true }, "why-is-node-running": { @@ -29222,7 +28834,7 @@ "dev": true }, "wordwrap": { - "version": "0.0.3", + "version": "1.0.0", "dev": true }, "workerpool": { @@ -29230,38 +28842,40 @@ "dev": true }, "wrap-ansi": { - "version": "2.1.0", + "version": "5.1.0", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", + "version": "4.1.1", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", "dev": true }, "is-fullwidth-code-point": { - "version": "1.0.0", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "version": "2.0.0", + "dev": true }, "string-width": { - "version": "1.0.2", + "version": "3.1.0", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "strip-ansi": { - "version": "3.0.1", + "version": "5.2.0", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^4.1.0" } } } @@ -29306,7 +28920,7 @@ "dev": true }, "y18n": { - "version": "3.2.2", + "version": "4.0.3", "dev": true }, "yallist": { @@ -29317,59 +28931,110 @@ "dev": true }, "yargs": { - "version": "7.1.2", + "version": "14.2.3", "dev": true, "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", + "cliui": "^5.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.1" + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^15.0.1" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", + "version": "4.1.1", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", "dev": true }, + "find-up": { + "version": "3.0.0", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, "is-fullwidth-code-point": { - "version": "1.0.0", + "version": "2.0.0", + "dev": true + }, + "locate-path": { + "version": "3.0.0", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "dev": true, + "requires": { + "p-limit": "^2.0.0" } }, + "path-exists": { + "version": "3.0.0", + "dev": true + }, "string-width": { - "version": "1.0.2", + "version": "3.1.0", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "strip-ansi": { - "version": "3.0.1", + "version": "5.2.0", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^4.1.0" + } + }, + "yargs-parser": { + "version": "15.0.3", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } }, "yargs-parser": { - "version": "5.0.1", + "version": "13.1.2", "dev": true, "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "dev": true + } } }, "yargs-unparser": { @@ -29380,25 +29045,11 @@ "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "dev": true - }, - "decamelize": { - "version": "4.0.0", - "dev": true - } } }, "yeast": { "version": "0.1.2", "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "dev": true } } } diff --git a/package.json b/package.json index 8209ce851..0249ce7b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "happner-suite", - "version": "1.4.0", + "version": "1.5.0", "scripts": { "test": "echo \"tests are not run from the main package of the workspace\" && exit 1", "re-install": "rm -rf node_modules && rm -rf ./packages/*/node_modules && rm -rf package-lock.json && npm i", @@ -10,6 +10,7 @@ "check-env": "node -e 'console.log(process.env)' | grep npm" }, "workspaces": [ + "packages/demos", "packages/happn-3", "packages/happn-db-provider-elasticsearch", "packages/happn-db-provider-loki", @@ -30,14 +31,15 @@ ], "dependencies": { "axios": "^0.26.0", + "cd": "^0.3.3", "ws": "6.1.4" }, "devDependencies": { "babel-eslint": "^10.1.0", "eslint": "^7.32.0", "eslint-config-prettier": "^6.15.0", - "eslint-plugin-prettier": "^3.4.1", "eslint-config-standard": "^16.0.3", + "eslint-plugin-prettier": "^3.4.1", "prettier": "^2.4.1" } } diff --git a/packages/demos/happner-2/security-exchange-as-happner-client.js b/packages/demos/happner-2/security-exchange-as-happner-client.js new file mode 100644 index 000000000..5070a4eca --- /dev/null +++ b/packages/demos/happner-2/security-exchange-as-happner-client.js @@ -0,0 +1,81 @@ +const Mesh = require('happner-2'); +const HappnerClient = require('happner-client'); +const assert = require('assert'); + +async function start() { + class MyComponent { + async myMethod(param, originUsername, $origin) { + return `${originUsername} called myMethod as ${$origin.username} with param ${param}`; + } + } + + // set up the happner config + const happnerConfig = { + name: 'meshname', + secure: true, + modules: { + myComponent: { + instance: new MyComponent(), + }, + }, + components: { + myComponent: {}, + }, + }; + + //start the mesh + const mesh = await Mesh.create(happnerConfig); + + // access the security layer directly (not over websockets) + const security = mesh.exchange.security; + + //create our delegate user + await security.addUser({ + username: 'delegate_username', + password: 'password', + }); + + //link to the mesh delegate + await security.linkGroup('_MESH_DELEGATE', 'delegate_username'); + + //create our delegated user, allowed to call myOtherMethod only + await security.addUser({ + username: 'some_other_username', + password: 'password', + permissions: { + methods: { + //in a /Mesh name/component name/method name - with possible wildcards + '/meshname/myComponent/myMethod': { authorized: true }, + }, + }, + }); + + // we call the above component from an external happner client using the user with the name 'delegate_username' as follows: + const createdClient = new HappnerClient({ secure: true }); + await createdClient.connect({ + username: 'delegate_username', + password: 'password', + }); + const mySession = createdClient.construct({ + myComponent: { + version: '*', + methods: { + myMethod: {}, + }, + }, + }); + const result = await mySession.exchange.$call({ + component: 'myComponent', + method: 'myMethod', + arguments: [1, 'delegate_username'], + as: 'some_other_username', + }); + // eslint-disable-next-line no-console + console.log(result); + // eslint-disable-next-line no-undef + assert(result === 'delegate_username called myMethod as some_other_username with param 1'); + await mesh.stop(); + process.exit(); +} + +start(); diff --git a/packages/demos/happner-2/security-exchange-as-http-rpc.js b/packages/demos/happner-2/security-exchange-as-http-rpc.js new file mode 100644 index 000000000..052f9a7fc --- /dev/null +++ b/packages/demos/happner-2/security-exchange-as-http-rpc.js @@ -0,0 +1,81 @@ +const Mesh = require('happner-2'); +const assert = require('assert'); +const test = require('happn-commons-test').create(); +const axios = test.axios; + +async function start() { + class MyComponent { + async myMethod(param, originUsername, $origin) { + return `${originUsername} called myMethod as ${$origin.username} with param ${param}`; + } + } + + // set up the happner config + const happnerConfig = { + name: 'meshname', + secure: true, + modules: { + myComponent: { + instance: new MyComponent(), + }, + }, + components: { + myComponent: {}, + }, + }; + + //start the mesh + const mesh = await Mesh.create(happnerConfig); + + // access the security layer directly (not over websockets) + const security = mesh.exchange.security; + + //create our delegate user + await security.addUser({ + username: 'delegate_username', + password: 'password', + }); + + //link to the mesh delegate + await security.linkGroup('_MESH_DELEGATE', 'delegate_username'); + + //create our delegated user, allowed to call myOtherMethod only + await security.addUser({ + username: 'some_other_username', + password: 'password', + permissions: { + methods: { + //in a /Mesh name/component name/method name - with possible wildcards + '/meshname/myComponent/myMethod': { authorized: true }, + }, + }, + }); + + const token = ( + await axios.post(`http://127.0.0.1:55000/rest/login`, { + username: 'delegate_username', + password: 'password', + }) + ).data.data.token; + + const result = ( + await axios.post( + `http://127.0.0.1:55000/rest/method/myComponent/myMethod?happn_token=${token}`, + { + parameters: { + param: 1, + originUsername: 'delegate_username', + }, + as: 'some_other_username', + } + ) + ).data.data; + // eslint-disable-next-line no-console + console.log(result); + // eslint-disable-next-line no-undef + assert(result === 'delegate_username called myMethod as some_other_username with param 1'); + await mesh.stop(); + process.exit(); +} + +start(); diff --git a/packages/demos/happner-2/security-exchange-as-light-client.js b/packages/demos/happner-2/security-exchange-as-light-client.js new file mode 100644 index 000000000..b1a9eba66 --- /dev/null +++ b/packages/demos/happner-2/security-exchange-as-light-client.js @@ -0,0 +1,73 @@ +const Mesh = require('happner-2'); +const LightClient = require('happner-client').Light; +const assert = require('assert'); + +async function start() { + class MyComponent { + async myMethod(param, originUsername, $origin) { + return `${originUsername} called myMethod as ${$origin.username} with param ${param}`; + } + } + + // set up the happner config + const happnerConfig = { + name: 'meshname', + secure: true, + modules: { + myComponent: { + instance: new MyComponent(), + }, + }, + components: { + myComponent: {}, + }, + }; + + //start the mesh + const mesh = await Mesh.create(happnerConfig); + + // access the security layer directly (not over websockets) + const security = mesh.exchange.security; + + //create our delegate user + await security.addUser({ + username: 'delegate_username', + password: 'password', + }); + + //link to the mesh delegate + await security.linkGroup('_MESH_DELEGATE', 'delegate_username'); + + //create our delegated user, allowed to call myOtherMethod only + await security.addUser({ + username: 'some_other_username', + password: 'password', + permissions: { + methods: { + //in a /Mesh name/component name/method name - with possible wildcards + '/meshname/myComponent/myMethod': { authorized: true }, + }, + }, + }); + + // we call the above component from an external happner client using the user with the name 'delegate_username' as follows: + const mySession = new LightClient({ secure: true, domain: 'meshname' }); + await mySession.connect({ + username: 'delegate_username', + password: 'password', + }); + const result = await mySession.exchange.$call({ + component: 'myComponent', + method: 'myMethod', + arguments: [1, 'delegate_username'], + as: 'some_other_username', + }); + // eslint-disable-next-line no-console + console.log(result); + // eslint-disable-next-line no-undef + assert(result === 'delegate_username called myMethod as some_other_username with param 1'); + await mesh.stop(); + process.exit(); +} + +start(); diff --git a/packages/demos/happner-2/security-exchange-as-mesh-client.js b/packages/demos/happner-2/security-exchange-as-mesh-client.js new file mode 100644 index 000000000..c84cf31d1 --- /dev/null +++ b/packages/demos/happner-2/security-exchange-as-mesh-client.js @@ -0,0 +1,72 @@ +const Mesh = require('happner-2'); +const MeshClient = Mesh.MeshClient; +const assert = require('assert'); + +async function start() { + class MyComponent { + async myMethod(param, originUsername, $origin) { + return `${originUsername} called myMethod as ${$origin.username} with param ${param}`; + } + } + + // set up the happner config + const happnerConfig = { + name: 'meshname', + secure: true, + modules: { + myComponent: { + instance: new MyComponent(), + }, + }, + components: { + myComponent: {}, + }, + }; + + //start the mesh + const mesh = await Mesh.create(happnerConfig); + + // access the security layer directly (not over websockets) + const security = mesh.exchange.security; + + //create our delegate user + await security.addUser({ + username: 'delegate_username', + password: 'password', + }); + + //link to the mesh delegate + await security.linkGroup('_MESH_DELEGATE', 'delegate_username'); + + //create our delegated user, allowed to call myOtherMethod only + await security.addUser({ + username: 'some_other_username', + password: 'password', + permissions: { + methods: { + //in a /Mesh name/component name/method name - with possible wildcards + '/meshname/myComponent/myMethod': { authorized: true }, + }, + }, + }); + + // we call the above component from an external happner client using the user with the name 'delegate_username' as follows: + const mySession = await MeshClient.create({ + username: 'delegate_username', + password: 'password', + }); + const result = await mySession.exchange.$call({ + component: 'myComponent', + method: 'myMethod', + arguments: [1, 'delegate_username'], + as: 'some_other_username', + }); + // eslint-disable-next-line no-console + console.log(result); + // eslint-disable-next-line no-undef + assert(result === 'delegate_username called myMethod as some_other_username with param 1'); + await mesh.stop(); + process.exit(); +} + +start(); diff --git a/packages/demos/happner-2/security-exchange-as.js b/packages/demos/happner-2/security-exchange-as.js new file mode 100644 index 000000000..6796221a3 --- /dev/null +++ b/packages/demos/happner-2/security-exchange-as.js @@ -0,0 +1,74 @@ +const Mesh = require('happner-2'); +const MeshClient = Mesh.MeshClient; +const assert = require('assert'); + +async function start() { + class MyComponent { + async myMethod(param, $happn, $origin) { + const result = await $happn + .as('some_other_username') + .exchange.myComponent.myOtherMethod(param, $origin.username); + return result; + } + // we are calling this other method in the same component for the purposes of brevity, but this could be a call to a remote component and method as well + async myOtherMethod(param, originUsername, $origin) { + return `${originUsername} called myOtherMethod as ${$origin.username} with param ${param}`; + } + } + + // set up the happner config + const happnerConfig = { + name: 'meshname', + secure: true, + modules: { + myComponent: { + instance: new MyComponent(), + }, + }, + components: { + myComponent: {}, + }, + }; + + //start the mesh + const mesh = await Mesh.create(happnerConfig); + + // access the security layer directly (not over websockets) + const security = mesh.exchange.security; + + //create our delegate user + await security.addUser({ + username: 'delegate_username', + password: 'password', + }); + + //link to the mesh delegate + await security.linkGroup('_MESH_DELEGATE', 'delegate_username'); + + //create our delegated user, allowed to call myOtherMethod only + await security.addUser({ + username: 'some_other_username', + password: 'password', + permissions: { + methods: { + //in a /Mesh name/component name/method name - with possible wildcards + '/meshname/myComponent/myOtherMethod': { authorized: true }, + }, + }, + }); + + // we call the above component from an external client using the user with the name 'delegate_username' as follows: + const mySession = await MeshClient.create({ + username: 'delegate_username', + password: 'password', + }); + const result = await mySession.exchange.myComponent.myMethod(1); + // eslint-disable-next-line no-undef + assert(result === 'delegate_username called myOtherMethod as some_other_username with param 1'); + // eslint-disable-next-line no-console + console.log(result); + await mesh.stop(); + process.exit(); +} + +start(); diff --git a/packages/demos/package.json b/packages/demos/package.json new file mode 100644 index 000000000..9d21af9f4 --- /dev/null +++ b/packages/demos/package.json @@ -0,0 +1,15 @@ +{ + "name": "happner-demos", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "happner-cluster": "^12.2.0", + "happn-commons-test": "^1.1.0" + } +} diff --git a/packages/happn-3/RELEASES.md b/packages/happn-3/RELEASES.md index 7bdf1857f..b29527961 100644 --- a/packages/happn-3/RELEASES.md +++ b/packages/happn-3/RELEASES.md @@ -999,11 +999,6 @@ ----------------- - TEN-125: body-parser v1.20.0 causes memory leak - - - - - - - - +13.2.0 2022-07-07 +----------------- + - TEN-31: added userBelongsToGroups to security.users diff --git a/packages/happn-3/lib/services/security/service.js b/packages/happn-3/lib/services/security/service.js index 139c5b178..f67dca689 100644 --- a/packages/happn-3/lib/services/security/service.js +++ b/packages/happn-3/lib/services/security/service.js @@ -92,7 +92,7 @@ SecurityService.prototype.processAuthorize = processAuthorize; SecurityService.prototype.processAuthorizeUnsecure = processAuthorizeUnsecure; SecurityService.prototype.authorize = util.maybePromisify(authorize); SecurityService.prototype.authorizeOnBehalfOf = authorizeOnBehalfOf; -SecurityService.prototype.__getOnBehalfOfSession = __getOnBehalfOfSession; +SecurityService.prototype.getOnBehalfOfSession = getOnBehalfOfSession; SecurityService.prototype.getCorrectSession = getCorrectSession; SecurityService.prototype.getRelevantPaths = getRelevantPaths; //Digest Authentication methods @@ -122,6 +122,8 @@ SecurityService.prototype.generateEmptySession = generateEmptySession; SecurityService.prototype.generateSession = generateSession; SecurityService.prototype.matchPassword = matchPassword; +SecurityService.prototype.userIsDelegate = userIsDelegate; + //takes a login request - and matches the request to a session, the session is then encoded with its associated policies into a JWT token. There are 2 policies, 1 a stateful one and 0 a stateless one, they can only be matched back during session requests. SecurityService.prototype.__profileSession = __profileSession; SecurityService.prototype.__cache_Profiles = null; @@ -191,7 +193,7 @@ async function initialize(config) { await this.__initializeLookupTables(config); await this.__initializeProfiles(config); await this.__initializeSessionManagement(config); - await this.__initializeOnBehalfOfCache(config); + this.__initializeOnBehalfOfCache(config); await this.__ensureAdminUser(config); this.anonymousUser = await this.__ensureAnonymousUser(config); await this.__initializeReplication(config); @@ -344,8 +346,13 @@ function processAuthorize(message, callback) { (e, authorized, reason, onBehalfOfSession) => { if (e) return callback(e); if (!authorized) { - if (!reason) reason = ''; - reason += ' request on behalf of: ' + message.request.options.onBehalfOf; + let onBehalfOfMessage = + 'request on behalf of unauthorised user: ' + message.request.options.onBehalfOf; + if (!reason) { + reason = onBehalfOfMessage; + } else { + reason += ' ' + onBehalfOfMessage; + } return callback(this.happn.services.error.AccessDeniedError('unauthorized', reason)); } message.session = onBehalfOfSession; @@ -565,15 +572,13 @@ function __clearOnBehalfOfCache() { } function __initializeOnBehalfOfCache() { - return new Promise((resolve) => { - if (!this.config.secure) return resolve(); - if (this.__cache_session_on_behalf_of) return resolve(); - this.__cache_session_on_behalf_of = this.cacheService.create( - 'cache_session_on_behalf_of', - this.options.onBehalfOfCache - ); - resolve(); - }); + if (!this.config.secure || this.__cache_session_on_behalf_of) { + return; + } + this.__cache_session_on_behalf_of = this.cacheService.create( + 'cache_session_on_behalf_of', + this.options.onBehalfOfCache + ); } function __initializeSessionManagement(config) { @@ -1530,6 +1535,16 @@ function authorize(session, path, action, callback) { }); } +function userIsDelegate(username, callback) { + if (username === '_ADMIN') { + return callback(null, true); + } + this.users.userBelongsToGroups(username, ['_MESH_DELEGATE'], (e, belongs) => { + if (e) return callback(e); + callback(null, belongs); + }); +} + function authorizeOnBehalfOf(session, path, action, onBehalfOf, callback) { let completeCall = (err, authorized, reason, onBehalfOfSession) => { callback(err, authorized, reason, onBehalfOfSession); @@ -1539,34 +1554,49 @@ function authorizeOnBehalfOf(session, path, action, onBehalfOf, callback) { }); }; - if (session.user.username !== '_ADMIN') - return completeCall(null, false, 'session attempting to act on behalf of is not authorized'); - - this.__getOnBehalfOfSession(session, onBehalfOf, (e, behalfOfSession) => { - if (e) return completeCall(e, false, 'failed to get on behalf of session'); - if (!behalfOfSession) return completeCall(null, false, 'on behalf of user does not exist'); - this.authorize(behalfOfSession, path, action, function (err, authorized, reason) { - if (err) return completeCall(err, false, reason); - if (!authorized) return completeCall(err, false, reason); - return completeCall(err, authorized, reason, behalfOfSession); + this.userIsDelegate(session.user.username, (e, isDelegate) => { + if (e) return callback(e); + if (!isDelegate) { + return completeCall(null, false, 'session attempting to act on behalf of is not authorized'); + } + this.getOnBehalfOfSession(session, onBehalfOf, session.type, (e, behalfOfSession) => { + if (e) return completeCall(e, false, 'failed to get on behalf of session'); + if (!behalfOfSession) return completeCall(null, false, 'on behalf of user does not exist'); + this.authorize(behalfOfSession, path, action, function (err, authorized, reason) { + if (err || !authorized) { + return completeCall(err, false, reason); + } + return completeCall(err, authorized, reason, behalfOfSession); + }); }); }); } -function __getOnBehalfOfSession(delegatedBy, onBehalfOf, callback) { - let behalfOfSession = this.__cache_session_on_behalf_of.get(onBehalfOf, { clone: false }); - if (behalfOfSession) return callback(null, behalfOfSession); +function getOnBehalfOfSession(delegatedBy, onBehalfOf, sessionType = 1, callback) { + let behalfOfSession = this.__cache_session_on_behalf_of.get(`${onBehalfOf}:${sessionType}`, { + clone: false, + }); + if (behalfOfSession) { + return callback(null, behalfOfSession); + } this.users.getUser(onBehalfOf, (e, onBehalfOfUser) => { if (e) return callback(e); if (!onBehalfOfUser) { return callback(null, null); } - behalfOfSession = this.generateSession(onBehalfOfUser, null, { - info: { delegatedBy: delegatedBy.user.username }, + behalfOfSession = this.generateSession( + onBehalfOfUser, + null, + { + info: { delegatedBy: delegatedBy.user.username }, + }, + { session: { type: sessionType } } + ); + behalfOfSession.happn = this.happn.services.system.getDescription(); + this.__cache_session_on_behalf_of.set(`${onBehalfOf}:${sessionType}`, behalfOfSession, { + clone: false, }); - behalfOfSession.happn = delegatedBy.happn; - this.__cache_session_on_behalf_of.set(onBehalfOf, behalfOfSession, { clone: false }); callback(null, behalfOfSession); }); } @@ -1580,7 +1610,12 @@ function getCorrectSession(message, callback) { ) ) return callback(null, message.session); - return this.__getOnBehalfOfSession(message.session, message.request.options.onBehalfOf, callback); + return this.getOnBehalfOfSession( + message.session, + message.request.options.onBehalfOf, + message.session.type, + callback + ); } function getRelevantPaths(message, callback) { diff --git a/packages/happn-3/lib/services/security/users.js b/packages/happn-3/lib/services/security/users.js index 798ff7921..c44d365d2 100644 --- a/packages/happn-3/lib/services/security/users.js +++ b/packages/happn-3/lib/services/security/users.js @@ -38,6 +38,7 @@ SecurityUsers.prototype.removePermission = removePermission; SecurityUsers.prototype.upsertPermission = upsertPermission; SecurityUsers.prototype.validateDeleteUser = validateDeleteUser; SecurityUsers.prototype.upsertPermissions = util.maybePromisify(upsertPermissions); +SecurityUsers.prototype.userBelongsToGroups = util.maybePromisify(userBelongsToGroups); /** * Clones the passed in user, and generates a hash of the users password to be pushed into the data store. @@ -71,15 +72,27 @@ function initialize(config, securityService, callback) { cache: config.__cache_users, }); - if (!config.__cache_users_by_groups) + if (!config.__cache_users_by_groups) { config.__cache_users_by_groups = { max: 10e3, maxAge: 0, }; + } this.__cache_users_by_groups = UsersByGroupCache.create( this.cacheService, config.__cache_users_by_groups ); + + if (!config.__cache_groups_by_user) { + config.__cache_groups_by_user = { + max: 10e3, + maxAge: 0, + }; + } + this.__cache_groups_by_user = this.cacheService.create('cache_groups_by_user', { + type: 'LRU', + cache: config.__cache_groups_by_user, + }); //backward compatibility after taking groups methods out this.unlinkGroup = this.groups.unlinkGroup.bind(this.groups); this.linkGroup = this.groups.linkGroup.bind(this.groups); @@ -115,6 +128,7 @@ function clearCaches(whatHappnd, changedData) { if (whatHappnd == null) { this.__cache_passwords.clear(); this.__cache_users.clear(); + this.__cache_groups_by_user.clear(); this.__cache_users_by_groups.clear(); this.permissionManager.cache.clear(); return; @@ -124,6 +138,7 @@ function clearCaches(whatHappnd, changedData) { whatHappnd === SD_EVENTS.UNLINK_GROUP || whatHappnd === SD_EVENTS.LINK_GROUP ) { + this.__cache_groups_by_user.clear(); let groupName; if (whatHappnd === SD_EVENTS.DELETE_GROUP) groupName = changedData.obj.name; if (whatHappnd === SD_EVENTS.LINK_GROUP) groupName = changedData._meta.path.split('/').pop(); @@ -135,27 +150,23 @@ function clearCaches(whatHappnd, changedData) { if (whatHappnd === SD_EVENTS.PERMISSION_REMOVED || whatHappnd === SD_EVENTS.PERMISSION_UPSERTED) { if (changedData.username) { this.__cache_users.remove(changedData.username); - if (this.permissionManager) this.permissionManager.cache.remove(changedData.username); + if (this.permissionManager) { + this.permissionManager.cache.remove(changedData.username); + } } } - return new Promise((resolve, reject) => { - try { - if (whatHappnd === SD_EVENTS.UPSERT_USER || whatHappnd === SD_EVENTS.DELETE_USER) { - const userName = - whatHappnd === SD_EVENTS.UPSERT_USER - ? changedData.username - : changedData.obj._meta.path.replace('/_SYSTEM/_SECURITY/_USER/', ''); - this.__cache_users_by_groups.userChanged(userName); - this.__cache_passwords.remove(userName); - this.__cache_users.remove(userName); - if (this.permissionManager) this.permissionManager.cache.remove(userName); - } - return resolve(); - } catch (e) { - reject(e); - } - }); + if (whatHappnd === SD_EVENTS.UPSERT_USER || whatHappnd === SD_EVENTS.DELETE_USER) { + const userName = + whatHappnd === SD_EVENTS.UPSERT_USER + ? changedData.username + : changedData.obj._meta.path.replace('/_SYSTEM/_SECURITY/_USER/', ''); + this.__cache_users_by_groups.userChanged(userName); + this.__cache_passwords.remove(userName); + this.__cache_users.remove(userName); + this.__cache_groups_by_user.remove(userName); + if (this.permissionManager) this.permissionManager.cache.remove(userName); + } } function __validate(validationType, options, obj, callback) { @@ -405,7 +416,26 @@ function __linkGroupsToUser(user, callback) { }); } +function userBelongsToGroups(username, groupNames, callback) { + if (!Array.isArray(groupNames)) { + return callback(new Error('groupNames must be an array')); + } + // TODO: possible optimisation for caching at this level + this.getGroupMemberships(username, (e, memberships) => { + if (e) return callback(e); + if (groupNames.length === 0) return callback(null, false); + const userGroupNames = memberships.map((membership) => membership.groupName); + const belongs = groupNames.every((element) => { + return userGroupNames.includes(element); + }); + callback(null, belongs); + }); +} + function getGroupMemberships(username, callback) { + if (this.__cache_groups_by_user.has(username)) { + return callback(null, this.__cache_groups_by_user.get(username)); + } const userPath = `/_SYSTEM/_SECURITY/_USER/${username}`; this.dataService.get( `${userPath}/_USER_GROUP/*`, @@ -416,19 +446,18 @@ function getGroupMemberships(username, callback) { }, (e, userGroups) => { if (e) return callback(e); - callback( - null, - userGroups - .filter((userGroup) => { - return userGroup._meta.path.indexOf(`${userPath}/`) === 0; - }) - .map((membership) => { - return { - groupName: membership._meta.path.replace(`${userPath}/_USER_GROUP/`, ''), - membership: commons._.omit(membership, '_meta'), - }; - }) - ); + const filtered = userGroups + .filter((userGroup) => { + return userGroup._meta.path.indexOf(`${userPath}/`) === 0; + }) + .map((membership) => { + return { + groupName: membership._meta.path.replace(`${userPath}/_USER_GROUP/`, ''), + membership: commons._.omit(membership, '_meta'), + }; + }); + this.__cache_groups_by_user.set(username, filtered); + callback(null, filtered); } ); } diff --git a/packages/happn-3/lib/services/system/service.js b/packages/happn-3/lib/services/system/service.js index 60714f22b..849a7543f 100644 --- a/packages/happn-3/lib/services/system/service.js +++ b/packages/happn-3/lib/services/system/service.js @@ -132,15 +132,14 @@ SystemService.prototype.logError = function (e, area, severity) { }; SystemService.prototype.getDescription = function (message) { - var description = { + const description = { name: this.name, - secure: this.happn.config.secure ? true : false, + secure: this.happn.config.secure === true, }; - if (message && message.session.cookieName) description.cookieName = message.session.cookieName; - - if (this.happn.services.security._keyPair) - description.publicKey = this.happn.services.security._keyPair.publicKey; + if (message?.session?.cookieName) { + return Object.assign({ cookieName: message.session.cookieName }, description); + } return description; }; diff --git a/packages/happn-3/package.json b/packages/happn-3/package.json index d3003d5c9..b9f8587b0 100644 --- a/packages/happn-3/package.json +++ b/packages/happn-3/package.json @@ -1,6 +1,6 @@ { "name": "happn-3", - "version": "13.1.4", + "version": "13.2.0", "description": "pub/sub api as a service using primus and mongo & redis or nedb, can work as cluster, single process or embedded using nedb", "keywords": [ "mongo", @@ -57,10 +57,10 @@ "debug": "4.1.1", "gulp": "^4.0.2", "happn": "^2.21.3", - "happn-cluster": "^12.0.12", + "happn-cluster": "^12.0.13", "happn-commons-test": "^1.1.0", - "happn-db-provider-elasticsearch": "^1.0.12", - "happn-db-provider-mongo": "^1.0.12", + "happn-db-provider-elasticsearch": "^1.0.13", + "happn-db-provider-mongo": "^1.0.13", "happn-random-activity-generator": "0.2.1", "jsprim": "^2.0.0", "mongodb": "^4.1.3", diff --git a/packages/happn-3/test/__fixtures/utils/test_helper.js b/packages/happn-3/test/__fixtures/utils/test_helper.js index 7d62308a5..39c8d173a 100644 --- a/packages/happn-3/test/__fixtures/utils/test_helper.js +++ b/packages/happn-3/test/__fixtures/utils/test_helper.js @@ -16,6 +16,18 @@ class TestHelper extends BaseTestHelper { //backward compatability this.shortid = this.newid; this.homedir = require('homedir'); + this.mockLogger = { + createLogger: () => { + return { + $$TRACE: this.log, + $$DEBUG: this.log, + info: this.log, + debug: this.log, + warn: this.log, + error: this.log, + }; + } + }; } static create() { diff --git a/packages/happn-3/test/integration/cache/cache-statistics.js b/packages/happn-3/test/integration/cache/cache-statistics.js index a373a90a9..a80c24448 100644 --- a/packages/happn-3/test/integration/cache/cache-statistics.js +++ b/packages/happn-3/test/integration/cache/cache-statistics.js @@ -166,6 +166,14 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 60e3 }, (test) hitsPerSec: 0, missesPerSec: 0, }, + cache_groups_by_user: { + hits: 0, + hitsPerSec: 0, + misses: 0, + missesPerSec: 0, + size: 1, + type: 'lru', + }, }); test.expect(test.commons._.omit(logs[1], 'timestamp', 'name')).to.eql({ @@ -289,6 +297,14 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 60e3 }, (test) hitsPerSec: 0, missesPerSec: 0, }, + cache_groups_by_user: { + hits: 0, + hitsPerSec: 0, + misses: 0, + missesPerSec: 0, + size: 1, + type: 'lru', + }, }); }); diff --git a/packages/happn-3/test/unit/security/service.js b/packages/happn-3/test/unit/security/service.js index 0406c3622..5b46f7539 100644 --- a/packages/happn-3/test/unit/security/service.js +++ b/packages/happn-3/test/unit/security/service.js @@ -170,7 +170,9 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi cache: {}, data: {}, crypto: {}, - security: {}, + security: { + secure: true, + }, }, }; @@ -181,6 +183,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi testServices.data = require('../../../lib/services/data/service'); testServices.security = require('../../../lib/services/security/service'); testServices.session = require('../../../lib/services/session/service'); + testServices.system = require('../../../lib/services/system/service'); testServices.utils = require('../../../lib/services/utils/service'); testServices.error = require('../../../lib/services/error/service'); testServices.log = require('../../../lib/services/log/service'); @@ -207,7 +210,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi if (servicesConfig) testConfig = servicesConfig; test.async.eachSeries( - ['log', 'error', 'utils', 'crypto', 'cache', 'session', 'data', 'security'], + ['log', 'error', 'utils', 'crypto', 'cache', 'session', 'data', 'system', 'security'], function (serviceName, eachServiceCB) { testServices[serviceName] = new testServices[serviceName]({ logger: Logger, @@ -2427,9 +2430,10 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi }); }; - happnMock.services.security.__getOnBehalfOfSession = function ( - username, - onBehalfOf, + happnMock.services.security.getOnBehalfOfSession = function ( + _username, + _onBehalfOf, + _sessionType, getOnBehalfOfCallback ) { getOnBehalfOfCallback(null, { @@ -2493,9 +2497,10 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi }); }; - happnMock.services.security.__getOnBehalfOfSession = function ( - username, - onBehalfOf, + happnMock.services.security.getOnBehalfOfSession = function ( + _username, + _onBehalfOf, + _sessionType, getOnBehalfOfCallback ) { getOnBehalfOfCallback(null, { @@ -2559,9 +2564,10 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi }); }; - happnMock.services.security.__getOnBehalfOfSession = function ( - username, - onBehalfOf, + happnMock.services.security.getOnBehalfOfSession = function ( + _username, + _onBehalfOf, + _sessionType, getOnBehalfOfCallback ) { getOnBehalfOfCallback(null, { @@ -2625,9 +2631,10 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi }); }; - happnMock.services.security.__getOnBehalfOfSession = function ( - username, - onBehalfOf, + happnMock.services.security.getOnBehalfOfSession = function ( + _username, + _onBehalfOf, + _sessionType, getOnBehalfOfCallback ) { getOnBehalfOfCallback(null, null); @@ -2682,9 +2689,10 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi }); }; - happnMock.services.security.__getOnBehalfOfSession = function ( - username, - onBehalfOf, + happnMock.services.security.getOnBehalfOfSession = function ( + _username, + _onBehalfOf, + _sessionType, getOnBehalfOfCallback ) { getOnBehalfOfCallback(null, { @@ -2728,7 +2736,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi }); }); - it('tests the __getOnBehalfOfSession method - uncached', function (done) { + it('tests the getOnBehalfOfSession method - uncached', function (done) { mockServices(function (e, happnMock) { if (e) return done(e); @@ -2762,16 +2770,16 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi }); }; - happnMock.services.security.__getOnBehalfOfSession(session, onBehalfOf, (e, onBehalfOf) => { + happnMock.services.security.getOnBehalfOfSession(session, onBehalfOf, 0, (e, onBehalfOf) => { if (e) return done(e); test.expect(fetchedUserFromDb).to.be(true); test.expect(onBehalfOf.user).to.eql({ username: 'test-user', groups: {}, }); - test.expect(onBehalfOf.happn).to.eql({ - happn: 'info', - }); + test.expect(onBehalfOf.happn.secure).to.eql(false); + test.expect(typeof onBehalfOf.happn.name).to.be('string'); + test.expect(onBehalfOf.type).to.eql(0); test.expect(wasCached.user).to.eql({ username: 'test-user', groups: {}, @@ -2781,7 +2789,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi }); }).timeout(5000); - it('tests the __getOnBehalfOfSession method - cached', function (done) { + it('tests the getOnBehalfOfSession method - cached', function (done) { mockServices(function (e, happnMock) { if (e) return done(e); @@ -2816,7 +2824,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 20e3 }, functi }); }; - happnMock.services.security.__getOnBehalfOfSession(session, onBehalfOf, (e, onBehalfOf) => { + happnMock.services.security.getOnBehalfOfSession(session, onBehalfOf, 1, (e, onBehalfOf) => { if (e) return done(e); test.expect(fetchedUserFromDb).to.be(false); test.expect(onBehalfOf.user).to.eql({ diff --git a/packages/happn-3/test/unit/security/users.js b/packages/happn-3/test/unit/security/users.js index b5f01714c..0cf03e31d 100644 --- a/packages/happn-3/test/unit/security/users.js +++ b/packages/happn-3/test/unit/security/users.js @@ -1,4 +1,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120000 }, function (test) { + const commons = require('happn-commons'); + const CONSTANTS = commons.constants; + const SD_EVENTS = CONSTANTS.SECURITY_DIRECTORY_EVENTS; var Logger = require('happn-logger'); const util = require('util'); var Services = {}; @@ -61,7 +64,12 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120000 }, func .then(mockService(happn, 'Data')) .then(mockService(happn, 'Cache')) .then(mockService(happn, 'System')) - .then(mockService(happn, 'Security')) + .then( + mockService(happn, 'Security', { + __cache_groups_by_user: { max: 5 }, + __cache_users_by_groups: { max: 5 }, + }) + ) .then(mockService(happn, 'Subscription')) .then(function () { happn.services.session.initializeCaches.bind(happn.services.session)(function (e) { @@ -882,6 +890,168 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120000 }, func }); }); + it('tests userBelongsToGroups, no groups', function (done) { + mockServices(function (e, happn) { + if (e) return done(e); + createUsersAndGroups(happn, function (e) { + if (e) return done(e); + happn.services.security.users.userBelongsToGroups('test_user', [], (e, belongs) => { + if (e) return done(e); + test.expect(belongs).to.be(false); + done(); + }); + }); + }); + }); + + it('tests userBelongsToGroups', function (done) { + mockServices(function (e, happn) { + if (e) return done(e); + createUsersAndGroups(happn, function (e) { + if (e) return done(e); + happn.services.security.users.userBelongsToGroups( + 'test_1', + ['test_1', 'test_2'], + (e, belongs) => { + if (e) return done(e); + test.expect(belongs).to.be(true); + done(); + } + ); + }); + }); + }); + + it('tests userBelongsToGroups, false', function (done) { + mockServices(function (e, happn) { + if (e) return done(e); + createUsersAndGroups(happn, function (e) { + if (e) return done(e); + happn.services.security.users.userBelongsToGroups( + 'test_1', + ['test_1', 'test_2', 'bad_group'], + (e, belongs) => { + if (e) return done(e); + test.expect(belongs).to.be(false); + done(); + } + ); + }); + }); + }); + + function testCorrectCacheEmptyBasedOnWhatHappened(whatHappened, changedData, expectedSize = 0) { + return new Promise((resolve, reject) => { + mockServices(function (e, happn) { + if (e) return reject(e); + createUsersAndGroups(happn, function (e) { + if (e) return reject(e); + let users = happn.services.security.users; + users.clearCaches(); + users.userBelongsToGroups(`test_1`, [`test_1`], (e) => { + if (e) return reject(e); + test.expect(users.__cache_groups_by_user.size()).to.be(1); + users.clearCaches(whatHappened, changedData); + test.expect(users.__cache_groups_by_user.size()).to.be(expectedSize); + resolve(true); + }); + }); + }); + }); + } + + it('tests userBelongsToGroups, cache clear on security directory event', async () => { + test + .expect( + await testCorrectCacheEmptyBasedOnWhatHappened(SD_EVENTS.DELETE_GROUP, { + obj: { name: 'test_1' }, + }) + ) + .to.be(true); + + test + .expect( + await testCorrectCacheEmptyBasedOnWhatHappened(SD_EVENTS.LINK_GROUP, { + _meta: { path: '/_SYSTEM/_SECURITY/_USER/test_1' }, + }) + ) + .to.be(true); + + test + .expect( + await testCorrectCacheEmptyBasedOnWhatHappened(SD_EVENTS.UNLINK_GROUP, { + path: '/_SYSTEM/_SECURITY/_USER/test_1', + }) + ) + .to.be(true); + + test + .expect( + await testCorrectCacheEmptyBasedOnWhatHappened( + SD_EVENTS.PERMISSION_UPSERTED, + { + path: '/_SYSTEM/_SECURITY/_USER/test_1', + }, + 1 + ) + ) + .to.be(true); + + test + .expect( + await testCorrectCacheEmptyBasedOnWhatHappened( + SD_EVENTS.PERMISSION_REMOVED, + { + path: '/_SYSTEM/_SECURITY/_USER/test_1', + }, + 1 + ) + ) + .to.be(true); + + test + .expect( + await testCorrectCacheEmptyBasedOnWhatHappened(SD_EVENTS.UPSERT_USER, { + username: 'test_1', + }) + ) + .to.be(true); + + test + .expect( + await testCorrectCacheEmptyBasedOnWhatHappened(SD_EVENTS.DELETE_USER, { + obj: { _meta: { path: '/_SYSTEM/_SECURITY/_USER/test_1' } }, + }) + ) + .to.be(true); + }); + + it('tests userBelongsToGroups, cache clear all', function (done) { + mockServices(function (e, happn) { + if (e) return done(e); + createUsersAndGroups(happn, function (e) { + if (e) return done(e); + test.commons.async.times( + 10, + (time, timeCb) => { + happn.services.security.users.userBelongsToGroups( + `test_${time}`, + [`test_${time}`], + timeCb + ); + }, + (e) => { + if (e) return done(e); + test.expect(happn.services.security.users.__cache_groups_by_user.size()).to.be(5); + happn.services.security.users.clearCaches(); + test.expect(happn.services.security.users.__cache_groups_by_user.size()).to.be(0); + done(); + } + ); + }); + }); + }); + it('__upsertUser should add a user', function (done) { mockServices(function (e, happn) { if (e) return done(e); diff --git a/packages/happn-3/test/unit/services/system/service.js b/packages/happn-3/test/unit/services/system/service.js new file mode 100644 index 000000000..932415e8a --- /dev/null +++ b/packages/happn-3/test/unit/services/system/service.js @@ -0,0 +1,14 @@ +require('../../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test) => { + const SystemService = require('../../../../lib/services/system/service'); + it('can getDescription', async () => { + const systemService = new SystemService({ logger: test.mockLogger }); + systemService.name = 'test'; + systemService.happn = { config: { secure: true } }; + test.expect(systemService.getDescription()).to.eql({ name: 'test', secure: true }); + systemService.happn = { config: { secure: false } }; + test.expect(systemService.getDescription()).to.eql({ name: 'test', secure: false }); + test + .expect(systemService.getDescription({ session: { cookieName: 'testCookieName' } })) + .to.eql({ name: 'test', secure: false, cookieName: 'testCookieName' }); + }); +}); diff --git a/packages/happn-cluster/RELEASES.md b/packages/happn-cluster/RELEASES.md index 6a0c6a7e5..c5bb318ae 100644 --- a/packages/happn-cluster/RELEASES.md +++ b/packages/happn-cluster/RELEASES.md @@ -290,4 +290,6 @@ non-release 2017-12-14 ----------------- - TEN-125: body-parser v1.20.0 causes memory leak - +12.0.13 2022-08-07 +----------------- + - TEN-31: updated unit tests diff --git a/packages/happn-cluster/package.json b/packages/happn-cluster/package.json index 31044878b..78ad5bf9a 100644 --- a/packages/happn-cluster/package.json +++ b/packages/happn-cluster/package.json @@ -1,6 +1,6 @@ { "name": "happn-cluster", - "version": "12.0.12", + "version": "12.0.13", "description": "extends happn with cluster ability", "main": "index.js", "scripts": { @@ -39,9 +39,9 @@ "bluebird": "^3.7.2", "clone": "^1.0.2", "dface": "1.0.1", - "happn-3": "^13.1.4", + "happn-3": "^13.2.0", "happn-commons": "^1.1.0", - "happn-db-provider-mongo": "^1.0.12", + "happn-db-provider-mongo": "^1.0.13", "happn-swim": "^1.0.3", "http-proxy": "^1.18.1", "mongodb": "^4.1.4" diff --git a/packages/happn-cluster/test/test-unit/02-unit-orchestrator.js b/packages/happn-cluster/test/test-unit/02-unit-orchestrator.js index b162224a7..7d14a53db 100644 --- a/packages/happn-cluster/test/test-unit/02-unit-orchestrator.js +++ b/packages/happn-cluster/test/test-unit/02-unit-orchestrator.js @@ -1,10 +1,10 @@ -var Orchestrator = require('../../lib/services/orchestrator'); -var MockHappn = require('../mocks/mock-happn'); -var MockHappnClient = require('../mocks/mock-happn-client'); -var MockSession = require('../mocks/mock-session'); -var MockMembership = require('../mocks/mock-membership'); -var mockOpts = require('../mocks/mock-opts'); -var address = require('../../lib/utils/get-address')()(); +const Orchestrator = require('../../lib/services/orchestrator'); +const MockHappn = require('../mocks/mock-happn'); +const MockHappnClient = require('../mocks/mock-happn-client'); +const MockSession = require('../mocks/mock-session'); +const MockMembership = require('../mocks/mock-membership'); +const mockOpts = require('../mocks/mock-opts'); +const address = require('../../lib/utils/get-address')()(); require('../lib/test-helper').describe({ timeout: 30e3 }, function (test) { before(function () { diff --git a/packages/happn-db-provider-elasticsearch/RELEASES.md b/packages/happn-db-provider-elasticsearch/RELEASES.md index 8a60bc372..45796c3f2 100644 --- a/packages/happn-db-provider-elasticsearch/RELEASES.md +++ b/packages/happn-db-provider-elasticsearch/RELEASES.md @@ -53,3 +53,7 @@ 1.0.12 2022-07-14 ----------------- - TEN-125: body-parser v1.20.0 causes memory leak + +1.0.13 2022-08-07 +----------------- + - TEN-31: onbehalf of / as diff --git a/packages/happn-db-provider-elasticsearch/package.json b/packages/happn-db-provider-elasticsearch/package.json index 52ae1812b..5e63d3511 100644 --- a/packages/happn-db-provider-elasticsearch/package.json +++ b/packages/happn-db-provider-elasticsearch/package.json @@ -1,6 +1,6 @@ { "name": "happn-db-provider-elasticsearch", - "version": "1.0.12", + "version": "1.0.13", "private": false, "scripts": { "test": "_mocha --recursive --exit silence.js test/*", @@ -15,12 +15,12 @@ "extract-values": "^0.1.2", "happn-logger": "^2.1.1", "micromustache": "^5.2.0", - "redis-lru-cache": "^1.0.12", + "redis-lru-cache": "^1.0.13", "traverse": "0.6.6" }, "devDependencies": { "happn-commons-test": "^1.1.0", - "happn-3": "^13.1.4", + "happn-3": "^13.2.0", "json-from-schema": "1.10.0" } } diff --git a/packages/happn-db-provider-mongo/RELEASES.md b/packages/happn-db-provider-mongo/RELEASES.md index 78f8abee0..3c7c2f577 100644 --- a/packages/happn-db-provider-mongo/RELEASES.md +++ b/packages/happn-db-provider-mongo/RELEASES.md @@ -54,3 +54,7 @@ 1.0.12 2022-07-14 ----------------- - TEN-125: body-parser v1.20.0 causes memory leak + +1.0.13 2022-08-07 +----------------- + - TEN-31: onbehalf of / as diff --git a/packages/happn-db-provider-mongo/package.json b/packages/happn-db-provider-mongo/package.json index 722b5df13..7447a5ef3 100644 --- a/packages/happn-db-provider-mongo/package.json +++ b/packages/happn-db-provider-mongo/package.json @@ -1,7 +1,7 @@ { "name": "happn-db-provider-mongo", "description": "service plugin for running happn on a mongo database, for happn-3 instances", - "version": "1.0.12", + "version": "1.0.13", "scripts": { "test": "_mocha --recursive --exit silence.js test/*", "test-cover": "nyc --reporter=lcov --reporter=text --reporter=html npm test", @@ -24,7 +24,7 @@ "devDependencies": { "byline": "^5.0.0", "gulp": "^3.9.0", - "happn-3": "^13.1.4", + "happn-3": "^13.2.0", "happn-commons-test": "^1.1.0" }, "readmeFilename": "README.md" diff --git a/packages/happner-2/RELEASES.md b/packages/happner-2/RELEASES.md index df6bbda3c..5868d6e97 100644 --- a/packages/happner-2/RELEASES.md +++ b/packages/happner-2/RELEASES.md @@ -973,12 +973,7 @@ SMC-1645: made error messages more consistent, encapsulating mesh.component.meth 12.1.9 2022-07-14 ----------------- - TEN-125: body-parser v1.20.0 causes memory leak - - - - - - - - +12.2.0 2022-08-07 +----------------- + - TEN-31: onbehalf of / as diff --git a/packages/happner-2/docs/happn.md b/packages/happner-2/docs/happn.md index 3a0936180..3976c7225 100644 --- a/packages/happner-2/docs/happn.md +++ b/packages/happner-2/docs/happn.md @@ -4,7 +4,7 @@ ### What is the happn layer? -The HAPPN layer is the underlying messaging and storage infrastructure in the mesh. It uses [happn](https://github.com/happner/happn-3)'s evented storage and pubsub websocket stack. +The HAPPN layer is the underlying messaging and storage infrastructure in the mesh. It uses [happn](https://github.com/happner/happner-suite/blob/develop/packages/happn-3)'s evented storage and pubsub websocket stack. Configured in the happn layer is the host and port upon which __this__ MeshNode listens for connections from other MeshNodes or clients. @@ -151,14 +151,14 @@ Happner.create(config, function(err, mesh) { 1. the _exchange bucket - where exchange method calls are stored and searched for 2. the _events bucket - where events subscriptions happen -3. the _optimised bucket - deeply nested subscriptions that you know the segment size for happen here, as long as the data is stored in the format /_optimised/[rest of key] - for more info please check out the [happn documentation](https://github.com/happner/happn-3#buckets-and-optimisation) +3. the _optimised bucket - deeply nested subscriptions that you know the segment size for happen here, as long as the data is stored in the format /_optimised/[rest of key] - for more info please check out the [happn documentation](https://github.com/happner/happner-suite/blob/develop/packages/happn-3#buckets-and-optimisation) 4. all sets 5. all removes 6. default anything else that isn't fielded above The first matching bucket found is used to store a matching subscription, all the buckets are checked against sets and removes that happen. -The subscription service is [configured in the lib/system/happn.js module as follows](https://github.com/happner/happner-2/blob/master/lib/system/happn.js#L265): +The subscription service is [configured in the lib/system/happn.js module as follows](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/blob/master/lib/system/happn.js#L265): ```javascript //happn subscription service if (!config.happn.services.subscription) { diff --git a/packages/happner-2/docs/security.md b/packages/happner-2/docs/security.md index 930b5b5db..abc148c6d 100644 --- a/packages/happner-2/docs/security.md +++ b/packages/happner-2/docs/security.md @@ -2,11 +2,7 @@ ## users groups and permissions -_happner meshes can run in secure mode, a scheme comprising of users, groups and permissions allows for this, we have yet to complete the documentation for this, but to get a comprehensive picture of how this works, please look at [the test for now](https://github.com/happner/happner-2/blob/master/test/integration/security/advanced-security.js)_ - -## payload encryption - -_happners messaging payload can be encrypted, the mesh must be running in secure mode, to see how this works client to mesh, please look at [the test](https://github.com/happner/happner-2/blob/master/test/integration/security/payload-encryption-client-to-mesh.js) - there is also a test demonstrating how this works [mesh to mesh](https://github.com/happner/happner-2/blob/master/test/integration/security/payload-encryption-mesh-to-mesh.js)_ +_happner meshes can run in secure mode, a scheme comprising of users, groups and permissions allows for this, we have yet to complete the documentation for this, but to get a comprehensive picture of how this works, please look at [the test for now](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/test/integration/security/advanced-security.js)_ ## security directory events @@ -29,7 +25,7 @@ adminClient.exchange.security.attachToSecurityChanges(function(e){ ``` -please look at [the test](https://github.com/happner/happner-2/blob/master/test/integration/security/permission-changes-events.js) +please look at [the test](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/test/integration/security/permission-changes-events.js) ## security session events @@ -47,7 +43,7 @@ _the security module emits an event for every time a client connects or disconne }); ``` -please look at [the test](https://github.com/happner/happner-2/blob/master/test/integration/security/session-changes-events.js) +please look at [the test](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/test/integration/security/session-changes-events.js) ## security service functions @@ -282,17 +278,17 @@ adminClient.exchange.security ## authority delegation: +### system-wide delegation: + By default inter mesh calls are done via the endpoint's user, and component to component calls are done using the \_ADMIN user, this means security is enforced only between the external mesh/client and the edge node of the mesh. To ensure that the originator of a call is checked against the security directory regardless of how deep the exchange call stack execution goes, the authorityDelegationOn config option should be set to true on a secure mesh: ```javascript -var meshConfig = {secure:true, authorityDelegationOn:true} - -var myMesh = new Mesh.create(meshConfig, function(e, created){ - ... -}); +const Mesh = require('happner-2'); +let meshConfig = { secure: true, authorityDelegationOn: true }; +const myMesh1 = await Mesh.create(meshConfig); //this can be configured per component as well, here is an example that excludes a specific component -var meshConfig = { +meshConfig = { secure:true, authorityDelegationOn:true, modules:{ @@ -320,13 +316,10 @@ var meshConfig = { } } } - -var myMesh = new Mesh.create(meshConfig, function(e, created){ - ... -}); +const myMesh2 = await Mesh.create(meshConfig); //here is an example that includes a specific component -var meshConfig = { +meshConfig = { secure:true, //authorityDelegationOn:true, - by default for all components authority delegation is off modules:{ @@ -355,9 +348,419 @@ var meshConfig = { } } -var myMesh = new Mesh.create(meshConfig, function(e, created){ - ... -}); +const myMesh3 = await Mesh.create(meshConfig); +``` + +### per request delegation: + +Provided a user belongs to the special system group "_MESH_DELEGATE", the user is able to invoke a method on the mesh "as" a different user, this is possible using the following mechanisms: + +#### inside a component method via $happn: +*code taken from this [demo](https://github.com/happner/happner-suite/blob/develop/packages/demos/happner-2/security-exchange-as.js):* +``` javascript +const assert = require('assert'); +const Mesh = require('happner-2'); +const MeshClient = Mesh.MeshClient; + + +async function start() { + class MyComponent { + async myMethod(param, $happn, $origin) { + const result = await $happn + .as('some_other_username') // NB: this is where the magic happns + .exchange.myComponent.myOtherMethod(param, $origin.username); + return result; + } + // we are calling this other method in the same component for the purposes of brevity, but this could be a call to a remote component and method as well + async myOtherMethod(param, originUsername, $origin) { + return `${originUsername} called myOtherMethod as ${$origin.username} with param ${param}`; + } + } + + // set up the happner config + const happnerConfig = { + name: 'meshname', + secure: true, + modules: { + myComponent: { + instance: new MyComponent(), + }, + }, + components: { + myComponent: {}, + }, + }; + + //start the mesh + const mesh = await Mesh.create(happnerConfig); + + // access the security layer directly (not over websockets) + const security = mesh.exchange.security; + + //create our delegate user + await security.addUser({ + username: 'delegate_username', + password: 'password', + }); + + //link to the mesh delegate + await security.linkGroup('_MESH_DELEGATE', 'delegate_username'); + + //create our delegated user, allowed to call myOtherMethod only + await security.addUser({ + username: 'some_other_username', + password: 'password', + permissions: { + methods: { + '/meshname/myComponent/myOtherMethod': { authorized: true }, + }, + }, + }); + + // we call the above component from an external client using the user with the name 'delegate_username' as follows: + const mySession = await MeshClient.create({ + username: 'delegate_username', + password: 'password', + }); + const result = await mySession.exchange.myComponent.myMethod(1); + // eslint-disable-next-line no-undef + assert(result === 'delegate_username called myOtherMethod as some_other_username with param 1'); + // eslint-disable-next-line no-console + console.log(result); + await mesh.stop(); + process.exit(); +} + +start(); +``` +#### from outside via the mesh client: +*code taken from this [demo](https://github.com/happner/happner-suite/blob/develop/packages/demos/happner-2/security-exchange-mesh-client.js):* +``` javascript +const Mesh = require('happner-2'); +const MeshClient = Mesh.MeshClient; +const assert = require('assert'); + +async function start() { + class MyComponent { + async myMethod(param, originUsername, $origin) { + return `${originUsername} called myMethod as ${$origin.username} with param ${param}`; + } + } + + // set up the happner config + const happnerConfig = { + name: 'meshname', + secure: true, + modules: { + myComponent: { + instance: new MyComponent(), + }, + }, + components: { + myComponent: {}, + }, + }; + + //start the mesh + const mesh = await Mesh.create(happnerConfig); + + // access the security layer directly (not over websockets) + const security = mesh.exchange.security; + + //create our delegate user + await security.addUser({ + username: 'delegate_username', + password: 'password', + }); + + //link to the mesh delegate + await security.linkGroup('_MESH_DELEGATE', 'delegate_username'); + + //create our delegated user, allowed to call myOtherMethod only + await security.addUser({ + username: 'some_other_username', + password: 'password', + permissions: { + methods: { + //in a /Mesh name/component name/method name - with possible wildcards + '/meshname/myComponent/myMethod': { authorized: true }, + }, + }, + }); + + // we call the above component from an external happner client using the user with the name 'delegate_username' as follows: + const mySession = await MeshClient.create({ + username: 'delegate_username', + password: 'password', + }); + const result = await mySession.exchange.$call({ + component: 'myComponent', + method: 'myMethod', + arguments: [1, 'delegate_username'], + as: 'some_other_username', + }); + // eslint-disable-next-line no-console + console.log(result); + // eslint-disable-next-line no-undef + assert(result === 'delegate_username called myMethod as some_other_username with param 1'); + await mesh.stop(); + process.exit(); +} + +start(); + +``` + +#### from outside via the happner-client: +*code taken from this [demo](https://github.com/happner/happner-suite/blob/develop/packages/demos/happner-2/security-exchange-as-happner-client.js):* +``` javascript +const Mesh = require('happner-2'); +const HappnerClient = require('happner-client'); +const assert = require('assert'); + +async function start() { + class MyComponent { + async myMethod(param, originUsername, $origin) { + return `${originUsername} called myMethod as ${$origin.username} with param ${param}`; + } + } + + // set up the happner config + const happnerConfig = { + name: 'meshname', + secure: true, + modules: { + myComponent: { + instance: new MyComponent(), + }, + }, + components: { + myComponent: {}, + }, + }; + + //start the mesh + const mesh = await Mesh.create(happnerConfig); + + // access the security layer directly (not over websockets) + const security = mesh.exchange.security; + + //create our delegate user + await security.addUser({ + username: 'delegate_username', + password: 'password', + }); + + //link to the mesh delegate + await security.linkGroup('_MESH_DELEGATE', 'delegate_username'); + + //create our delegated user, allowed to call myOtherMethod only + await security.addUser({ + username: 'some_other_username', + password: 'password', + permissions: { + methods: { + //in a /Mesh name/component name/method name - with possible wildcards + '/meshname/myComponent/myMethod': { authorized: true }, + }, + }, + }); + + // we call the above component from an external happner client using the user with the name 'delegate_username' as follows: + const createdClient = new HappnerClient({ secure: true }); + await createdClient.connect({ + username: 'delegate_username', + password: 'password', + }); + const mySession = createdClient.construct({ + myComponent: { + version: '*', + methods: { + myMethod: {}, + }, + }, + }); + const result = await mySession.exchange.$call({ + component: 'myComponent', + method: 'myMethod', + arguments: [1, 'delegate_username'], + as: 'some_other_username', + }); + // eslint-disable-next-line no-console + console.log(result); + // eslint-disable-next-line no-undef + assert(result === 'delegate_username called myMethod as some_other_username with param 1'); + await mesh.stop(); + process.exit(); +} + +start(); + +``` + +#### from outside via the light-client: +*code taken from this [demo](https://github.com/happner/happner-suite/blob/develop/packages/demos/happner-2/security-exchange-as-light-client.js):* +``` javascript +const Mesh = require('happner-2'); +const LightClient = require('happner-client').Light; +const assert = require('assert'); + +async function start() { + class MyComponent { + async myMethod(param, originUsername, $origin) { + return `${originUsername} called myMethod as ${$origin.username} with param ${param}`; + } + } + + // set up the happner config + const happnerConfig = { + name: 'meshname', + secure: true, + modules: { + myComponent: { + instance: new MyComponent(), + }, + }, + components: { + myComponent: {}, + }, + }; + + //start the mesh + const mesh = await Mesh.create(happnerConfig); + + // access the security layer directly (not over websockets) + const security = mesh.exchange.security; + + //create our delegate user + await security.addUser({ + username: 'delegate_username', + password: 'password', + }); + + //link to the mesh delegate + await security.linkGroup('_MESH_DELEGATE', 'delegate_username'); + + //create our delegated user, allowed to call myOtherMethod only + await security.addUser({ + username: 'some_other_username', + password: 'password', + permissions: { + methods: { + //in a /Mesh name/component name/method name - with possible wildcards + '/meshname/myComponent/myMethod': { authorized: true }, + }, + }, + }); + + // we call the above component from an external happner client using the user with the name 'delegate_username' as follows: + const mySession = new LightClient({ secure: true, domain: 'meshname' }); + await mySession.connect({ + username: 'delegate_username', + password: 'password', + }); + const result = await mySession.exchange.$call({ + component: 'myComponent', + method: 'myMethod', + arguments: [1, 'delegate_username'], + as: 'some_other_username', + }); + // eslint-disable-next-line no-console + console.log(result); + // eslint-disable-next-line no-undef + assert(result === 'delegate_username called myMethod as some_other_username with param 1'); + await mesh.stop(); + process.exit(); +} + +start(); +``` + +#### from outside via a http RPC request: +*code taken from this [demo](https://github.com/happner/happner-suite/blob/develop/packages/demos/happner-2/security-exchange-as-http-rpc.js):* +``` javascript +const Mesh = require('happner-2'); +const assert = require('assert'); +const test = require('happn-commons-test').create(); +const axios = test.axios; + +async function start() { + class MyComponent { + async myMethod(param, originUsername, $origin) { + return `${originUsername} called myMethod as ${$origin.username} with param ${param}`; + } + } + + // set up the happner config + const happnerConfig = { + name: 'meshname', + secure: true, + modules: { + myComponent: { + instance: new MyComponent(), + }, + }, + components: { + myComponent: {}, + }, + }; + + //start the mesh + const mesh = await Mesh.create(happnerConfig); + + // access the security layer directly (not over websockets) + const security = mesh.exchange.security; + + //create our delegate user + await security.addUser({ + username: 'delegate_username', + password: 'password', + }); + + //link to the mesh delegate + await security.linkGroup('_MESH_DELEGATE', 'delegate_username'); + + //create our delegated user, allowed to call myOtherMethod only + await security.addUser({ + username: 'some_other_username', + password: 'password', + permissions: { + methods: { + //in a /Mesh name/component name/method name - with possible wildcards + '/meshname/myComponent/myMethod': { authorized: true }, + }, + }, + }); + + const token = ( + await axios.post(`http://127.0.0.1:55000/rest/login`, { + username: 'delegate_username', + password: 'password', + }) + ).data.data.token; + + const result = ( + await axios.post( + `http://127.0.0.1:55000/rest/method/myComponent/myMethod?happn_token=${token}`, + { + parameters: { + param: 1, + originUsername: 'delegate_username', + }, + as: 'some_other_username', + } + ) + ).data.data; + // eslint-disable-next-line no-console + console.log(result); + // eslint-disable-next-line no-undef + assert(result === 'delegate_username called myMethod as some_other_username with param 1'); + await mesh.stop(); + process.exit(); +} + +start(); + ``` ## lookup tables and permissions: @@ -434,7 +837,7 @@ adminClient.exchange.security.removeLookupPath(tableName, path); hardening responses: -------------------- -Currently happn clients are prevented from accessing the /_exchange/responses/[mesh name]/[component name]/[method name]/\* path using a regular expression check - injected into the underlying happn service by way of a [custom layer](https://github.com/happner/happner-2/blob/master/test/integration/mesh/happn-layer-middleware.js), [over here](https://github.com/happner/happner-2/blob/master/lib/system/happn.js#L222), a better solution to this, is to use the [targetClients functionality](https://github.com/happner/happn-3/blob/master/test/integration/api/targetclients.js) of happn-3, to push _response messages only to the origin of the _request. This is made possible by passing the directResponses:true option in the mesh config, as follows: +Currently happn clients are prevented from accessing the /_exchange/responses/[mesh name]/[component name]/[method name]/\* path using a regular expression check - injected into the underlying happn service by way of a [custom layer](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/test/integration/mesh/happn-layer-middleware.js), [over here](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/lib/system/happn.js#L222), a better solution to this, is to use the [targetClients functionality](https://github.com/happner/happn-3/blob/master/test/integration/api/targetclients.js) of happn-3, to push _response messages only to the origin of the _request. This is made possible by passing the directResponses:true option in the mesh config, as follows: ```javascript diff --git a/packages/happner-2/docs/walkthrough/the-basics.md b/packages/happner-2/docs/walkthrough/the-basics.md index c8cf1684c..5a275b1eb 100644 --- a/packages/happner-2/docs/walkthrough/the-basics.md +++ b/packages/happner-2/docs/walkthrough/the-basics.md @@ -117,28 +117,26 @@ module.exports = { // Datalayer and network layer are the same thing. happn: { - // host: '0.0.0.0', - port: 50505, // Listening port - persist: false, // Persist data across restarts? (later) - secure: false, // Secure? (later) - }, - - - // // modules only necessary upon deviation from default - // // https://github.com/happner/happner/blob/master/docs/configuration.md#module-config - // modules: { - // 'master': { - // path: 'to/alternative/location' - // } - // }, - - // Include master as component - // It assumes that 'master' is an installed node_module which exports 1 class - components: { - 'master': { + // host: '0.0.0.0', + port: 50505, // Listening port + persist: false, // Persist data across restarts? (later) + secure: false, // Secure? (later) + }, + + + // // modules only necessary upon deviation from default + // // https://github.com/happner/happner/blob/master/docs/configuration.md#module-config + // modules: { + // 'master': { + // path: 'to/alternative/location' + // } + // }, + + // Include master as component + // It assumes that 'master' is an installed node_module which exports 1 class + components: { + 'master': {} } - } - } ``` @@ -290,7 +288,7 @@ module.exports = { config: { host: process.env.MASTER_IP, port: process.env.MASTER_PORT, - // // Secure? (later) + // // secure? (later) // username: '', // password: '', } diff --git a/packages/happner-2/lib/mesh.js b/packages/happner-2/lib/mesh.js index 81302997e..48b799a27 100644 --- a/packages/happner-2/lib/mesh.js +++ b/packages/happner-2/lib/mesh.js @@ -79,7 +79,7 @@ Logger.emitter.on( // Quick start. module.exports.create = util.promisify(function MeshFactory(config, callback) { - // node -e 'require("happner").create()' + // node -e 'require("happner-2").create()' if (typeof config === 'function') { callback = config; config = {}; @@ -1171,7 +1171,7 @@ Mesh.prototype._destroyElement = util.promisify(function (componentName, callbac }, function (done) { - _this._mesh.elements[componentName].component.instance._detatch(_this._mesh, done); + _this._mesh.elements[componentName].component.instance.detatch(_this._mesh, done); }, function (done) { @@ -1587,8 +1587,12 @@ Mesh.prototype._scanArguments = function (spec, callback) { let $originSeq = args.indexOf(`$origin`); let $happnSeq = args.indexOf(`$happn`); - if ($happnSeq > -1) Object.defineProperty(module[fnName], `$happnSeq`, { value: $happnSeq }); - if ($originSeq > -1) Object.defineProperty(module[fnName], `$originSeq`, { value: $originSeq }); + if ($happnSeq > -1) { + Object.defineProperty(module[fnName], `$happnSeq`, { value: $happnSeq }); + } + if ($originSeq > -1) { + Object.defineProperty(module[fnName], `$originSeq`, { value: $originSeq }); + } module[fnName].$argumentsLength = args.filter( (argName) => ['$happn', '$origin'].indexOf(argName) === -1 @@ -1658,27 +1662,17 @@ Mesh.prototype._createComponent = function (spec, callback) { ); } }.bind(_this); - - //TODO - we need to remove routes somewhere too: - - componentInstance.initialize( - componentName, - root, - _this, - spec.module, - componentConfig, - function (e) { - if (e) return callback(e); - try { - __addComponentDataStoreRoutes(componentConfig); - } catch (e) { - return callback(new Error(`bad component data route: ${e.message}`)); - } - spec.component.instance = componentInstance; - _this._mesh.elements[componentName] = spec; - callback(); + componentInstance.initialize(componentName, _this, spec.module, componentConfig, function (e) { + if (e) return callback(e); + try { + __addComponentDataStoreRoutes(componentConfig); + } catch (e) { + return callback(new Error(`bad component data route: ${e.message}`)); } - ); + spec.component.instance = componentInstance; + _this._mesh.elements[componentName] = spec; + callback(); + }); }; Mesh.prototype._integrateComponent = function (spec, done) { @@ -1998,14 +1992,18 @@ Mesh.prototype.componentAsyncMethod = function ( call, done ) { - return component.instance.operate(options.methodName, [], (e, responseArgs) => { - delete calls[call]; - if (e) return done(e); - if (options.logAction) { - this.log.debug("%s component '%s'", options.logAction, componentName); + return component.instance.operate( + options.methodName, + options.methodArguments || [], + (e, responseArgs) => { + delete calls[call]; + if (e) return done(e); + if (options.logAction) { + this.log.debug("%s component '%s'", options.logAction, componentName); + } + done.apply(this, responseArgs); } - done.apply(this, responseArgs); - }); + ); }; Mesh.prototype.deferStartMethod = function (componentName, component, options, calls, call, done) { @@ -2015,6 +2013,49 @@ Mesh.prototype.deferStartMethod = function (componentName, component, options, c }); }; +Mesh.prototype.possiblyDeferStartup = function ( + componentName, + config, + component, + options, + calls, + call, + eachComponentCallback +) { + if ( + this._mesh.clusterClient && + this._mesh.clusterClient.__implementors.addAndCheckDependencies( + componentName, + config.dependencies + ) + ) { + // all dependencies have started so we can start + return this.componentAsyncMethod( + componentName, + component, + options, + calls, + call, + eachComponentCallback + ); + } + // wait for cluster dependencies to be satisfied + return this.deferStartMethod( + componentName, + component, + options, + calls, + call, + eachComponentCallback + ); +}; + +Mesh.prototype.getMethodArguments = function (methodConfig, removeUndefined) { + const methodArguments = (methodConfig?.parameters || []).map((p) => p.value); + if (removeUndefined) return _.without(methodArguments, undefined); + return methodArguments; +}; + Mesh.prototype._eachComponentDo = function (options, callback) { if (!options.methodCategory && !options.methodName) return callback(new MeshError('methodName or methodCategory not included in options')); @@ -2022,8 +2063,7 @@ Mesh.prototype._eachComponentDo = function (options, callback) { if (!options.flow) options.flow = 'series'; if (!options.targets) options.targets = Object.keys(this._mesh.elements); - var calls, - _this = this; + let calls; this._mesh.calls = this._mesh.calls || {}; this._mesh.calls.starting = calls = {}; @@ -2031,88 +2071,59 @@ Mesh.prototype._eachComponentDo = function (options, callback) { this._eachComponent( options.targets, options.flow, - function (componentName, component, done) { - var call, + (componentName, component, eachComponentCallback) => { + let call, config = component.config || {}; - if (options.methodCategory) options.methodName = config[options.methodCategory]; + if (options.methodCategory) { + options.methodName = config[options.methodCategory]; + } + + const methodConfig = commons._.get(config, `schema.methods.${options.methodName}`); if (!options.methodName) { - return done(); // error? + return eachComponentCallback(); } call = componentName + '.' + options.methodName + '()'; + calls[call] = Date.now(); - // default assume async with no args and callback as (error){} only - if (!config.schema || !config.schema.methods || !config.schema.methods[options.methodName]) { - calls[call] = Date.now(); - _this.log.$$TRACE("calling %s '%s' as default async", options.methodCategory, call); - let emptyDependencies = JSON.stringify(config.dependencies) === JSON.stringify({}); - - if (options.methodCategory === 'startMethod' && !_this._mesh.ignoreDependenciesOnStartup) { - if (config.dependencies && !emptyDependencies) { - if ( - _this._mesh.clusterClient && - _this._mesh.clusterClient.__implementors.addAndCheckDependencies( - componentName, - config.dependencies - ) - ) { - return _this.componentAsyncMethod( - componentName, - component, - options, - calls, - call, - done - ); - } - return _this.deferStartMethod(componentName, component, options, calls, call, done); - } - } - return _this.componentAsyncMethod(componentName, component, options, calls, call, done); - } + const methodArguments = this.getMethodArguments(methodConfig, options, true); + const methodOptions = Object.assign({ methodArguments }, options); - var methodConfig = config.schema.methods[options.methodName]; - var methodParameters = (methodConfig.parameters ? methodConfig.parameters : []) - .map(function (p) { - return p.value; - }) - .filter(function (p) { - // Assumes startMthod and stopMethod schema either defines values - // or are optional. Filter out undefines. - // IMPORTANT because otherwise method receives (undefined, undefined, undefined, callback) - return typeof p !== 'undefined'; - }); + this.log.$$TRACE( + `calling %s '%s' as type: ${methodConfig?.type || 'unconfigured'}`, + options.methodCategory, + call + ); - if (methodConfig.type === 'sync') { - try { - _this.log.$$TRACE("calling %s '%s' as configured sync", options.methodCategory, call); - component.instance.operate(options.methodName, methodParameters); - if (options.logAction) { - _this.log.debug("%s component '%s'", options.logAction, componentName); - } - } catch (e) { - done(new Error(e)); - return; - } - done(); - return; + if ( + options.methodCategory === 'startMethod' && + !this._mesh.ignoreDependenciesOnStartup && + !commons._.isEmpty(config.dependencies) + ) { + // we need to wait for dependencies to have started + return this.possiblyDeferStartup( + componentName, + config, + component, + methodOptions, + calls, + call, + eachComponentCallback + ); } - - calls[call] = Date.now(); - _this.log.$$TRACE("calling %s '%s' as configured async", options.methodCategory, call); - component.instance.operate(options.methodName, methodParameters, function (e, responseArgs) { - delete calls[call]; - if (e) return done(e); - if (options.logAction) { - _this.log.debug("%s component '%s'", options.logAction, componentName); - } - done.apply(_this, responseArgs); - }); + this.componentAsyncMethod( + componentName, + component, + methodOptions, + calls, + call, + eachComponentCallback + ); }, - function (e) { - callback(e, _this); + (e) => { + callback(e, this); } ); }; diff --git a/packages/happner-2/lib/modules/rest/index.js b/packages/happner-2/lib/modules/rest/index.js index 50e60592f..76eb0a62f 100644 --- a/packages/happner-2/lib/modules/rest/index.js +++ b/packages/happner-2/lib/modules/rest/index.js @@ -60,7 +60,7 @@ Rest.prototype.login = function ($happn, req, res) { Rest.prototype.describe = function ($happn, _req, res, $origin) { let description = utilities.clone(this.__exchangeDescription); - if (!$origin || $origin.username === '_ADMIN') + if (!$origin || $origin.username === '_ADMIN') { return this.__respond( $happn, $happn._mesh.description.name + ' description', @@ -68,14 +68,15 @@ Rest.prototype.describe = function ($happn, _req, res, $origin) { null, res ); + } async.eachSeries( Object.keys(description.callMenu), - (accessPoint, accessPointCB) => { - this.__authorizeAccessPoint($happn, $origin, accessPoint, (e, authorized) => { - if (e) return accessPointCB(e); - if (!authorized) delete description.callMenu[accessPoint]; - accessPointCB(); + (methodURI, methodURICB) => { + this.__authorizeMethod($happn, $origin, methodURI, (e, authorized) => { + if (e) return methodURICB(e); + if (!authorized) delete description.callMenu[methodURI]; + methodURICB(); }); }, (e) => { @@ -100,7 +101,7 @@ Rest.prototype.__respond = function ($happn, message, data, error, res, code) { //doing the replacements to the response string, allows us to stringify errors without issues. if (error) { - const stringifiedError = utilities.stringifyError(error); + const stringifiedError = utilities.stringifyError(error, false); if (!code) code = 500; responseString = responseString.replace('{{ERROR}}', stringifiedError); $happn.log.warn(`rpc request failure: ${error.message ? error.message : stringifiedError}`); @@ -115,18 +116,24 @@ Rest.prototype.__respond = function ($happn, message, data, error, res, code) { res.end(responseString); }; -Rest.prototype.__authorizeAccessPoint = function ($happn, $origin, accessPoint, callback) { - const name = $happn._mesh.config.domain || $happn._mesh.config.name; - - accessPoint = utilities.removeLeading('/', accessPoint); - accessPoint = '/_exchange/requests/' + name + '/' + accessPoint; +Rest.prototype.__authorizeMethod = function ($happn, $origin, methodURI, callback) { + const requestPath = `/_exchange/requests/${ + $happn._mesh.config.domain || $happn._mesh.config.name + }/${utilities.removeLeading('/', methodURI)}`; - this.__securityService.authorize($origin, accessPoint, 'set', function (e, authorized, reason) { + this.__securityService.authorize($origin, requestPath, 'set', function (e, authorized, reason) { callback(e, authorized, reason); }); }; -Rest.prototype.__authorize = function (res, $happn, $origin, uri, successful) { +Rest.prototype.__validateCredentialsGetOrigin = function ( + $happn, + $origin, + res, + methodURI, + authorizeAs, + successful +) { if (!$happn._mesh.config.happn.secure) { return successful(); } @@ -141,15 +148,70 @@ Rest.prototype.__authorize = function (res, $happn, $origin, uri, successful) { 403 ); } - - this.__authorizeAccessPoint($happn, $origin, uri, (e, authorized, reason) => { - if (e) return this.__respond($happn, 'Authorization failed', null, e, res, 403); - if (!authorized) { - if (!reason) reason = 'Authorization failed'; - return this.__respond($happn, reason, null, new Error('Access denied'), res, 403); + this.__getAuthorizedOrigin( + $happn, + $origin, + res, + methodURI, + authorizeAs, + (e, authorizedOrigin) => { + // this will not get hit on a 403 + if (e) { + if (e.message === 'origin does not belong to the delegate group') { + return this.__respond($happn, 'Authorization failed', null, e, res, 403); + } + this.__respond($happn, 'Authorization failed due to system error', null, e, res, 500); + return $happn.log.warn(`authorization system error: ${e.message}`); + } + successful(authorizedOrigin); } - successful(); - }); + ); +}; + +Rest.prototype.__getAuthorizedOrigin = function ( + $happn, + $origin, + res, + methodURI, + authorizeAs, + callback +) { + if (authorizeAs == null) { + // backward compatible, if the incoming request is not being delegated, we authorize on the edge + // then return the _ADMIN session so that method request further down the stack automatically work + return this.__authorizeMethod($happn, $origin, methodURI, (e, authorized, reason) => { + if (e) { + return callback(e); + } + if (authorized === false) { + // return 403 error + if (!reason) reason = 'Authorization failed'; + return this.__respond($happn, reason, null, new Error('Access denied'), res, 403); + } + callback(null, Object.assign({}, $origin, { edgeAuthorized: true })); + }); + } + if ($origin.username === '_ADMIN') { + return callback(null, Object.assign({}, $origin, { username: authorizeAs })); + } + let callbackWasCalled = false; + this.__securityService.users + .userBelongsToGroups($origin.username, ['_MESH_DELEGATE']) + .then((belongs) => { + callbackWasCalled = true; + if (!belongs) { + return callback(new Error('origin does not belong to the delegate group')); + } + return callback(null, Object.assign({}, $origin, { username: authorizeAs })); + }) + .catch((e) => { + if (callbackWasCalled) { + return $happn.log.warn( + `failure after getAuthorizedOrigin, and callback already called: origin ${$origin.username} authorizing as ${authorizeAs}}` + ); + } + return callback(e); + }); }; Rest.prototype.__parseBody = function (req, res, $happn, callback) { @@ -171,7 +233,6 @@ Rest.prototype.__parseBody = function (req, res, $happn, callback) { Rest.prototype.__processRequest = function (req, res, body, callPath, $happn, $origin) { process.nextTick(() => { - let mesh = $happn.exchange; let component; let method; let meshDescription; @@ -182,6 +243,14 @@ Rest.prototype.__processRequest = function (req, res, body, callPath, $happn, $o let componentName = callPath.pop(); let meshName = callPath.pop(); + let mesh = $happn.as( + $origin?.username, + componentName, + methodName, + 0, + $origin?.edgeAuthorized + ).exchange; + if (componentName === 'security') { return this.__respond( $happn, @@ -232,7 +301,6 @@ Rest.prototype.__processRequest = function (req, res, body, callPath, $happn, $o 404 ); } - method = component[methodName]; meshDescription = this.__exchangeDescription; @@ -240,8 +308,7 @@ Rest.prototype.__processRequest = function (req, res, body, callPath, $happn, $o methodDescription = componentDescription.methods[methodName]; const args = this.__mapMethodArguments(req, res, methodDescription, body, $happn, $origin); - - method.apply(method, args); + method.apply(Object.assign({}, method, { $origin }), args); }); }; @@ -254,7 +321,13 @@ Rest.prototype.__mapMethodArguments = function ( $origin ) { const __callback = (e, response) => { - if (e) return this.__respond($happn, 'Call failed', null, e, res, 500); + if (e) { + if (e.message === 'unauthorized') { + return this.__respond($happn, e.reason, null, new Error('Access denied'), res, 403); + } + //TODO: handle malformed errors as well + return this.__respond($happn, 'Call failed', null, e, res, 500); + } this.__respond($happn, 'Call successful', response, null, res); }; @@ -297,21 +370,31 @@ Rest.prototype.__mapMethodArguments = function ( Rest.prototype.handleRequest = function (req, res, $happn, $origin) { try { const methodURI = utilities.removeLeading('/', utilities.getRelativePath(req.url)); + const callPath = methodURI.split('/'); + //ensure we don't have a leading / + if (callPath.length > 4) { + return this.__respond( + $happn, + 'Failure parsing request body', + null, + new Error('call path cannot have more than 4 segments'), + res, + 400 + ); + } this.__parseBody(req, res, $happn, (body) => { - this.__authorize(res, $happn, $origin, '/' + methodURI, () => { - const callPath = methodURI.split('/'); - //ensure we don't have a leading / - if (callPath.length > 4) { - return this.__respond( - $happn, - 'Failure parsing request body', - null, - new Error('call path cannot have more than 4 segments'), - res - ); + let authorizeAs = body?.as; + this.__validateCredentialsGetOrigin( + $happn, + $origin, + res, + methodURI, + authorizeAs, + (authorizedOrigin) => { + // will not be hit on 403 + this.__processRequest(req, res, body, callPath, $happn, authorizedOrigin); } - this.__processRequest(req, res, body, callPath, $happn, $origin); - }); + ); }); } catch (e) { return this.__respond($happn, 'Call failed', null, e, res, 500); diff --git a/packages/happner-2/lib/modules/security/index.js b/packages/happner-2/lib/modules/security/index.js index 1bf252668..943004810 100644 --- a/packages/happner-2/lib/modules/security/index.js +++ b/packages/happner-2/lib/modules/security/index.js @@ -27,11 +27,11 @@ Security.prototype.__createSystemGroup = function (name, adminUser, permissions, Security.prototype.__createSystemGroups = function (adminUser, callback) { async.eachSeries( - ['_MESH_ADM', '_MESH_GST'], + ['_MESH_ADM', '_MESH_GST', '_MESH_DELEGATE'], (groupName, eachCallback) => { let permissions; - if (groupName === '_MESH_ADM') + if (groupName === '_MESH_ADM') { permissions = { '/mesh/*': { actions: ['*'], @@ -46,7 +46,8 @@ Security.prototype.__createSystemGroups = function (adminUser, callback) { description: 'mesh system permission', }, }; - if (groupName === '_MESH_GST') + } + if (groupName === '_MESH_GST') { permissions = { '/mesh/schema/*': { actions: ['get', 'on'], @@ -61,6 +62,23 @@ Security.prototype.__createSystemGroups = function (adminUser, callback) { description: 'mesh system request permission', }, }; + } + if (groupName === '_MESH_DELEGATE') { + permissions = { + '/mesh/*': { + actions: ['*'], + description: 'mesh system permission', + }, + '/_exchange/*': { + actions: ['*'], + description: 'mesh system permission', + }, + '/_events/*': { + actions: ['*'], + description: 'mesh system permission', + }, + }; + } this.__createSystemGroup(groupName, adminUser, permissions, eachCallback); }, callback @@ -145,10 +163,11 @@ Security.prototype.getComponentId = function () { }; Security.prototype.__validateRequest = function (methodName, callArguments, callback) { - if (!this.__initialized) + if (!this.__initialized) { return callback( new Error('security module not initialized, is your happn configured to be secure?') ); + } if (methodName === 'updateOwnUser') { var sessionInfo = callArguments[1]; @@ -270,16 +289,12 @@ Security.prototype.getSystemPermissions = function ($happn, params, callback) { }; Security.prototype.__getPermissionPath = function ($happn, rawPath, prefix, wildcard) { - var meshName = $happn.info.mesh.domain; - + const meshName = $happn.info.mesh.domain; //we add a wildcard to the end of the path // eslint-disable-next-line no-useless-escape if (wildcard) rawPath = rawPath.replace(/[\/*]+$/, '') + '/*'; - if (rawPath.substring(0, 1) !== '/') rawPath = '/' + rawPath; - if (rawPath.indexOf('/' + meshName) === -1) rawPath = rawPath.replace('/', '/' + meshName + '/'); - return '/' + prefix + rawPath; }; @@ -863,27 +878,56 @@ Security.prototype.unlinkAnonymousGroup = function ($happn, groupName, callback) }); }; +Security.prototype.__getGroupIfString = function (group, callback) { + if (typeof group !== 'string') return callback(null, group); + this.__securityService.groups.getGroup(group, (e, foundGroup) => { + if (e) return callback(e); + if (!foundGroup) return callback(new Error('group with name ' + group + ' does not exist')); + return callback(null, foundGroup); + }); +}; + +Security.prototype.__getUserIfString = function (user, callback) { + if (typeof user !== 'string') return callback(null, user); + this.__securityService.users.getUser(user, (e, foundUser) => { + if (e) return callback(e); + if (!foundUser) return callback(new Error('user with name ' + user + ' does not exist')); + return callback(null, foundUser); + }); +}; + Security.prototype.linkGroup = function ($happn, group, user, callback) { this.__validateRequest('linkGroup', arguments, (e) => { if (e) return callback(e); - this.__securityService.users.linkGroup( - this.__transformMeshGroup($happn, group), - user, - {}, - callback - ); + this.__getGroupIfString(group, (e, foundGroup) => { + if (e) return callback(e); + this.__getUserIfString(user, (e, foundUser) => { + if (e) return callback(e); + const transformedGroup = this.__transformMeshGroup($happn, foundGroup); + this.__securityService.users.linkGroup(transformedGroup, foundUser, {}, (e, result) => { + if (e) return callback(e); + callback(null, result); + }); + }); + }); }); }; Security.prototype.unlinkGroup = function ($happn, group, user, callback) { this.__validateRequest('unlinkGroup', arguments, (e) => { if (e) return callback(e); - this.__securityService.users.unlinkGroup( - this.__transformMeshGroup($happn, group), - user, - {}, - callback - ); + this.__getGroupIfString(group, (e, foundGroup) => { + if (e) return callback(e); + this.__getUserIfString(user, (e, foundUser) => { + if (e) return callback(e); + this.__securityService.users.unlinkGroup( + this.__transformMeshGroup($happn, foundGroup), + foundUser, + {}, + callback + ); + }); + }); }); }; diff --git a/packages/happner-2/lib/system/component-instance-bound-factory.js b/packages/happner-2/lib/system/component-instance-bound-factory.js new file mode 100644 index 000000000..2e724a2b4 --- /dev/null +++ b/packages/happner-2/lib/system/component-instance-bound-factory.js @@ -0,0 +1,255 @@ +const Internals = require('./shared/internals'); +module.exports = class ComponentInstanceBoundFactory { + #componentInstance; + #mesh; + #componentName; + #boundExchangeCache; + #config; + + get cache() { + return this.#boundExchangeCache; + } + + constructor(componentInstance, mesh) { + this.#componentInstance = componentInstance; + this.#mesh = mesh; + this.#componentName = componentInstance.name; + this.#config = componentInstance.config; + this.#initialize(); + } + static create(componentInstance, mesh) { + return new ComponentInstanceBoundFactory(componentInstance, mesh); + } + #initialize() { + this.#boundExchangeCache = this.#mesh.happn.server.services.cache.getOrCreate( + 'happner-bound-exchange-' + this.#componentName, + { + type: 'LRU', + cache: { + max: this.#mesh.config.boundExchangeCacheSize || 10e3, + }, + } + ); + this.#clearBoundComponentCache(); + //ensure if security changes, we discard bound exchanges + this.#mesh.happn.server.services.security.on( + 'security-data-changed', + this.#clearBoundComponentCache.bind(this) + ); + } + #clearBoundComponentCache() { + return this.#boundExchangeCache.clear(); + } + #getCachedBoundComponentKey(origin, componentName = '*', methodName = '*', sessionType) { + return `${origin.username}:${componentName}:${methodName}:${sessionType}`; + } + #getCachedBoundComponent(origin, componentName, methodName, sessionType) { + return this.#boundExchangeCache.get( + this.#getCachedBoundComponentKey(origin, componentName, methodName, sessionType), + { + clone: false, + } + ); + } + #setCachedBoundComponent(origin, componentName, methodName, sessionType, exchange) { + this.#boundExchangeCache.set( + this.#getCachedBoundComponentKey(origin, componentName, methodName, sessionType), + exchange, + { + clone: false, + } + ); + return exchange; + } + // sometimes we want to stay bound regardless of whether the edge is authorized, this is when we are getting a bound component + // as opposed to doing the authorization in the component-instance + originBindingNecessary(origin, override, checkEdgeAuthorized = false) { + //not a secure mesh: + if (!this.#mesh.config.happn.secure) { + return false; + } + //null origin is an internal function: + if (origin == null) { + return false; + } + //don't delegate authority to _ADMIN, no origin is also an internal call: + if (origin?.username === '_ADMIN') { + return false; + } + // backward compatible edge authorization that allows _ADMIN passthrough on subsequent inter exchange requests + // when no "as" is specified + const edgeAuthorized = checkEdgeAuthorized && origin?.edgeAuthorized === true; + + // auth delegation is switched on specifically for this component or mesh-wide + const authDelegationOn = + this.#config?.security?.authorityDelegationOn === true || + this.#mesh?.config?.authorityDelegationOn === true; + + // auth delegation is off, and we have already authorized at the edge + if (edgeAuthorized && !authDelegationOn) { + return false; + } + + //origin binding for this request specifically, regardless of security settings + if (typeof override === 'boolean') { + return override; + } + + //origin binding for this origin specifically, regardless of security settings + if (typeof origin?.override === 'boolean') { + return origin.override; + } + + //mesh-wide auth delegation is on, but this component specifically is off + if (authDelegationOn && this.#config?.security?.authorityDelegationOn === false) { + return false; + } + + return authDelegationOn; + } + getBoundComponent(origin, override, componentName, methodName, sessionType = 1) { + if (!this.originBindingNecessary(origin, override)) { + return this.#componentInstance; + } + let bound = this.#getCachedBoundComponent(origin, componentName, methodName, sessionType); + if (bound) return bound; + + bound = Object.assign({}, this.#componentInstance); + bound.as = this.#componentInstance.as.bind(this.#componentInstance); + + Object.defineProperty(bound, 'info', { + value: this.#componentInstance.info, + writable: false, + }); + Object.defineProperty(bound, 'config', { + value: this.#componentInstance.config, + writable: false, + }); + Object.defineProperty(bound, 'log', { + value: this.#componentInstance.log, + writable: false, + }); + Object.defineProperty(bound, 'name', { + value: this.#componentInstance.name, + writable: false, + }); + //access level is down to _mesh in actual component + Object.defineProperty(bound, '_mesh', { + value: this.#componentInstance._mesh, + writable: false, + }); + //backward compatability for deprecation + Object.defineProperty(bound, 'mesh', { + get: () => { + return this.#componentInstance.mesh; + }, + }); + const boundOrigin = Object.assign({}, origin, { override: true, type: sessionType }); + Object.defineProperty(bound, 'bound', { + value: boundOrigin, + writable: false, + }); + + bound.data = require('./component-instance-data').create( + this.#mesh.data, + this.#componentName, + boundOrigin + ); + bound.exchange = this.#secureExchangeBoundToOrigin( + this.#componentInstance.exchange, + boundOrigin, + componentName, + methodName + ); + bound.event = this.#secureEventBoundToOrigin( + this.#componentInstance.event, + boundOrigin, + componentName + ); + return this.#setCachedBoundComponent( + boundOrigin, + componentName, + methodName, + sessionType, + bound + ); + } + + #secureExchangeBoundToOriginMethods(component, boundComponent, origin, methodName) { + Object.keys(component) + .filter((exchangeMethodName) => { + return methodName != null ? exchangeMethodName === methodName : true; + }) + .forEach((methodName) => { + if (typeof component[methodName] === 'function') { + boundComponent[methodName] = component[methodName].bind({ + $self: component[methodName], + $origin: origin, + }); + return; + } + // for nested methods, recursive + if (typeof component[methodName] === 'object') { + boundComponent[methodName] = {}; + return this.#secureExchangeBoundToOriginMethods( + component[methodName], + boundComponent[methodName], + origin + ); + } + boundComponent[methodName] = component[methodName]; + }); + } + #secureExchangeBoundToOrigin(exchange, origin, componentName, methodName) { + const boundExchange = {}; + Object.keys(exchange) + .filter((exchangeComponentName) => { + return componentName != null ? exchangeComponentName === componentName : true; + }) + .forEach((componentName) => { + if (componentName === '$call') { + boundExchange.$call = Internals._createDecoupledCall(boundExchange); + return; + } + boundExchange[componentName] = {}; + this.#secureExchangeBoundToOriginMethods( + exchange[componentName], + boundExchange[componentName], + origin, + methodName + ); + }); + return boundExchange; + } + #secureEventBoundToOrigin(event, origin, componentName) { + const boundEvent = {}; + Object.keys(event) + .filter((exchangeComponentName) => { + return componentName != null ? exchangeComponentName === componentName : true; + }) + .forEach(function (componentName) { + //special $call method - not an event api + if (componentName === '$call') return; + boundEvent[componentName] = {}; + if (event[componentName].__endpoint) { + boundEvent[componentName] = Internals._getSubscriber( + event[componentName].__endpoint, + event[componentName].__domain, + componentName, + origin.username + ); + return; + } + Object.keys(event[componentName]).forEach(function (subComponentName) { + if (event[componentName][subComponentName].__endpoint) + boundEvent[componentName][subComponentName] = Internals._getSubscriber( + event[componentName][subComponentName].__endpoint, + event[componentName][subComponentName].__domain, + subComponentName, + origin.username + ); + }); + }); + return boundEvent; + } +}; diff --git a/packages/happner-2/lib/system/component-instance-data.js b/packages/happner-2/lib/system/component-instance-data.js new file mode 100644 index 000000000..4c51f93bc --- /dev/null +++ b/packages/happner-2/lib/system/component-instance-data.js @@ -0,0 +1,206 @@ +module.exports = class SecureMeshData { + #meshData; + #componentName; + #persistedPath; + #origin; + constructor(meshData, componentName, origin) { + this.#meshData = meshData; + this.#componentName = componentName; + this.#persistedPath = '/_data/' + this.#componentName; + this.#origin = origin; + } + static create(meshData, componentName, origin) { + return new SecureMeshData(meshData, componentName, origin); + } + noConnection() { + return [1, 6].indexOf(this.#meshData.status) === -1; + } + #connectionValid(path, action, callback) { + if (this.noConnection()) { + callback( + new Error( + `client state not active or connected, action: ${action}, path: ${path}, component: ${ + this.#componentName + }` + ) + ); + return false; + } + return true; + } + #getPath(path) { + if (typeof path !== 'string' || path.length === 0) { + return '[bad path]: either empty or not a string'; + } + if (path[0] !== '/') path = '/' + path; + return this.#persistedPath + path; + } + + on(path, options, handler, callback) { + if (typeof options === 'function') { + callback = handler; + handler = options; + options = {}; + } + + if (!options) options = {}; + if (this.#origin) options.onBehalfOf = this.#origin.username; + + if (!this.#connectionValid(path, 'on', callback)) { + return; + } + + let componentPath; + if (path === '*') path = '**'; + if ((componentPath = this.#getPath(path)) === `[bad path]: either empty or not a string`) { + return callback(new Error(componentPath)); + } + this.#meshData.on(componentPath, options, handler, callback); + } + + off(listenerRef, callback) { + if (!this.#connectionValid(listenerRef, 'off', callback)) { + return; + } + if (typeof listenerRef === 'number') { + return this.#meshData.off(listenerRef, callback); + } + let componentPath; + if ( + (componentPath = this.#getPath(listenerRef)) === `[bad path]: either empty or not a string` + ) { + return callback(new Error(componentPath)); + } + this.#meshData.off(componentPath, callback); + } + + offAll(callback) { + if (!this.#connectionValid('*', 'offAll', callback)) { + return; + } + //we cannot do a true offAll, otherwise we get no message back + this.#meshData.offPath(this.#getPath('*'), callback); + } + + offPath(path, callback) { + if (!this.#connectionValid(path, 'offPath', callback)) { + return; + } + let componentPath; + if ((componentPath = this.#getPath(path)) === `[bad path]: either empty or not a string`) { + return callback(new Error(componentPath)); + } + this.#meshData.offPath(componentPath, callback); + } + + get(path, options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + if (!this.#connectionValid(path, 'get', callback)) { + return; + } + + if (!options) options = {}; + if (this.#origin) options.onBehalfOf = this.#origin.username; + + let componentPath; + if ((componentPath = this.#getPath(path)) === `[bad path]: either empty or not a string`) { + return callback(new Error(componentPath)); + } + return this.#meshData.get(componentPath, options, callback); + } + + count(path, options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + if (!this.#connectionValid(path, 'count', callback)) { + return; + } + if (!options) options = {}; + if (this.#origin) options.onBehalfOf = this.#origin.username; + let componentPath; + if ((componentPath = this.#getPath(path)) === `[bad path]: either empty or not a string`) { + return callback(new Error(componentPath)); + } + return this.#meshData.count(componentPath, options, callback); + } + + getPaths(path, callback) { + if (!this.#connectionValid(path, 'getPaths', callback)) { + return; + } + let options = {}; + if (this.#origin) options.onBehalfOf = this.#origin.username; + let componentPath; + if ((componentPath = this.#getPath(path)) === `[bad path]: either empty or not a string`) { + return callback(new Error(componentPath)); + } + return this.#meshData.getPaths(componentPath, options, callback); + } + + set(path, data, options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + + if (!this.#connectionValid(path, 'set', callback)) { + return; + } + + if (!options) options = {}; + if (this.#origin) options.onBehalfOf = this.#origin.username; + + let componentPath; + if ((componentPath = this.#getPath(path)) === `[bad path]: either empty or not a string`) { + return callback(new Error(componentPath)); + } + return this.#meshData.set(componentPath, data, options, callback); + } + + increment(path, gauge, increment, callback) { + if (typeof increment === 'function') { + callback = increment; + increment = gauge; + gauge = 'counter'; + } + + if (typeof gauge === 'function') { + callback = gauge; + increment = 1; + gauge = 'counter'; + } + + if (!this.#connectionValid(path, 'increment', callback)) { + return; + } + let options = {}; + if (this.#origin) options.onBehalfOf = this.#origin.username; + let componentPath; + if ((componentPath = this.#getPath(path)) === `[bad path]: either empty or not a string`) { + return callback(new Error(componentPath)); + } + return this.#meshData.increment(componentPath, gauge, increment, options, callback); + } + + remove(path, options, callback) { + if (typeof options === 'function') { + callback = options; + options = {}; + } + if (!this.#connectionValid(path, 'remove', callback)) { + return; + } + if (!options) options = {}; + if (this.#origin) options.onBehalfOf = this.#origin.username; + let componentPath; + if ((componentPath = this.#getPath(path)) === `[bad path]: either empty or not a string`) { + return callback(new Error(componentPath)); + } + return this.#meshData.remove(componentPath, options, callback); + } +}; diff --git a/packages/happner-2/lib/system/component-instance.js b/packages/happner-2/lib/system/component-instance.js index 05f004ff9..8690d6216 100644 --- a/packages/happner-2/lib/system/component-instance.js +++ b/packages/happner-2/lib/system/component-instance.js @@ -1,752 +1,125 @@ -const Internals = require('./shared/internals'); -const MeshError = require('./shared/mesh-error'); -const EventEmitter = require('events').EventEmitter; -let depWarned0 = false; // $happn.mesh.* +const commons = require('happn-commons'); const utilities = require('./utilities'); -const _ = require('happn-commons')._; - -module.exports = ComponentInstance; - -function ComponentInstance() { - this.localEventEmitter = new EventEmitter(); - this.semver = require('happner-semver'); -} - -ComponentInstance.prototype.clearCachedBoundExchange = function () { - if (!this.boundExchangeCache) return; - return this.boundExchangeCache.clear(); -}; - -ComponentInstance.prototype.initializeCachedBoundExchange = function (mesh, componentName) { - this.boundExchangeCache = mesh.happn.server.services.cache.getOrCreate( - 'happner-bound-exchange-' + componentName, - { - type: 'LRU', - cache: { - max: mesh.config.boundExchangeCacheSize || 10e3, - }, - } - ); - this.clearCachedBoundExchange(); - //ensure if security changes, we discard bound exchanges - mesh.happn.server.services.security.on( - 'security-data-changed', - this.clearCachedBoundExchange.bind(this) - ); -}; - -ComponentInstance.prototype.getCachedBoundExchange = function (origin) { - if (!this.boundExchangeCache) return null; - return this.boundExchangeCache.get(origin.username, { - clone: false, - }); -}; - -ComponentInstance.prototype.setCachedBoundExchange = function (origin, exchange) { - if (!this.boundExchangeCache) return exchange; - this.boundExchangeCache.set(origin.username, exchange, { - clone: false, - }); - return exchange; -}; - -ComponentInstance.prototype.originBindingNecessary = function (mesh, origin) { - //dont delegate authority to _ADMIN, no origin is an internal call: - if (!origin || origin.username === '_ADMIN') return false; - //not a secure mesh: - if (!mesh.config.happn.secure) return false; - //authority delegation not set up on component, and not set up on the server - if ( - (!this.config.security || this.config.security.authorityDelegationOn == null) && - !mesh.config.authorityDelegationOn - ) - return false; - //authority delegation explicitly set not to happen for this component - if (this.config.security && this.config.security.authorityDelegationOn === false) return false; - - return true; -}; - -const bindToOrigin = function (root, mesh, origin) { - if (!this.originBindingNecessary(mesh, origin)) { +const EventEmitter = require('events').EventEmitter; +const semver = require('happner-semver'); +module.exports = class ComponentInstance { + #authorizer; + #log; + #name; + #config; + #info; + #mesh; + #module; + #callbackIndexes; + #localEventEmitter; + #boundComponentInstanceFactory; + #tools; + constructor() { + this.#callbackIndexes = {}; + this.#localEventEmitter = new EventEmitter(); + } + get Mesh() { + // local Mesh definition avaliable on $happn + return require('../mesh'); + } + get name() { + return this.#name; + } + get config() { + return this.#config; + } + get info() { + return this.#info; + } + get mesh() { + this.#log.warn('Use of $happn.mesh.* is deprecated. Use $happn.*'); return this; } - - var bound = this.getCachedBoundExchange(origin); - if (bound) return bound; - - bound = Object.assign({}, this); - - bound.data = this.secureDataBoundToOrigin(mesh.data, this.name, origin); - bound.exchange = this.secureExchangeBoundToOrigin(this.exchange, origin); - bound.event = this.secureEventBoundToOrigin(this.event, origin); - - if (mesh.serializer) { - Object.defineProperty(bound, 'serializer', { - value: mesh._mesh.serializer, - }); + get module() { + return this.#module; } - - if (this.config.accessLevel === 'root') { - Object.defineProperty(bound, '_root', { - get: function () { - return root; - }, - enumerable: true, - }); + get log() { + return this.#log; } - - if (this.config.accessLevel === 'mesh' || this.config.accessLevel === 'root') { - Object.defineProperty(bound, '_mesh', { - get: function () { - return mesh; - }, - enumerable: true, - }); + get localEventEmitter() { + return this.#localEventEmitter; + } + //used by mesh & packager + get tools() { + return this.#tools; } - return this.setCachedBoundExchange(origin, bound); -}; - -ComponentInstance.prototype.secureExchangeBoundToOriginMethods = function ( - component, - boundComponent, - origin -) { - if (typeof component !== 'object') return; - - Object.keys(component).forEach((methodName) => { - if (typeof component[methodName] === 'function') { - boundComponent[methodName] = component[methodName].bind({ - $self: component[methodName], - $origin: origin, - }); - return; - } - if (typeof component[methodName] === 'object') { - boundComponent[methodName] = {}; - return this.secureExchangeBoundToOriginMethods( - component[methodName], - boundComponent[methodName], - origin - ); - } - boundComponent[methodName] = component[methodName]; - }); -}; - -ComponentInstance.prototype.secureExchangeBoundToOrigin = function (exchange, origin) { - const boundExchange = {}; - Object.keys(exchange).forEach((componentName) => { - if (componentName === '$call') { - boundExchange.$call = Internals._createDecoupledCall(boundExchange); - return; - } - boundExchange[componentName] = {}; - this.secureExchangeBoundToOriginMethods( - exchange[componentName], - boundExchange[componentName], - origin - ); - }); - return boundExchange; -}; - -ComponentInstance.prototype.secureEventBoundToOrigin = function (event, origin) { - const boundEvent = {}; - - Object.keys(event).forEach(function (componentName) { - //special $call method - not an event api - if (componentName === '$call') return; - boundEvent[componentName] = {}; - if (event[componentName].__endpoint) { - boundEvent[componentName] = Internals._getSubscriber( - event[componentName].__endpoint, - event[componentName].__domain, - componentName, - origin.username - ); - return; - } - Object.keys(event[componentName]).forEach(function (subComponentName) { - if (event[componentName][subComponentName].__endpoint) - boundEvent[componentName][subComponentName] = Internals._getSubscriber( - event[componentName][subComponentName].__endpoint, - event[componentName][subComponentName].__domain, - subComponentName, - origin.username - ); - }); - }); - return boundEvent; -}; - -ComponentInstance.prototype.secureDataBoundToOrigin = function (meshData, componentName, origin) { - var securedMeshData = {}; - - securedMeshData.__persistedPath = '/_data/' + componentName; - - securedMeshData.getPath = function (path) { - if (!path) throw new Error('invalid path: ' + path); - if (path[0] !== '/') path = '/' + path; - - return this.__persistedPath + path; - }; - - securedMeshData.noConnection = function () { - return [1, 6].indexOf(meshData.status) === -1; - }; - - securedMeshData.on = function (path, options, handler, callback) { - if (typeof options === 'function') { - callback = handler; - handler = options; - options = {}; - } - - if (!options) options = {}; - options.onBehalfOf = origin.username; - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, on:' + path + ', component:' + componentName - ) - ); - if (path === '*') path = '**'; - - return meshData.on(this.getPath(path), options, handler, callback); - }; - - securedMeshData.off = function (listenerRef, callback) { - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, off ref:' + - listenerRef + - ', component:' + - componentName - ) - ); - - if (typeof listenerRef === 'number') return meshData.off(listenerRef, callback); - - return meshData.off(this.getPath(listenerRef), callback); - }; - - securedMeshData.offAll = function (callback) { - if (this.noConnection()) - return callback( - new Error('client state not active or connected, offAll, component:' + componentName) - ); - - //we cannot do a true offAll, otherwise we get no message back - return meshData.offPath(this.getPath('*'), callback); - }; - - securedMeshData.offPath = function (path, callback) { - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, offPath:' + path + ', component:' + componentName - ) - ); - - return meshData.offPath(this.getPath(path), callback); - }; - - securedMeshData.get = function (path, options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, get:' + path + ', component:' + componentName - ) - ); - - if (!options) options = {}; - options.onBehalfOf = origin.username; - - return meshData.get(this.getPath(path), options, callback); - }; - - securedMeshData.count = function (path, options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, get:' + path + ', component:' + componentName - ) - ); - - if (!options) options = {}; - options.onBehalfOf = origin.username; - - return meshData.count(this.getPath(path), options, callback); - }; - - securedMeshData.getPaths = function (path, callback) { - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, getPaths:' + path + ', component:' + componentName - ) - ); - return meshData.getPaths(this.getPath(path), { onBehalfOf: origin.username }, callback); - }; - - securedMeshData.set = function (path, data, options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, set:' + path + ', component:' + componentName - ) - ); - if (!options) options = {}; - options.onBehalfOf = origin.username; - - return meshData.set(this.getPath(path), data, options, callback); - }; - - securedMeshData.increment = function (path, gauge, increment, callback) { - if (typeof increment === 'function') { - callback = increment; - increment = gauge; - gauge = 'counter'; - } - - if (typeof gauge === 'function') { - callback = gauge; - increment = 1; - gauge = 'counter'; - } - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, increment:' + path + ', component:' + componentName - ) - ); - //TODO: get paths needs to be done by origin - return meshData.increment( - this.getPath(path), - gauge, - increment, - { onBehalfOf: origin.username }, - callback - ); - }; - - securedMeshData.setSibling = function (path, data, callback) { - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, setSibling:' + - path + - ', component:' + - componentName - ) - ); - //TODO: get paths needs to be done by origin - return meshData.setSibling(this.getPath(path), data, { onBehalfOf: origin.username }, callback); - }; - - securedMeshData.remove = function (path, options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, remove:' + path + ', component:' + componentName - ) - ); - if (!options) options = {}; - options.onBehalfOf = origin.username; - return meshData.remove(this.getPath(path), options, callback); - }; - - return securedMeshData; -}; - -ComponentInstance.prototype.secureData = function (meshData, componentName) { - var securedMeshData = {}; - securedMeshData.__persistedPath = '/_data/' + componentName; - - securedMeshData.getPath = function (path) { - if (!path) throw new Error('invalid path: ' + path); - if (path[0] !== '/') path = '/' + path; - - return this.__persistedPath + path; - }; - - securedMeshData.noConnection = function () { - return [1, 6].indexOf(meshData.status) === -1; - }; - - securedMeshData.on = function (path, options, handler, callback) { - if (typeof options === 'function') { - callback = handler; - handler = options; - options = {}; - } - - if (!options) options = {}; - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, on:' + path + ', component:' + componentName - ) - ); - - if (path === '*') path = '**'; - - return meshData.on(this.getPath(path), options, handler, callback); - }; - - securedMeshData.off = function (listenerRef, callback) { - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, off ref:' + - listenerRef + - ', component:' + - componentName - ) - ); - - if (typeof listenerRef === 'number') return meshData.off(listenerRef, callback); - - return meshData.off(this.getPath(listenerRef), callback); - }; - - securedMeshData.offAll = function (callback) { - if (this.noConnection()) - return callback( - new Error('client state not active or connected, offAll, component:' + componentName) - ); - - //we cannot do a true offAll, otherwise we get no message back - return meshData.offPath(this.getPath('*'), callback); - }; - - securedMeshData.offPath = function (path, callback) { - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, offPath:' + path + ', component:' + componentName - ) - ); - - return meshData.offPath(this.getPath(path), callback); - }; - - securedMeshData.get = function (path, options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, get:' + path + ', component:' + componentName - ) - ); - - return meshData.get(this.getPath(path), options, callback); - }; - - securedMeshData.count = function (path, options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, get:' + path + ', component:' + componentName - ) - ); - - return meshData.count(this.getPath(path), options, callback); - }; - - securedMeshData.getPaths = function (path, callback) { - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, getPaths:' + path + ', component:' + componentName - ) - ); - - return meshData.getPaths(this.getPath(path), callback); - }; - - securedMeshData.set = function (path, data, options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, set:' + path + ', component:' + componentName - ) - ); - return meshData.set(this.getPath(path), data, options, callback); - }; - - securedMeshData.increment = function (path, gauge, increment, callback) { - if (typeof increment === 'function') { - callback = increment; - increment = gauge; - gauge = 'counter'; - } - - if (typeof gauge === 'function') { - callback = gauge; - increment = 1; - gauge = 'counter'; - } - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, increment:' + path + ', component:' + componentName - ) - ); - - return meshData.increment(this.getPath(path), gauge, increment, callback); - }; - - securedMeshData.setSibling = function (path, data, callback) { - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, setSibling:' + - path + - ', component:' + - componentName - ) - ); - - return meshData.setSibling(this.getPath(path), data, callback); - }; - - securedMeshData.remove = function (path, options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; - } - - if (this.noConnection()) - return callback( - new Error( - 'client state not active or connected, remove:' + path + ', component:' + componentName - ) - ); - - return meshData.remove(this.getPath(path), options, callback); - }; - - return securedMeshData; -}; - -ComponentInstance.prototype.initialize = function (name, root, mesh, module, config, callback) { - // eslint-disable-next-line no-self-assign - this.README = this.README; // make visible - this.name = name; - this.config = config; - - this.info = { - mesh: {}, // name, - happn: {}, // address, options - }; - - this.log = mesh._mesh.log.createLogger(this.name); - this.Mesh = require('../mesh'); // local Mesh definition avaliable on $happn - this.log.$$TRACE('create instance'); - - this.initializeCachedBoundExchange(mesh._mesh, this.name); - - var _this = this; - - const authorizer = require('./authorizer').create( - mesh._mesh.happn.server.services.security, - mesh._mesh.happn.server.services.session, - mesh._mesh.data - ); - - Object.defineProperty(_this, '__authorizer', { - get: function () { - return authorizer; - }, - }); - - Object.defineProperty(_this, 'mesh', { - get: function () { - if (depWarned0) return _this; - _this.log.warn('Use of $happn.mesh.* is deprecated. Use $happn.*'); - try { - _this.log.warn(' - at %s', mesh.getCallerTo('componentInstance.js')); - } catch (e) { - // do nothing - } - depWarned0 = true; - return _this; - }, - }); - - Object.defineProperty(_this, '__authorizeOriginMethod', { - get: function () { - return function (methodName, origin, callback) { - if (!_this.originBindingNecessary(mesh._mesh, origin)) return callback(null, true); - - var subscribeMask = _this.__getSubscribeMask(); - var permissionPath = subscribeMask.substring(0, subscribeMask.length - 1) + methodName; - - mesh._mesh.happn.server.services.security.__getOnBehalfOfSession( - { - user: { - username: '_ADMIN', - }, - }, - origin.username, - function (e, originSession) { - if (e) return callback(e); - mesh._mesh.happn.server.services.security.authorize( - originSession, - permissionPath, - 'set', - function (e, authorized) { - if (e) return callback(e); - if (!authorized) - return callback( - mesh._mesh.happn.server.services.error.AccessDeniedError( - 'unauthorized', - 'request on behalf of: ' + origin.username - ) - ); - callback(); - } - ); - } - ); - }; - }, - enumerable: true, - }); - - Object.defineProperty(_this, 'isAuthorized', { - get: function () { - return async (username, permissions) => { - return await _this.__authorizer.checkAuthorizations(username, permissions); - }; - }, - }); - - Object.defineProperty(_this, 'tools', { - get: function () { - return mesh.tools; - }, - enumerable: true, - }); - - var defaults; - - //TODO, here are the module.packaged settings + async isAuthorized(username, permissions) { + return await this.#authorizer.checkAuthorizations(username, permissions); + } - if (typeof (defaults = module.instance.$happner) === 'object') { - if (defaults.config && defaults.config.component) { - Object.keys((defaults = defaults.config.component)).forEach((key) => { + #defaults(config) { + try { + const defaults = this.#module.instance?.$happner?.config?.component; + Object.keys(defaults).forEach((key) => { // - Defaulting applies only to the 'root' keys nested immediately // under the 'component' config // - Does not merge. // - Each key in the default is only used if the corresponding key is // not present in the inbound config. - if (typeof this.config[key] === 'undefined') { - this.config[key] = utilities.clone(defaults[key]); + if (config[key] === undefined) { + config[key] = commons.fastClone(defaults[key]); } }); + } catch (e) { + //do nothing, defaults is null or not object } + return config; } - Object.defineProperty(this.info.mesh, 'name', { - enumerable: true, - value: mesh._mesh.config.name, - }); - - Object.defineProperty(this.info.mesh, 'domain', { - enumerable: true, - value: mesh._mesh.config.domain, - }); - - Object.defineProperty(this.info.happn, 'address', { - enumerable: true, - get: function () { - var address = mesh._mesh.happn.server.server.address(); - // TODO: ideally this value would come from the actual server, not the config - try { - address.protocol = mesh._mesh.config.happn.services.transport.config.mode; - } catch (e) { - address.protocol = 'http'; - } - return address; - }, - }); - - Object.defineProperty(this.info.happn, 'options', { - enumerable: true, - get: function () { - return mesh._mesh.config.happn.setOptions; // TODO: should rather point to actual happn options, - // it may have defaulted more than we passed in. - }, - }); - - if (mesh._mesh.serializer) { - Object.defineProperty(this, 'serializer', { - value: mesh._mesh.serializer, - }); - } + initialize(name, mesh, module, config, callback) { + this.#module = module; + this.#mesh = mesh; + this.#name = name; + this.#config = this.#defaults(config); + this.#tools = mesh.tools; + + this.#info = { + mesh: { + name: mesh._mesh.config.name, + domain: mesh._mesh.config.domain, + }, // name, + happn: { + options: mesh._mesh.config.happn.setOptions, + }, // address, options + }; - if (config.accessLevel === 'root') { - Object.defineProperty(this, '_root', { - get: function () { - return root; - }, - enumerable: true, - }); - } + this.#log = mesh._mesh.log.createLogger(this.name); + this.#log.trace('create instance'); - if (config.accessLevel === 'mesh' || config.accessLevel === 'root') { - Object.defineProperty(this, '_mesh', { + this.#authorizer = require('./authorizer').create( + mesh._mesh.happn.server.services.security, + mesh._mesh.happn.server.services.session, + mesh._mesh.data + ); + + Object.defineProperty(this.#info.happn, 'address', { + enumerable: true, get: function () { - return mesh._mesh; + var address = mesh._mesh.happn.server.server.address(); + try { + address.protocol = mesh._mesh.config.happn.services.transport.config.mode; + } catch (e) { + address.protocol = 'http'; + } + return address; }, - enumerable: true, }); - } - try { + if (this.#config.accessLevel === 'mesh' || this.#config.accessLevel === 'root') { + Object.defineProperty(this, '_mesh', { + get: function () { + return mesh._mesh; + }, + enumerable: true, + }); + } + // Each component has it's own exchange // to allow happner-cluster to replace components with the proper from elsewhere in the cluster // without affecting other components. @@ -759,707 +132,716 @@ ComponentInstance.prototype.initialize = function (name, root, mesh, module, con this.event = {}; this.localEvent = {}; this.asAdmin = this; //in case we use $happn.asAdmin but have not bound to origin - - this.data = this.secureData(mesh._mesh.data, this.name); - - Object.defineProperty(this, 'bindToOrigin', { - get: function () { - return bindToOrigin.bind(this, root, mesh._mesh); - }, - enumerable: true, - }); - - this._loadModule(module); - this._attach(config, mesh._mesh, callback); - } catch (err) { - callback(new MeshError('Failed to initialize component', err)); - } -}; - -ComponentInstance.prototype.satisfies = function (moduleVersion, version) { - return this.semver.coercedSatisfies(moduleVersion, version); -}; - -ComponentInstance.prototype.on = function (event, handler) { - try { - this.log.$$TRACE('component on called', event); - return this.localEventEmitter.on(event, handler); - } catch (e) { - this.log.$$TRACE('component on error', e); - } -}; - -ComponentInstance.prototype.offEvent = function (event, handler) { - try { - this.log.$$TRACE('component offEvent called', event); - return this.localEventEmitter.offEvent(event, handler); - } catch (e) { - this.log.$$TRACE('component offEvent error', e); - } -}; - -ComponentInstance.prototype.emitEvent = function (event, data) { - try { - this.log.$$TRACE('component emitEvent called', event); - return this.localEventEmitter.emit(event, data); - } catch (e) { - this.log.$$TRACE('component emitEvent error', e); - } -}; - -ComponentInstance.prototype.__getMethodDefn = function (config, methodName) { - if (!config.schema) return; - if (!config.schema.methods) return; - if (!config.schema.methods[methodName]) return; - return config.schema.methods[methodName]; -}; - -ComponentInstance.prototype.__parseWebRoutes = function () { - const webMethods = {}; // accum list of webMethods to exclude from exhange methods description - const routes = this.config.web.routes; - Object.keys(routes).forEach((routePath) => { - let route = routes[routePath]; - - if (route instanceof Array) - route.forEach(function (method) { - webMethods[method] = 1; - route = method; // last in route array is used to determine type: static || mware - }); - else webMethods[route] = 1; - - if (routePath === 'static') routePath = '/'; - else if (this.name === 'www' && routePath === 'global') return; - else if (this.name === 'www' && routePath !== 'global') routePath = '/' + routePath; - else if (routePath === 'resources' && this.name === 'resources') routePath = '/' + routePath; - else routePath = '/' + this.name + '/' + routePath; - - this.description.routes[routePath] = {}; - this.description.routes[routePath].type = route === 'static' ? 'static' : 'mware'; - }); - return webMethods; -}; - -ComponentInstance.prototype.describe = function (cached) { - if (cached !== false && this.description) { - return this.description; - } - Object.defineProperty(this, 'description', { - value: { - name: this.name, - version: this.module.version, - methods: {}, - routes: {}, - }, - configurable: true, - }); - - let webMethods = {}; - if (this.config.web && this.config.web.routes) { - webMethods = this.__parseWebRoutes(); + this.data = require('./component-instance-data').create(mesh._mesh.data, this.name); + this.#boundComponentInstanceFactory = require('./component-instance-bound-factory').create( + this, + mesh._mesh + ); + this.#attach(config, mesh._mesh, callback); } - // build description.events (components events) - if (this.config.events) this.description.events = utilities.clone(this.config.events); - else this.description.events = {}; - - if (this.config.data) this.description.data = utilities.clone(this.config.data); - else this.description.data = {}; - - //get all methods that are not inherited from Object, Stream, and EventEmitter - const methodNames = utilities.getAllMethodNames(this.module.instance, { - ignoreInheritedNativeMethods: true, - }); - - for (var methodName of methodNames) { - let method = this.module.instance[methodName]; - let methodDefined = this.__getMethodDefn(this.config, methodName); - let isAsyncMethod = method.toString().substring(0, 6) === 'async '; - if (methodDefined) methodDefined.isAsyncMethod = isAsyncMethod; - - if (method.$happner && method.$happner.ignore && !methodDefined) continue; - if (methodName.indexOf('_') === 0 && !methodDefined) continue; - if (!this.config.schema || (this.config.schema && !this.config.schema.exclusive)) { - // no schema or not exclusive, allow all (except those filtered above and those that are webMethods) - if (webMethods[methodName]) continue; - this.description.methods[methodName] = methodDefined = methodDefined || { - isAsyncMethod, - }; - if (!methodDefined.parameters) { - this._defaultParameters(method, methodDefined); + #getCallbackIndex(methodName, methodSchema) { + if (this.#callbackIndexes[methodName] == null) { + for (var i in methodSchema.parameters) { + if (methodSchema.parameters[i].type === 'callback') { + this.#callbackIndexes[methodName] = i; + return i; + } } - continue; + this.#callbackIndexes[methodName] = -1; } + return this.#callbackIndexes[methodName]; + } - if (methodDefined) { - // got schema and exclusive is true (per filter in previous if) and have definition - this.description.methods[methodName] = methodDefined; - if (!methodDefined.parameters) { - this._defaultParameters(method, methodDefined); + #getCallbackProxy(methodName, callback, origin) { + const callbackProxyContext = Object.assign({ wasCalled: false, log: this.#log }, this); + const callbackProxy = function () { + if (this.wasCalled) { + return this.log.error( + 'Callback invoked more than once for method %s', + methodName, + callback.toString() + ); } - } + this.wasCalled = true; + callback(null, Array.prototype.slice.apply(arguments)); + }.bind(callbackProxyContext); + callbackProxy.$origin = origin; //must be accessible from the outside, so not a bound property + return callbackProxy; } - return this.description; -}; -ComponentInstance.prototype._inject = function (methodDefn, parameters, origin) { - if (parameters.length < methodDefn.$argumentsLength) { - // pad undefined values - parameters = parameters.concat( - new Array(methodDefn.$argumentsLength - parameters.length).fill(undefined) - ); - } - if (methodDefn.$happnSeq != null && methodDefn.$originSeq != null) { - // these must happen in the order of the smallest sequence first - if (methodDefn.$happnSeq < methodDefn.$originSeq) { - parameters.splice(methodDefn.$happnSeq, 0, this.bindToOrigin(origin)); - parameters.splice(methodDefn.$originSeq, 0, origin); - } else { - parameters.splice(methodDefn.$originSeq, 0, origin); - parameters.splice(methodDefn.$happnSeq, 0, this.bindToOrigin(origin)); - } - } else { - if (methodDefn.$originSeq != null) { - parameters.splice(methodDefn.$originSeq, 0, origin); - } - if (methodDefn.$happnSeq != null) { - parameters.splice(methodDefn.$happnSeq, 0, this.bindToOrigin(origin)); - } + #callbackOrThrowError(e, callback) { + if (!callback) throw e; + callback(e); } - return parameters; -}; - -ComponentInstance.prototype.__callBackWithWarningAndError = function (category, message, callback) { - const error = new Error(message); - this.log.warn(`${category}:${message}`); - return callback(error); -}; - -ComponentInstance.prototype._loadModule = function (module) { - var _this = this; - - Object.defineProperty(this, 'module', { - // property: to remove internal components from view. - value: module, - }); - Object.defineProperty(this, 'operate', { - value: function (methodName, parameters, callback, origin, version) { - _this.__authorizeOriginMethod(methodName, origin, function (e) { - if (e) return callback(e); - - try { - var callbackIndex = -1; - var callbackCalled = false; + operate(methodName, parameters, callback, origin, version, originBindingOverride) { + this.#authorizeOriginMethod( + methodName, + origin, + (e) => { + if (e) { + return this.#callbackOrThrowError(e, callback); + } + const methodSchema = this.description.methods[methodName]; + const methodDefn = this.#module.instance[methodName]; + + if (!methodSchema || typeof methodDefn !== 'function') { + return this.#callBackWithWarningAndError( + 'Missing method', + `Call to unconfigured method [${this.name}.${methodName}()]`, + callback + ); + } + let callbackIndex = this.#getCallbackIndex(methodName, methodSchema); + + if (version != null && !this.#satisfies(this.#module.version, version)) { + return this.#callBackWithWarningAndError( + 'Component version mismatch', + `Call to unconfigured method [${ + this.name + }.${methodName}]: request version [${version}] does not match component version [${ + this.#module.version + }]`, + callback + ); + } - _this.stats.component[_this.name].calls++; + this.#log.trace('operate( %s', methodName); + this.#log.trace('parameters ', parameters); + this.#log.trace('methodSchema ', methodSchema); + let result, + syncError = null; - const methodSchema = _this.description.methods[methodName]; - const methodDefn = _this.module.instance[methodName]; + const callbackProxy = this.#getCallbackProxy(methodName, callback, origin); + let returnObject; - if (!methodSchema || typeof methodDefn !== 'function') { - return _this.__callBackWithWarningAndError( - 'Missing method', - `Call to unconfigured method [${_this.name}.${methodName}()]`, - callback - ); + if (callbackIndex === -1) { + if (!methodSchema.isAsyncMethod && methodSchema.type !== 'sync-promise') { + //unless we are dealing with an async method, pop the proxy in regardless - it may not actually be called + parameters.push(callbackProxy); } + } else { + parameters.splice(callbackIndex, 1, callbackProxy); + } - if (version != null && !_this.satisfies(_this.module.version, version)) { - return _this.__callBackWithWarningAndError( - 'Component version mismatch', - `Call to unconfigured method [${_this.name}.${methodName}]: request version [${version}] does not match component version [${_this.module.version}]`, - callback + if (methodSchema.type === 'sync') { + try { + result = methodDefn.apply( + this.#module.instance, + this.#inject(methodDefn, parameters, origin) ); + } catch (syncErr) { + syncError = syncErr; } + // the method was classified as sync but still called the callback + if (!callbackProxy.wasCalled) { + callbackProxy(syncError, result); + } + return; + } - _this.log.$$TRACE('operate( %s', methodName); - _this.log.$$TRACE('parameters ', parameters); - _this.log.$$TRACE('methodSchema ', methodSchema); - - if (callback) { - if (methodSchema.type === 'sync-promise') { - let result; - try { - result = methodDefn.apply( - _this.module.instance, - _this._inject(methodDefn, parameters, origin) - ); - } catch (syncPromiseError) { - return callback(null, [syncPromiseError]); - } - return callback(null, [null, result]); - } - - for (var i in methodSchema.parameters) { - if (methodSchema.parameters[i].type === 'callback') callbackIndex = i; - } - - var callbackProxy = function () { - if (callbackCalled) - return _this.log.error( - 'Callback invoked more than once for method %s', - methodName, - callback.toString() - ); - - callbackCalled = true; - callback(null, Array.prototype.slice.apply(arguments)); - }; - - callbackProxy.$origin = origin; - - if (callbackIndex === -1) { - if (!methodSchema.isAsyncMethod) { - parameters.push(callbackProxy); - } - } else { - parameters.splice(callbackIndex, 1, callbackProxy); - } + if (methodSchema.type === 'sync-promise') { + try { + result = methodDefn.apply( + this.#module.instance, + this.#inject(methodDefn, parameters, origin) + ); + } catch (syncPromiseError) { + syncError = syncPromiseError; } + if (syncError) return callbackProxy(syncError); + return callbackProxy(syncError, result); + } - let returnObject = methodDefn.apply( - _this.module.instance, - _this._inject(methodDefn, parameters, origin) + try { + returnObject = methodDefn.apply( + this.#module.instance, + this.#inject(methodDefn, parameters, origin) ); + } catch (err) { + callbackProxy(err); + return; + } - if (utilities.isPromise(returnObject)) { - if (callbackIndex > -1 && utilities.isPromise(returnObject)) - _this.log.warn('method has been configured as a promise with a callback...'); - else { - returnObject - .then(function (result) { - if (callbackProxy) callbackProxy(null, result); - }) - .catch(function (err) { - if (callbackProxy) callbackProxy(err); - }); - } + if (utilities.isPromise(returnObject)) { + if (callbackIndex > -1 && utilities.isPromise(returnObject)) { + this.#log.warn('method has been configured as a promise with a callback...'); + } else { + returnObject + .then(function (result) { + callbackProxy(null, result); + }) + .catch(function (err) { + callbackProxy(err); + }); } - } catch (callFailedError) { - _this.log.error('Call to method %s failed', methodName, callFailedError); - _this.stats.component[_this.name].errors++; - - if (callback) callback(callFailedError); } - }); - }, - }); -}; + }, + originBindingOverride + ); + } -ComponentInstance.prototype._defaultParameters = function (method, methodSchema) { - if (!methodSchema.parameters) methodSchema.parameters = []; - utilities - .getFunctionParameters(method) - .filter(function (argName) { - return argName !== '$happn' && argName !== '$origin'; - }) - .map(function (argName) { - methodSchema.parameters.push({ - name: argName, - }); - }); -}; + #callBackWithWarningAndError(category, message, callback) { + const error = new Error(message); + this.#log.warn(`${category}:${message}`); + this.#callbackOrThrowError(error, callback); + } -ComponentInstance.prototype._discardMessage = function (reason, message) { - this.log.warn('message discarded: %s', reason, message); -}; + #attach(config, mesh, callback) { + //attach module to the transport layer + this.#log.trace('_attach()'); + this.emit = (key, data, options, callback) => { + if (typeof options === 'function') { + callback = options; + options = {}; + } -ComponentInstance.prototype._hasNext = function (methodDefn) { - var parameters = utilities.getFunctionParameters(methodDefn); - return parameters.indexOf('next') >= 0; -}; + if (options == null) options = {}; + if (options.noStore == null) options.noStore = true; -ComponentInstance.prototype._getWebOrigin = function (mesh, params) { - var cookieName = null; + options.meta = { + componentVersion: this.#module.version, + }; - try { - cookieName = mesh.config.happn.services.connect.config.middleware.security.cookieName; - } catch (e) { - // do nothing - } //do nothing + const eventKey = `/_events/${this.info.mesh.domain}/${this.name}/`; - return mesh.happn.server.services.security.sessionFromRequest(params[0], { - cookieName: cookieName, - }); -}; + if ([1, 3].indexOf(options.consistency) > -1) { + options.onPublished = (e, results) => { + if (e) { + return this.emitEvent('on-publish-error', e); + } + this.emitEvent('on-publish-ok', results); + }; + } -ComponentInstance.prototype._runWithInjection = function (args, mesh, methodDefn) { - var _this = this; + mesh.data.set(eventKey + key, data, options, (e, response) => { + if (e) { + return this.emitEvent('on-emit-error', e); + } + this.emitEvent('on-emit-ok', response); + if (callback) callback(e, response); + }); + }; - var parameters = Array.prototype.slice.call(args); - var origin = _this._getWebOrigin(mesh, parameters); + this.emitLocal = (key, data, callback) => { + // differs from .emit() in that the publish does not replicate into the cluster + var eventKey = '/_events/' + this.info.mesh.domain + '/' + this.name + '/'; + + mesh.data.set( + eventKey + key, + data, + { + noStore: true, + noCluster: true, + meta: { + componentVersion: this.#module.version, + }, + }, + callback + ); + }; - methodDefn.apply(_this.module.instance, _this._inject(methodDefn, parameters, origin)); -}; + if (config.web && config.web.routes) { + try { + Object.keys(config.web.routes).forEach((route) => { + var routeTarget = config.web.routes[route]; + var meshRoutePath = '/' + this.info.mesh.name + '/' + this.name + '/' + route; + var componentRoutePath = '/' + this.name + '/' + route; + + if (Array.isArray(routeTarget)) { + routeTarget.map((targetMethod) => { + this.#attachRouteTarget(mesh, meshRoutePath, componentRoutePath, targetMethod, route); + }); + } else { + this.#attachRouteTarget(mesh, meshRoutePath, componentRoutePath, routeTarget, route); + } + }); + } catch (e) { + this.#log.error('Failure to attach web methods', e); + return callback(e); + } + } + const subscribeMask = this.#getSubscribeMask(); + this.#log.trace('data.on( ' + subscribeMask); + mesh.data.on( + subscribeMask, + { + event_type: 'set', + }, + (publication, meta) => { + this.#log.trace('received request at %s', subscribeMask); + let message = publication; + let method = meta.path.split('/').pop(); + const args = Array.isArray(message.args) ? message.args.slice(0, message.args.length) : []; + if (!message.callbackAddress) return this.#discardMessage('No callback address', message); + this.operate( + method, + args, + (e, responseArguments) => { + var serializedError; + + if (e) { + // error objects cant be sent / received (serialize) + serializedError = { + message: e.message, + name: e.name, + }; + + Object.keys(e).forEach(function (key) { + serializedError[key] = e[key]; + }); + + this.#log.trace('operate( reply( ERROR %s', message.callbackAddress); + + return this.#reply( + message.callbackAddress, + message.callbackPeer, + { + status: 'failed', + args: [serializedError], + }, + this.info.happn.options, + mesh + ); + } -ComponentInstance.prototype._attachRouteTarget = function ( - mesh, - meshRoutePath, - componentRoutePath, - targetMethod -) { - var serve; - var connect = mesh.happn.server.connect; - var methodDefn = - typeof targetMethod === 'function' ? targetMethod : this.module.instance[targetMethod]; - var componentRef = componentRoutePath.substring(1); - var _this = this; - - if (typeof methodDefn !== 'function') - throw new Error( - `Middleware target ${_this.name}:${targetMethod} not a function or null, check your happner web routes config` - ); + var response = { + status: 'ok', + args: responseArguments, + }; - if (typeof methodDefn.$happnSeq !== 'undefined' || typeof methodDefn.$originSeq !== 'undefined') { - if (this._hasNext(methodDefn)) { - serve = function () { - // preserve next in signature for connect - _this._runWithInjection(arguments, mesh, methodDefn); - }; - } else { - serve = function () { - _this._runWithInjection(arguments, mesh, methodDefn); - }; - } - } else { - serve = methodDefn.bind(this.module.instance); - } + if (responseArguments[0] instanceof Error) { + response.status = 'error'; - connect.use(meshRoutePath, serve); - connect.use(componentRoutePath, serve); + var responseError = responseArguments[0]; - this.log.$$TRACE(`attached web route for component ${this.name}: ${meshRoutePath}`); + serializedError = { + message: responseError.message, + name: responseError.name, + }; - // tag for _detatch() to be able to remove middleware when removing component - serve.__tag = this.name; + Object.keys(responseError).forEach(function (key) { + serializedError[key] = responseError[key]; + }); - if (!mesh.config.web) return; - if (!mesh.config.web.routes) return; + responseArguments[0] = serializedError; + } - // attach this as root middleware if configured - Object.keys(mesh.config.web.routes).forEach(function (mountRoute) { - var mountPoint = mesh.config.web.routes[mountRoute]; - if (componentRef !== mountPoint) return; - connect.use(mountRoute, function (req, res, next) { - req.rootWebRoute = mountRoute; - req.componentWebRoute = mountPoint; - serve(req, res, next); - }); - }); -}; + // Populate response to the callback address + this.#log.trace('operate( reply( RESULT %s', message.callbackAddress); -ComponentInstance.prototype.__createSetOptions = function (originId, options) { - if (this.config.directResponses) - return _.merge( - { - targetClients: [originId], + var options = this.#createSetOptions(publication.origin.id, this.info.happn.options); + this.#reply(message.callbackAddress, message.callbackPeer, response, options, mesh); + }, + meta.eventOrigin || message.origin, + message.version + ); }, - options + function (e) { + callback(e); + } ); - else return options; -}; - -ComponentInstance.prototype.__raiseOnEmitError = function (e) { - this.emitEvent('on-emit-error', e); -}; - -ComponentInstance.prototype.__raiseOnEmitOK = function (response) { - this.emitEvent('on-emit-ok', response); -}; + } -ComponentInstance.prototype.__raiseOnPublishError = function (e) { - this.emitEvent('on-publish-error', e); -}; + #createSetOptions(originId, options) { + if (this.config.directResponses) + return Object.assign( + { + targetClients: [originId], + }, + options + ); + else return options; + } -ComponentInstance.prototype.__raiseOnPublishOK = function (response) { - this.emitEvent('on-publish-ok', response); -}; + #getSubscribeMask() { + return `/_exchange/requests/${this.info.mesh.domain}/${this.name}/*`; + } -ComponentInstance.prototype.__getSubscribeMask = function () { - return `/_exchange/requests/${this.info.mesh.domain}/${this.name}/*`; -}; + #satisfies(moduleVersion, version) { + return semver.coercedSatisfies(moduleVersion, version); + } -ComponentInstance.prototype.__reply = function ( - callbackAddress, - callbackPeer, - response, - options, - mesh -) { - let client = mesh.data; - if (callbackPeer) { - // for cluster the set is performed back at the originating peer + on(event, handler) { try { - client = mesh.happn.server.services.orchestrator.peers[callbackPeer].client; + this.#log.trace('component on called', event); + return this.#localEventEmitter.on(event, handler); } catch (e) { - // no peer at callback (race conditions on servers stopping and starting) dead end... - this.log.warn('Failure on callback, missing peer', e); - return; + this.#log.trace('component on error', e); } } - client.publish(callbackAddress, response, options, (e) => { - if (e) { - var logMessage = 'Failure to set callback data on address ' + callbackAddress; - if (e.message && e.message === 'client is disconnected') - return this.log.warn(logMessage + ':client is disconnected'); - this.log.error(logMessage, e); - } - }); -}; - -ComponentInstance.prototype._attach = function (config, mesh, callback) { - //attach module to the transport layer - - this.log.$$TRACE('_attach()'); - var _this = this; - - _this.emit = function (key, data, options, callback) { - if (typeof options === 'function') { - callback = options; - options = {}; + offEvent(event, handler) { + try { + this.#log.trace('component offEvent called', event); + return this.#localEventEmitter.off(event, handler); + } catch (e) { + this.#log.trace('component offEvent error', e); } + } - if (options == null) options = {}; - if (options.noStore == null) options.noStore = true; - - options.meta = { - componentVersion: _this.module.version, - }; - _this.stats.component[_this.name].emits++; - - var eventKey = '/_events/' + _this.info.mesh.domain + '/' + _this.name + '/'; - - if ([1, 3].indexOf(options.consistency) > -1) { - options.onPublished = function (e, results) { - if (e) return _this.__raiseOnPublishError(e); - _this.__raiseOnPublishOK(results); - }; + emitEvent(event, data) { + try { + this.#log.trace('component emitEvent called', event); + return this.#localEventEmitter.emit(event, data); + } catch (e) { + this.#log.trace('component emitEvent error', e); } - mesh.data.set(eventKey + key, data, options, function (e, response) { - if (e) return _this.__raiseOnEmitError(e); - _this.__raiseOnEmitOK(response); - if (callback) callback(e, response); - }); - }; - - _this.emitLocal = function (key, data, callback) { - // differs from .emit() in that the publish does not replicate into the cluster - _this.stats.component[_this.name].emits++; - var eventKey = '/_events/' + _this.info.mesh.domain + '/' + _this.name + '/'; + } - mesh.data.set( - eventKey + key, - data, + #authorizeOriginMethod(methodName, origin, callback, originBindingOverride) { + if ( + !this.#boundComponentInstanceFactory.originBindingNecessary( + origin, + originBindingOverride, + true // we want to check whether the edge was authorized + ) + ) { + return callback(null); + } + const subscribeMask = this.#getSubscribeMask(); + // purpose of substring is to pop the * off the end of the mask + const permissionPath = subscribeMask.substring(0, subscribeMask.length - 1) + methodName; + this.#mesh._mesh.happn.server.services.security.getOnBehalfOfSession( { - noStore: true, - noCluster: true, - meta: { - componentVersion: _this.module.version, + user: { + username: '_ADMIN', }, }, - callback + origin.username, + origin.type, + (e, originSession) => { + if (e) return callback(e); + this.#mesh._mesh.happn.server.services.security.authorize( + originSession, + permissionPath, + 'set', + (e, authorized, reason) => { + if (e) return callback(e); + if (!authorized) + return callback( + this.#mesh._mesh.happn.server.services.error.AccessDeniedError( + 'unauthorized', + reason || 'request on behalf of unauthorised user: ' + origin.username + ) + ); + callback(); + } + ); + } ); - }; + } - if (config.web && config.web.routes) { - try { - Object.keys(config.web.routes).forEach(function (route) { - var routeTarget = config.web.routes[route]; - var meshRoutePath = '/' + _this.info.mesh.name + '/' + _this.name + '/' + route; - var componentRoutePath = '/' + _this.name + '/' + route; - - if (Array.isArray(routeTarget)) { - routeTarget.map(function (targetMethod) { - _this._attachRouteTarget(mesh, meshRoutePath, componentRoutePath, targetMethod, route); - }); - } else { - _this._attachRouteTarget(mesh, meshRoutePath, componentRoutePath, routeTarget, route); - } - }); - } catch (e) { - _this.log.error('Failure to attach web methods', e); - return callback(e); - } + #getMethodDefn(config, methodName) { + if (!config?.schema?.methods) return; + return config.schema.methods[methodName]; } - var subscribeMask = _this.__getSubscribeMask(); - - _this.log.$$TRACE('data.on( ' + subscribeMask); - mesh.data.on( - subscribeMask, - { - event_type: 'set', - }, - function (publication, meta) { - _this.log.$$TRACE('received request at %s', subscribeMask); - var message = publication; - var method = meta.path.split('/').pop(); - - if (_this.serializer && typeof _this.serializer.__decode === 'function') { - message.args = _this.serializer.__decode(message.args, { - req: true, - res: false, - at: { - mesh: _this.info.mesh.name, - component: _this.name, - }, - meta: meta, + #parseWebRoutes() { + const webMethods = {}; // accum list of webMethods to exclude from exhange methods description + const routes = this.config.web.routes; + Object.keys(routes).forEach((routePath) => { + let route = routes[routePath]; + + if (route instanceof Array) + route.forEach(function (method) { + webMethods[method] = 1; + route = method; // last in route array is used to determine type: static || mware }); - } + else webMethods[route] = 1; - var args = Array.isArray(message.args) ? message.args.slice(0, message.args.length) : []; + if (routePath === 'static') routePath = '/'; + else if (this.name === 'www' && routePath === 'global') return; + else if (this.name === 'www' && routePath !== 'global') routePath = '/' + routePath; + else if (routePath === 'resources' && this.name === 'resources') routePath = '/' + routePath; + else routePath = '/' + this.name + '/' + routePath; - if (!message.callbackAddress) return _this._discardMessage('No callback address', message); + this.description.routes[routePath] = {}; + this.description.routes[routePath].type = route === 'static' ? 'static' : 'mware'; + }); + return webMethods; + } - _this.operate( - method, - args, - function (e, responseArguments) { - var serializedError; + as(username, componentName, methodName, sessionType, edgeAuthorized) { + return this.#boundComponentInstanceFactory.getBoundComponent( + { username, edgeAuthorized }, + true, + componentName, + methodName, + sessionType + ); + } - if (e) { - // error objects cant be sent / received (serialize) - serializedError = { - message: e.message, - name: e.name, - }; + describe(cached) { + if (cached !== false && this.description) { + return this.description; + } + Object.defineProperty(this, 'description', { + value: { + name: this.name, + version: this.#module.version, + methods: {}, + routes: {}, + }, + configurable: true, + }); - Object.keys(e).forEach(function (key) { - serializedError[key] = e[key]; - }); + let webMethods = {}; + if (this.config.web && this.config.web.routes) { + webMethods = this.#parseWebRoutes(); + } - _this.log.$$TRACE('operate( reply( ERROR %s', message.callbackAddress); - - return _this.__reply( - message.callbackAddress, - message.callbackPeer, - { - status: 'failed', - args: [serializedError], - }, - _this.info.happn.options, - mesh - ); - } + // build description.events (components events) + if (this.config.events) this.description.events = utilities.clone(this.config.events); + else this.description.events = {}; - var response = { - status: 'ok', - args: responseArguments, - }; + if (this.config.data) this.description.data = utilities.clone(this.config.data); + else this.description.data = {}; - if (responseArguments[0] instanceof Error) { - response.status = 'error'; + //get all methods that are not inherited from Object, Stream, and EventEmitter + const methodNames = utilities.getAllMethodNames(this.#module.instance, { + ignoreInheritedNativeMethods: true, + }); - var responseError = responseArguments[0]; + for (var methodName of methodNames) { + let method = this.#module.instance[methodName]; + let methodDefined = this.#getMethodDefn(this.config, methodName); + let isAsyncMethod = method.toString().substring(0, 6) === 'async '; + if (methodDefined) methodDefined.isAsyncMethod = isAsyncMethod; + + if (method.$happner && method.$happner.ignore && !methodDefined) continue; + if (methodName.indexOf('_') === 0 && !methodDefined) continue; + if (!this.config.schema || (this.config.schema && !this.config.schema.exclusive)) { + // no schema or not exclusive, allow all (except those filtered above and those that are webMethods) + if (webMethods[methodName]) continue; + this.description.methods[methodName] = methodDefined = methodDefined || { + isAsyncMethod, + }; + if (!methodDefined.parameters) { + this.#defaultParameters(method, methodDefined); + } + continue; + } - serializedError = { - message: responseError.message, - name: responseError.name, - }; + if (methodDefined) { + // got schema and exclusive is true (per filter in previous if) and have definition + this.description.methods[methodName] = methodDefined; + if (!methodDefined.parameters) { + this.#defaultParameters(method, methodDefined); + } + } + } + return this.description; + } - Object.keys(responseError).forEach(function (key) { - serializedError[key] = responseError[key]; - }); + #inject(methodDefn, parameters, origin) { + if (parameters.length < methodDefn.$argumentsLength) { + // pad undefined values + parameters = parameters.concat( + new Array(methodDefn.$argumentsLength - parameters.length).fill(undefined) + ); + } + if (methodDefn.$happnSeq != null && methodDefn.$originSeq != null) { + // these must happen in the order of the smallest sequence first + if (methodDefn.$happnSeq < methodDefn.$originSeq) { + parameters.splice( + methodDefn.$happnSeq, + 0, + this.#boundComponentInstanceFactory.getBoundComponent(origin) + ); + parameters.splice(methodDefn.$originSeq, 0, origin); + } else { + parameters.splice(methodDefn.$originSeq, 0, origin); + parameters.splice( + methodDefn.$happnSeq, + 0, + this.#boundComponentInstanceFactory.getBoundComponent(origin) + ); + } + } else { + if (methodDefn.$originSeq != null) { + parameters.splice(methodDefn.$originSeq, 0, origin); + } + if (methodDefn.$happnSeq != null) { + parameters.splice( + methodDefn.$happnSeq, + 0, + this.#boundComponentInstanceFactory.getBoundComponent(origin) + ); + } + } + return parameters; + } - responseArguments[0] = serializedError; - } + #defaultParameters(method, methodSchema) { + //double validation was removed + methodSchema.parameters = []; + utilities + .getFunctionParameters(method) + .filter(function (argName) { + return argName !== '$happn' && argName !== '$origin'; + }) + .map(function (argName) { + methodSchema.parameters.push({ + name: argName, + }); + }); + } - if (_this.serializer && typeof _this.serializer.__encode === 'function') { - response.args = _this.serializer.__encode(response.args, { - req: false, - res: true, - src: { - mesh: _this.info.mesh.name, - component: _this.name, - }, - meta: meta, - opts: _this.__createSetOptions(publication.origin.id, _this.info.happn.options), - }); - } + #discardMessage(reason, message) { + this.#log.warn('message discarded: %s', reason, message); + } - // Populate response to the callback address - _this.log.$$TRACE('operate( reply( RESULT %s', message.callbackAddress); + #getWebOrigin(mesh, params) { + let cookieName = null; + try { + cookieName = mesh.config.happn.services.connect.config.middleware.security.cookieName; + } catch (e) { + // do nothing + } + return mesh.happn.server.services.security.sessionFromRequest(params[0], { + cookieName, + }); + } - var options = _this.__createSetOptions(publication.origin.id, _this.info.happn.options); - _this.__reply(message.callbackAddress, message.callbackPeer, response, options, mesh); - }, - meta.eventOrigin || message.origin, - message.version + #runWithInjection(args, mesh, methodDefn) { + const parameters = Array.prototype.slice.call(args); + const origin = this.#getWebOrigin(mesh, parameters); + methodDefn.apply(this.#module.instance, this.#inject(methodDefn, parameters, origin)); + } + + #attachRouteTarget(mesh, meshRoutePath, componentRoutePath, targetMethod) { + let serve; + let connect = mesh.happn.server.connect; + let methodDefn = + typeof targetMethod === 'function' ? targetMethod : this.#module.instance[targetMethod]; + let componentRef = componentRoutePath.substring(1); + let _this = this; + if (typeof methodDefn !== 'function') { + throw new Error( + `Middleware target ${_this.name}:${targetMethod} not a function or null, check your happner web routes config` ); - }, - function (e) { - callback(e); } - ); -}; -ComponentInstance.prototype._detatch = function (mesh, callback) { - // - // mesh._mesh - this.log.$$TRACE('_detatch() removing component from mesh'); + if ( + typeof methodDefn.$happnSeq !== 'undefined' || + typeof methodDefn.$originSeq !== 'undefined' + ) { + serve = function () { + // preserve next in signature for connect + return _this.#runWithInjection(arguments, mesh, methodDefn); + }; + } else { + serve = methodDefn.bind(this.#module.instance); + } + + connect.use(meshRoutePath, serve); + connect.use(componentRoutePath, serve); - var _this = this; - var connect = mesh.happn.server.connect; - var name = this.name; + this.#log.trace(`attached web route for component ${this.name}: ${meshRoutePath}`); - // Remove this component's middleware from the connect stack. + // tag for detatch() to be able to remove middleware when removing component + serve.__tag = this.name; - var toRemove = connect.stack + if (!mesh.config.web) return; + if (!mesh.config.web.routes) return; - .map(function (mware, i) { - if (mware.handle.__tag !== name) return -1; - return i; - }) + // attach this as root middleware if configured + Object.keys(mesh.config.web.routes).forEach(function (mountRoute) { + var mountPoint = mesh.config.web.routes[mountRoute]; - .filter(function (i) { - return i >= 0; - }) + if (componentRef !== mountPoint) return; + connect.use(mountRoute, function (req, res, next) { + req.rootWebRoute = mountRoute; + req.componentWebRoute = mountPoint; + serve(req, res, next); + }); + }); + } - // splice starting from the back end so that array size change does not offset + #reply(callbackAddress, callbackPeer, response, options, mesh) { + let client = mesh.data; + if (callbackPeer) { + // for cluster the set is performed back at the originating peer + try { + client = mesh.happn.server.services.orchestrator.peers[callbackPeer].client; + } catch (e) { + // no peer at callback (race conditions on servers stopping and starting) dead end... + this.#log.warn(`Failure on callback, missing peer: ${callbackPeer}`, e); + return; + } + } + client.publish(callbackAddress, response, options, (e) => { + if (e) { + var logMessage = 'Failure to set callback data on address ' + callbackAddress; + if (e.message && e.message === 'client is disconnected') + return this.#log.warn(logMessage + ':client is disconnected'); + this.#log.error(logMessage, e); + } + }); + } - .reverse(); + detatch(mesh, callback) { + this.#log.trace('detatch() removing component from mesh'); + const connect = mesh.happn.server.connect; + // Remove this component's middleware from the connect stack. + var toRemove = connect.stack - toRemove.forEach(function (i) { - _this.log.$$TRACE('removing mware at %s', connect.stack[i].route); - connect.stack.splice(i, 1); - }); + .map((mware, i) => { + if (mware.handle.__tag !== this.name) return -1; + return i; + }) - // Remove this component's request listener from the happn + .filter((i) => { + return i >= 0; + }) - var listenAddress = '/_exchange/requests/' + this.info.mesh.domain + '/' + this.name + '/'; - var subscribeMask = listenAddress + '*'; + // splice starting from the back end so that array size change does not offset - _this.log.$$TRACE('removing request listener %s', subscribeMask); + .reverse(); - mesh.data.offPath(subscribeMask, function (e) { - if (e) _this.log.warn('half detatched, failed to remove request listener %s', subscribeMask, e); - callback(e); - }); -}; + toRemove.forEach((i) => { + this.#log.trace('removing mware at %s', connect.stack[i].route); + connect.stack.splice(i, 1); + }); + const subscribeMask = this.#getSubscribeMask(); + // Remove this component's request listener from the happn + this.#log.trace('removing request listener %s', subscribeMask); + + mesh.data.offPath(subscribeMask, (e) => { + if (e) { + this.#log.warn( + `half detatched, failed to remove request listener: ${subscribeMask}, error: ${e.message}` + ); + } + callback(e); + }); + } -// terminal: inline help $happn.README -ComponentInstance.prototype.README = function () { - /* -
- ## This is the Component Instance - It is available in the terminal at **$happn**. From modules, it is optionally - injected (by argument name) into functions as **$happn**. - It has access to the **Exchange**, **Event** and **Data** APIs as well as some - built in utilities and informations. - ### Examples - __node> $happn.name - 'terminal' - __node> $happn.constructor.name - 'ComponentInstance' - __node> $happn.log.warn('blah blah') - **[ WARN]** - 13398ms home (terminal) blah blah - __node> $happn.info - __node> $happn.config - __node> $happn.data.README - __node> $happn.event.README - __node> $happn.exchange.README - __node> $happn._mesh.* // only with 'mesh'||'root' accessLevel - __node> $happn._root.* // only with 'root' accessLevel - */ + // terminal: inline help $happn.README + README() { + /* +
+ ## This is the Component Instance + It is available in the terminal at **$happn**. From modules, it is optionally + injected (by argument name) into functions as **$happn**. + It has access to the **Exchange**, **Event** and **Data** APIs as well as some + built in utilities and informations. + ### Examples + __node> $happn.name + 'terminal' + __node> $happn.constructor.name + 'ComponentInstance' + __node> $happn.log.warn('blah blah') + **[ WARN]** - 13398ms home (terminal) blah blah + __node> $happn.info + __node> $happn.config + __node> $happn.data.README + __node> $happn.event.README + __node> $happn.exchange.README + __node> $happn._mesh.* // only with 'mesh'||'root' accessLevel + __node> $happn._root.* // only with 'root' accessLevel + */ + } }; diff --git a/packages/happner-2/lib/system/config.js b/packages/happner-2/lib/system/config.js index faf3819fc..05c1f7fd3 100644 --- a/packages/happner-2/lib/system/config.js +++ b/packages/happner-2/lib/system/config.js @@ -8,8 +8,6 @@ function Config() {} // the deep copy ensures that configs passed in do not come out with new properties Config.prototype.process = function (mesh, config, callback) { - var serializer; - this.log = mesh.log.createLogger('Config'); this.log.$$TRACE('process()'); @@ -37,26 +35,5 @@ Config.prototype.process = function (mesh, config, callback) { }); clonedConfig.endpoints = clonedConfig.endpoints || {}; - - if (clonedConfig.exchange && (serializer = clonedConfig.exchange.serializer)) { - if (typeof serializer === 'string') { - try { - mesh._mesh.serializer = this.validateSerializer(require(serializer)); - } catch (e) { - this.log.warn('serializer load failed', e); - } - } else { - mesh._mesh.serializer = this.validateSerializer(serializer); - } - } - callback(null, clonedConfig); }; - -Config.prototype.validateSerializer = function (it) { - if (typeof it.__encode !== 'function' || typeof it.__decode !== 'function') { - this.log.warn('invalid serializer ignored'); - return; - } - return it; -}; diff --git a/packages/happner-2/lib/system/shared/internals.js b/packages/happner-2/lib/system/shared/internals.js index e521547a2..c369ca26b 100644 --- a/packages/happner-2/lib/system/shared/internals.js +++ b/packages/happner-2/lib/system/shared/internals.js @@ -358,7 +358,15 @@ } const args = Array.isArray(parameters.arguments) ? parameters.arguments : []; if (typeof callback === 'function') args.push(callback); - return endpoint[parameters.method].apply(endpoint, args); + let boundEndpoint = endpoint; + if (parameters.as) { + boundEndpoint = Object.assign( + {}, + { $origin: { username: parameters.as, override: true } }, + endpoint + ); + } + return endpoint[parameters.method].apply(boundEndpoint, args); }; }; diff --git a/packages/happner-2/lib/system/shared/mesh-client.js b/packages/happner-2/lib/system/shared/mesh-client.js index b28879a01..630c4e3c3 100644 --- a/packages/happner-2/lib/system/shared/mesh-client.js +++ b/packages/happner-2/lib/system/shared/mesh-client.js @@ -124,6 +124,26 @@ extend(MeshClient, EventEmitter); + MeshClient.create = function (opts) { + return new Promise((resolve, reject) => { + let client = new MeshClient({ + host: opts.host, + port: opts.port, + }); + client + .login({ + username: opts.username, + password: opts.password, + }) + .then(function () { + resolve(client); + }) + .catch((e) => { + reject(e); + }); + }); + }; + MeshClient.clearCookieEventObjects = function () { MeshHappnClient.clearCookieEventObjects(); }; diff --git a/packages/happner-2/lib/system/shared/messenger.js b/packages/happner-2/lib/system/shared/messenger.js index be390da3e..98c3adb0d 100644 --- a/packages/happner-2/lib/system/shared/messenger.js +++ b/packages/happner-2/lib/system/shared/messenger.js @@ -35,8 +35,6 @@ Object.defineProperty(this, '_exchange', { value: exchange }); Object.defineProperty(this, '__responseHandlerCache', { value: {} }); - if (mesh.serializer != null) this.serializer = mesh.serializer; - this.requestors = {}; this.initialized = {}; this.responseHandlers = {}; @@ -151,28 +149,7 @@ arguments[0], function (e, message) { if (e) return _this.__discardMessage(message, e); - - if (_this.serializer && typeof _this.serializer.__encode === 'function') { - message.args = _this.serializer.__encode(message.args, { - req: true, - res: false, - src: { - mesh: _this.meshName, - browser: isBrowser, - //////// component: 'possible?' - }, - dst: { - endpoint: endpoint.name, - component: componentName, - method: methodName, - }, - addr: message.callbackAddress, - opts: setOptions, - }); - } - _this.log.$$TRACE('data.publish( %s', requestPath); - endpoint.data.publish( requestPath, message, @@ -290,7 +267,7 @@ } }, timedout: setTimeout(function () { - thisMessenger.failResponse('Request timed out', message.callbackAddress); + thisMessenger.failResponse(new Error('Request timed out'), message.callbackAddress); }, thisMessenger._endpoint.description.setOptions.timeout || 10000), handler: actualHandler, // for use by the connection-ended event }; @@ -402,15 +379,6 @@ if (response.status === 'error' && !meta) return this._systemEvents('nohandler', response); this.log.$$TRACE('responseHandler( %s', meta.path); - - if (this.serializer && typeof this.serializer.__decode === 'function') { - response.args = this.serializer.__decode(response.args, { - req: false, - res: true, - meta: meta, - }); - } - var responseHandler = this.responseHandlers[meta.path]; if (responseHandler) { diff --git a/packages/happner-2/lib/system/utilities.js b/packages/happner-2/lib/system/utilities.js index 69f7744b5..e64d0751b 100644 --- a/packages/happner-2/lib/system/utilities.js +++ b/packages/happner-2/lib/system/utilities.js @@ -144,11 +144,14 @@ module.exports.findInModules = function (filename, modulePaths, callback) { }); }; -module.exports.stringifyError = function (err) { +module.exports.stringifyError = function (err, includeStack = true) { var plainError = {}; Object.getOwnPropertyNames(err).forEach(function (key) { plainError[key] = err[key]; }); + if (!includeStack) { + delete plainError.stack; + } return JSON.stringify(plainError); }; diff --git a/packages/happner-2/package.json b/packages/happner-2/package.json index 63a9f052e..9eeca1148 100644 --- a/packages/happner-2/package.json +++ b/packages/happner-2/package.json @@ -1,6 +1,6 @@ { "name": "happner-2", - "version": "12.1.9", + "version": "12.2.0", "description": "distributed application engine with evented storage and mesh services", "main": "lib/mesh.js", "bin": { @@ -19,7 +19,7 @@ "test-unit": "_mocha --exit test/unit/**", "test-integration": "_mocha --exit -- silence.js test/integration/**", "test-cover": "nyc --reporter=lcov --reporter=text --reporter=html npm test", - "test-browser": "gulp --gulpfile test/browser/gulp-01.js", + "test-browser": "mocha test/browser-leaking/01-test-disconnects.js && gulp --gulpfile test/browser/gulp-01.js", "test-backward-compatibility": "_mocha silence.js test/backward-compatibility/** --exit" }, "repository": { @@ -35,7 +35,7 @@ "devDependencies": { "address": "^1.1.2", "happn-commons-test": "^1.1.0", - "happn-db-provider-mongo": "^1.0.12", + "happn-db-provider-mongo": "^1.0.13", "happner": "1.33.4", "happner-test-modules": "^1.0.2", "is-ip": "^3.1.0", @@ -48,11 +48,11 @@ "change-case": "2.3.0", "commander": "2.9.0", "diskspace": "0.1.7", - "happn-3": "^13.1.4", + "happn-3": "^13.2.0", "happn-commons": "^1.1.0", "happn-logger": "^2.1.1", "happn-sillyname": "^0.1.1", - "happner-client": "^12.2.8", + "happner-client": "^12.3.0", "happner-semver": "^1.0.1", "homedir": "0.6.0", "later": "1.2.0", diff --git a/packages/happner-2/readme.md b/packages/happner-2/readme.md index 28e502c9b..a00f3a915 100644 --- a/packages/happner-2/readme.md +++ b/packages/happner-2/readme.md @@ -1,4 +1,4 @@ -[![npm](https://img.shields.io/npm/v/happner-2.svg)](https://www.npmjs.com/package/happner-2) [![Build Status](https://travis-ci.org/happner/happner-2.svg?branch=master)](https://travis-ci.org/happner/happner-2) [![Build status](https://ci.appveyor.com/api/projects/status/e5yrnt4fca59hksc/branch/master?svg=true)](https://ci.appveyor.com/project/happner/happner-2/branch/master) [![Coverage Status](https://coveralls.io/repos/github/happner/happner-2/badge.svg?branch=master)](https://coveralls.io/github/happner/happner-2?branch=master) [![David](https://img.shields.io/david/happner/happner-2.svg)](https://img.shields.io/david/happner/happner-2.svg) +[![npm](https://img.shields.io/npm/v/happner-2.svg)](https://www.npmjs.com/package/happner-2) @@ -8,52 +8,44 @@ Happner-2 is a cloud application and RPC framework ideal for integrating multipl ## uses happn-3 -Happner uses [happn-3](https://github.com/happner/happn-3) as the pub/sub framework that allows for communication between happner services and components. +Happner uses [happn-3](https://github.com/happner/happner-suite/tree/develop/packages/happn-3) as the data persistence and pub/sub framework that allows for communication between happner services and components. ## cluster-able -It is possible to create a cluster of happner services, using [happner-cluster](https://github.com/happner/happner-cluster) - -## Changes from [version 1](https://github.com/happner/happner) - -* using happn-3 -* has happn configuration instead of datalayer, the cofiguration can take any happn-3 config in, and has a few convenience settings - -please check the [migration plan](https://github.com/happner/happner-2/blob/master/docs/migration-plan.md) ---------------------------------------------- +It is possible to create a cluster of happner services, using [happner-cluster](https://github.com/happner/happner-suite/tree/develop/packages/happner-cluster) ## installation -`npm install happner-2 --save` +`npm i happner-2 --save` ## demonstration These walkthroughs use *happner* to create a rudimentary monitoring service. -* [The Basics](https://github.com/happner/happner-2/blob/master/docs/walkthrough/the-basics.md) +* [Quick Start](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/walkthrough/the-basics.md) ## documentation -* [Configuration](https://github.com/happner/happner-2/blob/master/docs/configuration.md) -* [Happn](https://github.com/happner/happner-2/blob/master/docs/happn.md) -* [Modules and Components](https://github.com/happner/happner-2/blob/master/docs/modules.md) -* [Autoloading and Defaulting](https://github.com/happner/happner-2/blob/master/docs/autoload.md) -* [Security](https://github.com/happner/happner-2/blob/master/docs/security.md) +* [Configuration](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/configuration.md) +* [Happn](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/happn.md) +* [Modules and Components](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/modules.md) +* [Autoloading and Defaulting](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/autoload.md) +* [Security](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/security.md) ### -* [Event Api](https://github.com/happner/happner-2/blob/master/docs/event.md) -* [Local Event Api](https://github.com/happner/happner-2/blob/master/docs/local-event.md) -* [Exchange Api](https://github.com/happner/happner-2/blob/master/docs/exchange.md) -* [Data Api](https://github.com/happner/happner-2/blob/master/docs/data.md) -* [Web Routes and Middleware](https://github.com/happner/happner-2/blob/master/docs/webroutes.md) -* [REST component](https://github.com/happner/happner-2/blob/master/docs/restcomponent.md) +* [Event Api](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/event.md) +* [Local Event Api](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/local-event.md) +* [Exchange Api](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/exchange.md) +* [Data Api](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/data.md) +* [Web Routes and Middleware](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/webroutes.md) +* [REST component](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/restcomponent.md) ### -* [Starting and Stopping Mesh Node](https://github.com/happner/happner-2/blob/master/docs/starting.md) -* [Mesh events](https://github.com/happner/happner-2/blob/master/docs/mesh-events.md) -* [Using the loader to start a mesh](https://github.com/happner/happner-2/blob/master/docs/loader.md) -* [System Components](https://github.com/happner/happner-2/blob/master/docs/system.md) -* [Using the Client](https://github.com/happner/happner-2/blob/master/docs/client.md) -* [utility scripts](https://github.com/happner/happner-2/blob/master/docs/utility-scripts.md) +* [Starting and Stopping Mesh Node](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/starting.md) +* [Mesh events](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/mesh-events.md) +* [Using the loader to start a mesh](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/loader.md) +* [System Components](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/system.md) +* [Using the Client](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/client.md) +* [utility scripts](https://github.com/happner/happner-suite/blob/develop/packages/happner-2/docs/utility-scripts.md) diff --git a/packages/happner-2/test/__fixtures/test/integration/events/component-on-emit-events/index.js b/packages/happner-2/test/__fixtures/test/integration/events/component-on-emit-events/index.js index 94250e8c5..0f91e0efc 100644 --- a/packages/happner-2/test/__fixtures/test/integration/events/component-on-emit-events/index.js +++ b/packages/happner-2/test/__fixtures/test/integration/events/component-on-emit-events/index.js @@ -122,10 +122,8 @@ Component.prototype.causeEmitError = function ($happn, eventKey, data, options, $happn.emit = function(eventKey, data, options, callback){ - $happn.__raiseOnPublishError(new Error('TEST ERROR')); - - $happn.__raiseOnEmitError(new Error('TEST ERROR')); - + $happn.emitEvent('on-publish-error', new Error('TEST ERROR')); + $happn.emitEvent('on-emit-error', new Error('TEST ERROR')); return callback(new Error('TEST ERROR')); }.bind($happn); diff --git a/packages/happner-2/test/__fixtures/utils/test_helper.js b/packages/happner-2/test/__fixtures/utils/test_helper.js index eb3752bbc..b91ef58ba 100644 --- a/packages/happner-2/test/__fixtures/utils/test_helper.js +++ b/packages/happner-2/test/__fixtures/utils/test_helper.js @@ -19,7 +19,7 @@ class TestHelper extends BaseTestHelper { this.path = require('path'); this.happnPackage = JSON.parse(this.fs.readFileSync(this.path.resolve(__dirname, '../../../../../node_modules/happn-3/package.json'))); this._ = commons._; - this.log = console.log; + this.log = this.sinon.spy(console.log); this.users = require('./users'); this.startUp = this.util.promisify(this.startUp); @@ -67,9 +67,6 @@ class TestHelper extends BaseTestHelper { }; startHappnerInstance (ctx, config, callback){ - - var _this = this; - if (!ctx) ctx = 'default'; if (typeof config == 'function') { diff --git a/packages/happner-2/test/browser-leaking/01-test-disconnects.js b/packages/happner-2/test/browser-leaking/01-test-disconnects.js new file mode 100644 index 000000000..22b372444 --- /dev/null +++ b/packages/happner-2/test/browser-leaking/01-test-disconnects.js @@ -0,0 +1,83 @@ +const { fork } = require('child_process'); +const path = require('path'); + +require('happn-commons-test').describe({ timeout: 45e3 }, (test) => { + let server1, server2; + let stats = []; + before('starts mesh', async () => { + server1 = fork(path.resolve(__dirname, './server.js')); + let done; + server1.on('message', async (data) => { + if (data === 'started') { + await test.delay(2000); + done(); + } + }); + await new Promise((res) => { + done = res; + }); + }); + + it('tests that after restarting a happner-2 server with connected browser, we dont have extra sessions or connections', async () => { + let done; + await test.delay(3000); + fork(path.resolve(__dirname, './_fixtures/karma-start.js')); + server1.on('message', (data) => { + if (typeof data === 'object') { + stats.push({ + connected: data.connected.length, + active: data.active.length, + attached: data.attached.length, + }); + } + }); + await test.delay(5000); + server1.send('listClients'); + server1.send('kill'); + server2 = fork(path.resolve(__dirname, './server.js')); + server2.on('message', async (data) => { + if (data === 'started') { + await test.delay(7000); + server2.send('listClients'); + } + if (typeof data === 'object') { + stats.push({ + connected: data.connected.length, + active: data.active.length, + attached: data.attached.length, + }); + server2.send('kill'); + await test.delay(1000); + + return done(); + } + }); + await new Promise((res) => { + done = res; + }); + let server3 = fork(path.resolve(__dirname, './server.js')); + + server3.on('message', async (data) => { + if (data === 'started') { + await test.delay(7000); + server3.send('listClients'); + } + if (typeof data === 'object') { + stats.push({ + connected: data.connected.length, + active: data.active.length, + attached: data.attached.length, + }); + server3.send('kill'); + await test.delay(1000); + + return done(); + } + }); + await new Promise((res) => { + done = res; + }); + // console.log(stats) + test.expect(stats[1]).to.eql(stats[2]); //There is an additional socker in stats[0] + }); +}); diff --git a/packages/happner-2/test/browser-leaking/_fixtures/01.karma.conf.js b/packages/happner-2/test/browser-leaking/_fixtures/01.karma.conf.js new file mode 100644 index 000000000..e630c7277 --- /dev/null +++ b/packages/happner-2/test/browser-leaking/_fixtures/01.karma.conf.js @@ -0,0 +1,61 @@ +// Karma configuration +// Generated on Tue Dec 01 2015 11:18:30 GMT+0200 (SAST) + +module.exports = function (config) { + config.set({ + crossOriginAttribute: false, + + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha', 'chai'], + + files: [ + { pattern: 'http://localhost:55000/api/client', type: 'js' }, + 'browsertest_01_happner_client.js', + ], + + // list of files / patterns to load in the browser + // files: [ + // 'build/crypto-min.js', + // {pattern: 'test/crypto-test.js', included: false} + // ], + + // list of files to exclude + exclude: [], + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['mocha'], + + // web server port + port: 9876, + + // enable / disable colors in the output (reporters and logs) + colors: true, + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: false, + detatched: true, + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['ChromeHeadless'], + browserDisconnectTimeout: 6000, + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: false, + + // Concurrency level + // how many browser should be started simultanous + concurrency: Infinity, + + browserNoActivityTimeout: 60000, + }); +}; diff --git a/packages/happner-2/test/browser-leaking/_fixtures/browsertest_01_happner_client.js b/packages/happner-2/test/browser-leaking/_fixtures/browsertest_01_happner_client.js new file mode 100644 index 000000000..3379cd2c1 --- /dev/null +++ b/packages/happner-2/test/browser-leaking/_fixtures/browsertest_01_happner_client.js @@ -0,0 +1,27 @@ +/* eslint-disable no-console */ + +describe('browsertest_01_happner_client', function () { + this.timeout(100e3); + + it('connects and disconnects clients', async () => { + let users = Array.from(Array(3).keys()).map((int) => ({ + username: 'user' + int.toString(), + password: 'pass', + })); + let clients = []; + for (let user of users) { + /* eslint-disable-next-line no-undef */ + let client = new Happner.HappnerClient(); + await client.connect(null, user); + clients.push(client); + } + await delay(35000); + }); + + function delay(ms) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + } +}); +/* eslint-enable no-console */ diff --git a/packages/happner-2/test/browser-leaking/_fixtures/karma-start.js b/packages/happner-2/test/browser-leaking/_fixtures/karma-start.js new file mode 100644 index 000000000..180462e2e --- /dev/null +++ b/packages/happner-2/test/browser-leaking/_fixtures/karma-start.js @@ -0,0 +1,10 @@ +var Server = require('karma').Server; +var karma = new Server( + { + configFile: __dirname + '/01.karma.conf.js', + singleRun: true, + }, + function () {} +); + +karma.start(); diff --git a/packages/happner-2/test/browser-leaking/server.js b/packages/happner-2/test/browser-leaking/server.js new file mode 100644 index 000000000..5e2d76668 --- /dev/null +++ b/packages/happner-2/test/browser-leaking/server.js @@ -0,0 +1,38 @@ +const Happner = require('../..'); + +(async () => { + let meshConfig = { + name: 'Server', + happn: { + secure: true, + adminPassword: 'xxx', + }, + }; + let mesh = await Happner.create(meshConfig); + let users = Array.from(Array(3).keys()).map((int) => ({ + username: 'user' + int.toString(), + password: 'pass', + })); + for (let user of users) { + await mesh.exchange.security.addUser(user); + } + let attached = []; + + mesh._mesh.happn.events.on('attach', async (data) => { + attached.push(data.user.username); + }); + process.on('message', async (msg) => { + if (msg === 'kill') { + mesh.stop({ reconnect: true, kill: true, wait: 50 }); + } + if (msg === 'listClients') { + let connected = Object.keys(mesh._mesh.happn.server.connections); + await mesh._mesh.happn.server.services.security.listActiveSessions((e, active) => { + process.send({ attached, active, connected }); + }); + } + }); + mesh._mesh.happn.server.services.security.activateSessionManagement(() => { + process.send('started'); + }); +})(); diff --git a/packages/happner-2/test/integration/client/client-timeout.js b/packages/happner-2/test/integration/client/client-timeout.js index dc3ad0842..42ed239cd 100644 --- a/packages/happner-2/test/integration/client/client-timeout.js +++ b/packages/happner-2/test/integration/client/client-timeout.js @@ -10,12 +10,8 @@ TestMesh.prototype.method1 = function ($happn, callback) { if (global.TESTING_D9 || global.TESTING_D9_1) return; // When 'requiring' the module above, // don't run the tests below -//............. require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test) => { - //require('benchmarket').start(); - //after(//require('benchmarket').store()); - var defaultConfigMesh; var Mesh = require('../../..'); var timeoutConfigMesh = new Mesh(); @@ -147,7 +143,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test it('runs a method on the default configured mesh', function (done) { defaultConfigClient.exchange.TestMesh.method1(function (e) { - test.expect(e).to.be('Request timed out'); + test.expect(e.message).to.be('Request timed out'); done(); }); }); diff --git a/packages/happner-2/test/integration/component/component-exchange-event-call-on.js b/packages/happner-2/test/integration/component/component-exchange-event-call-on.js index b9602a8af..d8ae3364a 100644 --- a/packages/happner-2/test/integration/component/component-exchange-event-call-on.js +++ b/packages/happner-2/test/integration/component/component-exchange-event-call-on.js @@ -412,15 +412,16 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test }); it('fails to call an internal function that is forbidden by an unauthorized user', async () => { - let message; + let message, result; try { - await clientTest.exchange.$call({ + result = await clientTest.exchange.$call({ component: 'component', method: 'exec', }); } catch (e) { message = e.message; } + test.expect(result).to.be(undefined); test.expect(message).to.be('unauthorized'); }); diff --git a/packages/happner-2/test/integration/exchange/exchange-promises.js b/packages/happner-2/test/integration/exchange/exchange-promises.js index c41c82315..742bbe504 100644 --- a/packages/happner-2/test/integration/exchange/exchange-promises.js +++ b/packages/happner-2/test/integration/exchange/exchange-promises.js @@ -23,8 +23,9 @@ SeeAbove.prototype.callCallbackTwice = function (opts, callback) { }, 100); }; -SeeAbove.prototype.fireAndForget = function () { - //do nothing +SeeAbove.prototype.fireAndForget = function (arg) { + //just echo the argument + return arg; }; SeeAbove.prototype.promiseMethod = util.promisify(function (opts, callback) { @@ -272,8 +273,6 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test }); it('supports calling a promise from a method on the exchange', function (done) { - this.timeout(1500); - this.mesh.exchange.component .promiseCaller({ number: 1 }) @@ -329,20 +328,19 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test }); }); - it('does not time out a sync function', function (done) { + it('sync function without callback gets exposed over the exchange', function (done) { this.timeout(2500); this.mesh.exchange.component .fireAndForget({ number: 1 }) - .then(function () { - // should never get here - done(new Error('Should not get a result')); + .then(function (result) { + // gets here even if we have not specified a callback + test.expect(result).to.eql({ number: 1 }); + done(); }) .catch(function (err) { done(err); }); - - setTimeout(done, 2000); }); it('does not fire a callback twice', function (done) { diff --git a/packages/happner-2/test/integration/rest/rest-component-secure.js b/packages/happner-2/test/integration/rest/rest-component-secure.js index 9cd3a8a6f..5a57241dd 100644 --- a/packages/happner-2/test/integration/rest/rest-component-secure.js +++ b/packages/happner-2/test/integration/rest/rest-component-secure.js @@ -182,6 +182,9 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test var happnUtils = require('../../../lib/system/utilities'); var mock$Happn = { + as: () => { + return mock$Happn; + }, log: { error: test.sinon.stub(), warn: test.sinon.stub(), @@ -428,14 +431,17 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test var RestModule = require('../../../lib/modules/rest/index.js'); var restModule = new RestModule(); - //$happn._mesh.happn.services.security - mockLogin(restModule, function (e) { if (e) return done(e); - //req, res, $happn, $origin, uri, successful - mock$Happn._mesh.happn.server.services.security = { + users: { + userBelongsToGroups: () => { + return new Promise((resolve) => { + resolve(true); + }); + }, + }, authorize: function (origin, accessPoint, action, callback) { try { test.expect(origin.test).to.be('data'); @@ -473,7 +479,17 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test }; restModule.__securityService = mock$Happn._mesh.happn.server.services.security; - restModule.__authorize(mockResponse, mock$Happn, mock$Origin, 'test/method', done); + restModule.__validateCredentialsGetOrigin( + mock$Happn, + mock$Origin, + mockResponse, + 'testComponent/methodName1', + 'testUser', + (authorizedOrigin) => { + test.expect(authorizedOrigin.username).to.be('testUser'); + done(); + } + ); }); }); @@ -520,7 +536,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test if (e) return done(e); mock$Happn._mesh.happn.server.services.security = { - authorize: function (origin, accessPoint, action, callback) { + authorize: function (_origin, _accessPoint, _action, callback) { callback(null, true); }, }; @@ -1046,7 +1062,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test ) .on('complete', function (result) { test.expect(result.data.userValue).to.eql(testUser.username); - test.expect(result.data.$origin.username).to.be('_ADMIN'); + test.expect(result.data.$origin.username).to.be(testUser.username); test.expect(result.data.$userSession.username).to.be(testUser.username); done(); diff --git a/packages/happner-2/test/integration/rest/rest-component.js b/packages/happner-2/test/integration/rest/rest-component.js index 108ba1ab2..a06778606 100644 --- a/packages/happner-2/test/integration/rest/rest-component.js +++ b/packages/happner-2/test/integration/rest/rest-component.js @@ -162,6 +162,9 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test var happnUtils = require('../../../lib/system/utilities'); var mock$Happn = { + as: () => { + return mock$Happn; + }, log: { error: test.sinon.stub(), info: test.sinon.stub(), diff --git a/packages/happner-2/test/integration/security/advanced-security.js b/packages/happner-2/test/integration/security/advanced-security.js index 4d6b3ec98..c0b722e57 100644 --- a/packages/happner-2/test/integration/security/advanced-security.js +++ b/packages/happner-2/test/integration/security/advanced-security.js @@ -148,10 +148,8 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test it('creates a test user', function (done) { adminClient.exchange.security.addUser(testUser, function (e, result) { if (e) return done(e); - test.expect(result.username).to.be(testUser.username); testUserSaved = result; - done(); }); }); @@ -268,12 +266,11 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test }); }); + // relies on preceding tests it('should list all groups', function (done) { adminClient.exchange.security.listGroups('*', function (e, groups) { if (e) return done(e); - - test.expect(groups.length).to.be(5); - + test.expect(groups.length).to.be(6); done(); }); }); diff --git a/packages/happner-2/test/integration/security/default-groups-upserted-even-if-exist.js b/packages/happner-2/test/integration/security/default-groups-upserted-even-if-exist.js index 738edbb44..7d8d6ba0c 100644 --- a/packages/happner-2/test/integration/security/default-groups-upserted-even-if-exist.js +++ b/packages/happner-2/test/integration/security/default-groups-upserted-even-if-exist.js @@ -76,7 +76,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test test.expect(admGroup).to.not.be(null); test.expect(gstGroup).to.not.be(null); - test.expect(upsertedGroups.length).to.be(2); + test.expect(upsertedGroups.length).to.be(3); test.delay(2000); }); @@ -88,7 +88,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test test.expect(admGroup).to.not.be(null); test.expect(gstGroup).to.not.be(null); - test.expect(upsertedGroups.length).to.be(4); + test.expect(upsertedGroups.length).to.be(6); //ensure we are able to add a user after this, and it is part of the _MESH_GST group await adminClient.exchange.security.addUser({ username: 'test', diff --git a/packages/happner-2/test/integration/security/login-token.js b/packages/happner-2/test/integration/security/login-token.js index 23e0e1639..8341ec9f8 100644 --- a/packages/happner-2/test/integration/security/login-token.js +++ b/packages/happner-2/test/integration/security/login-token.js @@ -1,6 +1,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 30e3 }, (test) => { var happnerInstance1 = null; var happnerInstance2 = null; + let client; var serviceConfig1 = { happn: { @@ -208,6 +209,12 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 30e3 }, (test) } }); + afterEach(async () => { + if (client) { + await client.disconnect(); + } + }); + after(function (done) { if (happnerInstance1) happnerInstance1 @@ -228,7 +235,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 30e3 }, (test) }); var getClient = function (options, credentials, callback) { - var client = new test.Mesh.MeshClient(options); + client = new test.Mesh.MeshClient(options); client .login(credentials) diff --git a/packages/happner-2/test/integration/security/on-behalf-of-auth-delegation-on.js b/packages/happner-2/test/integration/security/on-behalf-of-auth-delegation-on.js new file mode 100644 index 000000000..65c22b251 --- /dev/null +++ b/packages/happner-2/test/integration/security/on-behalf-of-auth-delegation-on.js @@ -0,0 +1,425 @@ +require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test) => { + const restClient = require('restler'); + const HappnerClient = require('happner-client'); + const LightClient = HappnerClient.Light; + let mesh, + adminUser, + testUsers = []; + before('it sets up the mesh', setUpMesh); + before('it connects the admin user', connectAdminUser); + before('it creates the test users', createTestUsers); + it('can do an http-rpc with as, delegated via the ADMIN user', async () => { + const token = adminUser.token; + test + .expect( + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ) + ) + .to.eql('origin:testUser:1:2'); + }); + it('can do an http-rpc with as, delegated via a delegate user', async () => { + const testDelegateUser = await connectTestUser(9); + const token = testDelegateUser.token; + test + .expect( + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ) + ) + .to.eql('origin:testUser:1:2'); + }); + it('can do an as, delegated via a delegate user, light client', async () => { + const testDelegateUser = await connectTestUserLightClient(9); + test + .expect( + await testDelegateUser.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: 'testUser', + }) + ) + .to.eql('origin:testUser:1:2'); + await testDelegateUser.disconnect(); + }); + it('cannot do without as, light client', async () => { + const testEdgeUser = await connectTestUserLightClient(8); + let errorMessage; + try { + await testEdgeUser.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowedNoAs', + arguments: [1, 2], + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.equal('unauthorized'); + await testEdgeUser.disconnect(); + }); + it('can do an as, delegated via a delegate user, happner client', async () => { + const testDelegateUser = await connectTestUserHappnerClient(9); + test + .expect( + await testDelegateUser.api.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: 'testUser', + }) + ) + .to.eql('origin:testUser:1:2'); + await testDelegateUser.session.disconnect(); + }); + it('cannot do without as, happner client', async () => { + const testEdgeUser = await connectTestUserHappnerClient(8); + let errorMessage; + try { + await testEdgeUser.api.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowedNoAs', + arguments: [1, 2], + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.equal('unauthorized'); + await testEdgeUser.session.disconnect(); + }); + it('can do an http-rpc with as, delegated via a user with delegate priviledges', async () => { + const testDelegateUser = await connectTestUser(9); + const token = testDelegateUser.token; + test + .expect( + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ) + ) + .to.eql('origin:testUser:1:2'); + }); + it('cannnot do an http-rpc without as, _ADMIN user is used after initial permissions check', async () => { + const edgeUser = await connectTestUser(8); + const token = edgeUser.token; + let errorMessage; + try { + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowedNoAs', + arguments: { param1: 1, param2: 2 }, + }, + token + ); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.equal('Access denied'); + }); + it('can do an http-rpc with as, using asAdmin in the edge method', async () => { + const edgeUser = await connectTestUser(7); + const testDelegateUser = await connectTestUser(9); + const token = testDelegateUser.token; + test + .expect( + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowedAsAdmin', + arguments: { param1: 1, param2: 2 }, + as: edgeUser.data.session.user.username, + }, + token + ) + ) + .to.eql('origin:testUser7:1:2'); + }); + it('fails to do an http-rpc with as', async () => { + const token = adminUser.token; + let errorMessage; + try { + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.eql('Access denied'); + }); + + it('fails to do an http-rpc with as because the origin is not a delegate user', async () => { + const testUser1 = await connectTestUser(1); + const token = testUser1.token; + let errorMessage; + try { + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.eql('origin does not belong to the delegate group'); + }); + + it('can do an exchange call with as in component method', async () => { + test + .expect(await adminUser.exchange.test.doOnBehalfOfAllowedAs(1, 2)) + .to.eql('origin:testUser:1:2'); + }); + + it('cannot do an exchange call without as, using _ADMIN user further down the stack', async () => { + const edgeUser = await connectTestUser(8); + let errorMessage; + try { + await edgeUser.exchange.test.doOnBehalfOfAllowedNoAs(1, 2); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.equal('unauthorized'); + }); + + it('fails to do an exchange call with as in component method', async () => { + const result = await adminUser.exchange.test.doOnBehalfOfNotAllowedAs(1, 2); + test.expect(result).to.eql(['unauthorized', 'unauthorized']); + }); + + it('can do an exchange $call with as', async () => { + test + .expect( + await adminUser.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: 'testUser', + }) + ) + .to.eql('origin:testUser:1:2'); + }); + + it('fails to do an exchange call with as', async () => { + let errorMessage; + try { + await adminUser.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [1, 2], + as: 'testUser', + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.be('unauthorized'); + }); + + after('it disconnects the admin user', disconnectAdminUser); + after('it disconnects the test users', disconnectTestUsers); + after('tears down mesh', stopMesh); + async function setUpMesh() { + mesh = await test.Mesh.create({ + authorityDelegationOn: true, + name: 'asMesh', + port: 12358, + secure: true, + modules: { + test: { + instance: { + doOnBehalfOfAllowedAsAdmin: async function (param1, param2, $origin, $happn) { + //this should work if we come in through the edge, without an as (backwards compatible with the existing system) + await $happn.asAdmin.exchange.test.doOnBehalfOfNotAllowed(); + return `origin:${$origin.username}:${param1}:${param2}`; + }, + doOnBehalfOfAllowedNoAs: async function (param1, param2, $origin, $happn) { + //this should work if we come in through the edge, without an as (backwards compatible with the existing system) + await $happn.exchange.test.doOnBehalfOfNotAllowed(); + return `origin:${$origin.username}:${param1}:${param2}`; + }, + doOnBehalfOfAllowed: async function (param1, param2, $origin) { + return `origin:${$origin.username}:${param1}:${param2}`; + }, + doOnBehalfOfNotAllowed: async function (_param1, _param2, $origin) { + return `unexpected:${$origin.username}`; + }, + doOnBehalfOfAllowedAs: async function (param1, param2, $happn) { + let result1 = await $happn.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [param1, param2], + as: 'testUser', + }); + let result2 = await $happn + .as('testUser') + .exchange.test.doOnBehalfOfAllowed(param1, param2); + test.expect(result1).to.eql(result2); + return result1; + }, + doOnBehalfOfNotAllowedAs: async function (param1, param2, $happn) { + const failures = []; + try { + await $happn.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [param1, param2], + as: 'testUser', + }); + } catch (e) { + failures.push(e.message); + } + try { + await $happn.as('testUser').exchange.test.doOnBehalfOfNotAllowed(param1, param2); + } catch (e) { + failures.push(e.message); + } + return failures; + }, + }, + }, + }, + components: { + test: {}, + }, + }); + } + async function stopMesh() { + if (mesh) await mesh.stop(); + } + async function connectAdminUser() { + adminUser = new test.Mesh.MeshClient({ port: 12358, secure: true }); + await adminUser.login({ + username: '_ADMIN', + password: 'happn', + }); + } + async function connectTestUser(id = '') { + const testUser = new test.Mesh.MeshClient({ port: 12358, secure: true }); + await testUser.login({ + username: `testUser${id}`, + password: `password`, + }); + testUsers.push(testUser); + return testUser; + } + async function connectTestUserLightClient(id = '') { + const mySession = new LightClient({ secure: true, domain: 'asMesh' }); + await mySession.connect({ + port: 12358, + username: `testUser${id}`, + password: `password`, + }); + return mySession; + } + async function connectTestUserHappnerClient(id = '') { + const createdClient = new HappnerClient({ secure: true }); + await createdClient.connect({ + port: 12358, + username: `testUser${id}`, + password: 'password', + }); + return { + session: createdClient, + api: createdClient.construct({ + test: { + version: '*', + methods: { + doOnBehalfOfAllowedNoAs: {}, + doOnBehalfOfAllowed: {}, + }, + }, + }), + }; + } + async function disconnectAdminUser() { + if (adminUser) await adminUser.disconnect(); + } + async function disconnectTestUsers() { + for (let testuserSession of testUsers) { + await testuserSession.disconnect(); + } + } + async function createTestUsers() { + for (var i = 0; i < 10; i++) { + await createTestUser(i === 0 ? '' : i.toString(), i === 9 ? true : false); + } + } + async function createTestUser(id = '', isDelegate) { + const testGroupUser = { + name: `testGroup${id}`, + permissions: { + methods: { + '/asMesh/test/doOnBehalfOfAllowedNoAs': { authorized: true }, + '/asMesh/test/doOnBehalfOfAllowedAsAdmin': { authorized: true }, + '/asMesh/test/doOnBehalfOfAllowed': { authorized: true }, + '/asMesh/test/doOnBehalfOfAllowedAs': { authorized: true }, + '/asMesh/test/doOnBehalfOfNotAllowedAs': { authorized: true }, + }, + }, + }; + await adminUser.exchange.security.upsertGroup(testGroupUser); + const upsertedUser = await adminUser.exchange.security.upsertUser({ + username: `testUser${id}`, + password: 'password', + }); + await adminUser.exchange.security.linkGroupName('testGroup', upsertedUser); + if (isDelegate) { + await adminUser.exchange.security.linkGroupName('_MESH_DELEGATE', upsertedUser); + } + } + async function testHttpRpc(requestInfo, token) { + return doRequest( + requestInfo.component, + requestInfo.method, + requestInfo.arguments, + requestInfo.as, + token + ); + } + function doRequest(componentName, methodName, operationArguments, as, token) { + var operation = { + parameters: operationArguments, + as, + }; + return new Promise((resolve, reject) => { + restClient + .postJson( + `http://127.0.0.1:12358/rest/method/${componentName}/${methodName}?happn_token=` + token, + operation + ) + .on('complete', function (result) { + if (result.error) { + return reject(new Error(result.error.message)); + } + resolve(result.data); + }) + .on('error', reject); + }); + } +}); diff --git a/packages/happner-2/test/integration/security/on-behalf-of.js b/packages/happner-2/test/integration/security/on-behalf-of.js new file mode 100644 index 000000000..24bfb2431 --- /dev/null +++ b/packages/happner-2/test/integration/security/on-behalf-of.js @@ -0,0 +1,414 @@ +require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test) => { + const restClient = require('restler'); + const HappnerClient = require('happner-client'); + const LightClient = HappnerClient.Light; + let mesh, + adminUser, + testUsers = []; + before('it sets up the mesh', setUpMesh); + before('it connects the admin user', connectAdminUser); + before('it creates the test users', createTestUsers); + it('can do an http-rpc with as, delegated via the ADMIN user', async () => { + const token = adminUser.token; + test + .expect( + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ) + ) + .to.eql('origin:testUser:1:2'); + }); + it('can do an http-rpc with as, delegated via a delegate user', async () => { + const testDelegateUser = await connectTestUser(9); + const token = testDelegateUser.token; + test + .expect( + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ) + ) + .to.eql('origin:testUser:1:2'); + }); + it('can do an as, delegated via a delegate user, light client', async () => { + const testDelegateUser = await connectTestUserLightClient(9); + test + .expect( + await testDelegateUser.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: 'testUser', + }) + ) + .to.eql('origin:testUser:1:2'); + await testDelegateUser.disconnect(); + }); + it('can do without as, light client', async () => { + const testEdgeUser = await connectTestUserLightClient(8); + test + .expect( + await testEdgeUser.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowedNoAs', + arguments: [1, 2], + }) + ) + .to.eql('origin:testUser8:1:2'); + await testEdgeUser.disconnect(); + }); + it('can do an as, delegated via a delegate user, happner client', async () => { + const testDelegateUser = await connectTestUserHappnerClient(9); + test + .expect( + await testDelegateUser.api.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: 'testUser', + }) + ) + .to.eql('origin:testUser:1:2'); + await testDelegateUser.session.disconnect(); + }); + it('can do without as, happner client', async () => { + const testEdgeUser = await connectTestUserHappnerClient(8); + test + .expect( + await testEdgeUser.api.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowedNoAs', + arguments: [1, 2], + }) + ) + .to.eql('origin:testUser8:1:2'); + await testEdgeUser.session.disconnect(); + }); + it('can do an http-rpc with as, delegated via a user with delegate priviledges', async () => { + const testDelegateUser = await connectTestUser(9); + const token = testDelegateUser.token; + test + .expect( + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ) + ) + .to.eql('origin:testUser:1:2'); + }); + it('can do an http-rpc without as, _ADMIN user is used after initial permissions check', async () => { + const edgeUser = await connectTestUser(8); + const token = edgeUser.token; + test + .expect( + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowedNoAs', + arguments: { param1: 1, param2: 2 }, + }, + token + ) + ) + .to.eql('origin:testUser8:1:2'); + }); + it('can do an http-rpc with as, using asAdmin in the edge method', async () => { + const edgeUser = await connectTestUser(8); + const testDelegateUser = await connectTestUser(9); + const token = testDelegateUser.token; + test + .expect( + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowedAsAdmin', + arguments: { param1: 1, param2: 2 }, + as: edgeUser.data.session.user.username, + }, + token + ) + ) + .to.eql('origin:testUser8:1:2'); + }); + it('fails to do an http-rpc with as', async () => { + const token = adminUser.token; + let errorMessage; + try { + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.eql('Access denied'); + }); + + it('fails to do an http-rpc with as because the origin is not a delegate user', async () => { + const testUser1 = await connectTestUser(1); + const token = testUser1.token; + let errorMessage; + try { + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.eql('origin does not belong to the delegate group'); + }); + + it('can do an exchange call with as in component method', async () => { + test + .expect(await adminUser.exchange.test.doOnBehalfOfAllowedAs(1, 2)) + .to.eql('origin:testUser:1:2'); + }); + + it('can do an exchange call without as, using _ADMIN user further down the stack', async () => { + const edgeUser = await connectTestUser(8); + test + .expect(await edgeUser.exchange.test.doOnBehalfOfAllowedNoAs(1, 2)) + .to.eql('origin:testUser8:1:2'); + }); + + it('fails to do an exchange call with as in component method', async () => { + const result = await adminUser.exchange.test.doOnBehalfOfNotAllowedAs(1, 2); + test.expect(result).to.eql(['unauthorized', 'unauthorized']); + }); + + it('can do an exchange $call with as', async () => { + test + .expect( + await adminUser.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: 'testUser', + }) + ) + .to.eql('origin:testUser:1:2'); + }); + + it('fails to do an exchange call with as', async () => { + let errorMessage; + try { + await adminUser.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [1, 2], + as: 'testUser', + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.be('unauthorized'); + }); + + after('it disconnects the admin user', disconnectAdminUser); + after('it disconnects the test users', disconnectTestUsers); + after('tears down mesh', stopMesh); + async function setUpMesh() { + mesh = await test.Mesh.create({ + name: 'asMesh', + port: 12358, + secure: true, + modules: { + test: { + instance: { + doOnBehalfOfAllowedAsAdmin: async function (param1, param2, $origin, $happn) { + //this should work if we come in through the edge, without an as (backwards compatible with the existing system) + await $happn.asAdmin.exchange.test.doOnBehalfOfNotAllowed(); + return `origin:${$origin.username}:${param1}:${param2}`; + }, + doOnBehalfOfAllowedNoAs: async function (param1, param2, $origin, $happn) { + //this should work if we come in through the edge, without an as (backwards compatible with the existing system) + await $happn.exchange.test.doOnBehalfOfNotAllowed(); + return `origin:${$origin.username}:${param1}:${param2}`; + }, + doOnBehalfOfAllowed: async function (param1, param2, $origin) { + return `origin:${$origin.username}:${param1}:${param2}`; + }, + doOnBehalfOfNotAllowed: async function (_param1, _param2, $origin) { + return `unexpected:${$origin.username}`; + }, + doOnBehalfOfAllowedAs: async function (param1, param2, $happn) { + let result1 = await $happn.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [param1, param2], + as: 'testUser', + }); + let result2 = await $happn + .as('testUser') + .exchange.test.doOnBehalfOfAllowed(param1, param2); + test.expect(result1).to.eql(result2); + return result1; + }, + doOnBehalfOfNotAllowedAs: async function (param1, param2, $happn) { + const failures = []; + try { + await $happn.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [param1, param2], + as: 'testUser', + }); + } catch (e) { + failures.push(e.message); + } + try { + await $happn.as('testUser').exchange.test.doOnBehalfOfNotAllowed(param1, param2); + } catch (e) { + failures.push(e.message); + } + return failures; + }, + }, + }, + }, + components: { + test: {}, + }, + }); + } + async function stopMesh() { + if (mesh) await mesh.stop(); + } + async function connectAdminUser() { + adminUser = new test.Mesh.MeshClient({ port: 12358, secure: true }); + await adminUser.login({ + username: '_ADMIN', + password: 'happn', + }); + } + async function connectTestUser(id = '') { + const testUser = new test.Mesh.MeshClient({ port: 12358, secure: true }); + await testUser.login({ + username: `testUser${id}`, + password: `password`, + }); + testUsers.push(testUser); + return testUser; + } + async function connectTestUserLightClient(id = '') { + const mySession = new LightClient({ secure: true, domain: 'asMesh' }); + await mySession.connect({ + port: 12358, + username: `testUser${id}`, + password: `password`, + }); + return mySession; + } + async function connectTestUserHappnerClient(id = '') { + const createdClient = new HappnerClient({ secure: true }); + await createdClient.connect({ + port: 12358, + username: `testUser${id}`, + password: 'password', + }); + return { + session: createdClient, + api: createdClient.construct({ + test: { + version: '*', + methods: { + doOnBehalfOfAllowedNoAs: {}, + doOnBehalfOfAllowed: {}, + }, + }, + }), + }; + } + async function disconnectAdminUser() { + if (adminUser) await adminUser.disconnect(); + } + async function disconnectTestUsers() { + for (let testuserSession of testUsers) { + await testuserSession.disconnect(); + } + } + async function createTestUsers() { + for (var i = 0; i < 10; i++) { + await createTestUser(i === 0 ? '' : i.toString(), i === 9 ? true : false); + } + } + async function createTestUser(id = '', isDelegate) { + const testGroupUser = { + name: `testGroup${id}`, + permissions: { + methods: { + '/asMesh/test/doOnBehalfOfAllowedNoAs': { authorized: true }, + '/asMesh/test/doOnBehalfOfAllowedAsAdmin': { authorized: true }, + '/asMesh/test/doOnBehalfOfAllowed': { authorized: true }, + '/asMesh/test/doOnBehalfOfAllowedAs': { authorized: true }, + '/asMesh/test/doOnBehalfOfNotAllowedAs': { authorized: true }, + }, + }, + }; + await adminUser.exchange.security.upsertGroup(testGroupUser); + const upsertedUser = await adminUser.exchange.security.upsertUser({ + username: `testUser${id}`, + password: 'password', + }); + await adminUser.exchange.security.linkGroupName('testGroup', upsertedUser); + if (isDelegate) { + await adminUser.exchange.security.linkGroupName('_MESH_DELEGATE', upsertedUser); + } + } + async function testHttpRpc(requestInfo, token) { + return doRequest( + requestInfo.component, + requestInfo.method, + requestInfo.arguments, + requestInfo.as, + token + ); + } + function doRequest(componentName, methodName, operationArguments, as, token) { + var operation = { + parameters: operationArguments, + as, + }; + return new Promise((resolve, reject) => { + restClient + .postJson( + `http://127.0.0.1:12358/rest/method/${componentName}/${methodName}?happn_token=` + token, + operation + ) + .on('complete', function (result) { + if (result.error) { + return reject(new Error(result.error.message)); + } + resolve(result.data); + }) + .on('error', reject); + }); + } +}); diff --git a/packages/happner-2/test/integration/security/permission-changes-events.js b/packages/happner-2/test/integration/security/permission-changes-events.js index e9127b93b..72b5c14a8 100644 --- a/packages/happner-2/test/integration/security/permission-changes-events.js +++ b/packages/happner-2/test/integration/security/permission-changes-events.js @@ -40,22 +40,16 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test after(function (done) { this.timeout(20000); - if (this.adminClient) - return this.adminClient.disconnect(() => { - this.adminClient.event.security.offPath('upsert-user'); - this.adminClient.event.security.offPath('upsert-group'); - this.adminClient.event.security.offPath('link-group'); - this.adminClient.event.security.offPath('unlink-group'); - this.adminClient.event.security.offPath('delete-group'); - this.adminClient.event.security.offPath('delete-user'); - mesh.stop({ reconnect: false }, function () { - setTimeout(() => { - //log(); - done(); - }, 11000); - }); - }); - return done(); + if (!adminClient) return done(); + adminClient.disconnect(() => { + adminClient.event.security.offPath('upsert-user'); + adminClient.event.security.offPath('upsert-group'); + adminClient.event.security.offPath('link-group'); + adminClient.event.security.offPath('unlink-group'); + adminClient.event.security.offPath('delete-group'); + adminClient.event.security.offPath('delete-user'); + mesh.stop({ reconnect: false }, done); + }); }); it('tests that all security events are being bubbled back from happn to happner security - and are consumable from an admin client', function (done) { diff --git a/packages/happner-2/test/integration/security/session-changes-events.js b/packages/happner-2/test/integration/security/session-changes-events.js index a4ad88928..2abe5c18e 100644 --- a/packages/happner-2/test/integration/security/session-changes-events.js +++ b/packages/happner-2/test/integration/security/session-changes-events.js @@ -31,19 +31,12 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 60e3 }, (test) ); }); - after(function (done) { - this.timeout(20000); + // test.printOpenHandlesAfter(5e3); - adminClient.disconnect(); - - setTimeout(function () { - mesh.stop({ reconnect: false }, () => { - setTimeout(() => { - //log(); - done(); - }, 11000); - }); - }, 2000); + after(async () => { + await testClient.disconnect(); + await adminClient.disconnect(); + await mesh.stop({ reconnect: false }); }); var eventsToFire = { diff --git a/packages/happner-2/test/integration/security/session-tokens.js b/packages/happner-2/test/integration/security/session-tokens.js index 4142cc00d..5c957899c 100644 --- a/packages/happner-2/test/integration/security/session-tokens.js +++ b/packages/happner-2/test/integration/security/session-tokens.js @@ -250,8 +250,6 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test }); it('tests the rest component with a managed profile, only able to access a trusted path', function (done) { - this.timeout(8000); - testAdminClient = new test.Mesh.MeshClient({ secure: true, port: 10000 }); var testGroupSaved; @@ -268,6 +266,7 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test methods: { '/remotetest.Mesh/remoteComponent/remoteFunction': { authorized: true }, '/testComponent/method2': { authorized: true }, + '/testComponent/method3': { authorized: true }, }, web: { '/rest/describe': { actions: ['get'], description: 'rest describe permission' }, diff --git a/packages/happner-2/test/issues/gc-heapdump/client.js b/packages/happner-2/test/issues/gc-heapdump/client.js index d8927d748..c99ed3fd5 100644 --- a/packages/happner-2/test/issues/gc-heapdump/client.js +++ b/packages/happner-2/test/issues/gc-heapdump/client.js @@ -59,24 +59,28 @@ async function connectClients() { return clients; } async function createAndConnectClient(index, adminClient) { - const testGroupAdded = await adminClient.exchange.security.upsertGroup({ + await adminClient.exchange.security.upsertGroup({ name: 'TEST GROUP' + index, permissions: { methods: { //in a /Mesh name/component name/method name - with possible wildcards '/meshname/component/*': { authorized: true }, + '/meshname/data/*': { authorized: true }, }, events: { //in a /Mesh name/component name/event key - with possible wildcards '/meshname/component/*': { authorized: true }, }, + data: { + '/_data/component/stress/test/*': { actions: ['set', 'on'] }, + }, }, }); - const testUserAdded = await adminClient.exchange.security.upsertUser({ + await adminClient.exchange.security.upsertUser({ username: 'user' + index, password: 'password', }); - await adminClient.exchange.security.linkGroup(testGroupAdded, testUserAdded); + await adminClient.exchange.security.linkGroup('TEST GROUP' + index, 'user' + index); let testClient = new test.Mesh.MeshClient({ secure: true }); await testClient.login({ username: 'user' + index, password: 'password' }); return testClient; diff --git a/packages/happner-2/test/unit/component/component-instance-bound-exchange-factory.js b/packages/happner-2/test/unit/component/component-instance-bound-exchange-factory.js new file mode 100644 index 000000000..bf614c9c1 --- /dev/null +++ b/packages/happner-2/test/unit/component/component-instance-bound-exchange-factory.js @@ -0,0 +1,204 @@ +require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test) => { + const BoundExchangeFactory = require('../../../lib/system/component-instance-bound-factory'); + const EventEmitter = require('events').EventEmitter; + const eventEmitter = new EventEmitter(); + const LRUCache = require('happn-3/lib/services/cache/cache-lru'); + + it('can initialize a bound exchange item', function () { + const mockedMesh = mockMesh(); + const mockedComponent = mockComponentInstance( + undefined, + mockedMesh, + 'backward-compatible-mesh' + ); + const boundExchangeFactory = BoundExchangeFactory.create(mockedComponent, mockedMesh); + const boundComponent = boundExchangeFactory.getBoundComponent({ username: 'test' }); + test.expect(boundComponent._mesh).to.be(mockedMesh); + test.expect(boundComponent.mesh).to.be('backward-compatible-mesh'); + test.expect(boundComponent.bound).to.eql({ username: 'test', override: true, type: 1 }); + test.expect(boundComponent.exchange.testComponent).to.not.be(undefined); + test.expect(boundComponent.exchange.testComponent.testMethod).to.not.be(undefined); + test.expect(boundComponent.exchange.testComponent.testMethod1).to.not.be(undefined); + test.expect(boundComponent.exchange.testComponent1).to.not.be(undefined); + test.expect(boundComponent.exchange.unknownComponent).to.be(undefined); + test.expect(boundComponent.event.testComponent1).to.not.be(undefined); + test.expect(boundComponent.event.testComponent).to.not.be(undefined); + test.expect(boundExchangeFactory.cache.size()).to.be(1); + const boundComponent1 = boundExchangeFactory.getBoundComponent( + { username: 'test' }, + undefined, + 'testComponent', + 'testMethod', + 0 + ); + test.expect(boundComponent1.exchange.testComponent).to.not.be(undefined); + test.expect(boundComponent1.exchange.testComponent.testMethod).to.not.be(undefined); + test.expect(boundComponent1.exchange.testComponent.testMethod1).to.be(undefined); + test.expect(boundComponent1.exchange.testComponent1).to.be(undefined); + test.expect(boundComponent1.event.testComponent1).to.be(undefined); + test.expect(boundComponent1.event.testComponent).to.not.be(undefined); + test.expect(boundComponent.exchange.unknownComponent).to.be(undefined); + test.expect(boundExchangeFactory.cache.size()).to.be(2); + test + .expect(boundExchangeFactory.cache.keys()) + .to.eql(['test:*:*:1', 'test:testComponent:testMethod:0']); + + const testBoundComponent = boundExchangeFactory.getBoundComponent( + { username: 'test' }, + undefined, + 'testComponent', + 'testMethod', + 0 + ); + + //check we are able to get a cached bound component + test.expect(testBoundComponent).to.be(boundComponent1); + test.expect(boundExchangeFactory.cache.size()).to.be(2); + + //cache must be cleared when the security changes + mockedMesh.happn.server.services.security.emit('security-data-changed'); + test.expect(boundExchangeFactory.cache.size()).to.be(0); + + test + .expect(boundExchangeFactory.getBoundComponent({ username: '_ADMIN' })) + .to.be(mockedComponent); + }); + + it('tests origin binding check', function () { + const boundExchangeFactory = BoundExchangeFactory.create( + mockComponentInstance(), + mockMesh(undefined, undefined, true) + ); + const boundExchangeFactoryUnsecure = BoundExchangeFactory.create( + mockComponentInstance(), + mockMesh(undefined, false) + ); + const boundExchangeFactoryAuthDelegationOff = BoundExchangeFactory.create( + mockComponentInstance(false), + mockMesh(undefined, undefined, true) + ); + const boundExchangeFactoryAllAuthDelegationOff = BoundExchangeFactory.create( + mockComponentInstance(false), + mockMesh(undefined, undefined, false) + ); + checkOriginBindingNecessary(boundExchangeFactoryUnsecure, { username: 'test' }, true, false); + checkOriginBindingNecessary(boundExchangeFactory, { username: '_ADMIN' }, true, false); + checkOriginBindingNecessary(boundExchangeFactory, { username: '_ADMIN' }, null, false); + checkOriginBindingNecessary(boundExchangeFactory, { username: 'test' }, null, true); + checkOriginBindingNecessary( + boundExchangeFactory, + { username: 'test', override: true }, + null, + true + ); + checkOriginBindingNecessary( + boundExchangeFactory, + { username: 'test', override: false }, + null, + false + ); + checkOriginBindingNecessary( + boundExchangeFactoryAuthDelegationOff, + { username: 'test' }, + null, + false + ); + checkOriginBindingNecessary( + boundExchangeFactoryAllAuthDelegationOff, + { username: 'test' }, + undefined, + false + ); + }); + + function checkOriginBindingNecessary(boundExchangeFactory, origin, override, expectation) { + test.expect(boundExchangeFactory.originBindingNecessary(origin, override)).to.be(expectation); + } + + function mockComponentInstance(authorityDelegationOn = true, _mesh, mesh) { + const mockEndpoint = { + data: {}, + }; + return { + as: test.sinon.stub(), + mesh, + _mesh, + config: { + security: { + authorityDelegationOn, + }, + }, + exchange: { + $call: test.sinon.stub(), + testComponent: { + testMethod: test.sinon.stub(), + testMethod1: test.sinon.stub(), + testField: 'test-field-value', + }, + testComponent1: { + testMethod: test.sinon.stub(), + testMethod1: test.sinon.stub(), + }, + testNestedComponent1: { + testChildComponent: { + testMethod: test.sinon.stub(), + testMethod1: test.sinon.stub(), + }, + }, + }, + event: { + $call: test.sinon.stub(), + testComponent: { + __endpoint: mockEndpoint, + __domain: 'test-domain', + }, + testComponent1: {}, + testNestedComponent1: { + testChildComponent: { + __endpoint: mockEndpoint, + __domain: 'test-domain', + }, + }, + testNestedComponent2: { + testChildComponent: { + __domain: 'test-domain', + }, + }, + }, + }; + } + + function mockMesh(boundExchangeCacheSize = 5, secure = true, authorityDelegationOn = true) { + return { + config: { + authorityDelegationOn, + happn: { + secure, + }, + components: { + security: { + config: { + boundExchangeCacheSize, + }, + }, + }, + }, + happn: { + server: { + services: { + security: eventEmitter, + cache: { + getOrCreate: function () { + return new LRUCache('test', { + cache: { + max: boundExchangeCacheSize, + }, + }); + }, + }, + }, + }, + }, + }; + } +}); diff --git a/packages/happner-2/test/unit/component/component-instance-bound-exchange.js b/packages/happner-2/test/unit/component/component-instance-bound-exchange.js deleted file mode 100644 index bd896c073..000000000 --- a/packages/happner-2/test/unit/component/component-instance-bound-exchange.js +++ /dev/null @@ -1,154 +0,0 @@ -describe( - require('../../__fixtures/utils/test_helper').create().testName(__filename, 3), - function () { - var expect = require('expect.js'); - - it('tests the clearCachedBoundExchange function, uninitalized cache', function () { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - componentInstance.clearCachedBoundExchange(); - }); - - it('tests the clearCachedBoundExchange function, initialized cache', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - componentInstance.boundExchangeCache = { - clear: done, - }; - componentInstance.clearCachedBoundExchange(); - }); - - it('tests the initializeCachedBoundExchange function, new cache', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var EventEmitter = require('events').EventEmitter; - var eventEmitter = new EventEmitter(); - var cleared = false; - var mesh = { - config: { - boundExchangeCacheSize: 5, - }, - happn: { - server: { - services: { - security: eventEmitter, - cache: { - __caches: {}, - getOrCreate: function (key, opts) { - expect(opts).to.eql({ - type: 'LRU', - cache: { - max: mesh.config.boundExchangeCacheSize || 10000, - }, - }); - return { - clear: function () { - if (cleared) return; - cleared = true; - done(); - }, - }; - }, - }, - }, - }, - }, - }; - - componentInstance.initializeCachedBoundExchange(mesh, 'test-component'); - mesh.happn.server.services.security.emit('security-data-changed', {}); - }); - - it('tests the initializeCachedBoundExchange function, initialized cache', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var EventEmitter = require('events').EventEmitter; - var eventEmitter = new EventEmitter(); - var cleared = false; - - var mesh = { - config: { - boundExchangeCacheSize: 5, - }, - happn: { - server: { - services: { - security: eventEmitter, - cache: { - __caches: { - 'happner-bound-exchangeSecuredComponent': { - clear: done, - }, - }, - getOrCreate: function (key, opts) { - expect(opts).to.eql({ - type: 'LRU', - cache: { - max: mesh.config.boundExchangeCacheSize || 10000, - }, - }); - return { - clear: function () { - if (cleared) return; - cleared = true; - done(); - }, - }; - }, - }, - }, - }, - }, - }; - - componentInstance.initializeCachedBoundExchange(mesh, 'test-component'); - mesh.happn.server.services.security.emit('security-data-changed', {}); - }); - - it('tests the getCachedBoundExchange function, uninitialized cache', function () { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - expect( - componentInstance.getCachedBoundExchange({ - username: 'test-user', - }) - ).to.be(null); - }); - - it('tests the getCachedBoundExchange function, initialized cache', function () { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - - componentInstance.boundExchangeCache = { - get: function () { - return {}; - }, - }; - - expect( - componentInstance.getCachedBoundExchange({ - username: 'test-user', - }) - ).to.eql({}); - }); - - it('tests the setCachedBoundExchange function, initialized cache', function () { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - - var cached = {}; - - componentInstance.boundExchangeCache = { - get: function (key) { - return this[key]; - }, - set: function (key, value) { - this[key] = value; - }, - }; - - expect(componentInstance.setCachedBoundExchange('username', cached)).to.be(cached); - expect(componentInstance.getCachedBoundExchange('username')).to.be(cached); - }); - } -); diff --git a/packages/happner-2/test/unit/component/component-instance-data.js b/packages/happner-2/test/unit/component/component-instance-data.js new file mode 100644 index 000000000..7fa55d6ba --- /dev/null +++ b/packages/happner-2/test/unit/component/component-instance-data.js @@ -0,0 +1,653 @@ +require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test) => { + function mockData(state) { + if (!state) state = 1; //active + + return { + status: state, + get: test.sinon.stub().callsArg(2), + on: test.sinon.stub().callsArg(3), + off: test.sinon.stub().callsArg(1), + offPath: test.sinon.stub().callsArg(1), + getPaths: test.sinon.stub().callsArg(2), + set: test.sinon.stub().callsArg(3), + increment: test.sinon.stub().callsArg(4), + remove: test.sinon.stub().callsArg(2), + count: test.sinon.stub().callsArg(2), + }; + } + + it('test the on with a connection, no origin and options', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent' + ); + secureData.on('test/path', null, function () {}, done); + }); + + it('test the on with a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + secureData.on('test/path', {}, function () {}, done); + }); + + it('test the on with a connection with preceding /', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + secureData.on('/test/path', {}, function () {}, done); + }); + + it('test the on with a connection, default opts', function (done) { + const mockedData = mockData(); + const secureData = require('../../../lib/system/component-instance-data').create( + mockedData, + 'testComponent', + { username: 'test' } + ); + secureData.on( + 'test/path', + function () {}, + () => { + test.expect(mockedData.on.lastCall.args[0]).to.eql('/_data/testComponent/test/path'); + test.expect(mockedData.on.lastCall.args[1]).to.eql({ + onBehalfOf: 'test', + }); + done(); + } + ); + }); + + it('test the on with a connection, default opts, with *', function (done) { + const mockedData = mockData(); + const secureData = require('../../../lib/system/component-instance-data').create( + mockedData, + 'testComponent', + { username: 'test' } + ); + secureData.on( + '*', + function () {}, + () => { + test.expect(mockedData.on.lastCall.args[0]).to.eql('/_data/testComponent/**'); + test.expect(mockedData.on.lastCall.args[1]).to.eql({ + onBehalfOf: 'test', + }); + done(); + } + ); + }); + + it('test the bad path, on', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + secureData.on( + '', + {}, + function () {}, + (e) => { + test.expect(e.message).to.be('[bad path]: either empty or not a string'); + done(); + } + ); + }); + + it('test the on without a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.on( + 'test/path', + {}, + function () {}, + function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: on, path: test/path, component: testComponent' + ); + done(); + } + ); + }); + + it('test the off with a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + secureData.off('test/path', done); + }); + + it('test the off by listenerRef with a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + secureData.off(1, done); + }); + + it('test the off with a connection, bad path', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + secureData.off(undefined, (e) => { + test.expect(e.message).to.be('[bad path]: either empty or not a string'); + done(); + }); + }); + + it('test the off without a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + secureData.off('test/path', function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: off, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the offAll with a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + + secureData.offAll(done); + }); + + it('test the offAll without a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.offAll(function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: offAll, path: *, component: testComponent' + ); + done(); + }); + }); + + it('test the offPath with a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + + secureData.offPath('test/path', done); + }); + + it('test the offPath with a connection, bad path', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + secureData.offPath(null, (e) => { + test.expect(e.message).to.be('[bad path]: either empty or not a string'); + done(); + }); + }); + + it('test the offPath without a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.offPath('test/path', function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: offPath, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the get with a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + secureData.get('test/path', {}, done); + }); + + it('test the get with a connection, default options, no origin', function (done) { + const mockedData = mockData(); + const secureData = require('../../../lib/system/component-instance-data').create( + mockedData, + 'testComponent' + ); + secureData.get('test/path', undefined, () => { + test.expect(mockedData.get.lastCall.args[0]).to.eql('/_data/testComponent/test/path'); + test.expect(mockedData.get.lastCall.args[1]).to.eql({}); + done(); + }); + }); + + it('test the get with a connection, bad path', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + secureData.get({}, {}, (e) => { + test.expect(e.message).to.be('[bad path]: either empty or not a string'); + done(); + }); + }); + + it('test the get without a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + secureData.get('test/path', {}, function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: get, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the get without a connection, default args', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.get('test/path', function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: get, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the count with a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + secureData.count('test/path', {}, done); + }); + + it('test the count with a connection, default options, no origin', function (done) { + const mockedData = mockData(); + const secureData = require('../../../lib/system/component-instance-data').create( + mockedData, + 'testComponent' + ); + secureData.count('test/path', undefined, () => { + test.expect(mockedData.count.lastCall.args[0]).to.eql('/_data/testComponent/test/path'); + test.expect(mockedData.count.lastCall.args[1]).to.eql({}); + done(); + }); + }); + + it('test the count with a connection. bad path', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + secureData.count(1, {}, (e) => { + test.expect(e.message).to.be('[bad path]: either empty or not a string'); + done(); + }); + }); + + it('test the count without a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.count('test/path', {}, function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: count, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the count without a connection, default args', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + secureData.count('test/path', function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: count, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the getPaths with a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + + secureData.getPaths('test/path/*', done); + }); + + it('test the getPaths with a connection, no origin', function (done) { + const mockedData = mockData(); + const secureData = require('../../../lib/system/component-instance-data').create( + mockedData, + 'testComponent' + ); + secureData.getPaths('test/path/*', () => { + test.expect(mockedData.getPaths.lastCall.args[0]).to.eql('/_data/testComponent/test/path/*'); + test.expect(mockedData.getPaths.lastCall.args[1]).to.eql({}); + done(); + }); + }); + + it('test the getPaths with a connection, bad path', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + + secureData.getPaths(null, (e) => { + test.expect(e.message).to.be('[bad path]: either empty or not a string'); + done(); + }); + }); + + it('test the getPaths without a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + secureData.getPaths('test/path/*', function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: getPaths, path: test/path/*, component: testComponent' + ); + done(); + }); + }); + + it('test the set with a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + + secureData.set('test/path', {}, {}, done); + }); + + it('test the set with a connection, no origin default opts', function (done) { + const mockedData = mockData(); + const secureData = require('../../../lib/system/component-instance-data').create( + mockedData, + 'testComponent' + ); + + secureData.set('test/path', {}, undefined, () => { + test.expect(mockedData.set.lastCall.args[0]).to.eql('/_data/testComponent/test/path'); + test.expect(mockedData.set.lastCall.args[1]).to.eql({}); + done(); + }); + }); + + it('test the set with a connection, bad path', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + + secureData.set(null, {}, {}, (e) => { + test.expect(e.message).to.be('[bad path]: either empty or not a string'); + done(); + }); + }); + + it('test the set without a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.set('test/path', {}, {}, function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: set, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the set without a connection, default args', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.set('test/path', {}, function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: set, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the increment with a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + + secureData.increment('test/path', 'test-gauge', 1, done); + }); + + it('test the increment with a connection, no origin', function (done) { + const mockedData = mockData(); + const secureData = require('../../../lib/system/component-instance-data').create( + mockedData, + 'testComponent' + ); + + secureData.increment('test/path', 'test-gauge', 10, () => { + test.expect(mockedData.increment.lastCall.args[0]).to.eql('/_data/testComponent/test/path'); + test.expect(mockedData.increment.lastCall.args[1]).to.eql('test-gauge'); + test.expect(mockedData.increment.lastCall.args[2]).to.eql(10); + test.expect(mockedData.increment.lastCall.args[3]).to.eql({}); + done(); + }); + }); + + it('test the increment with a connection, bad path', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + + secureData.increment(null, 'test-gauge', 1, (e) => { + test.expect(e.message).to.be('[bad path]: either empty or not a string'); + done(); + }); + }); + + it('test the increment without a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.increment('test/path', 'test-gauge', 1, function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: increment, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the increment without a connection, default args 1', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.increment('test/path', function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: increment, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the increment without a connection, default args 2', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.increment('test/path', 'test-gauge', function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: increment, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the remove with a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + + secureData.remove('test/path', {}, done); + }); + + it('test the remove with a connection, no origin, default opts', function (done) { + const mockedData = mockData(); + const secureData = require('../../../lib/system/component-instance-data').create( + mockedData, + 'testComponent' + ); + + secureData.remove('test/path', undefined, () => { + test.expect(mockedData.remove.lastCall.args[0]).to.eql('/_data/testComponent/test/path'); + test.expect(mockedData.remove.lastCall.args[1]).to.eql({}); + done(); + }); + }); + + it('test the remove with a connection, bad path', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(), + 'testComponent', + { username: 'test' } + ); + + secureData.remove(null, {}, (e) => { + test.expect(e.message).to.be('[bad path]: either empty or not a string'); + done(); + }); + }); + + it('test the remove without a connection', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.remove('test/path', {}, function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: remove, path: test/path, component: testComponent' + ); + done(); + }); + }); + + it('test the remove without a connection, default args', function (done) { + const secureData = require('../../../lib/system/component-instance-data').create( + mockData(2), + 'testComponent', + { username: 'test' } + ); + + secureData.remove('test/path', function (e) { + test + .expect(e.toString()) + .to.be( + 'Error: client state not active or connected, action: remove, path: test/path, component: testComponent' + ); + done(); + }); + }); +}); diff --git a/packages/happner-2/test/unit/component/component-instance-secure-data.js b/packages/happner-2/test/unit/component/component-instance-secure-data.js deleted file mode 100644 index 35a7709cf..000000000 --- a/packages/happner-2/test/unit/component/component-instance-secure-data.js +++ /dev/null @@ -1,423 +0,0 @@ -describe( - require('../../__fixtures/utils/test_helper').create().testName(__filename, 3), - function () { - var expect = require('expect.js'); - - function mockData(state) { - if (!state) state = 1; //active - - return { - status: state, - get: function (path, opts, callback) { - return callback(); - }, - on: function (path, opts, handler, callback) { - return callback(); - }, - off: function (path, callback) { - return callback(); - }, - offPath: function (path, callback) { - return callback(); - }, - getPaths: function (path, callback) { - return callback(); - }, - set: function (path, data, opts, callback) { - return callback(); - }, - setSibling: function (path, data, callback) { - return callback(); - }, - increment: function (path, gauge, increment, callback) { - return callback(); - }, - remove: function (path, opts, callback) { - return callback(); - }, - count: function (path, opts, callback) { - return callback(); - }, - }; - } - - it('test the on with a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(), 'test-component'); - - secureData.on('test/path', {}, function () {}, done); - }); - - it('test the on without a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.on( - 'test/path', - {}, - function () {}, - function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, on:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - } - ); - }); - - it('test the on without a connection, with default args', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.on( - 'test/path', - function () {}, - function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, on:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - } - ); - }); - - it('test the off with a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(), 'test-component'); - - secureData.off('test/path', done); - }); - - it('test the off without a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.off('test/path', function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, off ref:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the offAll with a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(), 'test-component'); - - secureData.offAll(done); - }); - - it('test the offAll without a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.offAll(function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, offAll, component:test-component' - ); - done(); - }); - }); - - it('test the offPath with a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(), 'test-component'); - - secureData.offPath('test/path', done); - }); - - it('test the offPath without a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.offPath('test/path', function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, offPath:test/path, component:test-component' - ); - done(); - }); - }); - - it('test the get with a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(), 'test-component'); - - secureData.get('test/path', {}, done); - }); - - it('test the get without a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.get('test/path', {}, function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, get:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the get without a connection, default args', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.get('test/path', function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, get:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the count with a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(), 'test-component'); - - secureData.count('test/path', {}, done); - }); - - it('test the count without a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.count('test/path', {}, function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, get:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the count without a connection, default args', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.count('test/path', function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, get:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the getPaths with a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(), 'test-component'); - - secureData.getPaths('test/path/*', done); - }); - - it('test the getPaths without a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.getPaths('test/path/*', function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, getPaths:' + - 'test/path/*' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the set with a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(), 'test-component'); - - secureData.set('test/path', {}, {}, done); - }); - - it('test the set without a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.set('test/path', {}, {}, function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, set:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the set without a connection, default args', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.set('test/path', {}, function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, set:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the increment with a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(), 'test-component'); - - secureData.increment('test/path', 'test-gauge', 1, done); - }); - - it('test the increment without a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.increment('test/path', 'test-gauge', 1, function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, increment:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the increment without a connection, default args 1', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.increment('test/path', function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, increment:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the increment without a connection, default args 2', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.increment('test/path', 'test-gauge', function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, increment:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the setSibling with a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(), 'test-component'); - - secureData.setSibling('test/path', {}, done); - }); - - it('test the setSibling without a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.setSibling('test/path', {}, function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, setSibling:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the remove with a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(), 'test-component'); - - secureData.remove('test/path', {}, done); - }); - - it('test the remove without a connection', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.remove('test/path', {}, function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, remove:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - - it('test the remove without a connection, default args', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - var secureData = componentInstance.secureData(mockData(2), 'test-component'); - - secureData.remove('test/path', function (e) { - expect(e.toString()).to.be( - 'Error: client state not active or connected, remove:' + - 'test/path' + - ', component:' + - 'test-component' - ); - done(); - }); - }); - } -); diff --git a/packages/happner-2/test/unit/component/component-instance.js b/packages/happner-2/test/unit/component/component-instance.js index 6513cc9df..47b92722b 100644 --- a/packages/happner-2/test/unit/component/component-instance.js +++ b/packages/happner-2/test/unit/component/component-instance.js @@ -1,227 +1,2114 @@ +const LRUCache = require('happn-3/lib/services/cache/cache-lru'); +const ComponentInstance = require('../../../lib/system/component-instance'); +const eventEmitter = require('events').EventEmitter; +const ComponentInstanceBoundFactory = require('../../../lib/system/component-instance-bound-factory'); +const utilities = require('../../../lib/system/utilities'); + require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test) => { - it('test the describe method', function () { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - componentInstance.name = 'test-component-instance'; - componentInstance.module = { - name: 'test-name-module', - version: '1.0.0', - instance: mockModuleInstance(), + const mockLogObj = { + info: test.sinon.stub(), + error: test.sinon.stub(), + debug: test.sinon.stub(), + trace: test.sinon.stub(), + $$TRACE: test.sinon.stub(), + warn: test.sinon.stub(), + }; + + beforeEach(() => { + test.sinon.restore(); + }); + + it('tests initialize method, config.accessLevel equal to root, creates _mesh variable', function () { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + config.accessLevel = 'root'; + const mockCallback = test.sinon.stub(); + + const getBoundComponentStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ getBoundComponent: test.sinon.stub().returns('mockComponent') }); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + test.expect(componentInstance._mesh).to.eql(mesh._mesh); + + getBoundComponentStub.restore(); + }); + + it('tests as method', function () { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + const getBoundComponentStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ getBoundComponent: test.sinon.stub().returns('mockComponent') }); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + const result = componentInstance.as( + 'mockUserName', + 'mockComponentName', + 'mockMethodName', + 'mockSessionType' + ); + + test.chai.expect(result).to.equal('mockComponent'); + + getBoundComponentStub.restore(); + }); + + it('tests #default method', function () { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + module.instance.$happner.config.component.events = 'mockEvent'; + const config = mockConfig(); + config.events = 'mockEvent'; + const mockCallback = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + test.chai.expect(config).to.have.ownProperty('keyOne').that.equals('keyOne'); + test.chai.expect(config).to.have.ownProperty('keyTwo').that.equals('keyTwo'); + }); + + it('tests isAuthorized method', async function () { + let componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + (mesh._mesh.happn.server.services.security.authorizeOnBehalfOf = test.sinon + .stub() + .withArgs('', '', '', '', test.sinon.match.func) + .callsArgWith(4, null, false, 'mockReason')), + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + const result = componentInstance.isAuthorized('mockUsername', { methods: ['mockMethod'] }); + + await test.chai.expect(result).to.eventually.eql({ + forbidden: [ + { + authorized: false, + reason: 'mockReason', + path: '/_exchange/requests/mockMethod', + action: 'set', + }, + ], + authorized: false, + }); + }); + + it('checks all the getters', function () { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + // test all getters + test.chai.expect(componentInstance.Mesh).to.be.instanceOf(Function); + test.chai.expect(componentInstance.name).to.equal('mockName'); + test.chai.expect(componentInstance.config).to.equal(config); + test.chai.expect(componentInstance.info).to.eql({ + happn: { + address: { + protocol: 'http', + }, + options: undefined, + }, + mesh: { + domain: 'mockDomain', + name: 'test-mesh-name', + }, + }); + test.chai.expect(componentInstance.mesh).to.be.instanceOf(ComponentInstance); + test.chai.expect(componentInstance.mesh.constructor.name).to.equal('ComponentInstance'); + test.chai.expect(componentInstance.module).to.eql({ + instance: { + $happner: { + config: { + component: { + keyOne: 'keyOne', + keyTwo: 'keyTwo', + }, + }, + }, + }, + name: 'test-module', + version: 'mockVersion', + }); + + const loggers = ['info', 'error', 'debug', 'trace', '$$TRACE', 'warn']; + loggers.forEach((log) => test.chai.expect(componentInstance.log).to.have.ownProperty(log)); + + test.chai.expect(componentInstance.localEventEmitter).to.be.instanceOf(eventEmitter); + test.chai.expect(componentInstance.tools).to.equal('mockTools'); + }); + + it('tests #inject method - parameters.length is less then methodDefn.$argumentsLength', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const mockModule = { + instance: { + mockMethodName: test.sinon.stub().returns('mockResult'), + version: 'mockVersion', + }, }; - componentInstance.description = { - test: 'description', + const config = mockConfig(); + const mockMethodName = 'mockMethodName'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + const origin = 'mockOrigin'; + const verion = null; + const originBindingOverride = 'mockBinding'; + + componentInstance.description = { methods: { mockMethodName: { type: 'sync-promise' } } }; + + componentInstance.initialize('mockName', mesh, mockModule, config, mockCallback1); + + mockModule.instance.mockMethodName.$argumentsLength = 3; + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + origin, + verion, + originBindingOverride + ); + + test.chai.expect(mockCallback2).to.have.been.calledWithExactly(null, [null, 'mockResult']); + test.chai.expect(mockModule.instance.mockMethodName).to.have.been.calledWith(1, 2); + }); + + it('tests #inject method - methodDefn.$happnSeq is less then methodDefn.$originSeq', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const mockModule = { + instance: { + mockMethodName: test.sinon.stub().returns('mockResult'), + version: 'mockVersion', + }, }; - componentInstance.config = { - methods: { - testMethod1: { - parameters: [ - { - name: 'arg11', + const config = mockConfig(); + const mockMethodName = 'mockMethodName'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + const origin = 'mockOrigin'; + const verion = null; + const originBindingOverride = 'mockBinding'; + + componentInstance.description = { methods: { mockMethodName: { type: 'sync-promise' } } }; + + componentInstance.initialize('mockName', mesh, mockModule, config, mockCallback1); + + mockModule.instance.mockMethodName.$happnSeq = 3; + mockModule.instance.mockMethodName.$originSeq = 4; + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + origin, + verion, + originBindingOverride + ); + + test.chai.expect(mockCallback2).to.have.been.calledWithExactly(null, [null, 'mockResult']); + test.chai + .expect(mockModule.instance.mockMethodName) + .to.have.been.calledWithExactly( + 1, + 2, + test.sinon.match.instanceOf(ComponentInstance), + 'mockOrigin' + ); + }); + + it('tests #inject method - methodDefn.$happnSeq is greater then methodDefn.$originSeq', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const mockModule = { + instance: { + mockMethodName: test.sinon.stub().returns('mockResult'), + version: 'mockVersion', + }, + }; + const config = mockConfig(); + const mockMethodName = 'mockMethodName'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + const origin = 'mockOrigin'; + const verion = null; + const originBindingOverride = 'mockBinding'; + + componentInstance.description = { methods: { mockMethodName: { type: 'sync-promise' } } }; + + componentInstance.initialize('mockName', mesh, mockModule, config, mockCallback1); + + mockModule.instance.mockMethodName.$happnSeq = 5; + mockModule.instance.mockMethodName.$originSeq = 4; + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + origin, + verion, + originBindingOverride + ); + + test.chai.expect(mockCallback2).to.have.been.calledWithExactly(null, [null, 'mockResult']); + test.chai + .expect(mockModule.instance.mockMethodName) + .to.have.been.calledWithExactly( + 1, + 2, + 'mockOrigin', + test.sinon.match.instanceOf(ComponentInstance) + ); + }); + + it('tests #inject method - methodDefn.$originSeq is not equal to null', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const mockModule = { + instance: { + mockMethodName: test.sinon.stub().returns('mockResult'), + version: 'mockVersion', + }, + }; + const config = mockConfig(); + const mockMethodName = 'mockMethodName'; + const mockParameters = [1, 2]; + const mockCallback = test.sinon.stub(); + + const origin = 'mockOrigin'; + const verion = null; + const originBindingOverride = 'mockBinding'; + + componentInstance.description = { methods: { mockMethodName: { type: 'sync-promise' } } }; + componentInstance.initialize('mockName', mesh, mockModule, config, mockCallback); + + mockModule.instance.mockMethodName.$originSeq = 4; + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback, + origin, + verion, + originBindingOverride + ); + + test.chai.expect(mockCallback).to.have.been.calledWithExactly(null, [null, 'mockResult']); + test.chai + .expect(mockModule.instance.mockMethodName) + .to.have.been.calledWithExactly(1, 2, 'mockOrigin'); + }); + + it('tests #inject method - methodDefn.$happnSeq is not equal to null', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const mockModule = { + instance: { + mockMethodName: test.sinon.stub().returns('mockResult'), + version: 'mockVersion', + }, + }; + const config = mockConfig(); + const mockMethodName = 'mockMethodName'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + const origin = 'mockOrigin'; + const verion = null; + const originBindingOverride = 'mockBinding'; + + componentInstance.description = { methods: { mockMethodName: { type: 'sync-promise' } } }; + componentInstance.initialize('mockName', mesh, mockModule, config, mockCallback1); + + mockModule.instance.mockMethodName.$happnSeq = 3; + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + origin, + verion, + originBindingOverride + ); + + test.chai.expect(mockCallback2).to.have.been.calledWithExactly(null, [null, 'mockResult']); + test.chai + .expect(mockModule.instance.mockMethodName) + .to.have.been.calledWithExactly(1, 2, test.sinon.match.instanceOf(ComponentInstance)); + }); + + it('tests describe method', function (done) { + let componentInstance = new ComponentInstance(); + let mesh = mockMesh('test-mesh-name'); + let config = mockConfig(); + componentInstance.name = 'test-component-instance'; + componentInstance.initialize( + 'test-component-instance', + mesh, + mockModule('test-name-module', '1.0.0'), + config, + (e) => { + if (e) return done(e); + componentInstance.description = { + test: 'description', + }; + test.expect(componentInstance.describe(false)).to.eql({ + name: 'test-component-instance', + version: '1.0.0', + methods: { + testMethod1: { + isAsyncMethod: true, + parameters: [ + { + name: 'arg11', + }, + { + name: 'arg12', + }, + ], + }, + testMethod2: { + isAsyncMethod: true, + parameters: [ + { + name: 'arg21', + }, + { + name: 'arg22', + }, + ], + }, + testMethodErrored: { + isAsyncMethod: true, + parameters: [ + { + name: '', + }, + ], + }, + testMethodUnauthorized: { + isAsyncMethod: true, + parameters: [ + { + name: '', + }, + ], + }, + }, + routes: { + '/test-component-instance/test/route/1': { + type: 'mware', }, - { - name: 'arg12', + '/test-component-instance/test/route/2': { + type: 'mware', }, - ], + '/': { + type: 'mware', + }, + }, + events: {}, + data: 'mockData', + }); + done(); + } + ); + }); + + it('tests describe method - loops over methods and returns this.describe method', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: { + method1: { $happner: { ignore: 'mockIgnore' } }, + _method2: { + $happner: {}, }, + testMethod1: {}, testMethod2: {}, + testMethod3: {}, + }, + }; + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + const getAllMethodNameslStub = test.sinon + .stub(utilities, 'getAllMethodNames') + .returns(['method1', '_method2', 'testMethod1', 'testMethod2', 'testMethod3']); + const getFunctionParametersStub = test.sinon + .stub(utilities, 'getFunctionParameters') + .returns([{ argName: 'mock' }]); + + config.schema = { + methods: { + testMethod1: { isAsyncMethod: 'mockIsAsyncMethod' }, + testMethod2: { isAsyncMethod: 'mockIsAsyncMethod', parameters: 'mockParameters' }, + }, + exclusive: 'mockExclusive', + }; + + componentInstance.describe(false); + + test.chai.expect(componentInstance.description).to.eql({ + name: 'mockName', + version: undefined, + methods: { + testMethod1: { isAsyncMethod: false, parameters: [{ name: { argName: 'mock' } }] }, + testMethod2: { isAsyncMethod: false, parameters: 'mockParameters' }, + }, + routes: { + '/mockName/test/route/1': { type: 'mware' }, + '/mockName/test/route/2': { type: 'mware' }, + '/': { type: 'mware' }, + }, + events: {}, + data: 'mockData', + }); + + getAllMethodNameslStub.restore(); + getFunctionParametersStub.restore(); + }); + + it("tests describe method - methods doesn't exist inside config and returns description", () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: {}, + }; + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + config.schema = {}; + + componentInstance.describe(false); + + test.chai.expect(componentInstance.description).to.eql({ + name: 'mockName', + version: undefined, + methods: {}, + routes: { + '/mockName/test/route/1': { type: 'mware' }, + '/mockName/test/route/2': { type: 'mware' }, + '/': { type: 'mware' }, + }, + events: {}, + data: 'mockData', + }); + }); + + it('tests describe method, without config', function (done) { + let componentInstance = new ComponentInstance(); + let mesh = mockMesh('test-mesh-name'); + // let config = mockConfig(); + let config = {}; + // delete config.web; + componentInstance.name = 'test-component-instance'; + componentInstance.initialize( + 'test-component-instance', + mesh, + mockModule('test-name-module', '1.0.0'), + config, + (e) => { + if (e) return done(e); + componentInstance.description = { + test: 'description', + }; + const result = componentInstance.describe(false); + test.chai.expect(result).to.eql({ + name: 'test-component-instance', + version: '1.0.0', + methods: { + staticHandler: { + isAsyncMethod: true, + parameters: [{ name: 'arg1' }, { name: 'arg2' }], + }, + testMethod1: { + isAsyncMethod: true, + parameters: [{ name: 'arg11' }, { name: 'arg12' }], + }, + testMethod2: { + isAsyncMethod: true, + parameters: [{ name: 'arg21' }, { name: 'arg22' }], + }, + testMethod3: { + isAsyncMethod: true, + parameters: [{ name: 'arg31' }, { name: 'arg32' }], + }, + testMethod4: { + isAsyncMethod: true, + parameters: [{ name: 'arg41' }, { name: 'arg42' }], + }, + testMethod5: { + isAsyncMethod: true, + parameters: [{ name: 'arg41' }, { name: 'arg42' }], + }, + testMethodErrored: { isAsyncMethod: true, parameters: [{ name: '' }] }, + testMethodUnauthorized: { isAsyncMethod: true, parameters: [{ name: '' }] }, + }, + routes: {}, + events: {}, + data: {}, + }); + done(); + } + ); + }); + + it('tests describe method, with config', function (done) { + let componentInstance = new ComponentInstance(); + let mesh = mockMesh('test-mesh-name'); + let config = mockConfig(); + componentInstance.name = 'test-component-instance'; + componentInstance.initialize( + 'test-component-instance', + mesh, + mockModule('test-name-module', '1.0.0'), + config, + (e) => { + if (e) return done(e); + componentInstance.description = { + test: 'description', + }; + const result = componentInstance.describe(false); + test.chai.expect(result).to.eql({ + name: 'test-component-instance', + version: '1.0.0', + methods: { + testMethod1: { + isAsyncMethod: true, + parameters: [{ name: 'arg11' }, { name: 'arg12' }], + }, + testMethod2: { + isAsyncMethod: true, + parameters: [{ name: 'arg21' }, { name: 'arg22' }], + }, + testMethodErrored: { isAsyncMethod: true, parameters: [{ name: '' }] }, + testMethodUnauthorized: { isAsyncMethod: true, parameters: [{ name: '' }] }, + }, + routes: { + '/test-component-instance/test/route/1': { type: 'mware' }, + '/test-component-instance/test/route/2': { type: 'mware' }, + '/': { type: 'mware' }, + }, + events: {}, + data: 'mockData', + }); + done(); + } + ); + }); + + it('tests describe method - cached', function (done) { + let componentInstance = new ComponentInstance(); + let mesh = mockMesh('test-mesh-name'); + let config = mockConfig(); + componentInstance.name = 'test-component-instance'; + componentInstance.initialize( + 'test-component-instance', + mesh, + mockModule('test-name-module', '1.0.0'), + config, + (e) => { + if (e) return done(e); + componentInstance.description = { + test: 'description', + }; + test.expect(componentInstance.describe(true)).to.eql({ + test: 'description', + }); + done(); + } + ); + }); + + it('tests #authorizeOriginMethod - return callback when there is an error when authorize is called', () => { + const mockAuthorize = test.sinon.stub(); + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name', null, null, null, null, mockAuthorize, null); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub().returns('test error'); + const mockMethodName = 'mockMethodName'; + const mockParameters = [1, 2]; + + test.sinon + .stub(ComponentInstanceBoundFactory.prototype, 'originBindingNecessary') + .returns(true); + + mesh._mesh.happn.server.services.security.authorize.callsFake((_, __, ___, callback) => { + callback('mockError', null); + }); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); + componentInstance.description = { methods: { mockMethodName: 'mockMethodName' } }; + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + null, + 'originBindingOverride' + ); + + test.chai.expect(mockCallback2).to.have.been.calledWithExactly('mockError'); + }); + + it('tests #authorizeOriginMethod - return callback when there is an error when getOnBehalfOfSession is called', () => { + const mockAuthorize = test.sinon.stub(); + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name', null, null, null, null, mockAuthorize, null); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback1 = test.sinon.stub(); + // const mockCallback2 = test.sinon.stub().returns('test error'); + const mockMethodName = 'mockMethodName'; + const mockParameters = [1, 2]; + + test.sinon + .stub(ComponentInstanceBoundFactory.prototype, 'originBindingNecessary') + .returns(true); + + mesh._mesh.happn.server.services.security.getOnBehalfOfSession = test.sinon + .stub() + .callsFake((_, __, ___, callback) => { + callback('mockError', null); + }); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); + componentInstance.description = { methods: { mockMethodName: 'mockMethodName' } }; + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback1, + 'mockOrigin', + null, + 'originBindingOverride' + ); + + test.chai.expect(mockCallback1).to.have.been.calledWithExactly('mockError'); + }); + + it('tests #parseWebRoutes - returns when name equals www and routePath equals global', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: {}, + }; + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + componentInstance.initialize('www', mesh, module, config, mockCallback); + + config.schema = {}; + config.web.routes.global = test.sinon.stub(); + config.web.routes.static = 'static'; + + componentInstance.describe(false); + + test.chai.expect(componentInstance.description).to.eql({ + data: 'mockData', + events: {}, + name: 'www', + version: undefined, + methods: {}, + routes: { + '/test/route/1': { type: 'mware' }, + '/test/route/2': { type: 'mware' }, + '/': { type: 'static' }, }, + }); + }); + + it('tests #parseWebRoutes - name equals resources and routePath equals resources', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: {}, + }; + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + componentInstance.initialize('resources', mesh, module, config, mockCallback); + + config.schema = {}; + config.web.routes.resources = test.sinon.stub(); + + componentInstance.describe(false); + test.chai.expect(componentInstance.description).to.eql({ + data: 'mockData', events: {}, - web: { - routes: { - 'test/route/1': ['testMethod3', 'testMethod4'], - 'test/route/2': 'testMethod5', - static: 'staticHandler', + name: 'resources', + version: undefined, + methods: {}, + routes: { + '/resources/test/route/1': { type: 'mware' }, + '/resources/test/route/2': { type: 'mware' }, + '/': { type: 'mware' }, + '/resources': { type: 'mware' }, + }, + }); + }); + + it('tests #createSetOptions method', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const mockModule = { instance: { $happner: { config: { component: 'mock' } } } }; + const config = mockConfig(); + config.directResponses = 'directResponses'; + const mockCallback = test.sinon.stub(); + + const e = new Error('mock Error'); + e.mockProperty = 'mockProperty'; + const mockArray = [e]; + + config.web.routes = { + 'test/route/1': test.sinon.stub(), + 'test/route/2': test.sinon.stub(), + static: test.sinon.stub(), + }; + mesh._mesh.data.on.callsFake((subscribeMask, eventType, testFunc, cb) => { + testFunc( + { + callbackAddress: '/callback/address', + origin: { + id: 'mockId', + }, }, + { + path: "'mockPath'", + } + ); + cb(null, {}); + }); + mesh._mesh.data.publish = test.sinon + .stub() + .callsFake((callbackAddress, response, options, cb) => { + cb(); + }); + + componentInstance.operate = (method, args, cb) => { + cb(null, mockArray); + }; + componentInstance.initialize('mockName', mesh, mockModule, config, mockCallback); + + test.chai.expect(mesh._mesh.data.publish).to.have.been.calledWithExactly( + '/callback/address', + { + status: 'error', + args: [ + { + message: 'mock Error', + name: 'Error', + mockProperty: 'mockProperty', + }, + ], }, + { targetClients: ['mockId'] }, + test.sinon.match.func + ); + }); + + it('tests #reply method - publish ok', function (done) { + let componentInstance = new ComponentInstance(); + let mesh = mockMesh('test-mesh-name'); + let config = mockConfig(); + componentInstance.name = 'test-component-instance'; + mesh._mesh.data.on.callsFake((subscribeMask, eventType, testFunc, cb) => { + testFunc( + { + callbackAddress: '/callback/address', + origin: { + id: 'mockId', + }, + }, + { + path: 'mockPath', + } + ); + cb(); + }); + mesh._mesh.data.publish = (callbackAddress, response, options, cb) => { + test.expect(callbackAddress).to.be('/callback/address'); + test.expect(response).to.eql({ status: 'ok', args: {} }); + test.chai.expect(options).to.eql(undefined); + cb(); + done(); }; - test.expect(componentInstance.describe(false)).to.eql({ - name: 'test-component-instance', - version: '1.0.0', - methods: { - testMethod1: { - isAsyncMethod: true, - parameters: [ - { - name: 'arg11', + componentInstance.operate = (method, args, cb) => { + cb(null, {}); + }; + componentInstance.initialize( + 'test-component-instance', + mesh, + mockModule('test-name-module', '1.0.0'), + config, + (e) => { + if (e) return done(e); + mesh._mesh.data.set( + { + callbackAddress: '/callback/address', + origin: { + id: 1, + }, + }, + { path: '/test/path' }, + () => {} + ); + } + ); + }); + + it('tests #reply method - publish failed', function (done) { + let componentInstance = new ComponentInstance(); + let mesh = mockMesh('test-mesh-name'); + let config = mockConfig(); + componentInstance.name = 'test-component-instance'; + mesh._mesh.data.on.callsFake((subscribeMask, eventType, testFunc, cb) => { + testFunc( + { + callbackAddress: '/callback/address', + origin: { + id: 'mockId', + }, + }, + { + path: 'mockPath', + } + ); + cb(); + }); + mesh._mesh.data.publish = (_callbackAddress, _response, _options, cb) => { + cb(new Error('test error')); + setTimeout(() => { + test + .expect(componentInstance.log.error.lastCall.args[0]) + .to.be('Failure to set callback data on address /callback/address'); + done(); + }, 1e3); + }; + componentInstance.operate = (method, args, cb) => { + cb(null, {}); + }; + componentInstance.initialize( + 'test-component-instance', + mesh, + mockModule('test-name-module', '1.0.0'), + config, + (e) => { + if (e) return done(e); + mesh._mesh.data.set( + { + callbackAddress: '/callback/address', + origin: { + id: 1, }, - { - name: 'arg12', + }, + { path: '/test/path' }, + null, + test.sinon.stub() + ); + } + ); + }); + + it('tests #reply method - no client', function (done) { + let componentInstance = new ComponentInstance(); + let mesh = mockMesh('test-mesh-name'); + let config = mockConfig(); + componentInstance.name = 'test-component-instance'; + mesh._mesh.data.on.callsFake((subscribeMask, eventType, testFunc, cb) => { + testFunc( + { + callbackAddress: '/callback/address', + origin: { + id: 'mockId', + }, + }, + { + path: 'mockPath', + } + ); + cb(); + }); + mesh._mesh.data.publish = (_callbackAddress, _response, _options, cb) => { + cb(new Error('client is disconnected')); + setTimeout(() => { + test + .expect(componentInstance.log.warn.lastCall.args[0]) + .to.be( + 'Failure to set callback data on address /callback/address:client is disconnected' + ); + done(); + }, 1e3); + }; + componentInstance.operate = (method, args, cb) => { + cb(null, {}); + }; + componentInstance.initialize( + 'test-component-instance', + mesh, + mockModule('test-name-module', '1.0.0'), + config, + (e) => { + if (e) return done(e); + mesh._mesh.data.set( + { + callbackAddress: '/callback/address', + origin: { + id: 1, }, - ], + }, + { path: '/test/path' }, + null, + test.sinon.stub() + ); + } + ); + }); + + it('tests #reply method - missing peer', function (done) { + let componentInstance = new ComponentInstance(); + let mesh = mockMesh('test-mesh-name'); + let config = mockConfig(); + componentInstance.name = 'test-component-instance'; + componentInstance.operate = (method, args, cb) => { + cb(null, {}); + }; + mesh._mesh.data.on.callsFake((subscribeMask, eventType, testFunc, cb) => { + testFunc( + { + callbackAddress: '/callback/address', + callbackPeer: 'test-peer', + origin: { + id: 'mockId', + }, }, - testMethod2: { - isAsyncMethod: true, - parameters: [ - { - name: 'arg21', + { + path: 'mockPath', + } + ); + cb(); + }); + componentInstance.initialize( + 'test-component-instance', + mesh, + mockModule('test-name-module', '1.0.0'), + config, + (e) => { + if (e) return done(e); + mesh._mesh.data.set( + { + callbackAddress: '/callback/address', + callbackPeer: 'test-peer', + origin: { + id: 1, }, - { - name: 'arg22', + }, + { path: '/test/path' }, + null, + test.sinon.stub() + ); + setTimeout(() => { + test + .expect(componentInstance.log.warn.lastCall.args[0]) + .to.be(`Failure on callback, missing peer: test-peer`); + done(); + }, 1e3); + } + ); + }); + + it('can detatch', function (done) { + initializeComponent((e, componentInstance, mesh) => { + if (e) return done(e); + componentInstance.detatch(mesh._mesh, (e) => { + if (e) return done(e); + test + .expect(mesh._mesh.data.offPath.lastCall.args[0]) + .to.be('/_exchange/requests/mockDomain/test-component-instance/*'); + done(); + }); + }); + }); + + it('fails to detatch', function (done) { + initializeComponent((e, componentInstance, mesh) => { + if (e) return done(e); + mesh._mesh.data.offPath = test.sinon.stub().callsArgWith(1, new Error('test-error')); + componentInstance.detatch(mesh._mesh, (e) => { + test.expect(e.message).to.be('test-error'); + test + .expect(componentInstance.log.warn.lastCall.args[0]) + .to.be( + 'half detatched, failed to remove request listener: /_exchange/requests/mockDomain/test-component-instance/*, error: test-error' + ); + done(); + }); + }); + }); + + it("tests detatch method - remove this component's middleware from the connect stack.", () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + componentInstance.description = { + methods: {}, + }; + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + componentInstance.detatch(mesh._mesh, mockCallback); + + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('removing mware at %s', 'mockRoute'); + test.chai.expect(mesh._mesh.happn.server.connect.stack.length).to.equal(1); + + createStub.restore(); + }); + + it('attach web route: bad target method', function (done) { + initializeComponent( + { + merge: { + config: { + web: { + routes: { + 'test/routebad': 'testMethodBad', + }, }, - ], + }, }, }, - routes: { - '/test-component-instance/test/route/1': { - type: 'mware', - }, - '/test-component-instance/test/route/2': { - type: 'mware', + (e) => { + test + .expect(e.message) + .to.be( + 'Middleware target test-component-instance:testMethodBad not a function or null, check your happner web routes config' + ); + done(); + } + ); + }); + + it('tests operate method - returns callback with error ', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: { + mockMethod: test.sinon.stub().throws(new Error('mock test')), + version: 'mockVersion', + }, + }; + const config = mockConfig(); + const mockMethodName = 'mockMethod'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); + componentInstance.description = { + methods: { + mockMethod: { name: 'mockName' }, + }, + }; + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + null, + 'originBindingOverride' + ); + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + null, + 'originBindingOverride' + ); + test.chai + .expect(mockCallback2) + .to.have.been.calledWithExactly(null, [test.sinon.match.instanceOf(Error)]); + + createStub.restore(); + }); + + it('tests operate method - method has been configured as a promise with a callback ', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: { + mockMethod: test.sinon.stub(), + version: 'mockVersion', + }, + }; + const config = mockConfig(); + const mockMethodName = 'mockMethod'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); + componentInstance.description = { + methods: { + mockMethod: { parameters: [{ type: 'callback' }] }, + }, + }; + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + const isPromiseStub = test.sinon.stub(utilities, 'isPromise').returns('mockResult'); + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + null, + 'originBindingOverride' + ); + + test.chai + .expect(mockLogObj.warn) + .to.have.been.calledWithExactly('method has been configured as a promise with a callback...'); + + isPromiseStub.restore(); + createStub.restore(); + }); + + it('tests operate method - callbackProxy', async () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: { + mockMethod: test.sinon.stub().resolves(), + version: 'mockVersion', + }, + }; + const config = mockConfig(); + const mockMethodName = 'mockMethod'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + mockCallback2.onCall(0).throws(new Error()); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); + componentInstance.description = { + methods: { + mockMethod: { name: 'mockName' }, + }, + }; + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + const isPromiseStub = test.sinon.stub(utilities, 'isPromise').returns('mockResult'); + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + null, + 'originBindingOverride' + ); + + await require('node:timers/promises').setTimeout(50); + + test.chai + .expect(mockLogObj.error) + .to.have.been.calledWithExactly( + 'Callback invoked more than once for method %s', + 'mockMethod', + 'stub' + ); + + isPromiseStub.restore(); + createStub.restore(); + }); + + it('tests operate method, blue sky, no auth necessary', function (done) { + initializeComponent((e, componentInstance) => { + if (e) return done(e); + //methodName, parameters, callback, origin, version, originBindingOverride + componentInstance.operate('testMethod1', [1, 2], (e, response) => { + if (e) return done(e); + if (response[0]) return done(response[0]); + test.expect(response[1]).to.be('method 1 called: 1,2'); + done(); + }); + }); + }); + + it('tests operate method, errored, no auth necessary', function (done) { + initializeComponent((e, componentInstance) => { + if (e) return done(e); + componentInstance.operate('testMethodErrored', [1, 2], (e, response) => { + if (e) return done(e); + test.expect(response[0].message).to.be('test error'); + done(); + }); + }); + }); + + it('tests operate method, unauthorized', function (done) { + const onBehalfOf = { username: 'unknown', override: true }; + initializeComponent( + { + onBehalfOf, + authorize: (_session, _path, _action, callback) => { + callback(null, false); }, - '/': { - type: 'mware', + }, + (e, componentInstance) => { + if (e) return done(e); + //methodName, parameters, callback, origin, version, originBindingOverride + componentInstance.operate( + 'testMethodUnauthorized', + [1, 2], + (e) => { + test.expect(e.message).to.be('unauthorized'); + done(); + }, + onBehalfOf + ); + } + ); + }); + + it('tests operate method, authorized', function (done) { + const onBehalfOf = { username: 'found', override: true }; + initializeComponent( + { + onBehalfOf, + authorize: (_session, _path, _action, callback) => { + callback(null, true); }, }, - events: {}, - data: {}, - }); + (e, componentInstance) => { + if (e) return done(e); + //methodName, parameters, callback, origin, version, originBindingOverride + componentInstance.operate( + 'testMethod1', + [1, 2], + (e, response) => { + if (e) return done(e); + if (response[0]) return done(response[0]); + test.expect(response[1]).to.be('method 1 called: 1,2'); + done(); + }, + onBehalfOf + ); + } + ); + }); + + it('tests operate method, returns if method is not found', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockMethodName = null; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + componentInstance.description = { + methods: {}, + }; + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + 'mockVersion', + 'originBindingOverride' + ); + + test.chai + .expect(mockLogObj.warn) + .to.have.been.calledWithExactly( + 'Missing method:Call to unconfigured method [mockName.null()]' + ); + test.chai + .expect(mockCallback2) + .to.have.been.calledWithExactly(test.sinon.match.instanceOf(Error)); + + createStub.restore(); + }); + + it('tests operate method, returns if component version does not match module version', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockMethodName = 'testMethod1'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); + componentInstance.description = { + methods: { testMethod1: test.sinon.stub() }, + }; + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + 'version', + 'originBindingOverride' + ); + + test.chai + .expect(mockLogObj.warn) + .to.have.been.calledWithExactly( + `Component version mismatch:Call to unconfigured method [${'mockName.testMethod1'}]: request version [${'version'}] does not match component version [${'mockVersion'}]` + ); + test.chai + .expect(mockCallback2) + .to.have.been.calledWithExactly(test.sinon.match.instanceOf(Error)); + + createStub.restore(); + }); + + it('tests operate method, returns callback with result', async () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: { + mockMethod: test.sinon.stub().returns('mockResult'), + version: 'mockVersion', + }, + }; + const config = mockConfig(); + const mockMethodName = 'mockMethod'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); + componentInstance.description = { + methods: { + mockMethod: { type: 'sync-promise' }, + }, + }; + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + null, + 'originBindingOverride' + ); + + test.chai.expect(mockCallback2).to.have.been.calledWithExactly(null, [null, 'mockResult']); + createStub.restore(); }); - it('test the describe method - cached', function () { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); + it('tests operate method, returns callback with error', async () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: { + mockMethod: test.sinon.stub().throws(new Error('mockError')), + version: 'mockVersion', + }, + }; + const config = mockConfig(); + const mockMethodName = 'mockMethod'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); componentInstance.description = { - test: 'description', + methods: { + mockMethod: { type: 'sync-promise' }, + }, }; - test.expect(componentInstance.describe(true)).to.eql({ - test: 'description', - }); + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + null, + 'originBindingOverride' + ); + + test.chai + .expect(mockCallback2) + .to.have.been.calledWithExactly(null, [test.sinon.match.instanceOf(Error)]); + + createStub.restore(); }); - it('test the describe method - clear-cache', function () { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - componentInstance.name = 'test-name'; - componentInstance.module = { - name: 'test-name-module', - version: '1.0.0', + it('tests operate method , isPromise returns false', async () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: { + testMethod3: test.sinon.stub().resolves('mockResult'), + testMethod4: test.sinon.stub().resolves('mockResult'), + testMethod5: test.sinon.stub().resolves('mockResult'), + staticHandler: test.sinon.stub().resolves('mockResult'), + version: 'mockVersion', + }, }; + const config = mockConfig(); + const mockMethodName = 'testMethod3'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); componentInstance.description = { - test: 'description', + methods: { + testMethod3: {}, + testMethod4: {}, + testMethod5: {}, + staticHandler: {}, + }, }; - componentInstance.config = {}; - test.expect(componentInstance.describe(false)).to.eql({ - name: 'test-name', - version: '1.0.0', - methods: {}, - routes: {}, - events: {}, - data: {}, - }); + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + const isPromisedStub = test.sinon.stub(utilities, 'isPromise').returns(false); + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + null, + 'originBindingOverride' + ); + + test.chai.expect(mockCallback2).to.not.have.been.called; + + isPromisedStub.restore(); + createStub.restore(); }); - it('test the describe method - clear-cache, web routes', function () { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - componentInstance.name = 'test-name'; - componentInstance.module = { - name: 'test-name-module', - version: '1.0.0', + it('tests #getWebOrigin - returns sessionFromRequest ', async () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: { + testMethod3: test.sinon.stub(), + testMethod4: test.sinon.stub(), + }, }; + + const config = mockConfig(); + const mockMethodName = 'testMethod3'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + module.instance.testMethod3.$happnSeq = 3; + mesh._mesh.config.web.routes[0] = 'mockName/test/route/1'; + + mesh._mesh.happn.server.connect.use = test.sinon.stub(); + mesh._mesh.happn.server.connect.use.callsFake((_, cb) => { + cb({ rootWebRoute: 'mockRootWebRoute' }, 'mockRes', 'mockNext'); + }); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); componentInstance.description = { - test: 'description', - }; - componentInstance.config = { - web: { - routes: { - static: 'static', - '/test/route': ['testMethod'], - global: ['testMethod'], - }, + methods: { + testMethod3: {}, + testMethod4: {}, }, }; - test.expect(componentInstance.describe(false)).to.eql({ - name: 'test-name', - version: '1.0.0', - methods: {}, - routes: { - '/': { type: 'static' }, - '/test-name//test/route': { type: 'mware' }, - '/test-name/global': { type: 'mware' }, + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + const isPromisedStub = test.sinon.stub(utilities, 'isPromise').returns(false); + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + null, + 'originBindingOverride' + ); + + test.chai + .expect(mesh._mesh.happn.server.services.security.sessionFromRequest) + .to.have.been.calledWithExactly( + { rootWebRoute: '0', componentWebRoute: 'mockName/test/route/1' }, + { cookieName: null } + ); + + test.chai + .expect(module.instance.testMethod3) + .to.have.been.calledWithExactly( + { rootWebRoute: '0', componentWebRoute: 'mockName/test/route/1' }, + 'mockRes', + 'mockNext', + test.sinon.match.instanceOf(ComponentInstance) + ); + + isPromisedStub.restore(); + createStub.restore(); + }); + + it('tests #attachRouteTarget - checks if mesh.config.web does not exist', async () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: { + testMethod3: test.sinon.stub(), + testMethod4: test.sinon.stub(), + testMethod5: test.sinon.stub(), + staticHandler: test.sinon.stub(), }, - events: {}, - data: {}, + }; + + module.instance.testMethod3.$happnSeq = 3; + delete mesh._mesh.config.web; + + const config = mockConfig(); + const mockMethodName = 'testMethod3'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + mesh._mesh.happn.server.connect.use = test.sinon.stub(); + mesh._mesh.happn.server.connect.use.callsFake((_, cb) => { + cb({ rootWebRoute: 'mockRootWebRoute' }, 'mockRes', 'mockNext'); }); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); + componentInstance.description = { + methods: { + testMethod3: {}, + testMethod4: {}, + testMethod5: {}, + staticHandler: {}, + }, + }; + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + const isPromisedStub = test.sinon.stub(utilities, 'isPromise').returns(false); + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + null, + 'originBindingOverride' + ); + + test.chai.expect(mesh._mesh.config).to.not.have.ownProperty('web'); + + isPromisedStub.restore(); + createStub.restore(); }); - it('test the describe method - clear-cache, web routes www', function () { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - componentInstance.name = 'www'; - componentInstance.module = { - name: 'test-name-module', - version: '1.0.0', + it('tests #attachRouteTarget - checks if mesh.config.web.routes does not exist', async () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = { + instance: { + testMethod3: test.sinon.stub(), + testMethod4: test.sinon.stub(), + testMethod5: test.sinon.stub(), + staticHandler: test.sinon.stub(), + }, }; + + module.instance.testMethod3.$happnSeq = 3; + delete mesh._mesh.config.web.routes; + + const config = mockConfig(); + const mockMethodName = 'testMethod3'; + const mockParameters = [1, 2]; + const mockCallback1 = test.sinon.stub(); + const mockCallback2 = test.sinon.stub(); + + mesh._mesh.happn.server.connect.use = test.sinon.stub(); + mesh._mesh.happn.server.connect.use.callsFake((_, cb) => { + cb({ rootWebRoute: 'mockRootWebRoute' }, 'mockRes', 'mockNext'); + }); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback1); componentInstance.description = { - test: 'description', - }; - componentInstance.config = { - web: { - routes: { - static: 'static', - '/test/route': ['testMethod'], - global: 'global', - }, + methods: { + testMethod3: {}, + testMethod4: {}, + testMethod5: {}, + staticHandler: {}, }, }; - test.expect(componentInstance.describe(false)).to.eql({ - name: 'www', - version: '1.0.0', - methods: {}, - routes: { - '/': { type: 'static' }, - '//test/route': { type: 'mware' }, - }, - events: {}, - data: {}, + + const createStub = test.sinon + .stub(ComponentInstanceBoundFactory, 'create') + .returns({ originBindingNecessary: test.sinon.stub() }); + + const isPromisedStub = test.sinon.stub(utilities, 'isPromise').returns(false); + + componentInstance.operate( + mockMethodName, + mockParameters, + mockCallback2, + 'mockOrigin', + null, + 'originBindingOverride' + ); + + test.chai.expect(mesh._mesh.config.web).to.not.have.ownProperty('routes'); + + isPromisedStub.restore(); + createStub.restore(); + }); + + it('tests on method, returns event', () => { + const onStub = test.sinon.stub(eventEmitter.prototype, 'on').returns('test event'); + + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + const result = componentInstance.on('mockEvent', 'mockHandler'); + + test.chai.expect(result).to.equal('test event'); + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('component on called', 'mockEvent'); + + onStub.restore(); + }); + + it('tests on method, catches and logs error', () => { + const onStub = test.sinon.stub(eventEmitter.prototype, 'on').throws(new Error('test error')); + + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + componentInstance.on('mockEvent', 'mockHandler'); + + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('component on error', test.sinon.match.instanceOf(Error)); + + onStub.restore(); + }); + + it('tests offEvent method, catches and logs error', () => { + const offStub = test.sinon.stub(eventEmitter.prototype, 'off').returns('test event'); + + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + const result = componentInstance.offEvent('mockEvent', 'mockHandler'); + + test.chai.expect(result).to.equal('test event'); + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('component offEvent called', 'mockEvent'); + + offStub.restore(); + }); + + it('tests offEvent method, catches and logs error', () => { + const offStub = test.sinon.stub(eventEmitter.prototype, 'off').throws(new Error('test error')); + + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + componentInstance.offEvent('mockEvent', 'mockHandler'); + + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly( + 'component offEvent error', + test.sinon.match.instanceOf(Error) + ); + + offStub.restore(); + }); + + it('tests emitEvent method, returns event', () => { + const emitStub = test.sinon.stub(eventEmitter.prototype, 'emit').returns('test event'); + + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + const result = componentInstance.emitEvent('mockEvent', 'mockData'); + + test.chai.expect(result).to.equal('test event'); + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('component emitEvent called', 'mockEvent'); + + emitStub.restore(); + }); + + it('tests emitEvent method, catches and logs error', () => { + const onStub = test.sinon.stub(eventEmitter.prototype, 'emit').throws(new Error('test error')); + + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + componentInstance.emitEvent('mockEvent', 'mockData'); + + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly( + 'component emitEvent error', + test.sinon.match.instanceOf(Error) + ); + + onStub.restore(); + }); + + it('tests #attach method - calling emit function and raises errors', function () { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + const mockOnPublished = test.sinon.stub(); + const mockOptions = { consistency: 1, onPublished: mockOnPublished }; + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + componentInstance.emit(1, 'mockData', mockOptions, mockCallback); + + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('component emitEvent called', 'on-emit-error'); + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('component emitEvent called', 'on-publish-error'); + }); + + it('tests #attach method - calling emit function and raises ok', function () { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + const mockOnPublished = test.sinon.stub(); + const mockOptions = { consistency: 1, onPublished: mockOnPublished }; + + mesh._mesh.data.set.callsFake((key, data, options, callback) => { + options.onPublished(null, 'mockResult'); + callback(null, 'mockResponse'); }); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + componentInstance.emit(1, 'mockData', mockOptions, mockCallback); + + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('component emitEvent called', 'on-emit-ok'); + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('component emitEvent called', 'on-publish-ok'); }); - it('test the __reply method missing peer', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - componentInstance.log = { - warn: (msg) => { - test.expect(msg).to.be('Failure on callback, missing peer'); - done(); + it('tests #attach method - calls emit when options is null', function () { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + const mockOptions = null; + + mesh._mesh.data.set.callsFake((key, data, options, callback) => { + callback(null, 'mockResponse'); + }); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + componentInstance.emit(1, 'mockData', mockOptions); + + test.chai + .expect(mesh._mesh.data.set) + .to.have.been.calledWithExactly( + '/_events/mockDomain/mockName/1', + 'mockData', + { noStore: true, meta: { componentVersion: 'mockVersion' } }, + test.sinon.match.func + ); + }); + + it('tests #attach method - calls emit when options.noStore is false', function () { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + const mockOptions = { noStore: false }; + + mesh._mesh.data.set.callsFake((key, data, options, callback) => { + callback(null, 'mockResponse'); + }); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + componentInstance.emit(1, 'mockData', mockOptions); + + test.chai + .expect(mesh._mesh.data.set) + .to.have.been.calledWithExactly( + '/_events/mockDomain/mockName/1', + 'mockData', + { noStore: false, meta: { componentVersion: 'mockVersion' } }, + test.sinon.match.func + ); + }); + + it('tests #attach method - calls emitLocal ', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + mesh._mesh.data.set.callsFake((key, data, options, callback) => { + callback(null, 'mockResponse'); + }); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + componentInstance.emitLocal(1, 'mockData', mockCallback); + + test.chai.expect(mesh._mesh.data.set).to.have.been.calledWithExactly( + '/_events/mockDomain/mockName/1', + 'mockData', + { + noStore: true, + noCluster: true, + meta: { componentVersion: 'mockVersion' }, }, - }; - componentInstance.__reply( - 'testCallbackAddress', - 'testCallbackPeer', - mockResponse(), - mockOptions(), - mockMesh( + mockCallback + ); + }); + + it('tests #attach method - calls operate and calls the callback with error.', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + mesh._mesh.data.on.callsFake((subscribeMask, eventType, testFunc, cb) => { + testFunc( { - publish: () => { - done(new Error('should not have happened')); + callbackAddress: '/callback/address', + origin: { + id: 'mockId', }, }, - {} - ) - ); + { + path: "'mockPath'", + } + ); + cb(null, {}); + }); + mesh._mesh.data.publish = (callbackAddress, response, options, cb) => { + cb(); + }; + + componentInstance.operate = (method, args, cb) => { + cb('mockError', {}); + }; + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('operate( reply( ERROR %s', '/callback/address'); }); - it('test the __callBackWithWarningAndError method', function (done) { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - let warningMsg; - componentInstance.log = { - warn: (msg) => { - warningMsg = msg; - }, + it('tests #attach method, message.args as array', () => { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + + mesh._mesh.data.on.callsFake((subscribeMask, eventType, testFunc, cb) => { + testFunc( + { + args: ['test'], + callbackAddress: '/callback/address', + origin: { + id: 'mockId', + }, + }, + { + path: "'mockPath'", + } + ); + cb(null, {}); + }); + mesh._mesh.data.publish = (callbackAddress, response, options, cb) => { + cb(); }; - componentInstance.__callBackWithWarningAndError('Test Category', 'Test Error', (e) => { - test.expect(e.message).to.be('Test Error'); - test.expect(warningMsg).to.be('Test Category:Test Error'); - done(); + + componentInstance.operate = test.sinon.stub().callsFake((method, args, cb) => { + cb('mockError', {}); }); + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + + test.chai.expect(componentInstance.operate.args[0][1]).to.eql(['test']); + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('operate( reply( ERROR %s', '/callback/address'); + }); + + it('tests #attach method - discards message if there is no callback addresss', function () { + const componentInstance = new ComponentInstance(); + const mesh = mockMesh('test-mesh-name'); + const module = mockModule('test-module', 'mockVersion'); + const config = mockConfig(); + const mockCallback = test.sinon.stub(); + const mockOptions = test.sinon.stub(); + + componentInstance.initialize('mockName', mesh, module, config, mockCallback); + componentInstance.emit(1, 'mockData', mockOptions); + + test.chai + .expect(mockLogObj.warn) + .to.have.been.calledWithExactly('message discarded: %s', 'No callback address', { + origin: { id: 'mockId' }, + }); + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly( + 'received request at %s', + '/_exchange/requests/mockDomain/mockName/*' + ); + test.chai + .expect(mockLogObj.trace) + .to.have.been.calledWithExactly('data.on( /_exchange/requests/mockDomain/mockName/*'); + }); + + it('serving method via connect, authorized', function (done) { + const onBehalfOf = { username: 'found', override: true }; + initializeComponent( + { + onBehalfOf, + authorize: (_session, _path, _action, callback) => { + callback(null, true); + }, + sessionFromRequest: { username: 'found', override: true }, + }, + (e, _componentInstance, mesh) => { + if (e) return done(e); + mesh.__middlewares['/test-component-instance/static']('connect1', 'connect2') + .then(() => { + test.expect(test.log.lastCall.args[0]).to.be('static method called: connect1,connect2'); + done(); + }) + .catch(done); + } + ); }); it('tests the semver component', () => { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - let semver = componentInstance.semver; + let semver = require('happner-semver'); test.expect(semver.satisfies('1.0.1', '^1.0.0')).to.be(true); test.expect(semver.satisfies('2.0.0', '^1.0.0')).to.be(false); test.expect(semver.satisfies('1.0.0-prerelease-1', '^1.0.0')).to.be(false); @@ -234,78 +2121,269 @@ require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test test.expect(semver.coercedSatisfies('16.1.4-prerelease-9', '16.1.4-prerelease-9')).to.be(true); }); - it('test the _inject method', function () { - var ComponentInstance = require('../../../lib/system/component-instance'); - var componentInstance = new ComponentInstance(); - componentInstance.bindToOrigin = (origin) => { - return { boundTo: origin }; - }; - let callback = function () {}; - test - .expect( - componentInstance._inject( - { - $happnSeq: 0, - $originSeq: 1, - $argumentsLength: 2, - }, - ['test', callback], - { username: 'test' } - ) - ) - .to.eql([{ boundTo: { username: 'test' } }, { username: 'test' }, 'test', callback]); - - test - .expect( - componentInstance._inject( - { - $happnSeq: 0, - $originSeq: 1, - $argumentsLength: 2, - }, - [callback], - { username: 'test' } - ) - ) - .to.eql([{ boundTo: { username: 'test' } }, { username: 'test' }, callback, undefined]); - }); + it('tests README', () => { + const componentInstance = new ComponentInstance(); + const readMeSpy = test.sinon.spy(componentInstance, 'README'); + componentInstance.README(); - function mockResponse() { - return {}; - } + test.chai.expect(readMeSpy).to.have.been.called; + }); - function mockOptions() { - return {}; + function initializeComponent(mocks, callback) { + if (typeof mocks === 'function') { + callback = mocks; + mocks = {}; + } + let componentInstance = new ComponentInstance(); + let mesh = mockMesh( + 'test-mesh-name', + mocks.data, + mocks.peers, + mocks?.merge?.mesh || undefined, + mocks.onBehalfOf, + mocks.authorize, + mocks.sessionFromRequest + ); + let config = mockConfig(mocks?.merge?.config || undefined); + componentInstance.name = 'test-component-instance'; + componentInstance.initialize( + 'test-component-instance', + mesh, + mockModule('test-name-module', '1.0.0'), + config, + (e) => { + if (e) return callback(e); + componentInstance.describe(); + callback(null, componentInstance, mesh, config); + } + ); } - function mockMesh(data, peers) { - return { - data, - happn: { - server: { - services: { - orchestrator: { - peers, - }, - }, - }, - }, - }; - } function mockModuleInstance() { class MockModule { + $happner = { + config: { + component: { + keyOne: 'keyOne', + keyTwo: 'keyTwo', + }, + }, + }; + static create() { return new MockModule(); } async testMethod1(arg11, arg12) { await test.delay(10); - test.log(`method 1 called, ${[arg11, arg12]}`); + let message = `method 1 called: ${[arg11, arg12]}`; + test.log(message); + return message; } async testMethod2(arg21, arg22) { await test.delay(10); - test.log(`method 1 called, ${[arg21, arg22]}`); + test.log(`method 2 called, ${[arg21, arg22]}`); + } + async testMethod3(arg31, arg32) { + await test.delay(10); + test.log(`method 3 called, ${[arg31, arg32]}`); + } + async testMethod4(arg41, arg42) { + await test.delay(10); + let message = `method 4 called: ${[arg41, arg42]}`; + test.log(message); + return message; + } + async testMethod5(arg41, arg42) { + await test.delay(10); + test.log(`method 5 called: ${[arg41, arg42]}`); + } + async staticHandler(arg1, arg2) { + await test.delay(10); + test.log(`static method called: ${[arg1, arg2]}`); + } + async testMethodUnauthorized() { + await test.delay(10); + test.log('should not have happened'); + } + async testMethodErrored() { + await test.delay(10); + throw new Error('test error'); } } return MockModule.create(); } + function mockLogger() { + return mockLogObj; + } + function mockMesh( + name, + data, + peers, + mergeConfig = {}, + onBehalfOf, + authorize, + sessionFromRequest + ) { + let middlewares = {}; + const mockedMesh = { + tools: 'mockTools', + __middlewares: middlewares, + _mesh: { + config: { + domain: 'mockDomain', + name, + happn: { + secure: true, + }, + web: { + routes: ['test-component-instance/static'], + }, + }, + log: { + createLogger: () => { + return mockLogger(); + }, + }, + happn: { + server: { + server: { + address: test.sinon.stub().returns({ protocol: null }), + }, + connect: { + use: (path, serve) => { + middlewares[path] = serve; + }, + stack: [ + { + handle: { + __tag: 'test-component-instance', + }, + }, + { + handle: { + __tag: 'mockName', + }, + route: 'mockRoute', + }, + ], + }, + services: { + cache: { + getOrCreate: test.sinon.stub().returns(mockCache()), + }, + session: { + getSession: test.sinon.stub(), + }, + security: { + authorizeOnBehalfOf: test.sinon.stub(), + sessionFromRequest: test.sinon.stub().returns(sessionFromRequest), + on: test.sinon.stub(), + authorize, + getOnBehalfOfSession: + onBehalfOf?.message != null + ? test.sinon.stub().callsArgWith(3, onBehalfOf) + : onBehalfOf != null + ? test.sinon.stub().callsArgWith(3, null, onBehalfOf) + : test.sinon.stub().callsArgWith(3, null, null), + }, + orchestrator: { + peers: peers || {}, + }, + error: { + AccessDeniedError: (message) => { + return new Error(message); + }, + }, + }, + }, + }, + data: { + session: { + id: 1, + }, + set: test.sinon.stub().callsFake((eventKey, data, options, cb) => { + if (typeof options === 'function') { + cb = options; + options = null; + } + if (options && options.onPublished) options.onPublished('mockError', 'mockResult'); + cb('mockError', 'mockResponse'); + }), + offPath: test.sinon.stub().callsArg(1), + on: test.sinon.stub().callsFake((subscribeMask, eventType, testFunc, cb) => { + testFunc( + { + origin: { + id: 'mockId', + }, + }, + { + path: 'mockPath', + } + ); + cb(); + }), + }, + }, + }; + return test.commons._.merge(mockedMesh, mergeConfig); + } + function mockModule(name, version) { + return { + name, + version, + instance: mockModuleInstance(), + }; + } + function mockConfig(mergeConfig = {}) { + return test.commons._.merge( + { + methods: { + testMethod1: { + parameters: [ + { + name: 'arg11', + }, + { + name: 'arg12', + }, + ], + }, + testMethod2: {}, + }, + events: {}, + web: { + routes: { + 'test/route/1': ['testMethod3', 'testMethod4'], + 'test/route/2': 'testMethod5', + static: 'staticHandler', + }, + }, + data: 'mockData', + schema: { + methods: { + testMethod1: { + isAsyncMethod: true, + parameters: [ + { + name: 'arg11', + }, + { + name: 'arg12', + }, + ], + }, + }, + }, + }, + mergeConfig + ); + } + function mockCache() { + return new LRUCache('test', { + cache: { + max: 5, + }, + }); + } }); diff --git a/packages/happner-2/test/unit/modules/rest.js b/packages/happner-2/test/unit/modules/rest.js index 4013b9871..b3d38ecd3 100644 --- a/packages/happner-2/test/unit/modules/rest.js +++ b/packages/happner-2/test/unit/modules/rest.js @@ -82,15 +82,13 @@ describe(test.testName(__filename, 3), function () { }); describe('describe', function () { - it('calls accessPointCB if error in __authorizeAccessPoint', function () { + it('calls accessPointCB if error in __authorizeMethod', function () { const restModule = new RestModule(); const describeMethod = restModule.describe; const error = new Error('error'); const mock = { __exchangeDescription: { callMenu: 'callMenu' }, - __authorizeAccessPoint: test.sinon - .stub(restModule, '__authorizeAccessPoint') - .callsArgWith(3, error), + __authorizeMethod: test.sinon.stub(restModule, '__authorizeMethod').callsArgWith(3, error), __respond: test.sinon.stub(restModule, '__respond'), }; describeMethod.call( @@ -110,18 +108,18 @@ describe(test.testName(__filename, 3), function () { ); }); }); - describe('__authorize', function () { + describe('__validateCredentialsGetOrigin', function () { it('calls __respond if !$origin', function () { const restModule = new RestModule(); - const __authorizeMethod = restModule.__authorize; + const __authorizeMethod = restModule.__validateCredentialsGetOrigin; const $happn = { _mesh: { config: { happn: { secure: 'secure' } } } }; const successful = test.sinon.fake(); const mock = { __respond: test.sinon.stub(restModule, '__respond'), - __authorizeAccessPoint: test.sinon.stub(restModule, '__authorizeAccessPoint'), + __authorizeMethod: test.sinon.stub(restModule, '__authorizeMethod'), }; - __authorizeMethod.call(mock, undefined, $happn, undefined, undefined, successful); + __authorizeMethod.call(mock, $happn, undefined, undefined, successful); test.sinon.assert.calledWith( mock.__respond, $happn, @@ -135,26 +133,31 @@ describe(test.testName(__filename, 3), function () { it('calls __respond if __respond errors', function () { const restModule = new RestModule(); - const __authorizeMethod = restModule.__authorize; - const $happn = { _mesh: { config: { happn: { secure: 'secure' } } } }; + const __authorizeMethod = restModule.__validateCredentialsGetOrigin; + const $happn = { + _mesh: { config: { happn: { secure: 'secure' } } }, + log: { + warn: test.sinon.stub(), + }, + }; const $origin = { origin: 'origin' }; const successful = test.sinon.fake(); const mock = { - __authorizeAccessPoint: test.sinon - .stub(restModule, '__authorizeAccessPoint') - .callsArgWith(3, 'error', true, 'reason'), + __getAuthorizedOrigin: test.sinon + .stub(restModule, '__getAuthorizedOrigin') + .callsArgWith(5, new Error('test')), __respond: test.sinon.stub(restModule, '__respond'), }; - __authorizeMethod.call(mock, undefined, $happn, $origin, undefined, successful); + __authorizeMethod.call(mock, $happn, $origin, undefined, undefined, successful); test.sinon.assert.calledWith( mock.__respond, $happn, - 'Authorization failed', + 'Authorization failed due to system error', null, test.sinon.match.any, undefined, - 403 + 500 ); }); }); @@ -284,6 +287,29 @@ describe(test.testName(__filename, 3), function () { ); }); + it('calls __respond 400 error bad methodURI', function () { + const restModule = new RestModule(); + const handleRequestMethod = restModule.handleRequest; + const req = { method: 'PUT', url: '1/2/3/4/5/6' }; + const res = 'res'; + const $happn = '$happn'; + const $origin = '$origin'; + + const mock = { + __respond: test.sinon.stub(), + }; + handleRequestMethod.call(mock, req, res, $happn, $origin); + test.sinon.assert.calledWith( + mock.__respond, + $happn, + 'Failure parsing request body', + null, + test.sinon.match.any, + res, + 400 + ); + }); + describe('__buildCallMenu', function () { it('callmenu should be menu', function () { const restModule = new RestModule(); diff --git a/packages/happner-2/test/unit/modules/security.js b/packages/happner-2/test/unit/modules/security.js new file mode 100644 index 000000000..034e06717 --- /dev/null +++ b/packages/happner-2/test/unit/modules/security.js @@ -0,0 +1,153 @@ +require('../../__fixtures/utils/test_helper').describe({ timeout: 120e3 }, (test) => { + const SecurityModule = require('../../../lib/modules/security/index'); + it('can initialize the security component', async () => { + const security = createSecurityModule(mockSecurityService()); + test.expect(security.__adminUser).to.be(null); + test.expect(security.__initialized).to.be(false); + test.expect(security.__systemGroups).to.eql({}); + test.expect(security.__attachToSecurityChangesActivated).to.be(false); + test.expect(security.__attachToSessionChangesActivated).to.be(false); + }); + it('links a group, using just strings', function (done) { + const securityService = mockSecurityService( + { username: 'testUser', permissions: {} }, + { name: 'testGroup', permissions: {} } + ); + const $happn = mockHappn(); + const security = createSecurityModule(securityService); + security.__initialized = true; + security.linkGroup($happn, 'testGroup', 'testUser', (e, linked) => { + test.expect(e).to.be(null); + test.expect(linked).to.be(true); + test.expect(securityService.users.getUser.lastCall.args[0]).to.be('testUser'); + test.expect(securityService.groups.getGroup.lastCall.args[0]).to.be('testGroup'); + done(); + }); + }); + + it('links a group, using group as string, user as object', function (done) { + const securityService = mockSecurityService( + { username: 'testUser', permissions: {} }, + { name: 'testGroup', permissions: {} } + ); + const $happn = mockHappn(); + const security = createSecurityModule(securityService); + security.__initialized = true; + security.linkGroup( + $happn, + 'testGroup', + { username: 'testUser', permissions: {} }, + (e, linked) => { + test.expect(e).to.be(null); + test.expect(linked).to.be(true); + test.expect(securityService.users.getUser.lastCall).to.eql(null); + test.expect(securityService.groups.getGroup.lastCall.args[0]).to.be('testGroup'); + done(); + } + ); + }); + + it('links a group, using group as string, group as object', function (done) { + const securityService = mockSecurityService( + { username: 'testUser', permissions: {} }, + { name: 'testGroup', permissions: {} } + ); + const $happn = mockHappn(); + const security = createSecurityModule(securityService); + security.__initialized = true; + security.linkGroup($happn, { name: 'testGroup', permissions: {} }, 'testUser', (e, linked) => { + test.expect(e).to.be(null); + test.expect(linked).to.be(true); + test.expect(securityService.users.getUser.lastCall.args[0]).to.be('testUser'); + test.expect(securityService.groups.getGroup.lastCall).to.eql(null); + done(); + }); + }); + + it('fails to link a group, could not find group', function (done) { + const securityService = mockSecurityService({ username: 'testUser', permissions: {} }, null); + const $happn = mockHappn(); + const security = createSecurityModule(securityService); + security.__initialized = true; + security.linkGroup($happn, 'testGroup', 'testUser', (e) => { + test.expect(e.message).to.be('group with name testGroup does not exist'); + done(); + }); + }); + + it('fails to link a group, could not find user', function (done) { + const securityService = mockSecurityService(null, { name: 'testGroup', permissions: {} }); + const $happn = mockHappn(); + const security = createSecurityModule(securityService); + security.__initialized = true; + security.linkGroup($happn, 'testGroup', 'testUser', (e) => { + test.expect(e.message).to.be('user with name testUser does not exist'); + done(); + }); + }); + + it('fails to link a group, getUser error', function (done) { + const securityService = mockSecurityService( + { username: 'testUser', permissions: {} }, + { name: 'testGroup', permissions: {} } + ); + securityService.users.getUser = test.sinon.stub().callsArgWith(1, new Error('test error')); + const $happn = mockHappn(); + const security = createSecurityModule(securityService); + security.__initialized = true; + security.linkGroup($happn, 'testGroup', 'testUser', (e) => { + test.expect(e.message).to.be('test error'); + done(); + }); + }); + + it('fails to link a group, getGroup error', function (done) { + const securityService = mockSecurityService( + { username: 'testUser', permissions: {} }, + { name: 'testGroup', permissions: {} } + ); + securityService.groups.getGroup = test.sinon.stub().callsArgWith(1, new Error('test error')); + const $happn = mockHappn(); + const security = createSecurityModule(securityService); + security.__initialized = true; + security.linkGroup($happn, 'testGroup', 'testUser', (e) => { + test.expect(e.message).to.be('test error'); + done(); + }); + }); + + it('fails to link a group, linkGroup error', function (done) { + const securityService = mockSecurityService( + { username: 'testUser', permissions: {} }, + { name: 'testGroup', permissions: {} } + ); + securityService.users.linkGroup = test.sinon.stub().callsArgWith(3, new Error('test error')); + const $happn = mockHappn(); + const security = createSecurityModule(securityService); + security.__initialized = true; + security.linkGroup($happn, 'testGroup', 'testUser', (e) => { + test.expect(e.message).to.be('test error'); + done(); + }); + }); + + function mockHappn() { + return {}; + } + function createSecurityModule(securityService) { + const security = new SecurityModule(); + security.__securityService = securityService; + return security; + } + function mockSecurityService(user = null, group = null) { + return { + users: { + linkGroup: test.sinon.stub().callsArgWith(3, null, true), + getUser: test.sinon.stub().callsArgWith(1, null, user), + }, + groups: { + getGroup: test.sinon.stub().callsArgWith(1, null, group), + }, + }; + } +}); diff --git a/packages/happner-client/.gitignore b/packages/happner-client/.gitignore index b2d77f132..6566adacb 100644 --- a/packages/happner-client/.gitignore +++ b/packages/happner-client/.gitignore @@ -24,4 +24,4 @@ coverage-web .jshintrc report.* .vscode -tmp \ No newline at end of file +tmp diff --git a/packages/happner-client/RELEASES.md b/packages/happner-client/RELEASES.md index 8608e3368..64487f126 100644 --- a/packages/happner-client/RELEASES.md +++ b/packages/happner-client/RELEASES.md @@ -352,8 +352,6 @@ ----------------- - TEN-125: body-parser v1.20.0 causes memory leak - - - - - \ No newline at end of file +12.3.0 2022-08-07 +----------------- + - TEN-31: onbehalf of / as diff --git a/packages/happner-client/lib/happner-client.js b/packages/happner-client/lib/happner-client.js index c85d87258..e05d0bb2b 100644 --- a/packages/happner-client/lib/happner-client.js +++ b/packages/happner-client/lib/happner-client.js @@ -278,7 +278,14 @@ } const args = Array.isArray(parameters.arguments) ? parameters.arguments : []; if (typeof callback === 'function') args.push(callback); - return endpoint[parameters.method].apply(endpoint, args); + let boundEndpoint = endpoint; + if (parameters.as) { + boundEndpoint = Object.assign( + { $origin: { username: parameters.as, override: true } }, + endpoint + ); + } + return endpoint[parameters.method].apply(boundEndpoint, args); }; }; diff --git a/packages/happner-client/lib/light-client.js b/packages/happner-client/lib/light-client.js index 7abadcd41..20c0c8b61 100644 --- a/packages/happner-client/lib/light-client.js +++ b/packages/happner-client/lib/light-client.js @@ -110,6 +110,7 @@ }; LightHappnerClient.prototype.__exchangeCall = function (parameters, callback) { + let origin = parameters.as ? { username: parameters.as, override: true } : parameters.origin; if (!callback) return new Promise((resolve, reject) => { this.__operations.request( @@ -123,7 +124,7 @@ if (args.length === 2) return resolve(args[1]); resolve(args.slice(1)); }, - parameters.origin + origin ); }); this.__operations.request( @@ -137,7 +138,7 @@ if (args.length === 2) return callback(null, args[1]); callback(...args); }, - parameters.origin + origin ); }; diff --git a/packages/happner-client/lib/providers/connection-provider.js b/packages/happner-client/lib/providers/connection-provider.js index edbc8b785..eccf89ef3 100644 --- a/packages/happner-client/lib/providers/connection-provider.js +++ b/packages/happner-client/lib/providers/connection-provider.js @@ -50,7 +50,7 @@ if (typeof options === 'function') { callback = options; - options = null; + options = connections || null; } return Happn.client.create(connections, options, function (e, client) { diff --git a/packages/happner-client/lib/providers/implementors-provider.js b/packages/happner-client/lib/providers/implementors-provider.js index b131d4662..e04db406d 100644 --- a/packages/happner-client/lib/providers/implementors-provider.js +++ b/packages/happner-client/lib/providers/implementors-provider.js @@ -18,6 +18,7 @@ this.log = happnerClient.log; this.connection = connection; this.dependencies = {}; + this.localDescriptions = []; this.descriptions = []; this.maps = {}; @@ -49,6 +50,7 @@ } ImplementorsProvider.prototype.clear = function () { + this.localDescriptions = []; this.maps = {}; this.descriptions = []; this.callersAwaitingDescriptions = []; @@ -86,6 +88,7 @@ if (cluster) { this.name = client.session.happn.name; + this.addLocalDescription(description); } else { this.addDescription(description); } @@ -93,10 +96,8 @@ if (cluster && description.brokered) { if (!client.session.info) client.session.info = {}; client.session.info.clusterName = description.meshName; - // ignores mesh 1 return onIgnore(`ignoring brokered description for peer: ${client.session.happn.name}`); } - // adds mesh 2, this is mesh 1 this.addDescription(description); } onSuccess(description); @@ -126,13 +127,14 @@ var peer = this.connection.clients.peers[name]; var onSuccess = function (description) { var clonedDescription = Object.assign({}, description); + _this.log.debug('logging dependencies met on addPeer'); _this.logDependenciesMet(clonedDescription); }; var onFailure = function (e) { - _this.happnerClient.log.error('failed to get description for %s', name, e); + _this.log.error('failed to get description for %s', name, e); }; var onIgnore = function (reason) { - _this.happnerClient.log.debug(reason); + _this.log.debug(reason); }; this.getSingleDescription(peer.client, peer.self, true, onSuccess, onFailure, onIgnore); @@ -169,6 +171,7 @@ } _this.gotDescriptions = true; _this.callersAwaitingDescriptions = false; + _this.log.debug('logging dependencies met on fetched descriptions'); _this.logDependenciesMet(description); }; @@ -221,6 +224,10 @@ }); }; + ImplementorsProvider.prototype.addLocalDescription = function (description) { + this.localDescriptions.push(description); + }; + ImplementorsProvider.prototype.addDescription = function (description) { var _this = this; this.descriptions.push(description); @@ -334,6 +341,7 @@ version ) { if (!dependorName) return; // no $happn.name, not in cluster + this.log.debug(`registering dependency: ${dependorName}.${componentName}@${version}`); this.dependencies[dependorName] = this.dependencies[dependorName] || {}; this.dependencies[dependorName][componentName] = version; }; @@ -343,12 +351,19 @@ Object.keys(dependencies).forEach((component) => { this.registerDependency(dependor, component, dependencies[component].version); }); + this.log.debug('logging dependencies met on add and check dependencies'); return this.logDependenciesMet(this.descriptions); }; ImplementorsProvider.prototype.logDependenciesMet = function (descriptions) { - if (!this.gotDescriptions) return false; - if (!this.dependencies || Object.keys(this.dependencies).length === 0) return true; + if (!this.gotDescriptions) { + this.log.debug('logging dependencies met false, gotDescriptions false'); + return false; + } + if (!this.dependencies || Object.keys(this.dependencies).length === 0) { + this.log.debug('logging dependencies met true, no dependencies'); + return true; + } let allSatisfied = true; Object.keys(this.dependencies).forEach((dependorName) => { @@ -357,6 +372,11 @@ tree: this.dependencies[dependorName], keys: Object.keys(this.dependencies[dependorName]), }; + if (dependencies.keys.length > 0) { + this.log.debug( + `logging dependencies ${dependencies.keys.join(',')} met for dependor ${dependorName}` + ); + } dependencies.keys.forEach((componentName) => { let version = dependencies.tree[componentName]; let countMatches = this.countDependencyMatches(componentName, version); @@ -370,7 +390,7 @@ this.__getUpdatedDependencyDescriptions(descriptions, componentName, version).forEach( (foundComponentDescription) => { if (!foundComponentDescription.self) { - this.happnerClient.emit('peer/arrived/description', { + let arrivedData = { dependorName: dependorName, countMatches: countMatches, componentName: componentName, @@ -378,7 +398,9 @@ description: foundComponentDescription.components[componentName], url: foundComponentDescription.url, meshName: foundComponentDescription.meshName, - }); + }; + this.log.debug(`emitting peer/arrived/description: ${JSON.stringify(arrivedData)}`); + this.happnerClient.emit('peer/arrived/description', arrivedData); } } ); @@ -412,11 +434,22 @@ }; ImplementorsProvider.prototype.countDependencyMatches = function (componentName, version) { + this.log.debug(`counting dependency matches for ${componentName}@${version}`); var count = 0; - this.descriptions.forEach(function (description) { - if (!description.components[componentName]) return; - var gotVersion = description.components[componentName].version; - if (!semver.coercedSatisfies(gotVersion, version)) return; + this.descriptions.concat(this.localDescriptions).forEach((description) => { + this.log.debug(`looking in description ${description.name}`); + if (!description.components[componentName]) { + this.log.debug(`component ${componentName} not found in description`); + return; + } + const gotVersion = description.components[componentName].version; + this.log.debug(`component ${componentName}@${gotVersion} found in description`); + if (!semver.coercedSatisfies(gotVersion, version)) { + this.log.debug( + `component ${componentName}@${gotVersion} not satisfied against required version: ${version}` + ); + return; + } count++; }); return count; diff --git a/packages/happner-client/package.json b/packages/happner-client/package.json index f646ba397..0c976648c 100644 --- a/packages/happner-client/package.json +++ b/packages/happner-client/package.json @@ -1,6 +1,6 @@ { "name": "happner-client", - "version": "12.2.8", + "version": "12.3.0", "description": "The client for happner-2 and happner cluster services", "homepage": "https://github.com/happner/happner-client#readme", "bugs": { @@ -21,12 +21,12 @@ "test-browser": "gulp --gulpfile test/browser/gulp-01.js" }, "dependencies": { - "happn-3": "^13.1.4", + "happn-3": "^13.2.0", "happn-commons": "^1.1.0", "happner-semver": "^1.0.1" }, "devDependencies": { "happn-commons-test": "^1.1.0", - "happner-2": "^12.1.9" + "happner-2": "^12.2.0" } } diff --git a/packages/happner-client/test/example.com.cert b/packages/happner-client/test/example.com.cert deleted file mode 100644 index daab1826e..000000000 --- a/packages/happner-client/test/example.com.cert +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICrzCCAZcCFASJhA39hch4m31btN1Slxz3BLvkMA0GCSqGSIb3DQEBCwUAMBQx -EjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0yMjA1MTAxMTQxMzBaFw0yMzA1MTAxMTQx -MzBaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBAN2PvdItFlKp9luWW8Qw1AuEALo/DKTZ6FCi7wpYS5axiCxmJ3bD -j2HW8ePnMu+K32FSWqRFPEpYoxFSXIfWMjOmd2p6PYNwUAqX7Q3QkxPoIAPWPrrJ -IdzHPCLl8iucOQ4OGhi9nA1gJ8wbhffSZlXVVqm1isHIV2SFK3fFySLTTNp79YLC -J83NEYOplV/YjYphH6OaiQAqa2aHsjMe+b7nkq6nHHrnC6WWOWaRhv5Ii4QY2fsM -vru9ALPpS08isDxZDwpr0AJQ3N+yL9XjSXFunLbr3Ld5Kh0kfGpd/RDYugioUabl -PldxM68ugdLNerlp8aKjBIVx0fuJtpuXAOsCAwEAATANBgkqhkiG9w0BAQsFAAOC -AQEApPdd6PyvygN63CMYg7h9trD6gmu0nkgZ9st/Zn6tAydXS5Cdc+QTJRtOZBOU -WI/A1yklW804EjxDFvVAnhK2ivF3DtdtrQXU2Qvw6Gof2upFp3tq/VWt+KwcEqtG -mP7raHIJN+ikPnn1X4LHF561CnTXut0b47CmbuOCDA+fmmJce5ZKAFmt7Hvb43qL -JqaigjQOmlZeDTcSto/0S/JpOVGwmd/lcQtgDs88d665LsRiHkFkE/ZzqQTjkCCg -0j95d+ICUPRovv4rqgQ2OepYEn2lsLoZ5iJ+TR0/ZocSn67wHAKRfwfkvzMJIdUw -7rC7dMUdLGp3m15Q7PVVLfM+DA== ------END CERTIFICATE----- \ No newline at end of file diff --git a/packages/happner-client/test/example.com.key b/packages/happner-client/test/example.com.key deleted file mode 100644 index 49dbd3bd3..000000000 --- a/packages/happner-client/test/example.com.key +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpQIBAAKCAQEA3Y+90i0WUqn2W5ZbxDDUC4QAuj8MpNnoUKLvClhLlrGILGYn -dsOPYdbx4+cy74rfYVJapEU8SlijEVJch9YyM6Z3ano9g3BQCpftDdCTE+ggA9Y+ -uskh3Mc8IuXyK5w5Dg4aGL2cDWAnzBuF99JmVdVWqbWKwchXZIUrd8XJItNM2nv1 -gsInzc0Rg6mVX9iNimEfo5qJACprZoeyMx75vueSrqcceucLpZY5ZpGG/kiLhBjZ -+wy+u70As+lLTyKwPFkPCmvQAlDc37Iv1eNJcW6ctuvct3kqHSR8al39ENi6CKhR -puU+V3Ezry6B0s16uWnxoqMEhXHR+4m2m5cA6wIDAQABAoIBAB11oV2y1QcExlcD -NQxvGaK2WIprG7lHqBYgs/wCJXrR/DM7GgA2nHf75onREfq70lvUYWz6L7wK8RO6 -iccd+erYNYSY4Fj7tAjUjpaJpyS8dpVMBWc8mx4J97sELCEUUpnF0j5756X3pRME -jdmXxjefeDh0hRCjHMum0VLJn6bbhkLzsKfUbB4rWp5Sfi1QGwVgbAGaqwBaIjYo -EUa1NXHzr5XL6vWEUIj0nKgrYQRlr5gscvCtmk+tTqa36ImZKj8jtnR8Gq44SGp6 -3ZJHeNQffPrUsczdH/u/VDjNsYAqSmkJLrq1748sN7kj20ylj3KbsCziSdUTG363 -hrpCMRECgYEA8grCSlAAP1NPf0Y6+HzfDL3ijZzxtVxCPNO6xF97qWHpWcGOSANc -1Aq0SvbRRgIFoTj7AAnzBGUjaLMNY1jV7YEornAoLBRMpA+cgWF4jwYuza/UyCb8 -U2nxK1j10m+I7JYxsHhgLTdAsWba31jZLLo7UgjI1WwuZP9omFTqT4cCgYEA6lah -af5BtDocA1rWEUm7CSDEVPpNCDJqbW8Rkp1VSAtoDjnJx+jm0K+W+FflHiZPXynM -+GcvJQ91J8dSBw78chvnD86ofX5pFlwA/3IYQs23DRCPN8WxhJea9pRvcX55vMe6 -+ELjetqhABkZZQC3IwqMI9gPsI6SUX4CSaTzdH0CgYEAokecZH6m685LqqXHu/rd -AYn+b7weQt6MeoPq4Oaz3qkK72baomW+w1w57Vj2jt2kMKgngasqCHRW/UevXkCd -jhPe1rXT+VnS2NyurgBP+HTIxJdzLo8U9kg9rjaC+ohVYWqB/jN3KFm3QjoX3U+Q -rHBgfWvuW0mhAY5M7nVgc9kCgYEAjTtM6R6t5rsm6vayEZVIPkYbTcPU7V3FOtM3 -2g8suND3E6vMasl5YsiQynfexH7+UzJUMFmv1jwstZ6xV0O27ebXKXW5onivSSSG -DW5sJMbqzdrvFgP16x2b7YSkbdh18krF6p4Vj5N4eSCnZ3I47cuLjobHXfdvQ+IX -6t6ZQ9kCgYEAuJ2WWDZO4TdWOLoAOQzk3YkkGhjurwzh6VfEl1Ueiok12+9RhcrF -zqa0b+6jARgQDB7PYmwq/+6+imLN0ah59FsHrMppuBGZhmvsoI1ywSta5ZACJVl1 -fGzLUAMu2mg46z/m2cPQsdr6qH7PRge5E1V3Wb+UIwcs2UvxYXcimXk= ------END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/packages/happner-client/test/unit/implementors-provider.js b/packages/happner-client/test/unit/implementors-provider.js index b00e1c550..c3446ca54 100644 --- a/packages/happner-client/test/unit/implementors-provider.js +++ b/packages/happner-client/test/unit/implementors-provider.js @@ -6,6 +6,12 @@ describe(test.name(__filename, 2), function () { beforeEach(function () { mockClient = { + log: { + debug: () => {}, + info: () => {}, + error: () => {}, + trace: () => {}, + }, on: () => {}, emit: () => {}, }; @@ -536,6 +542,12 @@ describe(test.name(__filename, 2), function () { var i; mockClient = { + log: { + debug: () => {}, + info: () => {}, + error: () => {}, + trace: () => {}, + }, on: function (event, handler) { test.expect(event).to.be('reconnected'); setTimeout(function () { @@ -555,6 +567,12 @@ describe(test.name(__filename, 2), function () { var i; mockClient = { + log: { + debug: () => {}, + info: () => {}, + error: () => {}, + trace: () => {}, + }, on: function (event, handler) { test.expect(event).to.be('reconnected'); setTimeout(function () { @@ -576,6 +594,12 @@ describe(test.name(__filename, 2), function () { beforeEach(function () { mockClient = { + log: { + debug: () => {}, + info: () => {}, + error: () => {}, + trace: () => {}, + }, on: function () {}, emit: function () {}, }; @@ -640,6 +664,12 @@ describe(test.name(__filename, 2), function () { beforeEach(function () { mockClient = { + log: { + debug: () => {}, + info: () => {}, + error: () => {}, + trace: () => {}, + }, on: function () {}, emit: function () {}, }; diff --git a/packages/happner-cluster/RELEASES.md b/packages/happner-cluster/RELEASES.md index deeb2af14..fa27c0a04 100644 --- a/packages/happner-cluster/RELEASES.md +++ b/packages/happner-cluster/RELEASES.md @@ -389,11 +389,6 @@ ----------------- - TEN-125: body-parser v1.20.0 causes memory leak - - - - - - - - \ No newline at end of file +12.2.0 2022-08-07 +----------------- + - TEN-31: onbehalf of / as diff --git a/packages/happner-cluster/package.json b/packages/happner-cluster/package.json index 0c9ab2335..5c9176d6b 100644 --- a/packages/happner-cluster/package.json +++ b/packages/happner-cluster/package.json @@ -1,12 +1,13 @@ { "name": "happner-cluster", - "version": "12.1.9", + "version": "12.2.0", "description": "Extends happner with clustering capabilities", "main": "index.js", "scripts": { "test-unit": "mocha silence.js test/unit/* --recursive --exit", "test": "mocha silence.js test/unit/* test/integration/* --recursive --exit", - "test-cover": "nyc --reporter=lcov --reporter=text --reporter=html npm test" + "test-cover": "nyc --reporter=lcov --reporter=text --reporter=html npm test", + "test-browser": "mocha test/browser/*test*.js" }, "repository": { "type": "git", @@ -26,10 +27,10 @@ }, "dependencies": { "bluebird": "^3.5.0", - "happn-cluster": "^12.0.12", + "happn-cluster": "^12.0.13", "happn-commons": "^1.1.0", - "happner-2": "^12.1.9", - "happner-client": "^12.2.8", + "happner-2": "^12.2.0", + "happner-client": "^12.3.0", "hashring": "^3.2.0", "http-proxy": "1.18.1", "semver": "^5.3.0" diff --git a/packages/happner-cluster/test/_lib/base-config.js b/packages/happner-cluster/test/_lib/base-config.js index 0f31294bc..45c51a9c8 100644 --- a/packages/happner-cluster/test/_lib/base-config.js +++ b/packages/happner-cluster/test/_lib/base-config.js @@ -8,7 +8,8 @@ module.exports = function ( hosts, joinTimeout, replicate, - logFile + logFile, + cacheStatisticsInterval ) { let [first, seq] = extendedSeq; var clusterRequestTimeout = requestTimeout ? requestTimeout : 10 * 1000; @@ -39,7 +40,7 @@ module.exports = function ( services: { cache: { config: { - statisticsInterval: 3e3, + statisticsInterval: cacheStatisticsInterval, }, }, security: { diff --git a/packages/happner-cluster/test/_lib/configurations/20/6.js b/packages/happner-cluster/test/_lib/configurations/20/6.js new file mode 100644 index 000000000..5a9301e4c --- /dev/null +++ b/packages/happner-cluster/test/_lib/configurations/20/6.js @@ -0,0 +1,53 @@ +const delay = require('await-delay'); +module.exports = { + modules: { + component6: { + instance: { + initialize: async () => { + this.state = { initialized: true }; + }, + start: async () => { + this.state = this.state || {}; + this.state.started = true; + }, + use: async () => { + return 6; + }, + is: async () => { + if (!this.state) this.state = {}; + return this.state; + }, + }, + }, + component7: { + instance: { + initialize: async () => { + await delay(8e3); + }, + start: async () => { + this.state = this.state || {}; + this.state.started = true; + }, + use: async () => { + return 7; + }, + }, + }, + }, + components: { + component6: { + initMethod: 'initialize', + startMethod: 'start', + dependencies: { + component7: { + version: '*', + }, + }, + }, + component7: { + initMethod: 'initialize', + startMethod: 'start', + dependencies: {}, + }, + }, +}; diff --git a/packages/happner-cluster/test/_lib/drop-mongo-db.js b/packages/happner-cluster/test/_lib/drop-mongo-db.js new file mode 100644 index 000000000..190a02340 --- /dev/null +++ b/packages/happner-cluster/test/_lib/drop-mongo-db.js @@ -0,0 +1,18 @@ +module.exports = function (name) { + return new Promise((resolve, reject) => { + let MongoClient = require('mongodb').MongoClient; + MongoClient.connect( + 'mongodb://127.0.0.1:27017', + { useNewUrlParser: true, useUnifiedTopology: true }, + function (err, client) { + if (err) return reject(err); + var db = client.db(name); + + db.dropDatabase(function (err) { + if (err) return reject(err); + client.close(resolve); + }); + } + ); + }); +}; diff --git a/packages/happner-cluster/test/_lib/helpers/cluster.js b/packages/happner-cluster/test/_lib/helpers/cluster.js index c6c21596f..ecac8df1a 100644 --- a/packages/happner-cluster/test/_lib/helpers/cluster.js +++ b/packages/happner-cluster/test/_lib/helpers/cluster.js @@ -8,20 +8,24 @@ module.exports = class Cluster extends Helper { data: [], }; this.member = { - start: async (configuration, wait) => { + start: async (configuration, waitAfter, wait = 0) => { + await this.delay(wait); // before you think you can tidy this up, we need to use the callback, otherwise the we cannot move on to start other test peers HappnerCluster.create(configuration, (e, instance) => { if (e) { // eslint-disable-next-line no-console console.warn('ERROR STARTING TEST INSTANCE: ' + e.message); } + // eslint-disable-next-line no-console + console.log(`started test instance: ${instance._mesh.config.name}`); this.events.data.push({ + timestamp: Date.now(), key: 'member-started', value: instance._mesh.config.name, }); this.instances.push(instance); }); - await this.delay(wait); + await this.delay(waitAfter); }, }; this.component = { @@ -43,12 +47,18 @@ module.exports = class Cluster extends Helper { static create() { return new Cluster(); } + clear() { + // eslint-disable-next-line no-console + console.log(`cleared test cluster events`); + this.events.data = []; + } async destroy(index) { if (index >= 0) { await this.instances[index].stop(); this.instances.splice(index, 1); return; } + this.clear(); this.instances.sort((a, b) => { if (a._mesh.config.name < b._mesh.config.name) return -1; return 1; diff --git a/packages/happner-cluster/test/browser/01-test-disconnects.js b/packages/happner-cluster/test/browser/01-test-disconnects.js new file mode 100644 index 000000000..0557e4d17 --- /dev/null +++ b/packages/happner-cluster/test/browser/01-test-disconnects.js @@ -0,0 +1,158 @@ +const { fork } = require('child_process'); +const path = require('path'); +const baseConfig = require('../_lib/base-config'); +const getSeq = require('../_lib/helpers/getSeq'); +const HappnerCluster = require('../..'); +const libDir = require('../_lib/lib-dir'); +const clearMongoCollection = require('../_lib/drop-mongo-db'); +require('happn-commons-test').describe({ timeout: 120e3 }, (test) => { + let broker1Proc, broker2Proc, broker3Proc, remoteMesh; + let brokerSeq; + let delayTime = 5e3; + before('clear mongo collection', async () => { + await clearMongoCollection('happn-cluster'); + }); + + before('starts mesh and first broker', async () => { + let done; + let remoteMeshPromise = HappnerCluster.create(remoteInstanceConfig(getSeq.getFirst(), 2)); + brokerSeq = getSeq.getNext(); + broker1Proc = fork(path.resolve(__dirname, './broker.js'), brokerSeq); + broker1Proc.on('message', async (data) => { + if (data === 'started') { + remoteMesh = await remoteMeshPromise; + let users = Array.from(Array(3).keys()).map((int) => ({ + username: 'user' + int.toString(), + password: 'pass', + })); + for (let user of users) { + await remoteMesh.exchange.security.addUser(user); + } + await test.delay(1000); + return done(); + } + }); + await new Promise((res) => { + done = res; + }); + }); + after('stop remote mesh', async () => { + await remoteMesh.stop(); + }); + it('tests the amount of active sessions, attached sessions, and connections on repeated restart of a broker', async () => { + let done; + let stats = []; + fork(path.resolve(__dirname, './_fixtures/karma-start.js')); + broker1Proc.on('message', async (data) => { + if (typeof data === 'object') { + stats.push({ + connected: data.connected.length, + active: data.active.length, + attached: data.attached.length, + }); + broker1Proc.send('kill'); + await test.delay(delayTime); + return done(); + } + }); + await test.delay(6000); + broker1Proc.send('listClients'); + await new Promise((res) => { + done = res; + }); + + broker2Proc = fork(path.resolve(__dirname, './broker.js'), brokerSeq); + + broker2Proc.on('message', async (data) => { + if (data === 'started') { + await test.delay(6000); + broker2Proc.send('listClients'); + } + if (typeof data === 'object') { + stats.push({ + connected: data.connected.length, + active: data.active.length, + attached: data.attached.length, + }); + broker2Proc.send('kill'); + await test.delay(delayTime); + + return done(); + } + }); + await new Promise((res) => { + done = res; + }); + broker3Proc = fork(path.resolve(__dirname, './broker.js'), brokerSeq); + + broker3Proc.on('message', async (data) => { + if (data === 'started') { + await test.delay(8000); + broker3Proc.send('listClients'); + } + if (typeof data === 'object') { + stats.push({ + connected: data.connected.length, + active: data.active.length, + attached: data.attached.length, + }); + broker3Proc.send('kill'); + await test.delay(delayTime); + + return done(); + } + }); + await new Promise((res) => { + done = res; + }); + let broker4Proc = fork(path.resolve(__dirname, './broker.js'), brokerSeq); + broker4Proc.on('message', async (data) => { + if (data === 'started') { + await test.delay(8000); + broker4Proc.send('listClients'); + } + if (typeof data === 'object') { + stats.push({ + connected: data.connected.length, + active: data.active.length, + attached: data.attached.length, + }); + broker4Proc.send('kill'); + return done(); + } + }); + await new Promise((res) => { + done = res; + }); + let compareStat = stats[0]; + test.expect(stats.every((stat) => test._.isEqual(stat, compareStat))).to.be(true); + }); + + function remoteInstanceConfig(seq, sync, replicate) { + var config = baseConfig(seq, sync, true, null, null, null, null, replicate); + config.modules = { + remoteComponent: { + path: libDir + 'integration-09-remote-component', + }, + remoteComponent1: { + path: libDir + 'integration-09-remote-component-1', + }, + }; + config.components = { + remoteComponent: { + startMethod: 'start', + stopMethod: 'stop', + }, + remoteComponent1: { + startMethod: 'start', + stopMethod: 'stop', + }, + }; + config.port = 57000; + config.happn.services.proxy = config.happn.services.proxy || {}; + config.happn.services.proxy.config = config.happn.services.proxy.config || {}; + config.happn.services.proxy.config.port = 55000; + config.happn.services.cache = { config: { statisticsIntervals: 0 } }; + return config; + } +}); diff --git a/packages/happner-cluster/test/browser/_fixtures/01.karma.conf.js b/packages/happner-cluster/test/browser/_fixtures/01.karma.conf.js new file mode 100644 index 000000000..0b2ec0623 --- /dev/null +++ b/packages/happner-cluster/test/browser/_fixtures/01.karma.conf.js @@ -0,0 +1,61 @@ +// Karma configuration +// Generated on Tue Dec 01 2015 11:18:30 GMT+0200 (SAST) + +module.exports = function (config) { + config.set({ + crossOriginAttribute: false, + + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha', 'chai'], + + files: [ + { pattern: 'http://localhost:55001/api/client', type: 'js' }, + 'browsertest_01_happner_client.js', + ], + + // list of files / patterns to load in the browser + // files: [ + // 'build/crypto-min.js', + // {pattern: 'test/crypto-test.js', included: false} + // ], + + // list of files to exclude + exclude: [], + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['mocha'], + + // web server port + port: 9876, + + // enable / disable colors in the output (reporters and logs) + colors: true, + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: false, + detatched: true, + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['ChromeHeadless'], + browserDisconnectTimeout: 15e3, + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: false, + + // Concurrency level + // how many browser should be started simultanous + concurrency: Infinity, + + browserNoActivityTimeout: 100000, + }); +}; diff --git a/packages/happner-cluster/test/browser/_fixtures/browsertest_01_happner_client.js b/packages/happner-cluster/test/browser/_fixtures/browsertest_01_happner_client.js new file mode 100644 index 000000000..4771b3cc0 --- /dev/null +++ b/packages/happner-cluster/test/browser/_fixtures/browsertest_01_happner_client.js @@ -0,0 +1,26 @@ +/* eslint-disable no-console */ +describe('browsertest_01_happner_client', function () { + this.timeout(100e3); + + it('connects and disonnects clients', async () => { + let users = Array.from(Array(3).keys()).map((int) => ({ + username: 'user' + int.toString(), + password: 'pass', + })); + let clients = []; + for (let user of users) { + /* eslint-disable-next-line no-undef */ + let client = new Happner.HappnerClient({ port: 55001 }); + await client.connect(null, user); + clients.push(client); + } + await delay(65000); + }); + + function delay(ms) { + return new Promise((resolve) => { + setTimeout(resolve, ms); + }); + } +}); +/* eslint-enable no-console */ diff --git a/packages/happner-cluster/test/browser/_fixtures/karma-start.js b/packages/happner-cluster/test/browser/_fixtures/karma-start.js new file mode 100644 index 000000000..180462e2e --- /dev/null +++ b/packages/happner-cluster/test/browser/_fixtures/karma-start.js @@ -0,0 +1,10 @@ +var Server = require('karma').Server; +var karma = new Server( + { + configFile: __dirname + '/01.karma.conf.js', + singleRun: true, + }, + function () {} +); + +karma.start(); diff --git a/packages/happner-cluster/test/browser/broker.js b/packages/happner-cluster/test/browser/broker.js new file mode 100644 index 000000000..83fe7d735 --- /dev/null +++ b/packages/happner-cluster/test/browser/broker.js @@ -0,0 +1,57 @@ +const HappnerCluster = require('../..'); +const baseConfig = require('../_lib/base-config'); +const libDir = require('../_lib/lib-dir'); +let seq = [parseInt(process.argv[2]), parseInt(process.argv[3])]; +(async () => { + let meshConfig = brokerConfig(seq, 2); + let mesh = await HappnerCluster.create(meshConfig); + + let attached = []; + + mesh._mesh.happn.events.on('attach', async (data) => { + attached.push(data.user.username); + }); + process.on('message', async (msg) => { + if (msg === 'kill') { + mesh.stop({ reconnect: true, kill: true, wait: 50 }); + } + if (msg === 'listClients') { + mesh._mesh.happn.server.services.security.listActiveSessions((e, active) => { + let connected = Object.keys(mesh._mesh.happn.server.connections); + process.send({ attached, active, connected }); + }); + } + }); + mesh._mesh.happn.server.services.security.activateSessionManagement(() => { + process.send('started'); + }); +})(); + +function brokerConfig(seq, sync, replicate) { + var config = baseConfig(seq, sync, true, null, null, null, null, replicate); + config.modules = { + localComponent: { + path: libDir + 'integration-09-local-component', + }, + brokerComponent: { + path: libDir + 'integration-09-broker-component', + }, + }; + config.components = { + localComponent: { + startMethod: 'start', + stopMethod: 'stop', + }, + brokerComponent: { + startMethod: 'start', + stopMethod: 'stop', + }, + }; + // config.happn.services.orchestrator.config.minimumPeers = 2; + config.happn.services.cache = { config: { statisticsIntervals: 0 } }; + config.port = 57001; + config.happn.services.proxy = config.happn.services.proxy || {}; + config.happn.services.proxy.config = config.happn.services.proxy.config || {}; + config.happn.services.proxy.config.port = 55001; + return config; +} diff --git a/packages/happner-cluster/test/integration/09-cluster-broker.js b/packages/happner-cluster/test/integration/09-cluster-broker.js index 7cee11c68..110b7b1af 100644 --- a/packages/happner-cluster/test/integration/09-cluster-broker.js +++ b/packages/happner-cluster/test/integration/09-cluster-broker.js @@ -255,6 +255,9 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredMethod1' ); }) + .then(function () { + return test.delay(3e3); + }) .then(function () { return testclient.create('username', 'password', getSeq.getPort(2)); }) @@ -276,10 +279,16 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { test.expect(result).to.be(getSeq.getMeshName(1) + ':remoteComponent1:brokeredMethod1'); return users.denyMethod(localInstance, 'username', 'remoteComponent', 'brokeredMethod1'); }) + .then(function () { + return test.delay(3e3); + }) .then(function () { gotToFinalAttempt = true; return thisClient.exchange.remoteComponent.brokeredMethod1(); }) + .then(function () { + done(new Error('unexpected success')); + }) .catch(function (e) { test.expect(gotToFinalAttempt).to.be(true); test.expect(e.toString()).to.be('AccessDenied: unauthorized'); @@ -524,7 +533,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { return client.exchange.remoteComponent.brokeredMethodTimeout(); }) .catch(function (e) { - test.expect(e.toString()).to.be('Request timed out'); + test.expect(e.message).to.be('Request timed out'); done(); }); }); diff --git a/packages/happner-cluster/test/integration/10-cluster-broker-dynamic.js b/packages/happner-cluster/test/integration/10-cluster-broker-dynamic.js index 5deac7190..00e68dcf2 100644 --- a/packages/happner-cluster/test/integration/10-cluster-broker-dynamic.js +++ b/packages/happner-cluster/test/integration/10-cluster-broker-dynamic.js @@ -1,11 +1,9 @@ -// const Promise = require('bluebird'); const libDir = require('../_lib/lib-dir'); const baseConfig = require('../_lib/base-config'); const stopCluster = require('../_lib/stop-cluster'); const users = require('../_lib/users'); const testclient = require('../_lib/client'); const testlightclient = require('../_lib/client-light'); -const delay = require('await-delay'); const getSeq = require('../_lib/helpers/getSeq'); const clearMongoCollection = require('../_lib/clear-mongo-collection'); @@ -33,7 +31,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { }); }); - // in case needed in future + //in case needed in future //test.printOpenHandlesAfter(5e3); context('exchange', function () { @@ -41,13 +39,13 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { var thisClient; startClusterInternalFirst(false) - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'brokerComponent', 'directMethod'); }) - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'remoteComponent', 'brokeredMethod1'); }) - .then(function () { + .then(() => { return users.allowMethod( localInstance, 'username', @@ -55,12 +53,10 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredMethod1' ); }) - .then(function () { - return new Promise((resolve) => { - setTimeout(resolve, 5000); - }); + .then(() => { + return test.delay(3e3); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(2)); }) .then(function (client) { @@ -80,7 +76,9 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { test.expect(result).to.be(getSeq.getMeshName(1) + ':remoteComponent:brokeredMethod1'); setTimeout(done, 2000); }) - .catch(done); + .catch((e) => { + done(e); + }); }); it('starts the cluster internal first, connects a client to the local instance, and is able to access the remote component via the broker, check we cannot access denied methods', function (done) { @@ -89,13 +87,13 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { var gotToFinalAttempt = false; startClusterInternalFirst() - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'brokerComponent', 'directMethod'); }) - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'remoteComponent', 'brokeredMethod1'); }) - .then(function () { + .then(() => { return users.allowMethod( localInstance, 'username', @@ -103,7 +101,10 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredMethod1' ); }) - .then(function () { + .then(() => { + return test.delay(3e3); + }) + .then(() => { return testclient.create('username', 'password', getSeq.getPort(2)); }) .then(function (client) { @@ -131,10 +132,13 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { getSeq.getMeshName(1) + ':remoteComponent1:brokeredMethod1:true' ); }) - .then(function () { + .then(() => { return users.denyMethod(localInstance, 'username', 'remoteComponent', 'brokeredMethod1'); }) - .then(function () { + .then(() => { + return test.delay(3e3); + }) + .then(() => { gotToFinalAttempt = true; return thisClient.exchange.remoteComponent.brokeredMethod1(); }) @@ -147,18 +151,16 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { it('starts up the edge cluster node first, we than start the internal node (with brokered component), pause and then assert we are able to run the brokered method', function (done) { startClusterEdgeFirst() - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'brokerComponent', 'directMethod'); }) - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'remoteComponent', 'brokeredMethod1'); }) - .then(function () { - return new Promise(function (resolve) { - setTimeout(resolve, 5000); - }); + .then(() => { + return test.delay(3e3); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(1)); }) .then(function (client) { @@ -179,18 +181,16 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { it('starts up the edge cluster node first, we then start the internal node (with brokered component), pause and then assert we are able to run a brokered method with an argument', function (done) { startClusterEdgeFirst() - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'brokerComponent', 'directMethod'); }) - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'remoteComponent', 'brokeredMethod3'); }) - .then(function () { - return new Promise(function (resolve) { - setTimeout(resolve, 5000); - }); + .then(() => { + return test.delay(3e3); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(1)); }) .then(function (client) { @@ -220,7 +220,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { it('starts up the edge cluster node first, we then start the internal node (with brokered component), pause and then assert we are able to run a brokered method with an argument, with the correct origin normal client callback', async () => { await startClusterEdgeFirst(); await setupPermissionsCorrectOrigin(); - await test.delay(2000); + await test.delay(2e3); const client = await testclient.create('username', 'password', getSeq.getPort(1)); const result1 = await client.exchange.remoteComponent1.brokeredMethod3('test'); @@ -353,13 +353,13 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { it('starts up the internal cluster node first, we then start the internal node (with brokered component), pause and then assert we are able to run a brokered method with an argument, with the correct origin', function (done) { startClusterInternalFirst() - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'brokerComponent', 'directMethod'); }) - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'remoteComponent', 'brokeredMethod3'); }) - .then(function () { + .then(() => { return users.allowMethod( localInstance, 'username', @@ -367,12 +367,10 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredMethod3' ); }) - .then(function () { - return new Promise(function (resolve) { - setTimeout(resolve, 5000); - }); + .then(() => { + return test.delay(3e3); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(1)); }) .then(function (client) { @@ -381,7 +379,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { test .expect(result) .to.be(getSeq.getMeshName(1) + ':remoteComponent1:brokeredMethod3:test:username'); - setTimeout(done, 2000); + done(); }); }) .catch(done); @@ -391,13 +389,13 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { let testClient; startClusterInternalFirst() - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'brokerComponent', 'directMethod'); }) - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'remoteComponent', 'brokeredMethod3'); }) - .then(function () { + .then(() => { return users.allowMethod( localInstance, 'username', @@ -405,12 +403,10 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredMethod3' ); }) - .then(function () { - return new Promise(function (resolve) { - setTimeout(resolve, 2000); - }); + .then(() => { + return test.delay(3e3); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(2)); }) .then(function (client) { @@ -424,11 +420,14 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { return new Promise((resolve, reject) => { localInstance.stop((e) => { if (e) return reject(e); - setTimeout(resolve, 2000); + resolve(); }); }); }) - .then(function () { + .then(() => { + return test.delay(3e3); + }) + .then(() => { return testClient.exchange.remoteComponent1.brokeredMethod3('test'); }) .catch(function (e) { @@ -442,13 +441,13 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { results = []; startClusterEdgeFirstHighAvailable() - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'brokerComponent', 'directMethod'); }) - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'remoteComponent', 'brokeredMethod3'); }) - .then(function () { + .then(() => { return users.allowMethod( localInstance, 'username', @@ -456,12 +455,10 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredMethod3' ); }) - .then(function () { - return new Promise(function (resolve) { - setTimeout(resolve, 2000); - }); + .then(() => { + return test.delay(3e3); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(1)); }) .then(function (client) { @@ -480,15 +477,18 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { results.push(result); return testClient.exchange.remoteComponent1.brokeredMethod3('test'); }) - .then(function () { + .then(() => { return new Promise((resolve, reject) => { localInstance.stop((e) => { if (e) return reject(e); - setTimeout(resolve, 2000); + resolve(); }); }); }) - .then(function () { + .then(() => { + return test.delay(3e3); + }) + .then(() => { return testClient.exchange.remoteComponent1.brokeredMethod3('test'); }) .then(function (result) { @@ -528,7 +528,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { .then(() => { return test.delay(5000); }) - .then(function () { + .then(() => { test.expect(getInjectedElements(getSeq.getMeshName(1) + '').length).to.be(4); test .expect(getInjectedElements(getSeq.getMeshName(1) + '')[0].meshName != null) @@ -545,9 +545,9 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { return stopServer(servers[1]); }) .then(() => { - return test.delay(3000); + return test.delay(3e3); }) - .then(function () { + .then(() => { //we check injected components is 1 test.expect(getInjectedElements(getSeq.getMeshName(1) + '').length).to.be(2); test @@ -559,9 +559,9 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { return stopServer(servers[2]); }) .then(() => { - return test.delay(3000); + return test.delay(3e3); }) - .then(function () { + .then(() => { //we check injected components is still 1 and injected component meshName is null test.expect(getInjectedElements(getSeq.getMeshName(1) + '').length).to.be(2); test @@ -573,9 +573,9 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { return startInternal(getSeq.getNext(), 2); }) .then(() => { - return test.delay(5000); + return test.delay(3e3); }) - .then(function () { + .then(() => { //we check injected components is still 1 and injected component meshName is null test.expect(getInjectedElements(getSeq.getMeshName(1) + '').length).to.be(2); test @@ -587,9 +587,9 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { return startInternal(getSeq.getNext(), 3); }) .then(() => { - return test.delay(5000); + return test.delay(3e3); }) - .then(function () { + .then(() => { //we check injected components is 2 //we check injected components is still 1 and injected component meshName is null test.expect(getInjectedElements(getSeq.getMeshName(1) + '').length).to.be(4); @@ -608,10 +608,10 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { context('events', function () { it('connects a client to the local instance, and is able to access the remote component events via the broker', function (done) { startClusterInternalFirst() - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'brokerComponent', 'directMethod'); }) - .then(function () { + .then(() => { return users.allowMethod( localInstance, 'username', @@ -619,10 +619,10 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredEventEmitMethod' ); }) - .then(function () { + .then(() => { return users.allowEvent(localInstance, 'username', 'remoteComponent', '/brokered/event'); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(2)); }) .then(function (client) { @@ -657,10 +657,10 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { context('happner-client', function () { it('does a comprehensive test using the happner-client', function (done) { startClusterEdgeFirst() - .then(function () { - return delay(5000); + .then(() => { + return test.delay(3e3); }) - .then(function () { + .then(() => { return users.allowMethod( localInstance, 'username', @@ -668,13 +668,13 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredMethod1' ); }) - .then(function () { + .then(() => { return users.allowWebMethod(localInstance, 'username', '/remoteComponent1/testJSON'); }) - .then(function () { + .then(() => { return users.allowEvent(localInstance, 'username', 'remoteComponent1', 'test/*'); }) - .then(function () { + .then(() => { return connectHappnerClient('username', 'password', getSeq.getPort(1)); }) .then(function (client) { @@ -689,7 +689,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { context('errors', function () { it('ensures an error is raised if we are injecting internal components with duplicate names', function (done) { test.HappnerCluster.create(errorInstanceConfigDuplicateBrokered(getSeq.getFirst(), 1)) - .then(function () { + .then(() => { done(new Error('unexpected success')); }) .catch(function (e) { @@ -704,7 +704,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { it('ensures an error is handled and returned accordingly if we execute an internal components failing method using a callback', function (done) { startClusterInternalFirst() - .then(function () { + .then(() => { return users.allowMethod( localInstance, 'username', @@ -712,7 +712,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredMethodFail' ); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(2)); }) .then(function (client) { @@ -727,7 +727,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { it('ensures an error is handled and returned accordingly if we execute an internal components failing method using a promise', function (done) { startClusterInternalFirst() - .then(function () { + .then(() => { return users.allowMethod( localInstance, 'username', @@ -735,7 +735,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredMethodFail' ); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(2)); }) .then(function (client) { @@ -752,7 +752,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { this.timeout(20000); startClusterInternalFirst() - .then(function () { + .then(() => { return users.allowMethod( localInstance, 'username', @@ -760,7 +760,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredMethodTimeout' ); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(2)); }) .then(function (client) { @@ -768,20 +768,20 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { return client.exchange.remoteComponent.brokeredMethodTimeout(); }) .catch(function (e) { - test.expect(e.toString()).to.be('Request timed out'); + test.expect(e.message).to.be('Request timed out'); done(); }); }); it('ensures an error is handled and returned accordingly if we execute a method that does not exist on the cluster mesh yet', function (done) { startClusterEdgeFirst() - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'brokerComponent', 'directMethod'); }) - .then(function () { + .then(() => { return users.allowMethod(localInstance, 'username', 'remoteComponent', 'brokeredMethod1'); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(1)); }) .then(function (client) { @@ -800,7 +800,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { it('does a rest call', function (done) { var thisClient; startClusterInternalFirst() - .then(function () { + .then(() => { return users.allowMethod( localInstance, 'username', @@ -808,7 +808,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { 'brokeredMethod1' ); }) - .then(function () { + .then(() => { return testclient.create('username', 'password', getSeq.getPort(2)); }) .then(function (client) { @@ -925,7 +925,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { } function stopServer(server) { - return server.stop({ reconnect: false }).then(function () { + return server.stop({ reconnect: false }).then(() => { // stopping all at once causes replicator client happn logouts to timeout // because happn logout attempts unsubscribe on server, and all servers // are gone @@ -1033,14 +1033,14 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { function startClusterEdgeFirstHighAvailable(dynamic) { return new Promise(function (resolve, reject) { startEdge(getSeq.getFirst(), 1, dynamic) - .then(function () { + .then(() => { return startInternal(getSeq.getNext(), 2); }) .then(function (server) { localInstance = server; return startInternal(getSeq.getNext(), 3); }) - .then(function () { + .then(() => { return users.add(localInstance, 'username', 'password'); }) .then(resolve) @@ -1055,10 +1055,10 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { localInstance = server; return startEdge(getSeq.getNext(), 2, dynamic); }) - .then(function () { + .then(() => { return users.add(localInstance, 'username', 'password'); }) - .then(function () { + .then(() => { setTimeout(resolve, 2000); }) .catch(reject); @@ -1068,7 +1068,7 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { function startClusterEdgeFirst(dynamic) { return new Promise(function (resolve, reject) { startEdge(getSeq.getFirst(), 1, dynamic) - .then(function () { + .then(() => { return startInternal(getSeq.getNext(), 2); }) .then(function (server) { diff --git a/packages/happner-cluster/test/integration/17-cluster-broker-component-versions.js b/packages/happner-cluster/test/integration/17-cluster-broker-component-versions.js index be93a4d8b..5af713276 100644 --- a/packages/happner-cluster/test/integration/17-cluster-broker-component-versions.js +++ b/packages/happner-cluster/test/integration/17-cluster-broker-component-versions.js @@ -7,7 +7,7 @@ const testclient = require('../_lib/client'); const getSeq = require('../_lib/helpers/getSeq'); const clearMongoCollection = require('../_lib/clear-mongo-collection'); -require('../_lib/test-helper').describe({ timeout: 40e3 }, (test) => { +require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { var servers = [], localInstance; diff --git a/packages/happner-cluster/test/integration/20-cluster-startup-dependencies.js b/packages/happner-cluster/test/integration/20-cluster-startup-dependencies.js index 90522861f..df06a2191 100644 --- a/packages/happner-cluster/test/integration/20-cluster-startup-dependencies.js +++ b/packages/happner-cluster/test/integration/20-cluster-startup-dependencies.js @@ -32,24 +32,51 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { it('starts up a cluster with interdependencies, happy path, we ensure the startup order is correct', async () => { const cluster = helpers.cluster.create(); - - await cluster.member.start(helpers.configuration.construct(20, [getSeq.getFirst(), 0]), 2000); - await cluster.member.start(helpers.configuration.construct(20, [getSeq.getNext(), 1]), 2000); - await cluster.member.start(helpers.configuration.construct(20, [getSeq.getNext(), 2]), 2000); - await cluster.member.start(helpers.configuration.construct(20, [getSeq.getNext(), 3]), 2000); - await test.delay(5000); - await cluster.member.start(helpers.configuration.construct(20, [getSeq.getNext(), 4]), 2000); - await cluster.member.start(helpers.configuration.construct(20, [getSeq.getNext(), 5]), 2000); - await test.delay(5000); + const mesh0Index = getSeq.getFirst(); + const mesh1Index = getSeq.getNext(); + const mesh2Index = getSeq.getNext(); + const mesh3Index = getSeq.getNext(); + const mesh4Index = getSeq.getNext(); + const mesh5Index = getSeq.getNext(); + // start member 0 + await cluster.member.start(helpers.configuration.construct(20, [mesh0Index, 0]), 0, 1e3); + // start member 1 + await cluster.member.start(helpers.configuration.construct(20, [mesh1Index, 1]), 0, 1e3); + // start member 2, depends on 4 + await cluster.member.start(helpers.configuration.construct(20, [mesh2Index, 2]), 0, 1e3); + // start member 3, depends on 5 + await cluster.member.start(helpers.configuration.construct(20, [mesh3Index, 3]), 0, 1e3); + await test.delay(6e3); // sizeable delay + // start member 4 + await cluster.member.start(helpers.configuration.construct(20, [mesh4Index, 4]), 0, 7e3); + // start member 5 + await cluster.member.start(helpers.configuration.construct(20, [mesh5Index, 5]), 0, 7e3); + await test.delay(6e3); //check member 2 (depending on member 4) is accessible const client = await helpers.client.create(username, password, getSeq.getPort(3)); const result = await client.exchange.component2.use(); test.expect(result).to.be(2); + + const mesh2StartTime = cluster.events.data.find((item) => { + return item.value === `MESH_${mesh2Index[1]}`; + }).timestamp; + const mesh3StartTime = cluster.events.data.find((item) => { + return item.value === `MESH_${mesh3Index[1]}`; + }).timestamp; + const mesh4StartTime = cluster.events.data.find((item) => { + return item.value === `MESH_${mesh4Index[1]}`; + }).timestamp; + const mesh5StartTime = cluster.events.data.find((item) => { + return item.value === `MESH_${mesh5Index[1]}`; + }).timestamp; + + // so 2 and 4 and 3 and 5 needed to start in proximity to each other + test.expect(Math.abs(mesh2StartTime - mesh4StartTime)).to.be.lessThan(3e3); + test.expect(Math.abs(mesh3StartTime - mesh5StartTime)).to.be.lessThan(3e3); + //check the members started in the correct order let values = cluster.events.data.map((item) => item.value); - test - .expect(values.indexOf(getSeq.getMeshName(5))) // Member 4 should start - .to.be.lessThan(values.indexOf(getSeq.getMeshName(3))); // before meber 2 + //check everything started values.sort(); test @@ -66,6 +93,25 @@ require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { await cluster.destroy(); }); + it('starts up a cluster with interdependencies, with intra-mesh dependencies', async () => { + const cluster = helpers.cluster.create(); + // start member 4 + await cluster.member.start(helpers.configuration.construct(20, [getSeq.getFirst(), 4]), 0, 1e3); + // start member 5 + await cluster.member.start(helpers.configuration.construct(20, [getSeq.getNext(), 5]), 0, 1e3); + // start member 6 + await cluster.member.start(helpers.configuration.construct(20, [getSeq.getNext(), 6]), 0, 1e3); + + test.log(`waiting 16 seconds...`); + await test.delay(16e3); + //check member 2 (depending on member 4) is accessible + const client = await helpers.client.create(username, password, getSeq.getPort(3)); + const result = await client.exchange.component6.use(); + test.expect(result).to.be(6); + await helpers.client.destroy(client); + await cluster.destroy(); + }); + it('starts up a cluster with interdependencies, we ensure that members with unsatisfied dependencies are not accessible', async () => { const cluster = helpers.cluster.create(); diff --git a/packages/happner-cluster/test/integration/25-cluster-brokering-after-member-dies.js b/packages/happner-cluster/test/integration/25-cluster-brokering-after-member-dies.js index 4d58df1bb..1e45955ae 100644 --- a/packages/happner-cluster/test/integration/25-cluster-brokering-after-member-dies.js +++ b/packages/happner-cluster/test/integration/25-cluster-brokering-after-member-dies.js @@ -54,7 +54,7 @@ require('../_lib/test-helper').describe({ timeout: 50e3 }, (test) => { await client.exchange.breakingComponent.breakingMethod(1); // Too few arguments throw new Error("shouldn't happen"); } catch (e) { - test.expect(e).to.be('Request timed out'); + test.expect(e.message).to.be('Request timed out'); } child = await fork(libDir + 'test-25-sub-process.js', ['3', getSeq.lookupFirst().toString()]); await test.delay(8000); diff --git a/packages/happner-cluster/test/integration/37-on-behalf-of-inter-cluster.js b/packages/happner-cluster/test/integration/37-on-behalf-of-inter-cluster.js new file mode 100644 index 000000000..e1b92af60 --- /dev/null +++ b/packages/happner-cluster/test/integration/37-on-behalf-of-inter-cluster.js @@ -0,0 +1,568 @@ +const baseConfig = require('../_lib/base-config'); +const stopCluster = require('../_lib/stop-cluster'); +const users = require('../_lib/users'); +const clearMongoCollection = require('../_lib/clear-mongo-collection'); +const getSeq = require('../_lib/helpers/getSeq'); +const testclient = require('../_lib/client'); +const HappnerClient = require('happner-client'); +const LightClient = require('happner-client').Light; + +require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { + const restClient = require('restler'); + let adminUser, + adminUserHappnerClient, + adminUserHappnerClientAPI, + adminUserLightClient, + testUserHappnerClient, + testUserHappnerClientAPI, + testUserLightClient, + testUsers = []; + + before('clear mongo', clearMongo); + before('start cluster', startCluster); + before('it connects the admin user', connectAdminUsers); + before('it creates the test users', createTestUsers); + + it('can do without as, happner client', async () => { + const [testUserHappnerClient, testUserHappnerClientAPI] = await createHappnerClientAndAPI( + { username: 'testUser', password: 'password' }, + getSeq.getPort(1) + ); + test + .expect( + await testUserHappnerClientAPI.exchange.$call({ + component: 'local', + method: 'doOnBehalfOfAllowedNoAs', + arguments: [1, 2], + }) + ) + .to.eql('origin:testUser:1:2'); + await testUserHappnerClient.disconnect(); + }); + + it('can do without as, light client', async () => { + const testEdgeUser = await createLightClient( + { username: 'testUser', password: 'password', domain: 'DOMAIN_NAME' }, + getSeq.getPort(1) + ); + test + .expect( + await testEdgeUser.exchange.$call({ + component: 'local', + method: 'doOnBehalfOfAllowedNoAs', + arguments: [1, 2], + }) + ) + .to.eql('origin:testUser:1:2'); + await testEdgeUser.disconnect(); + }); + + it('can do an http-rpc with as, delegated via the ADMIN user', async () => { + const token = adminUser.token; + test + .expect( + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ) + ) + .to.eql('origin:testUser:1:2'); + }); + it('can do an http-rpc with as, delegated via a user with delegate priviledges', async () => { + const testDelegateUser = await connectTestUser(9); + const token = testDelegateUser.token; + test + .expect( + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ) + ) + .to.eql('origin:testUser:1:2'); + }); + it('fails to do an http-rpc with as', async () => { + const token = adminUser.token; + let errorMessage; + try { + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.eql('Access denied'); + }); + + it('fails to do an http-rpc with as because the origin is not a delegate user', async () => { + const testUser1 = await connectTestUser(1); + const token = testUser1.token; + let errorMessage; + try { + await testHttpRpc( + { + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: { param1: 1, param2: 2 }, + as: 'testUser', + }, + token + ); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.eql('origin does not belong to the delegate group'); + }); + + it('can do an exchange call with as in component method', async () => { + test + .expect(await adminUser.exchange.local.doOnBehalfOfAllowedAs(1, 2)) + .to.eql('origin:testUser:1:2'); + }); + + it('fails to do an exchange call with as in component method', async () => { + const result = await adminUser.exchange.local.doOnBehalfOfNotAllowedAs(1, 2); + test.expect(result).to.eql(['unauthorized', 'unauthorized']); + }); + + it('can do an exchange $call with as', async () => { + test + .expect( + await adminUser.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: 'testUser', + }) + ) + .to.eql('origin:testUser:1:2'); + }); + + it('fails to do an exchange call with as', async () => { + let errorMessage; + try { + await adminUser.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [1, 2], + as: 'testUser', + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.be('unauthorized'); + }); + + it('can do an exchange $call with as, light-client', async () => { + test + .expect( + await adminUserLightClient.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: 'testUser', + }) + ) + .to.eql('origin:testUser:1:2'); + }); + + it('fails to do an exchange call with as, light-client', async () => { + let errorMessage; + try { + await adminUserLightClient.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [1, 2], + as: 'testUser', + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.be('unauthorized'); + }); + + it('fails to try an exchange call with as _ADMIN, light-client', async () => { + let errorMessage; + testUserLightClient = await createLightClient( + { username: 'testUser', password: 'password', domain: 'DOMAIN_NAME' }, + getSeq.getPort(1) + ); + try { + await testUserLightClient.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [1, 2], + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.be('unauthorized'); + try { + await testUserLightClient.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [1, 2], + as: '_ADMIN', + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.be('unauthorized'); + }); + + it('can do an exchange $call with as, happner-client', async () => { + test + .expect( + await adminUserHappnerClientAPI.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: 'testUser', + }) + ) + .to.eql('origin:testUser:1:2'); + }); + + it('fails to do an exchange call with as, happner-client', async () => { + let errorMessage; + try { + await adminUserHappnerClientAPI.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [1, 2], + as: 'testUser', + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.be('unauthorized'); + }); + + it('fails to do an exchange call with as, happner-client, unknown user', async () => { + let errorMessage; + try { + await adminUserHappnerClientAPI.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: 'unknown', + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.be('unauthorized'); + }); + + it('fails to do an exchange call with as, happner-client, anonymous user', async () => { + let errorMessage; + try { + await adminUserHappnerClientAPI.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: '_ANONYMOUS', + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.be('unauthorized'); + }); + + it('fails to try an exchange call with as _ADMIN, happner-client', async () => { + let errorMessage; + [testUserHappnerClient, testUserHappnerClientAPI] = await createHappnerClientAndAPI( + { username: 'testUser', password: 'password' }, + getSeq.getPort(1) + ); + try { + await testUserHappnerClientAPI.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [1, 2], + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.be('unauthorized'); + try { + await testUserHappnerClientAPI.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [1, 2], + as: '_ADMIN', + }); + } catch (e) { + errorMessage = e.message; + } + test.expect(errorMessage).to.be('unauthorized'); + }); + + var servers, localInstance; + + function localInstanceConfig(seq) { + var config = baseConfig(seq, undefined, true); + config.happn.services.security.config.allowAnonymousAccess = true; + config.modules = { + local: { + instance: { + doOnBehalfOfAllowedAsAdmin: async function (param1, param2, $origin, $happn) { + //this should work if we come in through the edge, without an as (backwards compatible with the existing system) + await $happn.asAdmin.exchange.test.doOnBehalfOfNotAllowed(); + return `origin:${$origin.username}:${param1}:${param2}`; + }, + doOnBehalfOfAllowedNoAs: async function (param1, param2, $origin, $happn) { + //this should work if we come in through the edge, without an as (backwards compatible with the existing system) + await $happn.exchange.test.doOnBehalfOfNotAllowed(); + return `origin:${$origin.username}:${param1}:${param2}`; + }, + doOnBehalfOfAllowedAs: async function (param1, param2, $happn) { + let result1 = await $happn.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [param1, param2], + as: 'testUser', + }); + let result2 = await $happn + .as('testUser') + .exchange.test.doOnBehalfOfAllowed(param1, param2); + test.expect(result1).to.eql(result2); + return result1; + }, + doOnBehalfOfNotAllowedAs: async function (param1, param2, $happn) { + const failures = []; + try { + await $happn.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [param1, param2], + as: 'testUser', + }); + } catch (e) { + failures.push(e.message); + } + try { + await $happn.as('testUser').exchange.test.doOnBehalfOfNotAllowed(param1, param2); + } catch (e) { + failures.push(e.message); + } + return failures; + }, + }, + }, + }; + config.components = { + local: { + dependencies: { + $broker: { + test: { + version: '*', + methods: { + doOnBehalfOfAllowed: {}, + doOnBehalfOfNotAllowed: {}, + }, + }, + }, + }, + }, + }; + return config; + } + + function remoteInstanceConfig(seq) { + var config = baseConfig(seq, undefined, true); + config.modules = { + test: { + instance: { + doOnBehalfOfAllowed: async function (param1, param2, $origin) { + return `origin:${$origin.username}:${param1}:${param2}`; + }, + doOnBehalfOfNotAllowed: async function (_param1, _param2, $origin) { + return `unexpected:${$origin.username}`; + }, + }, + }, + }; + config.components = { + test: {}, + }; + return config; + } + + function clearMongo(done) { + clearMongoCollection('mongodb://localhost', 'happn-cluster', function (e) { + done(e); + }); + } + + function startCluster(done) { + this.timeout(20000); + test.HappnerCluster.create(localInstanceConfig(getSeq.getFirst(), 1)).then(function (local) { + localInstance = local; + }); + + setTimeout(() => { + Promise.all([ + test.HappnerCluster.create(remoteInstanceConfig(getSeq.getNext(), 1)), + test.HappnerCluster.create(remoteInstanceConfig(getSeq.getNext(), 1)), + test.HappnerCluster.create(remoteInstanceConfig(getSeq.getNext(), 1)), + ]) + .then(function (_servers) { + servers = _servers; + //localInstance = servers[0]; + return users.add(servers[0], 'username', 'password'); + }) + .then(function () { + setTimeout(done, 5e3); + }) + .catch(done); + }, 2000); + } + + after('it disconnects the admin user', disconnectAdminUsers); + after('it disconnects the test users', disconnectTestUsers); + + after('stop cluster', function (done) { + if (!servers) return done(); + stopCluster(servers.concat(localInstance), done); + }); + + async function createHappnerClientAndAPI(opts, port) { + const createdClient = new HappnerClient(opts); + await createdClient.connect({ + username: opts.username || '_ADMIN', + password: opts.password || 'happn', + port, + }); + var model = { + test: { + version: '*', + methods: { + doOnBehalfOfAllowed: {}, + doOnBehalfOfNotAllowed: {}, + }, + }, + local: { + version: '*', + methods: { + doOnBehalfOfAllowedNoAs: {}, + doOnBehalfOfAllowedAs: {}, + doOnBehalfOfNotAllowedAs: {}, + }, + }, + }; + const createdApi = createdClient.construct(model); + return [createdClient, createdApi]; + } + + async function createLightClient(opts, port) { + const createdClient = new LightClient(opts); + await createdClient.connect({ + username: opts.username || '_ADMIN', + password: opts.password || 'happn', + port, + }); + return createdClient; + } + + async function connectAdminUsers() { + adminUser = await new testclient.create('_ADMIN', 'happn', getSeq.getPort(1)); + [adminUserHappnerClient, adminUserHappnerClientAPI] = await createHappnerClientAndAPI( + { + discoverMethods: true, + }, + getSeq.getPort(1) + ); + adminUserLightClient = await createLightClient({ domain: 'DOMAIN_NAME' }, getSeq.getPort(1)); + } + async function connectTestUser(id = '') { + const testUser = await new testclient.create(`testUser${id}`, 'password', getSeq.getPort(1)); + testUsers.push(testUser); + return testUser; + } + async function disconnectAdminUsers() { + if (adminUser) await adminUser.disconnect(); + if (adminUserHappnerClient) await adminUserHappnerClient.disconnect(); + if (adminUserLightClient) await adminUserLightClient.disconnect(); + } + async function disconnectTestUsers() { + if (testUserHappnerClient) await testUserHappnerClient.disconnect(); + if (testUserLightClient) await testUserLightClient.disconnect(); + for (let testuserSession of testUsers) { + await testuserSession.disconnect(); + } + } + async function createTestUsers() { + for (var i = 0; i < 10; i++) { + await createTestUser(i === 0 ? '' : i.toString(), i === 9 ? true : false); + } + } + async function createTestUser(id = '', isDelegate) { + const testGroupUser = { + name: `testGroup${id}`, + permissions: { + methods: { + '/local/doOnBehalfOfAllowedNoAs': { authorized: true }, + '/local/doOnBehalfOfAllowedAsAdmin': { authorized: true }, + '/test/doOnBehalfOfAllowed': { authorized: true }, + '/test/doOnBehalfOfAllowedAs': { authorized: true }, + '/test/doOnBehalfOfNotAllowedAs': { authorized: true }, + }, + }, + }; + await adminUser.exchange.security.upsertGroup(testGroupUser); + const upsertedUser = await adminUser.exchange.security.upsertUser({ + username: `testUser${id}`, + password: 'password', + }); + await adminUser.exchange.security.linkGroupName('testGroup', upsertedUser); + if (isDelegate) { + await adminUser.exchange.security.linkGroupName('_MESH_DELEGATE', upsertedUser); + } + } + async function testHttpRpc(requestInfo, token) { + return doRequest( + requestInfo.component, + requestInfo.method, + requestInfo.arguments, + requestInfo.as, + token + ); + } + function doRequest(componentName, methodName, operationArguments, as, token) { + var operation = { + parameters: operationArguments, + as, + }; + return new Promise((resolve, reject) => { + restClient + .postJson( + `http://127.0.0.1:${getSeq.getPort( + 1 + )}/rest/method/${componentName}/${methodName}?happn_token=` + token, + operation + ) + .on('complete', function (result) { + if (result.error) { + return reject(new Error(result.error.message)); + } + resolve(result.data); + }) + .on('error', reject); + }); + } +}); diff --git a/packages/happner-cluster/test/integration/38-on-behalf-of-inter-cluster-concurrency.js b/packages/happner-cluster/test/integration/38-on-behalf-of-inter-cluster-concurrency.js new file mode 100644 index 000000000..5e105b760 --- /dev/null +++ b/packages/happner-cluster/test/integration/38-on-behalf-of-inter-cluster-concurrency.js @@ -0,0 +1,457 @@ +const baseConfig = require('../_lib/base-config'); +const stopCluster = require('../_lib/stop-cluster'); +const users = require('../_lib/users'); +const clearMongoCollection = require('../_lib/clear-mongo-collection'); +const getSeq = require('../_lib/helpers/getSeq'); +const testclient = require('../_lib/client'); +const HappnerClient = require('happner-client'); +const LightClient = require('happner-client').Light; + +require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { + const restClient = require('restler'); + let adminUser, + adminUserHappnerClient, + adminUserHappnerClientAPI, + adminUserLightClient, + testUserHappnerClient, + testUserLightClient, + testUsers = [], + testUserNames = [], + script = [], + CONCURRENT_REQUESTS_COUNT = 20, + CONCURRENT_BATCHES_COUNT = 1; + + before('clear mongo', clearMongo); + before('start cluster', startCluster); + before('it connects the admin user', connectAdminUsers); + before('it creates the test users', createTestUsers); + before('generates call and expectation script', generateScript); + + it('runs $call tests on mesh-client', async () => { + await callTests(adminUser.exchange); + }); + + it('runs $call tests on happner-client', async () => { + await callTests(adminUserHappnerClientAPI.exchange); + }); + + it('runs $call tests on light client', async () => { + await callTests(adminUserLightClient.exchange); + }); + + it('runs $call tests on rest client', async () => { + await callTests(RpcExchange.create(adminUser.token)); + }); + + it('runs inter-mesh $call tests on mesh-client', async () => { + await callTestsInterMesh(adminUser.exchange); + }); + + it('runs inter-mesh $call tests on happner-client', async () => { + await callTestsInterMesh(adminUserHappnerClientAPI.exchange); + }); + + it('runs inter-mesh $call tests on light client', async () => { + await callTestsInterMesh(adminUserLightClient.exchange); + }); + + it('runs inter-mesh $call tests on rest client', async () => { + await callTestsInterMesh(RpcExchange.create(adminUser.token)); + }); + + after('it disconnects the admin user', disconnectAdminUsers); + after('it disconnects the test users', disconnectTestUsers); + after('stop cluster', function (done) { + if (!servers) return done(); + stopCluster(servers.concat(localInstance), done); + }); + + async function callTestsInterMesh(exchange) { + const stats = { + unauthorized: 0, + adminSucceeded: 0, + testUserSucceeded: 0, + }; + for (let batchId in script.batches) { + await Promise.all( + script.batches[batchId].map((scriptItem) => { + return ( + test + // delay to interleave _ADMIN users + .delay(scriptItem.username === '_ADMIN' ? 1e3 : 0) + .then(() => { + return exchange.$call({ + component: 'local', + method: 'doOnBehalfOfAllowedAs', + arguments: [1, 2, scriptItem.username], + }); + }) + .then((result) => { + test.expect(result).to.be(`origin:${scriptItem.username}:1:2`); + if (scriptItem.username === '_ADMIN') { + stats.adminSucceeded++; + } else { + stats.testUserSucceeded++; + } + return exchange.$call({ + component: 'local', + method: 'doOnBehalfOfNotAllowedAs', + arguments: [1, 2, scriptItem.username], + }); + }) + .then(() => { + test.expect(scriptItem.expectation.allowedSucceeded).to.be(true); + }) + .catch((e) => { + test.expect(scriptItem.expectation.notAllowedSucceeded).to.be(false); + test.expect(e.message).to.be('unauthorized'); + stats.unauthorized++; + }) + ); + }) + ); + } + test.expect(stats).to.eql({ + unauthorized: CONCURRENT_BATCHES_COUNT * (CONCURRENT_REQUESTS_COUNT - 1), // -1 is for the delegate user + adminSucceeded: CONCURRENT_BATCHES_COUNT * CONCURRENT_REQUESTS_COUNT, + testUserSucceeded: CONCURRENT_BATCHES_COUNT * CONCURRENT_REQUESTS_COUNT, + }); + } + + async function callTests(exchange) { + const stats = { + unauthorized: 0, + adminSucceeded: 0, + testUserSucceeded: 0, + }; + for (let batchId in script.batches) { + await Promise.all( + script.batches[batchId].map((scriptItem) => { + return ( + test + // delay to interleave _ADMIN users + .delay(scriptItem.username === '_ADMIN' ? 1e3 : 0) + .then(() => { + return exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [1, 2], + as: scriptItem.username, + }); + }) + .then((result) => { + test.expect(result).to.be(`origin:${scriptItem.username}:1:2`); + if (scriptItem.username === '_ADMIN') { + stats.adminSucceeded++; + } else { + stats.testUserSucceeded++; + } + return exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [1, 2], + as: scriptItem.username, + }); + }) + .then(() => { + test.expect(scriptItem.expectation.allowedSucceeded).to.be(true); + }) + .catch((e) => { + test.expect(scriptItem.expectation.notAllowedSucceeded).to.be(false); + test.expect(e.message).to.be('unauthorized'); + stats.unauthorized++; + }) + ); + }) + ); + } + test.expect(stats).to.eql({ + unauthorized: CONCURRENT_BATCHES_COUNT * (CONCURRENT_REQUESTS_COUNT - 1), // -1 is for the delegate user + adminSucceeded: CONCURRENT_BATCHES_COUNT * CONCURRENT_REQUESTS_COUNT, + testUserSucceeded: CONCURRENT_BATCHES_COUNT * CONCURRENT_REQUESTS_COUNT, + }); + } + + var servers, localInstance; + + function localInstanceConfig(seq) { + var config = baseConfig(seq, undefined, true); + config.boundExchangeCacheSize = 2; + config.happn.services.security.config.allowAnonymousAccess = true; + config.modules = { + local: { + instance: { + doOnBehalfOfAllowedAs: async function (param1, param2, as, $happn) { + let result1 = await $happn.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfAllowed', + arguments: [param1, param2], + as, + }); + let result2 = await $happn.as(as).exchange.test.doOnBehalfOfAllowed(param1, param2); + test.expect(result1).to.eql(result2); + return result1; + }, + doOnBehalfOfNotAllowedAs: async function (param1, param2, as, $happn) { + const failures = []; + try { + await $happn.exchange.$call({ + component: 'test', + method: 'doOnBehalfOfNotAllowed', + arguments: [param1, param2], + as, + }); + } catch (e) { + failures.push(e); + } + try { + await $happn.as(as).exchange.test.doOnBehalfOfNotAllowed(param1, param2); + } catch (e) { + failures.push(e); + } + throw failures[0]; + }, + }, + }, + }; + config.components = { + local: { + dependencies: { + $broker: { + test: { + version: '*', + methods: { + doOnBehalfOfAllowed: {}, + doOnBehalfOfNotAllowed: {}, + }, + }, + }, + }, + }, + }; + return config; + } + + function remoteInstanceConfig(seq) { + let config = baseConfig(seq, undefined, true); + config.boundExchangeCacheSize = 2; + config.modules = { + test: { + instance: { + doOnBehalfOfAllowed: async function (param1, param2, $origin) { + return `origin:${$origin.username}:${param1}:${param2}`; + }, + doOnBehalfOfNotAllowed: async function (_param1, _param2, $origin) { + return `unexpected:${$origin.username}`; + }, + }, + }, + }; + config.components = { + test: {}, + }; + return config; + } + + function clearMongo(done) { + clearMongoCollection('mongodb://localhost', 'happn-cluster', function (e) { + done(e); + }); + } + + function startCluster(done) { + this.timeout(20000); + test.HappnerCluster.create(localInstanceConfig(getSeq.getFirst(), 1)).then(function (local) { + localInstance = local; + }); + + setTimeout(() => { + Promise.all([ + test.HappnerCluster.create(remoteInstanceConfig(getSeq.getNext(), 1)), + test.HappnerCluster.create(remoteInstanceConfig(getSeq.getNext(), 1)), + test.HappnerCluster.create(remoteInstanceConfig(getSeq.getNext(), 1)), + ]) + .then(function (_servers) { + servers = _servers; + //localInstance = servers[0]; + return users.add(servers[0], 'username', 'password'); + }) + .then(function () { + setTimeout(done, 5e3); + }) + .catch(done); + }, 2000); + } + + async function createHappnerClientAndAPI(opts, port) { + const createdClient = new HappnerClient(opts); + await createdClient.connect({ + username: opts.username || '_ADMIN', + password: opts.password || 'happn', + port, + }); + var model = { + test: { + version: '*', + methods: { + doOnBehalfOfAllowed: {}, + doOnBehalfOfNotAllowed: {}, + }, + }, + local: { + version: '*', + methods: { + doOnBehalfOfAllowedAs: {}, + doOnBehalfOfNotAllowedAs: {}, + }, + }, + }; + const createdApi = createdClient.construct(model); + return [createdClient, createdApi]; + } + + async function createLightClient(opts, port) { + const createdClient = new LightClient(opts); + await createdClient.connect({ + username: opts.username || '_ADMIN', + password: opts.password || 'happn', + port, + }); + return createdClient; + } + + async function connectAdminUsers() { + adminUser = await new testclient.create('_ADMIN', 'happn', getSeq.getPort(1)); + [adminUserHappnerClient, adminUserHappnerClientAPI] = await createHappnerClientAndAPI( + { + discoverMethods: true, + }, + getSeq.getPort(1) + ); + adminUserLightClient = await createLightClient({ domain: 'DOMAIN_NAME' }, getSeq.getPort(1)); + } + async function disconnectAdminUsers() { + if (adminUser) await adminUser.disconnect(); + if (adminUserHappnerClient) await adminUserHappnerClient.disconnect(); + if (adminUserLightClient) await adminUserLightClient.disconnect(); + } + async function disconnectTestUsers() { + if (testUserHappnerClient) await testUserHappnerClient.disconnect(); + if (testUserLightClient) await testUserLightClient.disconnect(); + for (let testuserSession of testUsers) { + await testuserSession.disconnect(); + } + } + async function createTestUsers() { + for (var i = 0; i < CONCURRENT_REQUESTS_COUNT; i++) { + await createTestUser( + i === 0 ? '' : i.toString(), + i === CONCURRENT_REQUESTS_COUNT - 1 ? true : false + ); + } + } + async function createTestUser(id = '', isDelegate) { + const testGroupUser = { + name: `testGroup${id}`, + permissions: { + methods: { + '/test/doOnBehalfOfAllowed': { authorized: true }, + '/test/doOnBehalfOfAllowedAs': { authorized: true }, + '/test/doOnBehalfOfNotAllowedAs': { authorized: true }, + }, + }, + }; + await adminUser.exchange.security.upsertGroup(testGroupUser); + const upsertedUser = await adminUser.exchange.security.upsertUser({ + username: `testUser${id}`, + password: 'password', + }); + await adminUser.exchange.security.linkGroupName('testGroup', upsertedUser); + if (isDelegate) { + await adminUser.exchange.security.linkGroupName('_MESH_DELEGATE', upsertedUser); + } + testUserNames.push(`testUser${id}`); + } + + function generateScript() { + script = { batches: {} }; + for (let batchId = 0; batchId < CONCURRENT_BATCHES_COUNT; batchId++) { + script.batches[batchId] = []; + for (let username of testUserNames) { + script.batches[batchId].push({ + username, + expectation: { + allowedSucceeded: true, + notAllowedSucceeded: false, + allowedIntermeshSucceeded: true, + notAllowedIntermeshSucceeded: false, + }, + }); + script.batches[batchId].push({ + username: '_ADMIN', + expectation: { + allowedSucceeded: true, + notAllowedSucceeded: true, + allowedIntermeshSucceeded: true, + notAllowedIntermeshSucceeded: true, + }, + }); + } + } + } + + class RpcExchange { + #token; + constructor(token) { + this.#token = token; + this.exchange; + } + static create(token) { + return new RpcExchange(token); + } + async $call(operation) { + return await doRequest( + operation.component, + operation.method, + operation.arguments, + operation.as, + this.#token + ); + } + } + + function doRequest(componentName, methodName, operationArguments, as, token) { + var operation = { + parameters: operationArguments.reduce((reducer, argValue, argIndex) => { + if (argIndex === operationArguments.length - 1 && operationArguments.length === 3) { + reducer['as'] = argValue; + } else { + reducer[`param${argIndex + 1}`] = argValue; + } + return reducer; + }, {}), + as, + }; + return new Promise((resolve, reject) => { + restClient + .postJson( + `http://127.0.0.1:${getSeq.getPort( + 1 + )}/rest/method/${componentName}/${methodName}?happn_token=` + token, + operation + ) + .on('complete', function (result) { + if (result.error) { + if (result.error.message === 'Access denied') { + return reject(new Error('unauthorized')); + } + return reject(new Error(result.error.message)); + } + resolve(result.data); + }) + .on('error', (error) => { + return reject(error); + }); + }); + } +}); diff --git a/packages/happner-cluster/test/unit/02-broker-component.js b/packages/happner-cluster/test/unit/02-broker-component.js index bc3ccddeb..860e67816 100644 --- a/packages/happner-cluster/test/unit/02-broker-component.js +++ b/packages/happner-cluster/test/unit/02-broker-component.js @@ -1,7 +1,4 @@ -var Promise = require('bluebird'); -var expect = require('expect.js'); - -describe('02 - unit - brokerage component', function () { +require('../_lib/test-helper').describe({ timeout: 120e3 }, (test) => { it('injects the brokerage component', function (done) { //package, mesh, client var mockModels = {}; @@ -20,9 +17,9 @@ describe('02 - unit - brokerage component', function () { brokerage.inject(function (e) { if (e) return done(e); - expect(brokerage.__models).to.be(mockModels); - expect(brokerage.__mesh).to.be(mockMesh); - expect(brokerage.__client).to.be(mockClient); + test.expect(brokerage.__models).to.be(mockModels); + test.expect(brokerage.__mesh).to.be(mockMesh); + test.expect(brokerage.__client).to.be(mockClient); done(); }); }); @@ -60,9 +57,11 @@ describe('02 - unit - brokerage component', function () { var brokerage = require('../../lib/brokerage').create(mockModels, mockMesh, mockClient); brokerage.inject(function (e) { - expect(e.toString()).to.be( - 'Error: Duplicate attempts to broker the remoteComponent3 component by brokerComponent & brokerComponent1' - ); + test + .expect(e.toString()) + .to.be( + 'Error: Duplicate attempts to broker the remoteComponent3 component by brokerComponent & brokerComponent1' + ); done(); }); }); @@ -95,7 +94,7 @@ describe('02 - unit - brokerage component', function () { }; var brokerage = require('../../lib/brokerage').create(mockModels, mockMesh, mockClient); - expect(require('../../lib/brokerage').instance('mock')).to.eql(brokerage); + test.expect(require('../../lib/brokerage').instance('mock')).to.eql(brokerage); }); it('tests the deferProxyStart method', function (done) { @@ -130,7 +129,7 @@ describe('02 - unit - brokerage component', function () { test: 'proxy', }) .then(function () { - expect(brokerage.__proxy).to.eql({ + test.expect(brokerage.__proxy).to.eql({ test: 'proxy', }); done(); @@ -167,11 +166,11 @@ describe('02 - unit - brokerage component', function () { var brokerage = require('../../lib/brokerage').create(mockModels, mockMesh, mockClient); brokerage.__satisfiedElementNames = ['test1', 'test2']; brokerage.__injectedElementNames = ['test2', 'test1']; - expect(brokerage.dependenciesSatisfied()).to.be(true); + test.expect(brokerage.dependenciesSatisfied()).to.be(true); brokerage.__satisfiedElementNames = ['test1', 'test2']; brokerage.__injectedElementNames = ['test2']; - expect(brokerage.dependenciesSatisfied()).to.be(false); + test.expect(brokerage.dependenciesSatisfied()).to.be(false); }); it('tests the __checkDependenciesSatisfied method', function (done) { @@ -202,9 +201,7 @@ describe('02 - unit - brokerage component', function () { on: function () {}, }; - var mockLogger = { - info: () => {}, - }; + var mockLogger = getMockLogger(); var brokerage = require('../../lib/brokerage').create( mockModels, @@ -254,18 +251,18 @@ describe('02 - unit - brokerage component', function () { on: function () {}, }; let count = 0; - var mockLogger = { + let mockLogger = getMockLogger({ debug: function (msg) { count++; if (count === 2) { - expect('remote dependency satisfied: remote-mesh.test').to.be(msg); + test.expect('remote dependency satisfied: remote-mesh.test').to.be(msg); done(); } }, error: function () { done(arguments[0]); }, - }; + }); var brokerage = require('../../lib/brokerage').create( mockModels, @@ -311,4 +308,14 @@ describe('02 - unit - brokerage component', function () { description: {}, }); }); + function getMockLogger(replacements = {}) { + const mockLogger = { + info: () => {}, + debug: () => {}, + warn: () => {}, + error: () => {}, + trace: () => {}, + }; + return test.commons._.merge(mockLogger, replacements); + } }); diff --git a/packages/redis-lru-cache/package.json b/packages/redis-lru-cache/package.json index 6636d01a3..7f30b0c62 100644 --- a/packages/redis-lru-cache/package.json +++ b/packages/redis-lru-cache/package.json @@ -1,7 +1,7 @@ { "name": "redis-lru-cache", "description": "cluster friendly cache, that relies on redis pub/sub to share data", - "version": "1.0.12", + "version": "1.0.13", "scripts": { "test": "mocha test/functional", "test-cover": "nyc npm test" @@ -31,7 +31,7 @@ }, "devDependencies": { "happn-commons-test": "^1.1.0", - "happn-db-provider-mongo": "^1.0.12" + "happn-db-provider-mongo": "^1.0.13" }, "readmeFilename": "README.md" }