diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 5bd2c0c001..c888acaffa 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,7 +11,7 @@ jobs: strategy: matrix: - node-version: [16.x] + node-version: [14.x, 16.x] steps: - uses: actions/checkout@v1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 935b3ddcc1..4bfa044c6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,28 @@ +# [0.171.0](https://github.com/n8n-io/n8n/compare/n8n@0.170.0...n8n@0.171.0) (2022-04-03) + + +### Bug Fixes + +* **core:** Fix crash on webhook when last node did not return data ([c50d04a](https://github.com/n8n-io/n8n/commit/c50d04af9eb033d82860c336fc7350b5c3f22242)) +* **EmailReadImap Node:** Fix issue that crashed process if node was configured wrong ([#3079](https://github.com/n8n-io/n8n/issues/3079)) ([85f15d4](https://github.com/n8n-io/n8n/commit/85f15d49896d876fa3ab84e9fa1846f856851274)) +* **Google Tasks Node:** Fix "Show Completed" option and hide title field where not needed ([#2741](https://github.com/n8n-io/n8n/issues/2741)) ([9d703e3](https://github.com/n8n-io/n8n/commit/9d703e366b8e191e0f588469892ebb7b6d03c1d3)) +* **NocoDB Node:** Fix pagination ([#3081](https://github.com/n8n-io/n8n/issues/3081)) ([5f44b0d](https://github.com/n8n-io/n8n/commit/5f44b0dad5254fe9f985b314db8f7d43ab48c712)) +* **Salesforce Node:** Fix issue that "status" did not get used for Case => Create & Update ([#2212](https://github.com/n8n-io/n8n/issues/2212)) ([1018146](https://github.com/n8n-io/n8n/commit/1018146f21c47eda9f888bd19e92d1106c49267a)) + + +### Features + +* **editor:** Add download button for binary data ([#2992](https://github.com/n8n-io/n8n/issues/2992)) ([13a9db7](https://github.com/n8n-io/n8n/commit/13a9db774576a00d4e3ce1988557654d00067073)) +* **Emelia Node:** Add Campaign > Duplicate functionality ([#3000](https://github.com/n8n-io/n8n/issues/3000)) ([0b08be1](https://github.com/n8n-io/n8n/commit/0b08be1c0b2961f235fc2446a36afe3995b4d847)), closes [#3065](https://github.com/n8n-io/n8n/issues/3065) [#2741](https://github.com/n8n-io/n8n/issues/2741) [#3075](https://github.com/n8n-io/n8n/issues/3075) +* **FTP Node:** Add option to recursively create directories on rename ([#3001](https://github.com/n8n-io/n8n/issues/3001)) ([39a6f41](https://github.com/n8n-io/n8n/commit/39a6f417203b76cfa2c68816c49e86dc7236aba4)) +* **Mautic Node:** Add credential test and allow trailing slash in host ([#3080](https://github.com/n8n-io/n8n/issues/3080)) ([0a75539](https://github.com/n8n-io/n8n/commit/0a75539cc3d696a8946d7db5ff5842ff54835134)) +* **Microsoft Teams Node:** Add chat message support ([#2635](https://github.com/n8n-io/n8n/issues/2635)) ([984f62d](https://github.com/n8n-io/n8n/commit/984f62df9ed92cdf297b3b56300c9f23bf128d2d)) +* **Mocean Node:** Add "Delivery Report URL" option and credential tests ([#3075](https://github.com/n8n-io/n8n/issues/3075)) ([c89d2b1](https://github.com/n8n-io/n8n/commit/c89d2b10f2461ff8e90209b8f29c222f9430dba5)) +* **ServiceNow Node:** Add basicAuth support and fix getColumns loadOptions ([#2712](https://github.com/n8n-io/n8n/issues/2712)) ([2c72584](https://github.com/n8n-io/n8n/commit/2c72584b55521b437baa20ddad7c919807fd9f8f)), closes [#2741](https://github.com/n8n-io/n8n/issues/2741) [#3075](https://github.com/n8n-io/n8n/issues/3075) [#3000](https://github.com/n8n-io/n8n/issues/3000) [#3065](https://github.com/n8n-io/n8n/issues/3065) [#2741](https://github.com/n8n-io/n8n/issues/2741) [#3075](https://github.com/n8n-io/n8n/issues/3075) [#3071](https://github.com/n8n-io/n8n/issues/3071) [#3001](https://github.com/n8n-io/n8n/issues/3001) [#2635](https://github.com/n8n-io/n8n/issues/2635) [#3080](https://github.com/n8n-io/n8n/issues/3080) [#3061](https://github.com/n8n-io/n8n/issues/3061) [#3081](https://github.com/n8n-io/n8n/issues/3081) [#2582](https://github.com/n8n-io/n8n/issues/2582) [#2212](https://github.com/n8n-io/n8n/issues/2212) +* **Strava Node:** Add "Get Streams" operation ([#2582](https://github.com/n8n-io/n8n/issues/2582)) ([6bbb4df](https://github.com/n8n-io/n8n/commit/6bbb4df05925362404f844a23a695f186d27b72e)) + + + # [0.170.0](https://github.com/n8n-io/n8n/compare/n8n@0.169.0...n8n@0.170.0) (2022-03-27) ### Bug Fixes diff --git a/package-lock.json b/package-lock.json index 1ac4898beb..d015e3bc59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -174,7 +174,7 @@ "markdown-it-link-attributes": "^4.0.0", "markdown-it-task-lists": "^2.1.1", "mime-types": "^2.1.27", - "moment": "2.29.1", + "moment": "~2.29.2", "moment-timezone": "^0.5.28", "monaco-editor": "^0.29.1", "monaco-editor-webpack-plugin": "^5.0.0", @@ -213,7 +213,7 @@ "rss-parser": "^3.7.0", "sass": "^1.26.5", "sass-loader": "^8.0.2", - "simple-git": "^2.36.2", + "simple-git": "^3.5.0", "snowflake-sdk": "^1.5.3", "source-map-support": "^0.5.9", "sqlite3": "^5.0.2", @@ -231,7 +231,7 @@ "tslib": "1.14.1", "tslint": "^6.1.2", "typeorm": "0.2.30", - "typescript": "~4.3.5", + "typescript": "~4.6.0", "uuid": "^8.3.2", "v-click-outside": "^3.1.2", "validator": "13.7.0", @@ -535,24 +535,24 @@ } }, "node_modules/@babel/core": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz", - "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.9.tgz", + "integrity": "sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==", "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.7", + "@babel/generator": "^7.17.9", "@babel/helper-compilation-targets": "^7.17.7", "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.8", - "@babel/parser": "^7.17.8", + "@babel/helpers": "^7.17.9", + "@babel/parser": "^7.17.9", "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", + "@babel/traverse": "^7.17.9", "@babel/types": "^7.17.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", + "json5": "^2.2.1", "semver": "^6.3.0" }, "engines": { @@ -564,9 +564,9 @@ } }, "node_modules/@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz", + "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==", "dependencies": { "@babel/types": "^7.17.0", "jsesc": "^2.5.1", @@ -617,14 +617,14 @@ } }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz", - "integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.9.tgz", + "integrity": "sha512-kUjip3gruz6AJKOq5i3nC6CoCEEF/oHH3cp6tOZhB+IyyyPyW0g1Gfsxn3mkk6S08pIA2y8GQh609v9G/5sHVQ==", "dependencies": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-member-expression-to-functions": "^7.17.7", "@babel/helper-optimise-call-expression": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7" @@ -692,24 +692,12 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", "dependencies": { - "@babel/helper-get-function-arity": "^7.16.7", "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "dependencies": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.17.0" }, "engines": { "node": ">=6.9.0" @@ -877,12 +865,12 @@ } }, "node_modules/@babel/helpers": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.8.tgz", - "integrity": "sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", + "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", "dependencies": { "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", + "@babel/traverse": "^7.17.9", "@babel/types": "^7.17.0" }, "engines": { @@ -890,9 +878,9 @@ } }, "node_modules/@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", @@ -903,9 +891,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz", - "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -991,13 +979,14 @@ } }, "node_modules/@babel/plugin-proposal-decorators": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.8.tgz", - "integrity": "sha512-U69odN4Umyyx1xO1rTII0IDkAEC+RNlcKXtqOblfpzqy1C+aOplb76BQNq0+XdpVkOaPlpEDwd++joY8FNFJKA==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.9.tgz", + "integrity": "sha512-EfH2LZ/vPa2wuPwJ26j+kYRkaubf89UlwxKXtxqEm57HrgSEYDB8t4swFP+p8LcI9yiP9ZRJJjo/58hS6BnaDA==", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.17.6", + "@babel/helper-create-class-features-plugin": "^7.17.9", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", "@babel/plugin-syntax-decorators": "^7.17.0", "charcodes": "^0.2.0" }, @@ -1705,9 +1694,9 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.7.tgz", - "integrity": "sha512-ITPmR2V7MqioMJyrxUo2onHNC3e+MvfFiFIR0RP21d3PtlVb6sfzoxNKiphSZUOM9hEIdzCcZe83ieX3yoqjUA==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.9.tgz", + "integrity": "sha512-2TBFd/r2I6VlYn0YRTz2JdazS+FoUuQ2rIFHoAxtyP/0G3D82SBLaRq9rnUkpqlLg03Byfl/+M32mpxjO6KaPw==", "dependencies": { "@babel/helper-module-transforms": "^7.17.7", "@babel/helper-plugin-utils": "^7.16.7", @@ -1887,11 +1876,11 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", - "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.17.9.tgz", + "integrity": "sha512-Lc2TfbxR1HOyn/c6b4Y/b6NHoTb67n/IoWLxTu4kC7h4KQnWlhCq2S8Tx0t2SVvv5Uu87Hs+6JEJ5kt2tYGylQ==", "dependencies": { - "regenerator-transform": "^0.14.2" + "regenerator-transform": "^0.15.0" }, "engines": { "node": ">=6.9.0" @@ -2221,9 +2210,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.8.tgz", - "integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", + "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", "dependencies": { "regenerator-runtime": "^0.13.4" }, @@ -2245,17 +2234,17 @@ } }, "node_modules/@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz", + "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==", "dependencies": { "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", + "@babel/generator": "^7.17.9", "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", "@babel/helper-hoist-variables": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", + "@babel/parser": "^7.17.9", "@babel/types": "^7.17.0", "debug": "^4.1.0", "globals": "^11.1.0" @@ -9256,9 +9245,9 @@ } }, "node_modules/@lerna/prompt/node_modules/string-width/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, "engines": { "node": ">=4" @@ -10835,35 +10824,27 @@ } }, "node_modules/@npmcli/fs/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@npmcli/fs/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/@npmcli/move-file": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", @@ -10907,35 +10888,27 @@ } }, "node_modules/@oclif/command/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/@oclif/command/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@oclif/command/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/@oclif/config": { "version": "1.18.3", "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.3.tgz", @@ -11474,17 +11447,17 @@ } }, "node_modules/@opentelemetry/api": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.1.0.tgz", - "integrity": "sha512-hf+3bwuBwtXsugA2ULBc95qxrOqP2pOekLz34BJhcAKawt94vfeNyUKpYc0lZQ/3sCP6LqRa7UAdHA7i5UODzQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.0.4.tgz", + "integrity": "sha512-BuJuXRSJNQ3QoKA6GWWDyuLpOUck+9hAXNMCnrloc1aWVoy6Xq6t9PUV08aBZ4Lutqq2LEHM486bpZqoViScog==", "engines": { "node": ">=8.0.0" } }, "node_modules/@popperjs/core": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.4.tgz", - "integrity": "sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg==", + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", + "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==", "funding": { "type": "opencollective", "url": "https://opencollective.com/popperjs" @@ -11636,16 +11609,16 @@ "integrity": "sha512-/5O7Fq6Vnv8L6ucmPjaWbVG1XkP4FO+w5glqfkIsq3Xw4oyNAdJddbnYodNDAfjVUvo/rrSCTom4kAND7T1o5Q==" }, "node_modules/@storybook/addon-actions": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.4.19.tgz", - "integrity": "sha512-GpSvP8xV8GfNkmtGJjfCgaOx6mbjtyTK0aT9FqX9pU0s+KVMmoCTrBh43b7dWrwxxas01yleBK9VpYggzhi/Fw==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.4.21.tgz", + "integrity": "sha512-rqEsAHwywZZv9Zzv6A/QXNLiosKY6S+JAEoT9VSeDW07d/MvH7FKoF7fQCnm3ZR53et9AazBJttoiyODZsbjxA==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/theming": "6.4.19", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", "global": "^4.4.0", @@ -11677,17 +11650,17 @@ } }, "node_modules/@storybook/addon-backgrounds": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-6.4.19.tgz", - "integrity": "sha512-yn8MTE7lctO48Rdw+DmmA1wKdf5eyAbA/vrug5ske/U2WPgGc65sApzwT8BItZfuyAMjuT5RnCWwd7o6hGRgGQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-6.4.21.tgz", + "integrity": "sha512-W7FTIBdztuj3zwQX6c+YdnQQqqk5JrWGJ+OwMIRusG7uPOLeADLVHNwC19avytWuK5xsioawzsj7ZB/Od+z9aA==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/theming": "6.4.19", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "global": "^4.4.0", "memoizerific": "^1.11.3", @@ -11713,19 +11686,19 @@ } }, "node_modules/@storybook/addon-controls": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-6.4.19.tgz", - "integrity": "sha512-JHi5z9i6NsgQLfG5WOeQE1AyOrM+QJLrjT+uOYx40bq+OC1yWHH7qHiphPP8kjJJhCZlaQk1qqXYkkQXgaeHSw==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-6.4.21.tgz", + "integrity": "sha512-lrBmFB/Zog41rIKOohYXmA6yjeust5AtO+ZK02iqQZVCSMfYF9FXN7XRsnd0wv4WbFgPtQbLyWRWerb+IPOvBw==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-common": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-common": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/node-logger": "6.4.19", - "@storybook/store": "6.4.19", - "@storybook/theming": "6.4.19", + "@storybook/node-logger": "6.4.21", + "@storybook/store": "6.4.21", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "lodash": "^4.17.21", "ts-dedent": "^2.0.0" @@ -11748,9 +11721,9 @@ } }, "node_modules/@storybook/addon-docs": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-6.4.19.tgz", - "integrity": "sha512-OEPyx/5ZXmZOPqIAWoPjlIP8Q/YfNjAmBosA8tmA8t5KCSiq/vpLcAvQhxqK6n0wk/B8Xp67Z8RpLfXjU8R3tw==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-6.4.21.tgz", + "integrity": "sha512-yaj6f5wHUwju1mq3sAs1CuP01EJ3jwJ5awes/1oH6T3FSumphhECzyMeSWbNheQU/9wGVwMdPRPSjuNumTMOrQ==", "dependencies": { "@babel/core": "^7.12.10", "@babel/generator": "^7.12.11", @@ -11761,21 +11734,21 @@ "@mdx-js/loader": "^1.6.22", "@mdx-js/mdx": "^1.6.22", "@mdx-js/react": "^1.6.22", - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/builder-webpack4": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/builder-webpack4": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/csf-tools": "6.4.19", - "@storybook/node-logger": "6.4.19", - "@storybook/postinstall": "6.4.19", - "@storybook/preview-web": "6.4.19", - "@storybook/source-loader": "6.4.19", - "@storybook/store": "6.4.19", - "@storybook/theming": "6.4.19", + "@storybook/csf-tools": "6.4.21", + "@storybook/node-logger": "6.4.21", + "@storybook/postinstall": "6.4.21", + "@storybook/preview-web": "6.4.21", + "@storybook/source-loader": "6.4.21", + "@storybook/store": "6.4.21", + "@storybook/theming": "6.4.21", "acorn": "^7.4.1", "acorn-jsx": "^5.3.1", "acorn-walk": "^7.2.0", @@ -11804,12 +11777,12 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "@storybook/angular": "6.4.19", - "@storybook/html": "6.4.19", - "@storybook/react": "6.4.19", - "@storybook/vue": "6.4.19", - "@storybook/vue3": "6.4.19", - "@storybook/web-components": "6.4.19", + "@storybook/angular": "6.4.21", + "@storybook/html": "6.4.21", + "@storybook/react": "6.4.21", + "@storybook/vue": "6.4.21", + "@storybook/vue3": "6.4.21", + "@storybook/web-components": "6.4.21", "lit": "^2.0.0", "lit-html": "^1.4.1 || ^2.0.0", "react": "^16.8.0 || ^17.0.0", @@ -11876,21 +11849,21 @@ } }, "node_modules/@storybook/addon-essentials": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-6.4.19.tgz", - "integrity": "sha512-vbV8sjepMVEuwhTDBHjO3E6vXluG7RiEeozV1QVuS9lGhjQdvUPdZ9rDNUcP6WHhTdEkS/ffTMaGIy1v8oZd7g==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-6.4.21.tgz", + "integrity": "sha512-2vhbzSMAfQ2Trwrg7E+doWLHy++mhXtV+ksgezo7PATMCKnBK6ItUwGvL7fQzLtaz+JbLqx/tgI8spMCUod+BA==", "dependencies": { - "@storybook/addon-actions": "6.4.19", - "@storybook/addon-backgrounds": "6.4.19", - "@storybook/addon-controls": "6.4.19", - "@storybook/addon-docs": "6.4.19", - "@storybook/addon-measure": "6.4.19", - "@storybook/addon-outline": "6.4.19", - "@storybook/addon-toolbars": "6.4.19", - "@storybook/addon-viewport": "6.4.19", - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/node-logger": "6.4.19", + "@storybook/addon-actions": "6.4.21", + "@storybook/addon-backgrounds": "6.4.21", + "@storybook/addon-controls": "6.4.21", + "@storybook/addon-docs": "6.4.21", + "@storybook/addon-measure": "6.4.21", + "@storybook/addon-outline": "6.4.21", + "@storybook/addon-toolbars": "6.4.21", + "@storybook/addon-viewport": "6.4.21", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/node-logger": "6.4.21", "core-js": "^3.8.2", "regenerator-runtime": "^0.13.7", "ts-dedent": "^2.0.0" @@ -11901,8 +11874,8 @@ }, "peerDependencies": { "@babel/core": "^7.9.6", - "@storybook/vue": "6.4.19", - "@storybook/web-components": "6.4.19", + "@storybook/vue": "6.4.21", + "@storybook/web-components": "6.4.21", "babel-loader": "^8.0.0", "lit-html": "^1.4.1 || ^2.0.0-rc.3", "react": "^16.8.0 || ^17.0.0", @@ -11931,15 +11904,15 @@ } }, "node_modules/@storybook/addon-links": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.4.19.tgz", - "integrity": "sha512-ebFHYlGDQkHSmI5QEJb1NxGNToVOLgjKkxXUe+JXX7AfHvrWiXVrN/57aOtBPZzj4h2jRPRTZgwR5glhPIlfEQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.4.21.tgz", + "integrity": "sha512-KajbsVAmCLVSKsrPnUEsfWuD5V0lbNBAtdil0EiOqWZU0r3ch92aSMh6H13zfT+lEPlh0PVLKamHur1js1iXGQ==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/router": "6.4.19", + "@storybook/router": "6.4.21", "@types/qs": "^6.9.5", "core-js": "^3.8.2", "global": "^4.4.0", @@ -11966,15 +11939,15 @@ } }, "node_modules/@storybook/addon-measure": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-6.4.19.tgz", - "integrity": "sha512-PXeU0AlpnGEvnzBQ6snkzmlIpwE0ci8LdFtL1Vz1V1Xk5fbuETWYuEkPuk1oZ7L9igB9cfT32SyJlE5MC1iaGg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-6.4.21.tgz", + "integrity": "sha512-Gg+/os8erwwMkxqMnMeRtS7zrRBqPlWxYoXCdDEDqWe+sbJ8lbIXpJpBDC7PfVpotVYWuNETSxR3qAfJjWrBRg==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", "core-js": "^3.8.2", "global": "^4.4.0" @@ -11997,15 +11970,15 @@ } }, "node_modules/@storybook/addon-outline": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-6.4.19.tgz", - "integrity": "sha512-7ZDXo8qrms6dx0KRP9PInXIie82h5g9XCNrGOUdfZkQPvgofJVj0kNv6p+WOiGiaVfKPC5KMgIofqzBTFV+k6Q==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-6.4.21.tgz", + "integrity": "sha512-ADVnl3dOKkzdv32qkS63Fm37keellV98RrNbGDmE4xMiu55/srn/LfklTHRdbUwpKvVxf/44EQ0HXSNJBuWeDg==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -12030,14 +12003,14 @@ } }, "node_modules/@storybook/addon-toolbars": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-6.4.19.tgz", - "integrity": "sha512-2UtuX9yB1rD/CAZv1etnOnunfPTvsEKEg/J2HYMKE1lhenWC5muIUXvDXCXvwDC65WviPJ56nFNKaKK1Zz7JDg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-6.4.21.tgz", + "integrity": "sha512-eu1OkMy4slGsK1jYxfEydQXDW+/VnhBf9zf6JexUh9SVzIWswDzmtsoZ4L1ws/vw7EQcbBBXU4UIG/xy5qH8dA==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/theming": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "regenerator-runtime": "^0.13.7" }, @@ -12059,16 +12032,16 @@ } }, "node_modules/@storybook/addon-viewport": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-6.4.19.tgz", - "integrity": "sha512-T1hdImxbLj8suQSTbp6HSA1LLHOlqaNK5jjnqzEOoAxY0O8LNPXMJ2jKIeT2fPQ0v+tWGU3tbwf+3xFq0parVQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-6.4.21.tgz", + "integrity": "sha512-O+SarJuO+S3ZrGskgMDmDnDjZg+7spCE6zdOuv2OX2wB+OTnoka0P0OhwHsg14Lc5DOWn22rv4q91v6RqAx6Yg==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", - "@storybook/theming": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "global": "^4.4.0", "memoizerific": "^1.11.3", @@ -12093,17 +12066,17 @@ } }, "node_modules/@storybook/addons": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.4.19.tgz", - "integrity": "sha512-QNyRYhpqmHV8oJxxTBdkRlLSbDFhpBvfvMfIrIT1UXb/eemdBZTaCGVvXZ9UixoEEI7f8VwAQ44IvkU5B1509w==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.4.21.tgz", + "integrity": "sha512-TFLv4FyqP5SBOHEqE6tiW+2++HngkyQ2KRbHICC7khQgRqDkrwvrdKZwzF29igseglhSmftpZrBLXyWbA7q1vg==", "dependencies": { - "@storybook/api": "6.4.19", - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/api": "6.4.21", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/router": "6.4.19", - "@storybook/theming": "6.4.19", + "@storybook/router": "6.4.21", + "@storybook/theming": "6.4.21", "@types/webpack-env": "^1.16.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -12119,17 +12092,17 @@ } }, "node_modules/@storybook/api": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.4.19.tgz", - "integrity": "sha512-aDvea+NpQCBjpNp9YidO1Pr7fzzCp15FSdkG+2ihGQfv5raxrN+IIJnGUXecpe71nvlYiB+29UXBVK7AL0j51Q==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.4.21.tgz", + "integrity": "sha512-AULsLd7ew11IRCpzffyLFGl5cwt9BLMok33DcIlCyvXsiqLm4/OsbgM4sj6QqWVuxcFlWMQJHoRJyeFlULFvZA==", "dependencies": { - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/router": "6.4.19", + "@storybook/router": "6.4.21", "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.4.19", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", "global": "^4.4.0", @@ -12151,9 +12124,9 @@ } }, "node_modules/@storybook/builder-webpack4": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.4.19.tgz", - "integrity": "sha512-wxA6SMH11duc9D53aeVVBwrVRemFIoxHp/dOugkkg6ZZFAb4ZmWzf/ENc3vQIZdZpfNRi7IZIZEOfoHc994cmw==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.4.21.tgz", + "integrity": "sha512-tetK8iZJ/S7U1Hrvm9i5ejH/SKJ/UHJcZ+j1VrzQK15wuwalevYJGJI3Gk2NzqKE8rda4CXPK1ES3iGcS67eZw==", "dependencies": { "@babel/core": "^7.12.10", "@babel/plugin-proposal-class-properties": "^7.12.1", @@ -12176,22 +12149,22 @@ "@babel/preset-env": "^7.12.11", "@babel/preset-react": "^7.12.10", "@babel/preset-typescript": "^7.12.7", - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/channel-postmessage": "6.4.19", - "@storybook/channels": "6.4.19", - "@storybook/client-api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-common": "6.4.19", - "@storybook/core-events": "6.4.19", - "@storybook/node-logger": "6.4.19", - "@storybook/preview-web": "6.4.19", - "@storybook/router": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/channel-postmessage": "6.4.21", + "@storybook/channels": "6.4.21", + "@storybook/client-api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-common": "6.4.21", + "@storybook/core-events": "6.4.21", + "@storybook/node-logger": "6.4.21", + "@storybook/preview-web": "6.4.21", + "@storybook/router": "6.4.21", "@storybook/semver": "^7.3.2", - "@storybook/store": "6.4.19", - "@storybook/theming": "6.4.19", - "@storybook/ui": "6.4.19", + "@storybook/store": "6.4.21", + "@storybook/theming": "6.4.21", + "@storybook/ui": "6.4.21", "@types/node": "^14.0.10", "@types/webpack": "^4.41.26", "autoprefixer": "^9.8.6", @@ -12270,13 +12243,13 @@ } }, "node_modules/@storybook/channel-postmessage": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.4.19.tgz", - "integrity": "sha512-E5h/itFzQ/6M08LR4kqlgqqmeO3tmavI+nUAlZrkCrotpJFNMHE2i0PQHg0TkFJrRDpYcrwD+AjUW4IwdqrisQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.4.21.tgz", + "integrity": "sha512-9mYtc4khwALGA9m4oh2ssnIoyYyKs/q6CZ+luaxct5bd1AZ6iZGBW+qwPaE+g/jjJyLotcSA/1FVr3AiImlWIQ==", "dependencies": { - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "core-js": "^3.8.2", "global": "^4.4.0", "qs": "^6.10.0", @@ -12288,12 +12261,12 @@ } }, "node_modules/@storybook/channel-websocket": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.4.19.tgz", - "integrity": "sha512-cXKwQjIXttfdUyZlcHORelUmJ5nUKswsnCA/qy7IRWpZjD8yQJcNk1dYC+tTHDVqFgdRT89pL0hRRB1rlaaR8Q==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.4.21.tgz", + "integrity": "sha512-qsyxR0e9ErqyDuCLTh/bSTnBkuNmD1GfVXp7f+NpKoSyfTOYKkaqydOiYDwN0LIHMt4ml9v6NN/zQ/i3avI4jw==", "dependencies": { - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", "core-js": "^3.8.2", "global": "^4.4.0", "telejson": "^5.3.2" @@ -12304,9 +12277,9 @@ } }, "node_modules/@storybook/channels": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.4.19.tgz", - "integrity": "sha512-EwyoncFvTfmIlfsy8jTfayCxo2XchPkZk/9txipugWSmc057HdklMKPLOHWP0z5hLH0IbVIKXzdNISABm36jwQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.4.21.tgz", + "integrity": "sha512-qgy8z3Hp04Q4p+E/8V9MamYYJLW8z1uv1Z+rvosNkg+eAApPg+Qe08BSj59OAUwPLrr2vpBW7WZ/BYSieW1tUg==", "dependencies": { "core-js": "^3.8.2", "ts-dedent": "^2.0.0", @@ -12318,17 +12291,17 @@ } }, "node_modules/@storybook/client-api": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.4.19.tgz", - "integrity": "sha512-OCrT5Um3FDvZnimQKwWtwsaI+5agPwq2i8YiqlofrI/NPMKp0I7DEkCGwE5IRD1Q8BIKqHcMo5tTmfYi0AxyOg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.4.21.tgz", + "integrity": "sha512-qdxRdVQLO9A4KsQVT3o3Xj1PF3cSdasHz1mwuH8/l2p5Zce5vWKtNSUuxcSoI50P0A18FLntVMpgyM+8+bHxhQ==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/channel-postmessage": "6.4.19", - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/channel-postmessage": "6.4.21", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/store": "6.4.19", + "@storybook/store": "6.4.21", "@types/qs": "^6.9.5", "@types/webpack-env": "^1.16.0", "core-js": "^3.8.2", @@ -12353,9 +12326,9 @@ } }, "node_modules/@storybook/client-logger": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.4.19.tgz", - "integrity": "sha512-zmg/2wyc9W3uZrvxaW4BfHcr40J0v7AGslqYXk9H+ERLVwIvrR4NhxQFaS6uITjBENyRDxwzfU3Va634WcmdDQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.4.21.tgz", + "integrity": "sha512-XkVCQ5swyYDVh5U+87DGRBdC5utJBpVW7kU5P14TQKMnSc/yHbMcXWaA89K8WKDa/WGkGbc0bKi4WrUwHFg2FA==", "dependencies": { "core-js": "^3.8.2", "global": "^4.4.0" @@ -12366,14 +12339,14 @@ } }, "node_modules/@storybook/components": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.4.19.tgz", - "integrity": "sha512-q/0V37YAJA7CNc+wSiiefeM9+3XVk8ixBNylY36QCGJgIeGQ5/79vPyUe6K4lLmsQwpmZsIq1s1Ad5+VbboeOA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.4.21.tgz", + "integrity": "sha512-OnuAS/bMdLKdmkWtDNUxM9qSFCU3pcGWqXzasU3sjvibIcz3472xTFiwjW9UiHR7ipu/YQKALnIbyyjznGY4Kg==", "dependencies": { "@popperjs/core": "^2.6.0", - "@storybook/client-logger": "6.4.19", + "@storybook/client-logger": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/theming": "6.4.19", + "@storybook/theming": "6.4.21", "@types/color-convert": "^2.0.0", "@types/overlayscrollbars": "^1.12.0", "@types/react-syntax-highlighter": "11.0.5", @@ -12405,19 +12378,19 @@ } }, "node_modules/@storybook/core": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/core/-/core-6.4.19.tgz", - "integrity": "sha512-55LOQ/h/kf1jMhjN85t/pIEdIwWEG9yV7bdwv3niVvmoypCxyyjn9/QNK0RKYAeDSUtdm6FVoJ6k5CpxWz2d8w==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-6.4.21.tgz", + "integrity": "sha512-HNy3L/5stURU5CPyo4Gh/NHhgs6qgvNq82pOr9mhnr2chNOUTh/kaWjrR4k/Mnh8qzItYLs1tpIFKvhclHXAdw==", "dependencies": { - "@storybook/core-client": "6.4.19", - "@storybook/core-server": "6.4.19" + "@storybook/core-client": "6.4.21", + "@storybook/core-server": "6.4.21" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "@storybook/builder-webpack5": "6.4.19", + "@storybook/builder-webpack5": "6.4.21", "react": "^16.8.0 || ^17.0.0", "react-dom": "^16.8.0 || ^17.0.0", "webpack": "*" @@ -12432,20 +12405,20 @@ } }, "node_modules/@storybook/core-client": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.4.19.tgz", - "integrity": "sha512-rQHRZjhArPleE7/S8ZUolgzwY+hC0smSKX/3PQxO2GcebDjnJj6+iSV3h+aSMHMmTdoCQvjYw9aBpT8scuRe+A==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.4.21.tgz", + "integrity": "sha512-1zdfhL7ryP5xgcBNuaQplkiPIgPZ2OnIFA1gqun1xl9OBA7K2J115uZ2grQwS7hrhRBqsRIvMv1k9UmAYzXqiw==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/channel-postmessage": "6.4.19", - "@storybook/channel-websocket": "6.4.19", - "@storybook/client-api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/channel-postmessage": "6.4.21", + "@storybook/channel-websocket": "6.4.21", + "@storybook/client-api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/preview-web": "6.4.19", - "@storybook/store": "6.4.19", - "@storybook/ui": "6.4.19", + "@storybook/preview-web": "6.4.21", + "@storybook/store": "6.4.21", + "@storybook/ui": "6.4.21", "airbnb-js-shims": "^2.2.1", "ansi-to-html": "^0.6.11", "core-js": "^3.8.2", @@ -12473,9 +12446,9 @@ } }, "node_modules/@storybook/core-common": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.4.19.tgz", - "integrity": "sha512-X1pJJkO48DFxl6iyEemIKqRkJ7j9/cBh3BRBUr+xZHXBvnD0GKDXIocwh0PjSxSC6XSu3UCQnqtKi3PbjRl8Dg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.4.21.tgz", + "integrity": "sha512-apYT4CTRn0iR3DEf59Sc2i9L1WjbewmzYrmHTjNuygS7sjKxV8nppz60yvtLiHu4AWE+quXL3hen5yW9n9mnjw==", "dependencies": { "@babel/core": "^7.12.10", "@babel/plugin-proposal-class-properties": "^7.12.1", @@ -12498,7 +12471,7 @@ "@babel/preset-react": "^7.12.10", "@babel/preset-typescript": "^7.12.7", "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.4.19", + "@storybook/node-logger": "6.4.21", "@storybook/semver": "^7.3.2", "@types/node": "^14.0.10", "@types/pretty-hrtime": "^1.0.0", @@ -12630,9 +12603,9 @@ } }, "node_modules/@storybook/core-common/node_modules/fork-ts-checker-webpack-plugin": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz", - "integrity": "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.1.tgz", + "integrity": "sha512-x1wumpHOEf4gDROmKTaB6i4/Q6H3LwmjVO7fIX47vBwlZbtPjU33hgoMuD/Q/y6SU8bnuYSoN6ZQOLshGp0T/g==", "dependencies": { "@babel/code-frame": "^7.8.3", "@types/json-schema": "^7.0.5", @@ -12668,17 +12641,17 @@ } }, "node_modules/@storybook/core-common/node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@storybook/core-common/node_modules/fs-extra": { @@ -12715,14 +12688,11 @@ } }, "node_modules/@storybook/core-common/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/@storybook/core-common/node_modules/schema-utils": { @@ -12769,15 +12739,10 @@ "node": ">= 10.0.0" } }, - "node_modules/@storybook/core-common/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/@storybook/core-events": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.4.19.tgz", - "integrity": "sha512-KICzUw6XVQUJzFSCXfvhfHAuyhn4Q5J4IZEfuZkcGJS4ODkrO6tmpdYE5Cfr+so95Nfp0ErWiLUuodBsW9/rtA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.4.21.tgz", + "integrity": "sha512-K6b9M1zYvW/Kfb1cnH6JDfmFvTYDMx/ot9zdl9O5SPH9glUwzOXSk8qKu6GmZTiW2YnC2nKbjaN20mfMsCBPGw==", "dependencies": { "core-js": "^3.8.2" }, @@ -12787,21 +12752,21 @@ } }, "node_modules/@storybook/core-server": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.4.19.tgz", - "integrity": "sha512-bKsUB9f7hl5ya2JXxpIrErmbDQjoH39FVbzYZWjMo4t/b7+Xyi6vYadwyWcqlpUQmis09ZaSMv8L/Tw0TuwLAA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.4.21.tgz", + "integrity": "sha512-uOBrLKzERAJvGAtd9ieozoTjEu0Hnr7DnufppG4t14Yu61lcbsT3IzPeZDuFaM3tGjWlNgXIezZ2aBoxTMVokQ==", "dependencies": { "@discoveryjs/json-ext": "^0.5.3", - "@storybook/builder-webpack4": "6.4.19", - "@storybook/core-client": "6.4.19", - "@storybook/core-common": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/builder-webpack4": "6.4.21", + "@storybook/core-client": "6.4.21", + "@storybook/core-common": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/csf-tools": "6.4.19", - "@storybook/manager-webpack4": "6.4.19", - "@storybook/node-logger": "6.4.19", + "@storybook/csf-tools": "6.4.21", + "@storybook/manager-webpack4": "6.4.21", + "@storybook/node-logger": "6.4.21", "@storybook/semver": "^7.3.2", - "@storybook/store": "6.4.19", + "@storybook/store": "6.4.21", "@types/node": "^14.0.10", "@types/node-fetch": "^2.5.7", "@types/pretty-hrtime": "^1.0.0", @@ -12839,8 +12804,8 @@ "url": "https://opencollective.com/storybook" }, "peerDependencies": { - "@storybook/builder-webpack5": "6.4.19", - "@storybook/manager-webpack5": "6.4.19", + "@storybook/builder-webpack5": "6.4.21", + "@storybook/manager-webpack5": "6.4.21", "react": "^16.8.0 || ^17.0.0", "react-dom": "^16.8.0 || ^17.0.0" }, @@ -12946,9 +12911,9 @@ } }, "node_modules/@storybook/csf-tools": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.4.19.tgz", - "integrity": "sha512-gf/zRhGoAVsFwSyV2tc+jeJfZQkxF6QsaZgbUSe24/IUvGFCT/PS/jZq1qy7dECAwrTOfykgu8juyBtj6WhWyw==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.4.21.tgz", + "integrity": "sha512-Qt7NFEWkVaAWsy9sc0+0nLsi0k8UE+JjsR8Dit2Z/51ED7CMBJCl6nZKSU2vTnwDdRWwUj3d1a+zeKlozKsXYA==", "dependencies": { "@babel/core": "^7.12.10", "@babel/generator": "^7.12.11", @@ -13018,19 +12983,19 @@ } }, "node_modules/@storybook/manager-webpack4": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.4.19.tgz", - "integrity": "sha512-R8ugZjTYqXvlc6gDOcw909L65sIleOmIJLZR+N6/H85MivGXHu39jOwONqB7tVACufRty4FNecn8tEiQL2SAKA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.4.21.tgz", + "integrity": "sha512-JhcGU6KtmNQUfSNNgAWIKVKOaupx7+RYw3y6P0JN5km5nzqpipkeJzh+jdMqefJbIRV/psqKm/jpt/pPfaIHyQ==", "dependencies": { "@babel/core": "^7.12.10", "@babel/plugin-transform-template-literals": "^7.12.1", "@babel/preset-react": "^7.12.10", - "@storybook/addons": "6.4.19", - "@storybook/core-client": "6.4.19", - "@storybook/core-common": "6.4.19", - "@storybook/node-logger": "6.4.19", - "@storybook/theming": "6.4.19", - "@storybook/ui": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/core-client": "6.4.21", + "@storybook/core-common": "6.4.21", + "@storybook/node-logger": "6.4.21", + "@storybook/theming": "6.4.21", + "@storybook/ui": "6.4.21", "@types/node": "^14.0.10", "@types/webpack": "^4.41.26", "babel-loader": "^8.0.0", @@ -13155,9 +13120,9 @@ } }, "node_modules/@storybook/node-logger": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.4.19.tgz", - "integrity": "sha512-hO2Aar3PgPnPtNq2fVgiuGlqo3EEVR6TKVBXMq7foL3tN2k4BQFKLDHbm5qZQQntyYKurKsRUGKPJFPuI1ov/w==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.4.21.tgz", + "integrity": "sha512-iCQ6ToARy0Ri6oP3UPDGsiIqDKf/gsL3XwZ5iPj80HyuCdUwm2dB+e3/09gD7XkHNkY2//TxKOUxcAkorQRFUQ==", "dependencies": { "@types/npmlog": "^4.1.2", "chalk": "^4.1.0", @@ -13219,9 +13184,9 @@ } }, "node_modules/@storybook/postinstall": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-6.4.19.tgz", - "integrity": "sha512-/0tHHxyIV82zt1rw4BW70GmrQbDVu9IJPAxOqFzGjC1fNojwJ53mK6FfUsOzbhG5mWk5p0Ip5+zr74moP119AA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-6.4.21.tgz", + "integrity": "sha512-vuynjqEnjoRoe0E0jo27vJQ5JH2lRPAGR0lZMNvmw3EasWSA586eyJvEVTAte/z1wO9ZV2dTHbgAozv33N1Z2w==", "dependencies": { "core-js": "^3.8.2" }, @@ -13231,16 +13196,16 @@ } }, "node_modules/@storybook/preview-web": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.4.19.tgz", - "integrity": "sha512-jqltoBv5j7lvnxEfV9w8dLX9ASWGuvgz97yg8Yo5FqkftEwrHJenyvMGcTgDJKJPorF+wiz/9aIqnmd3LCAcZQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.4.21.tgz", + "integrity": "sha512-v0AS7rDbdcD3aw/1pY525EJ4jmgY5ntz9CqiLmBKVBgshjng7Cza8AVR8Kvhr+ppoP/v63w4sEdxIw7jYsO5rQ==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/channel-postmessage": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/channel-postmessage": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/store": "6.4.19", + "@storybook/store": "6.4.21", "ansi-to-html": "^0.6.11", "core-js": "^3.8.2", "global": "^4.4.0", @@ -13262,11 +13227,11 @@ } }, "node_modules/@storybook/router": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.4.19.tgz", - "integrity": "sha512-KWWwIzuyeEIWVezkCihwY2A76Il9tUNg0I410g9qT7NrEsKyqXGRYOijWub7c1GGyNjLqz0jtrrehtixMcJkuA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.4.21.tgz", + "integrity": "sha512-otn3xYc017SNebeA95xLQ7P6elfyu9541QteXbLR5gFvrT+MB/8zMRZrVuD7n1xwpBgazlonzAdODC736Be9jQ==", "dependencies": { - "@storybook/client-logger": "6.4.19", + "@storybook/client-logger": "6.4.21", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", "global": "^4.4.0", @@ -13351,12 +13316,12 @@ } }, "node_modules/@storybook/source-loader": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.4.19.tgz", - "integrity": "sha512-XqTsqddRglvfW7mhyjwoqd/B8L6samcBehhO0OEbsFp6FPWa9eXuObCxtRYIcjcSIe+ksbW3D/54ppEs1L/g1Q==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.4.21.tgz", + "integrity": "sha512-rRu3uWla1c73F5FKl7mdkIKcj+Of4jzIT7aHycS0j6rYKwbGpsptLgxbpMUaEdNHjSDyAzSM6Mj5XcnE5rC8nQ==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/client-logger": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/client-logger": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", "core-js": "^3.8.2", "estraverse": "^5.2.0", @@ -13387,13 +13352,13 @@ } }, "node_modules/@storybook/store": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/store/-/store-6.4.19.tgz", - "integrity": "sha512-N9/ZjemRHGfT3InPIbqQqc6snkcfnf3Qh9oOr0smbfaVGJol//KOX65kzzobtzFcid0WxtTDZ3HmgFVH+GvuhQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/store/-/store-6.4.21.tgz", + "integrity": "sha512-j0cMo3JUs6yGc1cJi29kkzZK2zCGmx03BCMtMflnqNnMVnhuIF2iOTnwj4z01keL8/7hosUAz0OJxhvIV0JHIg==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", @@ -13417,14 +13382,14 @@ } }, "node_modules/@storybook/theming": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.4.19.tgz", - "integrity": "sha512-V4pWmTvAxmbHR6B3jA4hPkaxZPyExHvCToy7b76DpUTpuHihijNDMAn85KhOQYIeL9q14zP/aiz899tOHsOidg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.4.21.tgz", + "integrity": "sha512-7pLNwmqbyqCeHXzjsacI69IdJcAZr6zoZA84iGqx+Na32OI8wtIpFczbwuYpVPN2jzgRYp23CgIv1Gz27yk/zw==", "dependencies": { "@emotion/core": "^10.1.1", "@emotion/is-prop-valid": "^0.8.6", "@emotion/styled": "^10.0.27", - "@storybook/client-logger": "6.4.19", + "@storybook/client-logger": "6.4.21", "core-js": "^3.8.2", "deep-object-diff": "^1.1.0", "emotion-theming": "^10.0.27", @@ -13444,20 +13409,20 @@ } }, "node_modules/@storybook/ui": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-6.4.19.tgz", - "integrity": "sha512-gFwdn5LA2U6oQ4bfUFLyHZnNasGQ01YVdwjbi+l6yjmnckBNtZfJoVTZ1rzGUbxSE9rK48InJRU+latTsr7xAg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-6.4.21.tgz", + "integrity": "sha512-jjEEFDm8PAzscn5dN+3YJap9033ce98YYC9FCQVF5sB41CIwI0PD5LUafxWbaxQdL+t/ZlRYXNz3FLNFHMwzcQ==", "dependencies": { "@emotion/core": "^10.1.1", - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", - "@storybook/router": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", + "@storybook/router": "6.4.21", "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.4.19", + "@storybook/theming": "6.4.21", "copy-to-clipboard": "^3.3.1", "core-js": "^3.8.2", "core-js-pure": "^3.8.2", @@ -13487,15 +13452,15 @@ } }, "node_modules/@storybook/vue": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/vue/-/vue-6.4.19.tgz", - "integrity": "sha512-Uqy2F7qIV90IQwhT7BCwDWWHwDvAgT2MFMripVmzUQfYfPoTsja54viDBS8i0uEc7R1qPrRA2CpofINKAuZM0A==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/vue/-/vue-6.4.21.tgz", + "integrity": "sha512-KR1uq1IBfZ6RT652Dl9HCg+QRJnDANF80/GOYwtryHmnERDJTizAvG02QOwxSgfHQf+ZmG9MxOZpAcSXGyjH7w==", "dependencies": { - "@storybook/addons": "6.4.19", - "@storybook/core": "6.4.19", - "@storybook/core-common": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/core": "6.4.21", + "@storybook/core-common": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/store": "6.4.19", + "@storybook/store": "6.4.21", "@types/webpack-env": "^1.16.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -13555,9 +13520,9 @@ } }, "node_modules/@types/aws4": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@types/aws4/-/aws4-1.11.1.tgz", - "integrity": "sha512-yUnPMlHP5JMZJiiNZElJG5qj1ShezlaET6Bug9SBhYsxKVamh7aOwl7Q/XR1Y//cZ5PoeRb9j4hi9svb2+FLlg==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@types/aws4/-/aws4-1.11.2.tgz", + "integrity": "sha512-x0f96eBPrCCJzJxdPbUvDFRva4yPpINJzTuXXpmS2j9qLUpF2nyGzvXPlRziuGbCsPukwY4JfuO+8xwsoZLzGw==", "dependencies": { "@types/node": "*" } @@ -13964,9 +13929,9 @@ "integrity": "sha512-3YxO7RHRrmtYNX6Rhkr97bnXHrF1Ckfo4axENWLcBXWi+8B1WsNbqPqe5Eg6TA5survjAWWvLTu1KQesuLHVgQ==" }, "node_modules/@types/lodash": { - "version": "4.14.180", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.180.tgz", - "integrity": "sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g==" + "version": "4.14.181", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.181.tgz", + "integrity": "sha512-n3tyKthHJbkiWhDZs3DkhkCzt2MexYHXlX0td5iMplyfwketaOeKboEVBqzceH7juqvEg3q5oUoBFxSLu7zFag==" }, "node_modules/@types/lodash.camelcase": { "version": "4.3.6", @@ -14201,9 +14166,9 @@ } }, "node_modules/@types/prettier": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz", - "integrity": "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==" + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==" }, "node_modules/@types/pretty-hrtime": { "version": "1.0.1", @@ -14227,9 +14192,9 @@ "integrity": "sha512-mqo6D4qdiJdzeqlzFwEIchQQZk2hZacjssmjoAX7nClcREmRUUsnmgbWXEfA2qK986rwOPqepfRoSu7rsjAKag==" }, "node_modules/@types/prop-types": { - "version": "15.7.4", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", - "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" }, "node_modules/@types/q": { "version": "1.5.5", @@ -14256,9 +14221,9 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "node_modules/@types/react": { - "version": "17.0.43", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.43.tgz", - "integrity": "sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A==", + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.1.tgz", + "integrity": "sha512-VnWlrVgG0dYt+NqlfMI0yUYb8Rdl4XUROyH+c6gq/iFCiZ805Vi//26UW38DHnxQkbDhnrIWTBiy6oKZqL11cw==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -14355,9 +14320,9 @@ "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==" }, "node_modules/@types/ssh2": { - "version": "0.5.51", - "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.51.tgz", - "integrity": "sha512-aIq7ownezauW/+VWYaeXwd5J1Evnn4EXyeKi7bT3H6ZLBLoqsmhdvkHYPLpnZPM6unKKKsxTHIyQAVOZnPiJBw==", + "version": "0.5.52", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.52.tgz", + "integrity": "sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg==", "dependencies": { "@types/node": "*", "@types/ssh2-streams": "*" @@ -14451,9 +14416,9 @@ } }, "node_modules/@types/uglify-js": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz", - "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==", + "version": "3.13.2", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.2.tgz", + "integrity": "sha512-/xFrPIo+4zOeNGtVMbf9rUm0N+i4pDf1ynExomqtokIJmVzR3962lJ1UE+MmexMkA0cmN9oTzg5Xcbwge0Ij2Q==", "dependencies": { "source-map": "^0.6.1" } @@ -14595,35 +14560,27 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/@typescript-eslint/experimental-utils": { "version": "4.33.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", @@ -14728,35 +14685,27 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/@typescript-eslint/visitor-keys": { "version": "4.33.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", @@ -17319,9 +17268,9 @@ } }, "node_modules/@vue/cli-plugin-unit-jest/node_modules/string-length/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "engines": { "node": ">=4" } @@ -19711,17 +19660,17 @@ } }, "node_modules/avsc": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/avsc/-/avsc-5.7.3.tgz", - "integrity": "sha512-uUbetCWczQHbsKyX1C99XpQHBM8SWfovvaZhPIj23/1uV7SQf0WeRZbiLpw0JZm+LHTChfNgrLfDJOVoU2kU+A==", + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/avsc/-/avsc-5.7.4.tgz", + "integrity": "sha512-z4oo33lmnvvNRqfUe3YjDGGpqu/L2+wXBIhMtwq6oqZ+exOUAkQYM6zd2VWKF7AIlajOF8ZZuPFfryTG9iLC/w==", "engines": { "node": ">=0.11" } }, "node_modules/aws-sdk": { - "version": "2.1101.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1101.0.tgz", - "integrity": "sha512-7lyVb7GXGl8yyu954Qxf6vU6MrcgFlmKyTLBVXJyo3Phn1OB+qOExA55WtSC6gQiQ7e5TeWOn1RUHLg30ywTBA==", + "version": "2.1111.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1111.0.tgz", + "integrity": "sha512-WRyNcCckzmu1djTAWfR2r+BuI/PbuLrhG3oa+oH39v4NZ4EecYWFL1CoCPlC2kRUML4maSba5T4zlxjcNl7ELQ==", "dependencies": { "buffer": "4.9.2", "events": "1.1.1", @@ -21341,23 +21290,26 @@ "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" }, "node_modules/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, "node_modules/body-parser-xml": { @@ -21395,17 +21347,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/bonjour": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", @@ -21832,35 +21773,27 @@ } }, "node_modules/bull/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/bull/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/bull/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/byline": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", @@ -22271,9 +22204,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001320", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", - "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==", + "version": "1.0.30001327", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001327.tgz", + "integrity": "sha512-1/Cg4jlD9qjZzhbzkzEaAC2JHsP0WrOc8Rd/3a3LuajGzGWR/hD7TVyvq99VqmTy99eVh8Zkmdq213OgvgXx7w==", "funding": [ { "type": "opencollective", @@ -22346,47 +22279,21 @@ } }, "node_modules/cfb": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.1.tgz", - "integrity": "sha512-wT2ScPAFGSVy7CY+aauMezZBnNrfnaLSrxHUHdea+Td/86vrk6ZquggV+ssBR88zNs0OnBkL2+lf9q0K+zVGzQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", "dependencies": { "adler-32": "~1.3.0", - "crc-32": "~1.2.0", - "printj": "~1.3.0" + "crc-32": "~1.2.0" }, "engines": { "node": ">=0.8" } }, "node_modules/cfb/node_modules/adler-32": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.0.tgz", - "integrity": "sha512-f5nltvjl+PRUh6YNfUstRaXwJxtfnKEWhAWWlmKvh+Y3J2+98a0KKVYDEhz6NdKGqswLhjNGznxfSsZGOvOd9g==", - "dependencies": { - "printj": "~1.2.2" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/cfb/node_modules/adler-32/node_modules/printj": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.2.3.tgz", - "integrity": "sha512-sanczS6xOJOg7IKDvi4sGOUOe7c1tsEzjwlLFH/zgwx/uyImVM9/rgBkc8AfiQa/Vg54nRd8mkm9yI7WV/O+WA==", - "bin": { - "printj": "bin/printj.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/cfb/node_modules/printj": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", - "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==", - "bin": { - "printj": "bin/printj.njs" - }, + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", "engines": { "node": ">=0.8" } @@ -22514,15 +22421,15 @@ } }, "node_modules/cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", + "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", "dependencies": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", + "css-select": "^4.3.0", + "css-what": "^6.0.1", "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" + "domhandler": "^4.3.1", + "domutils": "^2.8.0" }, "funding": { "url": "https://github.com/sponsors/fb55" @@ -22976,28 +22883,25 @@ } }, "node_modules/cli-ux/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/cli-ux/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/cli-ux/node_modules/supports-color": { @@ -23019,11 +22923,6 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, - "node_modules/cli-ux/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/cli-width": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", @@ -23335,6 +23234,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "optional": true, "engines": { "node": ">=0.1.90" } @@ -25125,9 +25025,9 @@ } }, "node_modules/cpu-features": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.3.tgz", - "integrity": "sha512-p6C/uud4F4bDyCz9+BNU22KdV1AGxPK6L9rQG9x3x4SSzdMPyBPErP7Rxn8avT2ex1M2g5Rpjz5Us/ri/766Qg==", + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.4.tgz", + "integrity": "sha512-fKiZ/zp1mUwQbnzb9IghXtHtDoTMtNeb8oYGx6kX2SYfhnG0HNdBEBIzB9b5KlXu5DQPhfy3mInbBxFcgwAr3A==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -25429,13 +25329,9 @@ } }, "node_modules/crc-32": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz", - "integrity": "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==", - "dependencies": { - "exit-on-epipe": "~1.0.1", - "printj": "~1.3.1" - }, + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", "bin": { "crc32": "bin/crc32.njs" }, @@ -25443,17 +25339,6 @@ "node": ">=0.8" } }, - "node_modules/crc-32/node_modules/printj": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", - "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==", - "bin": { - "printj": "bin/printj.njs" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/create-ecdh": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", @@ -25692,13 +25577,13 @@ } }, "node_modules/css-select": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", - "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", "dependencies": { "boolbase": "^1.0.0", - "css-what": "^5.1.0", - "domhandler": "^4.3.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", "domutils": "^2.8.0", "nth-check": "^2.0.1" }, @@ -25732,9 +25617,9 @@ } }, "node_modules/css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "engines": { "node": ">= 6" }, @@ -25990,9 +25875,9 @@ } }, "node_modules/d/node_modules/es5-ext": { - "version": "0.10.59", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.59.tgz", - "integrity": "sha512-cOgyhW0tIJyQY1Kfw6Kr0viu9ZlUctVchRMZ7R0HiH3dxTSp5zJDLecwxUqPUrGKMsgBI1wd1FL+d9Jxfi4cLw==", + "version": "0.10.60", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", + "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", "hasInstallScript": true, "dependencies": { "es6-iterator": "^2.0.3", @@ -26078,9 +25963,9 @@ "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=" }, "node_modules/deasync": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.24.tgz", - "integrity": "sha512-i98vg42xNfRZCymummMAN0rIcQ1gZFinSe3btvPIvy6JFTaeHcumeKybRo2HTv86nasfmT0nEgAn2ggLZhOCVA==", + "version": "0.1.26", + "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.26.tgz", + "integrity": "sha512-YKw0BmJSWxkjtQsbgn6Q9CHSWB7DKMen8vKrgyC006zy0UZ6nWyGidB0IzZgqkVRkOglAeUaFtiRTeLyel72bg==", "hasInstallScript": true, "dependencies": { "bindings": "^1.5.0", @@ -26472,11 +26357,11 @@ } }, "node_modules/depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", "engines": { - "node": ">= 0.6" + "node": ">= 0.8" } }, "node_modules/deprecation": { @@ -26495,9 +26380,13 @@ } }, "node_modules/destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } }, "node_modules/detab": { "version": "2.0.4", @@ -26582,9 +26471,10 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "node_modules/dezalgo": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, "dependencies": { "asap": "^2.0.0", "wrappy": "1" @@ -26719,9 +26609,9 @@ } }, "node_modules/dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", @@ -26746,9 +26636,9 @@ } }, "node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "funding": [ { "type": "github", @@ -27015,9 +26905,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.95", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.95.tgz", - "integrity": "sha512-h2VAMV/hPtmAeiDkwA8c5sjS+cWt6GlQL4ERdrOUWu7cRIG5IRk9uwR9f0utP+hPJ9ZZsADTq9HpbuT46eBYAg==" + "version": "1.4.106", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.106.tgz", + "integrity": "sha512-ZYfpVLULm67K7CaaGP7DmjyeMY4naxsbTy+syVVxT6QHI1Ww8XbJjmr9fDckrhq44WzCrcC5kH3zGpdusxwwqg==" }, "node_modules/element-resize-detector": { "version": "1.2.4", @@ -27238,9 +27128,9 @@ } }, "node_modules/es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.2.tgz", + "integrity": "sha512-gfSBJoZdlL2xRiOCy0g8gLMryhoe1TlimjzU99L/31Z8QEGIhVQI+EWwt5lT+AuU9SnorVupXFqqOGqGfsyO6w==", "dependencies": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", @@ -27248,15 +27138,15 @@ "get-intrinsic": "^1.1.1", "get-symbol-description": "^1.0.0", "has": "^1.0.3", - "has-symbols": "^1.0.2", + "has-symbols": "^1.0.3", "internal-slot": "^1.0.3", "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", + "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.1", "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -27336,9 +27226,9 @@ } }, "node_modules/es6-iterator/node_modules/es5-ext": { - "version": "0.10.59", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.59.tgz", - "integrity": "sha512-cOgyhW0tIJyQY1Kfw6Kr0viu9ZlUctVchRMZ7R0HiH3dxTSp5zJDLecwxUqPUrGKMsgBI1wd1FL+d9Jxfi4cLw==", + "version": "0.10.60", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", + "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", "hasInstallScript": true, "dependencies": { "es6-iterator": "^2.0.3", @@ -27390,9 +27280,9 @@ } }, "node_modules/es6-weak-map/node_modules/es5-ext": { - "version": "0.10.59", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.59.tgz", - "integrity": "sha512-cOgyhW0tIJyQY1Kfw6Kr0viu9ZlUctVchRMZ7R0HiH3dxTSp5zJDLecwxUqPUrGKMsgBI1wd1FL+d9Jxfi4cLw==", + "version": "0.10.60", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", + "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", "hasInstallScript": true, "dependencies": { "es6-iterator": "^2.0.3", @@ -27794,23 +27684,23 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.25.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", - "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", + "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", "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.2", + "eslint-module-utils": "^2.7.3", "has": "^1.0.3", - "is-core-module": "^2.8.0", + "is-core-module": "^2.8.1", "is-glob": "^4.0.3", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "object.values": "^1.1.5", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.12.0" + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" }, "engines": { "node": ">=4" @@ -28048,14 +27938,11 @@ } }, "node_modules/eslint/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/eslint/node_modules/optionator": { @@ -28075,17 +27962,17 @@ } }, "node_modules/eslint/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/eslint/node_modules/supports-color": { @@ -28099,11 +27986,6 @@ "node": ">=8" } }, - "node_modules/eslint/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/espree": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", @@ -28597,6 +28479,26 @@ "node": ">= 0.10.0" } }, + "node_modules/express/node_modules/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/express/node_modules/cookie": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", @@ -28613,11 +28515,56 @@ "ms": "2.0.0" } }, + "node_modules/express/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/express/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/express/node_modules/qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", @@ -28629,6 +28576,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/express/node_modules/raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/ext": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", @@ -29069,6 +29030,17 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/finalhandler/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/find-babel-config": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/find-babel-config/-/find-babel-config-1.2.0.tgz", @@ -29409,9 +29381,9 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" }, "node_modules/flow-parser": { - "version": "0.174.1", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.174.1.tgz", - "integrity": "sha512-nDMOvlFR+4doLpB3OJpseHZ7uEr3ENptlF6qMas/kzQmNcLzMwfQeFX0gGJ/+em7UdldB/nGsk55tDTOvjbCuw==", + "version": "0.175.1", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.175.1.tgz", + "integrity": "sha512-gYes5/nxeLYiu02MMb+WH4KaOIYrVcTVIuV9M4aP/4hqJ+zULxxS/In+WEj/tEBsQ+8/wSHo9IDWKQL1FhrLmA==", "engines": { "node": ">=0.4.0" } @@ -29631,15 +29603,12 @@ } }, "node_modules/fork-ts-checker-webpack-plugin-v5/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/fork-ts-checker-webpack-plugin-v5/node_modules/schema-utils": { @@ -29661,18 +29630,18 @@ } }, "node_modules/fork-ts-checker-webpack-plugin-v5/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "optional": true, "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/fork-ts-checker-webpack-plugin-v5/node_modules/supports-color": { @@ -29705,12 +29674,6 @@ "node": ">= 10.0.0" } }, - "node_modules/fork-ts-checker-webpack-plugin-v5/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true - }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -31875,9 +31838,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/growly": { "version": "1.3.0", @@ -32379,9 +32342,9 @@ } }, "node_modules/gulp-dart-sass/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "engines": { "node": ">=4" } @@ -33131,11 +33094,14 @@ "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=" }, "node_modules/html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/html-to-text": { @@ -33306,18 +33272,26 @@ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" }, "node_modules/http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "dependencies": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" } }, "node_modules/http-parser-js": { @@ -34348,9 +34322,9 @@ } }, "node_modules/is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -34504,9 +34478,12 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -38183,28 +38160,25 @@ } }, "node_modules/jest-snapshot/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/jest-snapshot/node_modules/source-map": { @@ -38226,11 +38200,6 @@ "node": ">=8" } }, - "node_modules/jest-snapshot/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/jest-transform-stub": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/jest-transform-stub/-/jest-transform-stub-2.0.0.tgz", @@ -38735,9 +38704,9 @@ } }, "node_modules/jest-watch-typeahead/node_modules/jest-watcher/node_modules/ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "engines": { "node": ">=4" } @@ -39000,11 +38969,11 @@ "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==" }, "node_modules/js-beautify": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.0.tgz", - "integrity": "sha512-yuck9KirNSCAwyNJbqW+BxJqJ0NLJ4PwBUzQQACl5O3qHMBXVkXb/rD0ilh/Lat/tn88zSZ+CAHOlk0DsY7GuQ==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.3.tgz", + "integrity": "sha512-f1ra8PHtOEu/70EBnmiUlV8nJePS58y9qKjl4JHfYWlFH6bo7ogZBz//FAZp7jDuXtYnGYKymZPlrg2I/9Zo4g==", "dependencies": { - "config-chain": "^1.1.12", + "config-chain": "^1.1.13", "editorconfig": "^0.15.3", "glob": "^7.1.3", "nopt": "^5.0.0" @@ -39081,31 +39050,49 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "node_modules/jscodeshift": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.7.1.tgz", - "integrity": "sha512-YMkZSyoc8zg5woZL23cmWlnFLPH/mHilonGA7Qbzs7H6M4v4PH0Qsn4jeDyw+CHhVoAnm9UxQyB0Yw1OT+mktA==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.13.1.tgz", + "integrity": "sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ==", "dependencies": { - "@babel/core": "^7.1.6", - "@babel/parser": "^7.1.6", - "@babel/plugin-proposal-class-properties": "^7.1.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/preset-env": "^7.1.6", - "@babel/preset-flow": "^7.0.0", - "@babel/preset-typescript": "^7.1.0", - "@babel/register": "^7.0.0", + "@babel/core": "^7.13.16", + "@babel/parser": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/preset-flow": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/register": "^7.13.16", "babel-core": "^7.0.0-bridge.0", - "colors": "^1.1.2", + "chalk": "^4.1.2", "flow-parser": "0.*", - "graceful-fs": "^4.1.11", + "graceful-fs": "^4.2.4", "micromatch": "^3.1.10", "neo-async": "^2.5.0", "node-dir": "^0.1.17", - "recast": "^0.18.1", - "temp": "^0.8.1", + "recast": "^0.20.4", + "temp": "^0.8.4", "write-file-atomic": "^2.3.0" }, "bin": { "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/jscodeshift/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/jscodeshift/node_modules/arr-diff": { @@ -39116,14 +39103,6 @@ "node": ">=0.10.0" } }, - "node_modules/jscodeshift/node_modules/ast-types": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.3.tgz", - "integrity": "sha512-XTZ7xGML849LkQP86sWdQzfhwbt3YwIO6MqbX9mUNYY98VKaaVZP7YNNm70IpwecbkkxmfC5IYAzOQ/2p29zRA==", - "engines": { - "node": ">=4" - } - }, "node_modules/jscodeshift/node_modules/braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", @@ -39163,6 +39142,21 @@ "node": ">=0.10.0" } }, + "node_modules/jscodeshift/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, "node_modules/jscodeshift/node_modules/extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", @@ -39208,6 +39202,14 @@ "node": ">=0.10.0" } }, + "node_modules/jscodeshift/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/jscodeshift/node_modules/is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -39253,26 +39255,15 @@ "node": ">=0.10.0" } }, - "node_modules/jscodeshift/node_modules/recast": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.18.10.tgz", - "integrity": "sha512-XNvYvkfdAN9QewbrxeTOjgINkdY/odTgTS56ZNEWL9Ml0weT4T3sFtvnTuF+Gxyu46ANcRm1ntrF6F5LAJPAaQ==", + "node_modules/jscodeshift/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dependencies": { - "ast-types": "0.13.3", - "esprima": "~4.0.0", - "private": "^0.1.8", - "source-map": "~0.6.1" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 4" - } - }, - "node_modules/jscodeshift/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, "node_modules/jscodeshift/node_modules/to-regex-range": { @@ -39424,9 +39415,9 @@ } }, "node_modules/jshint/node_modules/dom-serializer/node_modules/domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "funding": [ { "type": "github", @@ -41922,9 +41913,9 @@ } }, "node_modules/moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==", + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.2.tgz", + "integrity": "sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==", "engines": { "node": "*" } @@ -42321,9 +42312,9 @@ "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" }, "node_modules/nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.2.tgz", + "integrity": "sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -42470,9 +42461,9 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/nested-error-stacks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", - "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz", + "integrity": "sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==" }, "node_modules/next-tick": { "version": "1.1.0", @@ -42867,35 +42858,27 @@ } }, "node_modules/node-notifier/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/node-notifier/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/node-notifier/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/node-pre-gyp": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", @@ -43407,17 +43390,25 @@ } }, "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/normalize-package-data/node_modules/semver/node_modules/lru-cache": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", + "engines": { + "node": ">=12" } }, "node_modules/normalize-package-data/node_modules/yallist": { @@ -43978,9 +43969,9 @@ "dev": true }, "node_modules/on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "dependencies": { "ee-first": "1.1.1" }, @@ -45336,11 +45327,11 @@ } }, "node_modules/polished": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.1.4.tgz", - "integrity": "sha512-Nq5Mbza+Auo7N3sQb1QMFaQiDO+4UexWuSGR7Cjb4Sw11SZIJcrrFtiZ+L0jT9MBsUsxDboHVASbCLbE1rnECg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", + "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", "dependencies": { - "@babel/runtime": "^7.16.7" + "@babel/runtime": "^7.17.8" }, "engines": { "node": ">=10" @@ -45687,14 +45678,11 @@ } }, "node_modules/postcss-loader/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/postcss-loader/node_modules/schema-utils": { @@ -45715,24 +45703,19 @@ } }, "node_modules/postcss-loader/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/postcss-loader/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/postcss-merge-longhand": { "version": "4.0.11", "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", @@ -46166,9 +46149,9 @@ "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==" }, "node_modules/postcss-selector-parser": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", - "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -46273,9 +46256,9 @@ } }, "node_modules/prettier": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.1.tgz", - "integrity": "sha512-8UVbTBYGwN37Bs9LERmxCPjdvPxlEowx2urIL6urHzdb3SDq4B/Z6xLFCblrSnE4iKWcS6ziJ3aOYrc1kz/E2A==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==", "bin": { "prettier": "bin-prettier.js" }, @@ -46389,14 +46372,6 @@ "node": ">=6" } }, - "node_modules/private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -47352,12 +47327,12 @@ } }, "node_modules/raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "dependencies": { "bytes": "3.1.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -47572,9 +47547,9 @@ } }, "node_modules/react-router": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.2.tgz", - "integrity": "sha512-/MbxyLzd7Q7amp4gDOGaYvXwhEojkJD5BtExkuKmj39VEE0m3l/zipf6h2WIB2jyAO0lI6NGETh4RDcktRm4AQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz", + "integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==", "dependencies": { "history": "^5.2.0" }, @@ -47583,12 +47558,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.2.tgz", - "integrity": "sha512-AtYEsAST7bDD4dLSQHDnk/qxWLJdad5t1HFa1qJyUrCeGgEuCSw0VB/27ARbF9Fi/W5598ujvJOm3ujUCVzuYQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz", + "integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==", "dependencies": { "history": "^5.2.0", - "react-router": "6.2.2" + "react-router": "6.3.0" }, "peerDependencies": { "react": ">=16.8", @@ -48042,9 +48017,9 @@ "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "node_modules/regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", "dependencies": { "@babel/runtime": "^7.8.4" } @@ -48557,9 +48532,9 @@ } }, "node_modules/replace-in-file/node_modules/yargs": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.0.tgz", - "integrity": "sha512-WJudfrk81yWFSOkZYpAZx4Nt7V4xp7S/uJkX0CnxovMCt1wCE8LNftPpNuF9X/u9gN5nsD7ycYtRcDf2pL3UiA==", + "version": "17.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", + "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -49270,9 +49245,9 @@ } }, "node_modules/sass": { - "version": "1.49.9", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.9.tgz", - "integrity": "sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.50.0.tgz", + "integrity": "sha512-cLsD6MEZ5URXHStxApajEh7gW189kkjn4Rc8DQweMyF+o5HF5nfEz8QYLMlPsTOD88DknatTmBWkOcw5/LnJLQ==", "dependencies": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -49496,6 +49471,45 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/send/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "node_modules/send/node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/sentence-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", @@ -49574,6 +49588,14 @@ "ms": "2.0.0" } }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/serve-index/node_modules/http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", @@ -49769,13 +49791,13 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/simple-git": { - "version": "2.48.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.48.0.tgz", - "integrity": "sha512-z4qtrRuaAFJS4PUd0g+xy7aN4y+RvEt/QTJpR184lhJguBA1S/LsVlvE/CM95RsYMOFJG3NGGDjqFCzKU19S/A==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.6.0.tgz", + "integrity": "sha512-2e+4QhOVO59GeLsHgwSMKNrSKCnuACeA/gMNrLCYR8ID9qwm4hViVt4WsODcUGjx//KDv6GMLC6Hs/MeosgXxg==", "dependencies": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.3.2" + "debug": "^4.3.3" }, "funding": { "type": "github", @@ -50752,9 +50774,9 @@ } }, "node_modules/ssh2": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.8.0.tgz", - "integrity": "sha512-NVIRkIwJvWl+mcRozp+EBzHMVCcbDKBea64ToPdZEk43yAVGwmfqYZRPFRnnvGjsKC34wYCmiupTcKgCVNVNNg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.9.0.tgz", + "integrity": "sha512-rhhIZT0eMPvCBSOG8CpqZZ7gre2vgXaIqmb3Jb83t88rjsxIsFzDanqBJM9Ns8BmP1835A5IbQ199io4EUZwOA==", "hasInstallScript": true, "dependencies": { "asn1": "^0.2.4", @@ -50764,7 +50786,7 @@ "node": ">=10.16.0" }, "optionalDependencies": { - "cpu-features": "0.0.3", + "cpu-features": "~0.0.4", "nan": "^2.15.0" } }, @@ -51471,9 +51493,10 @@ } }, "node_modules/superagent": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.1.tgz", - "integrity": "sha512-CQ2weSS6M+doIwwYFoMatklhRbx6sVNdB99OEJ5czcP3cng76Ljqus694knFWgOj3RkrtxZqIgpe6vhe0J7QWQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.2.tgz", + "integrity": "sha512-o9/fP6dww7a4xmEF5a484o2rG34UUGo8ztDlv7vbCWuqPhpndMi0f7eXxdlryk5U12Kzy46nh8eNpLAJ93Alsg==", + "deprecated": "Deprecated due to bug in CI build https://github.com/visionmedia/superagent/pull/1677\\#issuecomment-1081361876", "dependencies": { "component-emitter": "^1.3.0", "cookiejar": "^2.1.3", @@ -51491,6 +51514,15 @@ "node": ">=6.4.0 <13 || >=14" } }, + "node_modules/superagent/node_modules/dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "node_modules/superagent/node_modules/formidable": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz", @@ -51517,14 +51549,11 @@ } }, "node_modules/superagent/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/superagent/node_modules/mime": { @@ -51552,24 +51581,19 @@ } }, "node_modules/superagent/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/superagent/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/supertest": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/supertest/-/supertest-6.2.2.tgz", @@ -51934,14 +51958,6 @@ "readable-stream": "^3.0.1" } }, - "node_modules/tedious/node_modules/depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "engines": { - "node": ">= 0.8" - } - }, "node_modules/tedious/node_modules/iconv-lite": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", @@ -53126,28 +53142,25 @@ } }, "node_modules/ts-jest/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/ts-jest/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/ts-jest/node_modules/supports-color": { @@ -53161,11 +53174,6 @@ "node": ">=8" } }, - "node_modules/ts-jest/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/ts-loader": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.3.0.tgz", @@ -53241,14 +53249,11 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "node_modules/ts-loader/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/ts-loader/node_modules/memory-fs": { @@ -53283,17 +53288,17 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/ts-loader/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/ts-loader/node_modules/string_decoder": { @@ -53323,11 +53328,6 @@ "node": ">=6" } }, - "node_modules/ts-loader/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/ts-map": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ts-map/-/ts-map-1.0.3.tgz", @@ -53686,9 +53686,9 @@ } }, "node_modules/typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -53703,9 +53703,9 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, "node_modules/uglify-js": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.3.tgz", - "integrity": "sha512-6iCVm2omGJbsu3JWac+p6kUiOpg3wFO2f8lIXjfEb8RrmLjzog1wTPMmwKB7swfzzqxj9YM+sGUM++u1qN4qJg==", + "version": "3.15.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.4.tgz", + "integrity": "sha512-vMOPGDuvXecPs34V74qDKk4iJ/SN4vL3Ow/23ixafENYvtrNvtbcgUeugTcUGRGsOF/5fU8/NYSL5Hyb3l1OJA==", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -54272,28 +54272,25 @@ } }, "node_modules/update-notifier/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/update-notifier/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "dependencies": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" }, "bin": { "semver": "bin/semver.js" }, "engines": { - "node": ">=10" + "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/update-notifier/node_modules/supports-color": { @@ -54307,11 +54304,6 @@ "node": ">=8" } }, - "node_modules/update-notifier/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/upper-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", @@ -54462,11 +54454,11 @@ } }, "node_modules/use-isomorphic-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz", - "integrity": "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==", "peerDependencies": { - "react": "^16.8.0 || ^17.0.0" + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@types/react": { @@ -54994,12 +54986,12 @@ "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" }, "node_modules/vue-docgen-loader": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/vue-docgen-loader/-/vue-docgen-loader-1.5.0.tgz", - "integrity": "sha512-LKZ8mxeIQ44uSUMTplnwOXbC4bO4E2vyZDTbn7/1QlVwJPEIjk3ahL0DA1m27IEw6YTlHOwtWS0PrHmDkFgyAg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/vue-docgen-loader/-/vue-docgen-loader-1.5.1.tgz", + "integrity": "sha512-coMmQYsg+fy18SVtBNU7/tztdqEyrneFfwQFLmx8O7jaJ11VZ//9tRWXlwGzJM07cPRwMHDKMlAdWrpuw3U46A==", "dependencies": { "clone": "^2.1.2", - "jscodeshift": "^0.7.0", + "jscodeshift": "^0.13.1", "loader-utils": "^1.2.3", "querystring": "^0.2.0" }, @@ -55093,9 +55085,9 @@ "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==" }, "node_modules/vue-i18n": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.27.0.tgz", - "integrity": "sha512-SX35iJHL5PJ4Gfh0Mo/q0shyHiI2V6Zkh51c+k8E9O1RKv5BQyYrCxRzpvPrsIOJEnLaeiovet3dsUB0e/kDzw==" + "version": "8.27.1", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.27.1.tgz", + "integrity": "sha512-lWrGm4F25qReJ7XxSnFVb2h3PfW54ldnM4C+YLBGGJ75+Myt/kj4hHSTKqsyDLamvNYpvINMicSOdW+7yuqgIQ==" }, "node_modules/vue-inbrowser-compiler-demi": { "version": "4.44.23", @@ -57224,9 +57216,9 @@ } }, "node_modules/winston": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.6.0.tgz", - "integrity": "sha512-9j8T75p+bcN6D00sF/zjFVmPp+t8KMPB1MzbbzYjeN9VWxdsYnTB40TkbNUEXAmILEfChMvAMgidlX64OG3p6w==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.7.2.tgz", + "integrity": "sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng==", "dependencies": { "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", @@ -58201,31 +58193,31 @@ "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==" }, "@babel/core": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz", - "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.9.tgz", + "integrity": "sha512-5ug+SfZCpDAkVp9SFIZAzlW18rlzsOcJGaetCjkySnrXXDUw9AR8cDUm1iByTmdWM6yxX6/zycaV76w3YTF2gw==", "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.7", + "@babel/generator": "^7.17.9", "@babel/helper-compilation-targets": "^7.17.7", "@babel/helper-module-transforms": "^7.17.7", - "@babel/helpers": "^7.17.8", - "@babel/parser": "^7.17.8", + "@babel/helpers": "^7.17.9", + "@babel/parser": "^7.17.9", "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", + "@babel/traverse": "^7.17.9", "@babel/types": "^7.17.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", + "json5": "^2.2.1", "semver": "^6.3.0" } }, "@babel/generator": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", - "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.9.tgz", + "integrity": "sha512-rAdDousTwxbIxbz5I7GEQ3lUip+xVCXooZNbsydCWs3xA7ZsYOv+CFRdzGxRX78BmQHu9B1Eso59AOZQOJDEdQ==", "requires": { "@babel/types": "^7.17.0", "jsesc": "^2.5.1", @@ -58261,14 +58253,14 @@ } }, "@babel/helper-create-class-features-plugin": { - "version": "7.17.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz", - "integrity": "sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.9.tgz", + "integrity": "sha512-kUjip3gruz6AJKOq5i3nC6CoCEEF/oHH3cp6tOZhB+IyyyPyW0g1Gfsxn3mkk6S08pIA2y8GQh609v9G/5sHVQ==", "requires": { "@babel/helper-annotate-as-pure": "^7.16.7", "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-member-expression-to-functions": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-member-expression-to-functions": "^7.17.7", "@babel/helper-optimise-call-expression": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7" @@ -58315,21 +58307,12 @@ } }, "@babel/helper-function-name": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz", - "integrity": "sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", "requires": { - "@babel/helper-get-function-arity": "^7.16.7", "@babel/template": "^7.16.7", - "@babel/types": "^7.16.7" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz", - "integrity": "sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==", - "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.17.0" } }, "@babel/helper-hoist-variables": { @@ -58452,19 +58435,19 @@ } }, "@babel/helpers": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.8.tgz", - "integrity": "sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", + "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", "requires": { "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.3", + "@babel/traverse": "^7.17.9", "@babel/types": "^7.17.0" } }, "@babel/highlight": { - "version": "7.16.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz", - "integrity": "sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", "requires": { "@babel/helper-validator-identifier": "^7.16.7", "chalk": "^2.0.0", @@ -58472,9 +58455,9 @@ } }, "@babel/parser": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz", - "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==" + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.9.tgz", + "integrity": "sha512-vqUSBLP8dQHFPdPi9bc5GK9vRkYHJ49fsZdtoJ8EQ8ibpwk5rPKfvNIwChB0KVXcIjcepEBBd2VHC5r9Gy8ueg==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.16.7", @@ -58524,13 +58507,14 @@ } }, "@babel/plugin-proposal-decorators": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.8.tgz", - "integrity": "sha512-U69odN4Umyyx1xO1rTII0IDkAEC+RNlcKXtqOblfpzqy1C+aOplb76BQNq0+XdpVkOaPlpEDwd++joY8FNFJKA==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.17.9.tgz", + "integrity": "sha512-EfH2LZ/vPa2wuPwJ26j+kYRkaubf89UlwxKXtxqEm57HrgSEYDB8t4swFP+p8LcI9yiP9ZRJJjo/58hS6BnaDA==", "requires": { - "@babel/helper-create-class-features-plugin": "^7.17.6", + "@babel/helper-create-class-features-plugin": "^7.17.9", "@babel/helper-plugin-utils": "^7.16.7", "@babel/helper-replace-supers": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", "@babel/plugin-syntax-decorators": "^7.17.0", "charcodes": "^0.2.0" } @@ -58971,9 +58955,9 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.17.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.7.tgz", - "integrity": "sha512-ITPmR2V7MqioMJyrxUo2onHNC3e+MvfFiFIR0RP21d3PtlVb6sfzoxNKiphSZUOM9hEIdzCcZe83ieX3yoqjUA==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.17.9.tgz", + "integrity": "sha512-2TBFd/r2I6VlYn0YRTz2JdazS+FoUuQ2rIFHoAxtyP/0G3D82SBLaRq9rnUkpqlLg03Byfl/+M32mpxjO6KaPw==", "requires": { "@babel/helper-module-transforms": "^7.17.7", "@babel/helper-plugin-utils": "^7.16.7", @@ -59081,11 +59065,11 @@ } }, "@babel/plugin-transform-regenerator": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz", - "integrity": "sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.17.9.tgz", + "integrity": "sha512-Lc2TfbxR1HOyn/c6b4Y/b6NHoTb67n/IoWLxTu4kC7h4KQnWlhCq2S8Tx0t2SVvv5Uu87Hs+6JEJ5kt2tYGylQ==", "requires": { - "regenerator-transform": "^0.14.2" + "regenerator-transform": "^0.15.0" } }, "@babel/plugin-transform-reserved-words": { @@ -59316,9 +59300,9 @@ } }, "@babel/runtime": { - "version": "7.17.8", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.8.tgz", - "integrity": "sha512-dQpEpK0O9o6lj6oPu0gRDbbnk+4LeHlNcBpspf6Olzt3GIX4P1lWF1gS+pHLDFlaJvbR6q7jCfQ08zA4QJBnmA==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz", + "integrity": "sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -59334,17 +59318,17 @@ } }, "@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.9.tgz", + "integrity": "sha512-PQO8sDIJ8SIwipTPiR71kJQCKQYB5NGImbOviK8K+kg5xkNSYXLBupuX9QhatFowrsvo9Hj8WgArg3W7ijNAQw==", "requires": { "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", + "@babel/generator": "^7.17.9", "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", "@babel/helper-hoist-variables": "^7.16.7", "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", + "@babel/parser": "^7.17.9", "@babel/types": "^7.17.0", "debug": "^4.1.0", "globals": "^11.1.0" @@ -65331,9 +65315,9 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true }, "strip-ansi": { @@ -66721,25 +66705,17 @@ }, "dependencies": { "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -66773,25 +66749,17 @@ }, "dependencies": { "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -67254,14 +67222,14 @@ } }, "@opentelemetry/api": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.1.0.tgz", - "integrity": "sha512-hf+3bwuBwtXsugA2ULBc95qxrOqP2pOekLz34BJhcAKawt94vfeNyUKpYc0lZQ/3sCP6LqRa7UAdHA7i5UODzQ==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.0.4.tgz", + "integrity": "sha512-BuJuXRSJNQ3QoKA6GWWDyuLpOUck+9hAXNMCnrloc1aWVoy6Xq6t9PUV08aBZ4Lutqq2LEHM486bpZqoViScog==" }, "@popperjs/core": { - "version": "2.11.4", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.4.tgz", - "integrity": "sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg==" + "version": "2.11.5", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.5.tgz", + "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==" }, "@rudderstack/rudder-sdk-node": { "version": "1.0.6", @@ -67381,16 +67349,16 @@ "integrity": "sha512-/5O7Fq6Vnv8L6ucmPjaWbVG1XkP4FO+w5glqfkIsq3Xw4oyNAdJddbnYodNDAfjVUvo/rrSCTom4kAND7T1o5Q==" }, "@storybook/addon-actions": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.4.19.tgz", - "integrity": "sha512-GpSvP8xV8GfNkmtGJjfCgaOx6mbjtyTK0aT9FqX9pU0s+KVMmoCTrBh43b7dWrwxxas01yleBK9VpYggzhi/Fw==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-6.4.21.tgz", + "integrity": "sha512-rqEsAHwywZZv9Zzv6A/QXNLiosKY6S+JAEoT9VSeDW07d/MvH7FKoF7fQCnm3ZR53et9AazBJttoiyODZsbjxA==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/theming": "6.4.19", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", "global": "^4.4.0", @@ -67406,17 +67374,17 @@ } }, "@storybook/addon-backgrounds": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-6.4.19.tgz", - "integrity": "sha512-yn8MTE7lctO48Rdw+DmmA1wKdf5eyAbA/vrug5ske/U2WPgGc65sApzwT8BItZfuyAMjuT5RnCWwd7o6hGRgGQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-6.4.21.tgz", + "integrity": "sha512-W7FTIBdztuj3zwQX6c+YdnQQqqk5JrWGJ+OwMIRusG7uPOLeADLVHNwC19avytWuK5xsioawzsj7ZB/Od+z9aA==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/theming": "6.4.19", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "global": "^4.4.0", "memoizerific": "^1.11.3", @@ -67426,28 +67394,28 @@ } }, "@storybook/addon-controls": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-6.4.19.tgz", - "integrity": "sha512-JHi5z9i6NsgQLfG5WOeQE1AyOrM+QJLrjT+uOYx40bq+OC1yWHH7qHiphPP8kjJJhCZlaQk1qqXYkkQXgaeHSw==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-6.4.21.tgz", + "integrity": "sha512-lrBmFB/Zog41rIKOohYXmA6yjeust5AtO+ZK02iqQZVCSMfYF9FXN7XRsnd0wv4WbFgPtQbLyWRWerb+IPOvBw==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-common": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-common": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/node-logger": "6.4.19", - "@storybook/store": "6.4.19", - "@storybook/theming": "6.4.19", + "@storybook/node-logger": "6.4.21", + "@storybook/store": "6.4.21", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "lodash": "^4.17.21", "ts-dedent": "^2.0.0" } }, "@storybook/addon-docs": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-6.4.19.tgz", - "integrity": "sha512-OEPyx/5ZXmZOPqIAWoPjlIP8Q/YfNjAmBosA8tmA8t5KCSiq/vpLcAvQhxqK6n0wk/B8Xp67Z8RpLfXjU8R3tw==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-6.4.21.tgz", + "integrity": "sha512-yaj6f5wHUwju1mq3sAs1CuP01EJ3jwJ5awes/1oH6T3FSumphhECzyMeSWbNheQU/9wGVwMdPRPSjuNumTMOrQ==", "requires": { "@babel/core": "^7.12.10", "@babel/generator": "^7.12.11", @@ -67458,21 +67426,21 @@ "@mdx-js/loader": "^1.6.22", "@mdx-js/mdx": "^1.6.22", "@mdx-js/react": "^1.6.22", - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/builder-webpack4": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/builder-webpack4": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/csf-tools": "6.4.19", - "@storybook/node-logger": "6.4.19", - "@storybook/postinstall": "6.4.19", - "@storybook/preview-web": "6.4.19", - "@storybook/source-loader": "6.4.19", - "@storybook/store": "6.4.19", - "@storybook/theming": "6.4.19", + "@storybook/csf-tools": "6.4.21", + "@storybook/node-logger": "6.4.21", + "@storybook/postinstall": "6.4.21", + "@storybook/preview-web": "6.4.21", + "@storybook/source-loader": "6.4.21", + "@storybook/store": "6.4.21", + "@storybook/theming": "6.4.21", "acorn": "^7.4.1", "acorn-jsx": "^5.3.1", "acorn-walk": "^7.2.0", @@ -67505,36 +67473,36 @@ } }, "@storybook/addon-essentials": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-6.4.19.tgz", - "integrity": "sha512-vbV8sjepMVEuwhTDBHjO3E6vXluG7RiEeozV1QVuS9lGhjQdvUPdZ9rDNUcP6WHhTdEkS/ffTMaGIy1v8oZd7g==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-6.4.21.tgz", + "integrity": "sha512-2vhbzSMAfQ2Trwrg7E+doWLHy++mhXtV+ksgezo7PATMCKnBK6ItUwGvL7fQzLtaz+JbLqx/tgI8spMCUod+BA==", "requires": { - "@storybook/addon-actions": "6.4.19", - "@storybook/addon-backgrounds": "6.4.19", - "@storybook/addon-controls": "6.4.19", - "@storybook/addon-docs": "6.4.19", - "@storybook/addon-measure": "6.4.19", - "@storybook/addon-outline": "6.4.19", - "@storybook/addon-toolbars": "6.4.19", - "@storybook/addon-viewport": "6.4.19", - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/node-logger": "6.4.19", + "@storybook/addon-actions": "6.4.21", + "@storybook/addon-backgrounds": "6.4.21", + "@storybook/addon-controls": "6.4.21", + "@storybook/addon-docs": "6.4.21", + "@storybook/addon-measure": "6.4.21", + "@storybook/addon-outline": "6.4.21", + "@storybook/addon-toolbars": "6.4.21", + "@storybook/addon-viewport": "6.4.21", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/node-logger": "6.4.21", "core-js": "^3.8.2", "regenerator-runtime": "^0.13.7", "ts-dedent": "^2.0.0" } }, "@storybook/addon-links": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.4.19.tgz", - "integrity": "sha512-ebFHYlGDQkHSmI5QEJb1NxGNToVOLgjKkxXUe+JXX7AfHvrWiXVrN/57aOtBPZzj4h2jRPRTZgwR5glhPIlfEQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-6.4.21.tgz", + "integrity": "sha512-KajbsVAmCLVSKsrPnUEsfWuD5V0lbNBAtdil0EiOqWZU0r3ch92aSMh6H13zfT+lEPlh0PVLKamHur1js1iXGQ==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/router": "6.4.19", + "@storybook/router": "6.4.21", "@types/qs": "^6.9.5", "core-js": "^3.8.2", "global": "^4.4.0", @@ -67545,30 +67513,30 @@ } }, "@storybook/addon-measure": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-6.4.19.tgz", - "integrity": "sha512-PXeU0AlpnGEvnzBQ6snkzmlIpwE0ci8LdFtL1Vz1V1Xk5fbuETWYuEkPuk1oZ7L9igB9cfT32SyJlE5MC1iaGg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-6.4.21.tgz", + "integrity": "sha512-Gg+/os8erwwMkxqMnMeRtS7zrRBqPlWxYoXCdDEDqWe+sbJ8lbIXpJpBDC7PfVpotVYWuNETSxR3qAfJjWrBRg==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", "core-js": "^3.8.2", "global": "^4.4.0" } }, "@storybook/addon-outline": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-6.4.19.tgz", - "integrity": "sha512-7ZDXo8qrms6dx0KRP9PInXIie82h5g9XCNrGOUdfZkQPvgofJVj0kNv6p+WOiGiaVfKPC5KMgIofqzBTFV+k6Q==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-6.4.21.tgz", + "integrity": "sha512-ADVnl3dOKkzdv32qkS63Fm37keellV98RrNbGDmE4xMiu55/srn/LfklTHRdbUwpKvVxf/44EQ0HXSNJBuWeDg==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -67577,29 +67545,29 @@ } }, "@storybook/addon-toolbars": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-6.4.19.tgz", - "integrity": "sha512-2UtuX9yB1rD/CAZv1etnOnunfPTvsEKEg/J2HYMKE1lhenWC5muIUXvDXCXvwDC65WviPJ56nFNKaKK1Zz7JDg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-6.4.21.tgz", + "integrity": "sha512-eu1OkMy4slGsK1jYxfEydQXDW+/VnhBf9zf6JexUh9SVzIWswDzmtsoZ4L1ws/vw7EQcbBBXU4UIG/xy5qH8dA==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/theming": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "regenerator-runtime": "^0.13.7" } }, "@storybook/addon-viewport": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-6.4.19.tgz", - "integrity": "sha512-T1hdImxbLj8suQSTbp6HSA1LLHOlqaNK5jjnqzEOoAxY0O8LNPXMJ2jKIeT2fPQ0v+tWGU3tbwf+3xFq0parVQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-6.4.21.tgz", + "integrity": "sha512-O+SarJuO+S3ZrGskgMDmDnDjZg+7spCE6zdOuv2OX2wB+OTnoka0P0OhwHsg14Lc5DOWn22rv4q91v6RqAx6Yg==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", - "@storybook/theming": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "global": "^4.4.0", "memoizerific": "^1.11.3", @@ -67608,17 +67576,17 @@ } }, "@storybook/addons": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.4.19.tgz", - "integrity": "sha512-QNyRYhpqmHV8oJxxTBdkRlLSbDFhpBvfvMfIrIT1UXb/eemdBZTaCGVvXZ9UixoEEI7f8VwAQ44IvkU5B1509w==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.4.21.tgz", + "integrity": "sha512-TFLv4FyqP5SBOHEqE6tiW+2++HngkyQ2KRbHICC7khQgRqDkrwvrdKZwzF29igseglhSmftpZrBLXyWbA7q1vg==", "requires": { - "@storybook/api": "6.4.19", - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/api": "6.4.21", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/router": "6.4.19", - "@storybook/theming": "6.4.19", + "@storybook/router": "6.4.21", + "@storybook/theming": "6.4.21", "@types/webpack-env": "^1.16.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -67626,17 +67594,17 @@ } }, "@storybook/api": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.4.19.tgz", - "integrity": "sha512-aDvea+NpQCBjpNp9YidO1Pr7fzzCp15FSdkG+2ihGQfv5raxrN+IIJnGUXecpe71nvlYiB+29UXBVK7AL0j51Q==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.4.21.tgz", + "integrity": "sha512-AULsLd7ew11IRCpzffyLFGl5cwt9BLMok33DcIlCyvXsiqLm4/OsbgM4sj6QqWVuxcFlWMQJHoRJyeFlULFvZA==", "requires": { - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/router": "6.4.19", + "@storybook/router": "6.4.21", "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.4.19", + "@storybook/theming": "6.4.21", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", "global": "^4.4.0", @@ -67650,9 +67618,9 @@ } }, "@storybook/builder-webpack4": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.4.19.tgz", - "integrity": "sha512-wxA6SMH11duc9D53aeVVBwrVRemFIoxHp/dOugkkg6ZZFAb4ZmWzf/ENc3vQIZdZpfNRi7IZIZEOfoHc994cmw==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack4/-/builder-webpack4-6.4.21.tgz", + "integrity": "sha512-tetK8iZJ/S7U1Hrvm9i5ejH/SKJ/UHJcZ+j1VrzQK15wuwalevYJGJI3Gk2NzqKE8rda4CXPK1ES3iGcS67eZw==", "requires": { "@babel/core": "^7.12.10", "@babel/plugin-proposal-class-properties": "^7.12.1", @@ -67675,22 +67643,22 @@ "@babel/preset-env": "^7.12.11", "@babel/preset-react": "^7.12.10", "@babel/preset-typescript": "^7.12.7", - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/channel-postmessage": "6.4.19", - "@storybook/channels": "6.4.19", - "@storybook/client-api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-common": "6.4.19", - "@storybook/core-events": "6.4.19", - "@storybook/node-logger": "6.4.19", - "@storybook/preview-web": "6.4.19", - "@storybook/router": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/channel-postmessage": "6.4.21", + "@storybook/channels": "6.4.21", + "@storybook/client-api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-common": "6.4.21", + "@storybook/core-events": "6.4.21", + "@storybook/node-logger": "6.4.21", + "@storybook/preview-web": "6.4.21", + "@storybook/router": "6.4.21", "@storybook/semver": "^7.3.2", - "@storybook/store": "6.4.19", - "@storybook/theming": "6.4.19", - "@storybook/ui": "6.4.19", + "@storybook/store": "6.4.21", + "@storybook/theming": "6.4.21", + "@storybook/ui": "6.4.21", "@types/node": "^14.0.10", "@types/webpack": "^4.41.26", "autoprefixer": "^9.8.6", @@ -67752,13 +67720,13 @@ } }, "@storybook/channel-postmessage": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.4.19.tgz", - "integrity": "sha512-E5h/itFzQ/6M08LR4kqlgqqmeO3tmavI+nUAlZrkCrotpJFNMHE2i0PQHg0TkFJrRDpYcrwD+AjUW4IwdqrisQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-6.4.21.tgz", + "integrity": "sha512-9mYtc4khwALGA9m4oh2ssnIoyYyKs/q6CZ+luaxct5bd1AZ6iZGBW+qwPaE+g/jjJyLotcSA/1FVr3AiImlWIQ==", "requires": { - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "core-js": "^3.8.2", "global": "^4.4.0", "qs": "^6.10.0", @@ -67766,21 +67734,21 @@ } }, "@storybook/channel-websocket": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.4.19.tgz", - "integrity": "sha512-cXKwQjIXttfdUyZlcHORelUmJ5nUKswsnCA/qy7IRWpZjD8yQJcNk1dYC+tTHDVqFgdRT89pL0hRRB1rlaaR8Q==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-6.4.21.tgz", + "integrity": "sha512-qsyxR0e9ErqyDuCLTh/bSTnBkuNmD1GfVXp7f+NpKoSyfTOYKkaqydOiYDwN0LIHMt4ml9v6NN/zQ/i3avI4jw==", "requires": { - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", "core-js": "^3.8.2", "global": "^4.4.0", "telejson": "^5.3.2" } }, "@storybook/channels": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.4.19.tgz", - "integrity": "sha512-EwyoncFvTfmIlfsy8jTfayCxo2XchPkZk/9txipugWSmc057HdklMKPLOHWP0z5hLH0IbVIKXzdNISABm36jwQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.4.21.tgz", + "integrity": "sha512-qgy8z3Hp04Q4p+E/8V9MamYYJLW8z1uv1Z+rvosNkg+eAApPg+Qe08BSj59OAUwPLrr2vpBW7WZ/BYSieW1tUg==", "requires": { "core-js": "^3.8.2", "ts-dedent": "^2.0.0", @@ -67788,17 +67756,17 @@ } }, "@storybook/client-api": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.4.19.tgz", - "integrity": "sha512-OCrT5Um3FDvZnimQKwWtwsaI+5agPwq2i8YiqlofrI/NPMKp0I7DEkCGwE5IRD1Q8BIKqHcMo5tTmfYi0AxyOg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-6.4.21.tgz", + "integrity": "sha512-qdxRdVQLO9A4KsQVT3o3Xj1PF3cSdasHz1mwuH8/l2p5Zce5vWKtNSUuxcSoI50P0A18FLntVMpgyM+8+bHxhQ==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/channel-postmessage": "6.4.19", - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/channel-postmessage": "6.4.21", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/store": "6.4.19", + "@storybook/store": "6.4.21", "@types/qs": "^6.9.5", "@types/webpack-env": "^1.16.0", "core-js": "^3.8.2", @@ -67815,23 +67783,23 @@ } }, "@storybook/client-logger": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.4.19.tgz", - "integrity": "sha512-zmg/2wyc9W3uZrvxaW4BfHcr40J0v7AGslqYXk9H+ERLVwIvrR4NhxQFaS6uITjBENyRDxwzfU3Va634WcmdDQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.4.21.tgz", + "integrity": "sha512-XkVCQ5swyYDVh5U+87DGRBdC5utJBpVW7kU5P14TQKMnSc/yHbMcXWaA89K8WKDa/WGkGbc0bKi4WrUwHFg2FA==", "requires": { "core-js": "^3.8.2", "global": "^4.4.0" } }, "@storybook/components": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.4.19.tgz", - "integrity": "sha512-q/0V37YAJA7CNc+wSiiefeM9+3XVk8ixBNylY36QCGJgIeGQ5/79vPyUe6K4lLmsQwpmZsIq1s1Ad5+VbboeOA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.4.21.tgz", + "integrity": "sha512-OnuAS/bMdLKdmkWtDNUxM9qSFCU3pcGWqXzasU3sjvibIcz3472xTFiwjW9UiHR7ipu/YQKALnIbyyjznGY4Kg==", "requires": { "@popperjs/core": "^2.6.0", - "@storybook/client-logger": "6.4.19", + "@storybook/client-logger": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/theming": "6.4.19", + "@storybook/theming": "6.4.21", "@types/color-convert": "^2.0.0", "@types/overlayscrollbars": "^1.12.0", "@types/react-syntax-highlighter": "11.0.5", @@ -67855,29 +67823,29 @@ } }, "@storybook/core": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/core/-/core-6.4.19.tgz", - "integrity": "sha512-55LOQ/h/kf1jMhjN85t/pIEdIwWEG9yV7bdwv3niVvmoypCxyyjn9/QNK0RKYAeDSUtdm6FVoJ6k5CpxWz2d8w==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-6.4.21.tgz", + "integrity": "sha512-HNy3L/5stURU5CPyo4Gh/NHhgs6qgvNq82pOr9mhnr2chNOUTh/kaWjrR4k/Mnh8qzItYLs1tpIFKvhclHXAdw==", "requires": { - "@storybook/core-client": "6.4.19", - "@storybook/core-server": "6.4.19" + "@storybook/core-client": "6.4.21", + "@storybook/core-server": "6.4.21" } }, "@storybook/core-client": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.4.19.tgz", - "integrity": "sha512-rQHRZjhArPleE7/S8ZUolgzwY+hC0smSKX/3PQxO2GcebDjnJj6+iSV3h+aSMHMmTdoCQvjYw9aBpT8scuRe+A==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-6.4.21.tgz", + "integrity": "sha512-1zdfhL7ryP5xgcBNuaQplkiPIgPZ2OnIFA1gqun1xl9OBA7K2J115uZ2grQwS7hrhRBqsRIvMv1k9UmAYzXqiw==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/channel-postmessage": "6.4.19", - "@storybook/channel-websocket": "6.4.19", - "@storybook/client-api": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/channel-postmessage": "6.4.21", + "@storybook/channel-websocket": "6.4.21", + "@storybook/client-api": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/preview-web": "6.4.19", - "@storybook/store": "6.4.19", - "@storybook/ui": "6.4.19", + "@storybook/preview-web": "6.4.21", + "@storybook/store": "6.4.21", + "@storybook/ui": "6.4.21", "airbnb-js-shims": "^2.2.1", "ansi-to-html": "^0.6.11", "core-js": "^3.8.2", @@ -67891,9 +67859,9 @@ } }, "@storybook/core-common": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.4.19.tgz", - "integrity": "sha512-X1pJJkO48DFxl6iyEemIKqRkJ7j9/cBh3BRBUr+xZHXBvnD0GKDXIocwh0PjSxSC6XSu3UCQnqtKi3PbjRl8Dg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-6.4.21.tgz", + "integrity": "sha512-apYT4CTRn0iR3DEf59Sc2i9L1WjbewmzYrmHTjNuygS7sjKxV8nppz60yvtLiHu4AWE+quXL3hen5yW9n9mnjw==", "requires": { "@babel/core": "^7.12.10", "@babel/plugin-proposal-class-properties": "^7.12.1", @@ -67916,7 +67884,7 @@ "@babel/preset-react": "^7.12.10", "@babel/preset-typescript": "^7.12.7", "@babel/register": "^7.12.1", - "@storybook/node-logger": "6.4.19", + "@storybook/node-logger": "6.4.21", "@storybook/semver": "^7.3.2", "@types/node": "^14.0.10", "@types/pretty-hrtime": "^1.0.0", @@ -68012,9 +67980,9 @@ } }, "fork-ts-checker-webpack-plugin": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.0.tgz", - "integrity": "sha512-cS178Y+xxtIjEUorcHddKS7yCMlrDPV31mt47blKKRfMd70Kxu5xruAFE2o9sDY6wVC5deuob/u/alD04YYHnw==", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.1.tgz", + "integrity": "sha512-x1wumpHOEf4gDROmKTaB6i4/Q6H3LwmjVO7fIX47vBwlZbtPjU33hgoMuD/Q/y6SU8bnuYSoN6ZQOLshGp0T/g==", "requires": { "@babel/code-frame": "^7.8.3", "@types/json-schema": "^7.0.5", @@ -68032,11 +68000,11 @@ }, "dependencies": { "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } } } @@ -68067,12 +68035,9 @@ } }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "schema-utils": { "version": "2.7.0", @@ -68101,38 +68066,33 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, "@storybook/core-events": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.4.19.tgz", - "integrity": "sha512-KICzUw6XVQUJzFSCXfvhfHAuyhn4Q5J4IZEfuZkcGJS4ODkrO6tmpdYE5Cfr+so95Nfp0ErWiLUuodBsW9/rtA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.4.21.tgz", + "integrity": "sha512-K6b9M1zYvW/Kfb1cnH6JDfmFvTYDMx/ot9zdl9O5SPH9glUwzOXSk8qKu6GmZTiW2YnC2nKbjaN20mfMsCBPGw==", "requires": { "core-js": "^3.8.2" } }, "@storybook/core-server": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.4.19.tgz", - "integrity": "sha512-bKsUB9f7hl5ya2JXxpIrErmbDQjoH39FVbzYZWjMo4t/b7+Xyi6vYadwyWcqlpUQmis09ZaSMv8L/Tw0TuwLAA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-6.4.21.tgz", + "integrity": "sha512-uOBrLKzERAJvGAtd9ieozoTjEu0Hnr7DnufppG4t14Yu61lcbsT3IzPeZDuFaM3tGjWlNgXIezZ2aBoxTMVokQ==", "requires": { "@discoveryjs/json-ext": "^0.5.3", - "@storybook/builder-webpack4": "6.4.19", - "@storybook/core-client": "6.4.19", - "@storybook/core-common": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/builder-webpack4": "6.4.21", + "@storybook/core-client": "6.4.21", + "@storybook/core-common": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/csf-tools": "6.4.19", - "@storybook/manager-webpack4": "6.4.19", - "@storybook/node-logger": "6.4.19", + "@storybook/csf-tools": "6.4.21", + "@storybook/manager-webpack4": "6.4.21", + "@storybook/node-logger": "6.4.21", "@storybook/semver": "^7.3.2", - "@storybook/store": "6.4.19", + "@storybook/store": "6.4.21", "@types/node": "^14.0.10", "@types/node-fetch": "^2.5.7", "@types/pretty-hrtime": "^1.0.0", @@ -68232,9 +68192,9 @@ } }, "@storybook/csf-tools": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.4.19.tgz", - "integrity": "sha512-gf/zRhGoAVsFwSyV2tc+jeJfZQkxF6QsaZgbUSe24/IUvGFCT/PS/jZq1qy7dECAwrTOfykgu8juyBtj6WhWyw==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-6.4.21.tgz", + "integrity": "sha512-Qt7NFEWkVaAWsy9sc0+0nLsi0k8UE+JjsR8Dit2Z/51ED7CMBJCl6nZKSU2vTnwDdRWwUj3d1a+zeKlozKsXYA==", "requires": { "@babel/core": "^7.12.10", "@babel/generator": "^7.12.11", @@ -68288,19 +68248,19 @@ } }, "@storybook/manager-webpack4": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.4.19.tgz", - "integrity": "sha512-R8ugZjTYqXvlc6gDOcw909L65sIleOmIJLZR+N6/H85MivGXHu39jOwONqB7tVACufRty4FNecn8tEiQL2SAKA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/manager-webpack4/-/manager-webpack4-6.4.21.tgz", + "integrity": "sha512-JhcGU6KtmNQUfSNNgAWIKVKOaupx7+RYw3y6P0JN5km5nzqpipkeJzh+jdMqefJbIRV/psqKm/jpt/pPfaIHyQ==", "requires": { "@babel/core": "^7.12.10", "@babel/plugin-transform-template-literals": "^7.12.1", "@babel/preset-react": "^7.12.10", - "@storybook/addons": "6.4.19", - "@storybook/core-client": "6.4.19", - "@storybook/core-common": "6.4.19", - "@storybook/node-logger": "6.4.19", - "@storybook/theming": "6.4.19", - "@storybook/ui": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/core-client": "6.4.21", + "@storybook/core-common": "6.4.21", + "@storybook/node-logger": "6.4.21", + "@storybook/theming": "6.4.21", + "@storybook/ui": "6.4.21", "@types/node": "^14.0.10", "@types/webpack": "^4.41.26", "babel-loader": "^8.0.0", @@ -68388,9 +68348,9 @@ } }, "@storybook/node-logger": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.4.19.tgz", - "integrity": "sha512-hO2Aar3PgPnPtNq2fVgiuGlqo3EEVR6TKVBXMq7foL3tN2k4BQFKLDHbm5qZQQntyYKurKsRUGKPJFPuI1ov/w==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.4.21.tgz", + "integrity": "sha512-iCQ6ToARy0Ri6oP3UPDGsiIqDKf/gsL3XwZ5iPj80HyuCdUwm2dB+e3/09gD7XkHNkY2//TxKOUxcAkorQRFUQ==", "requires": { "@types/npmlog": "^4.1.2", "chalk": "^4.1.0", @@ -68432,24 +68392,24 @@ } }, "@storybook/postinstall": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-6.4.19.tgz", - "integrity": "sha512-/0tHHxyIV82zt1rw4BW70GmrQbDVu9IJPAxOqFzGjC1fNojwJ53mK6FfUsOzbhG5mWk5p0Ip5+zr74moP119AA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-6.4.21.tgz", + "integrity": "sha512-vuynjqEnjoRoe0E0jo27vJQ5JH2lRPAGR0lZMNvmw3EasWSA586eyJvEVTAte/z1wO9ZV2dTHbgAozv33N1Z2w==", "requires": { "core-js": "^3.8.2" } }, "@storybook/preview-web": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.4.19.tgz", - "integrity": "sha512-jqltoBv5j7lvnxEfV9w8dLX9ASWGuvgz97yg8Yo5FqkftEwrHJenyvMGcTgDJKJPorF+wiz/9aIqnmd3LCAcZQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/preview-web/-/preview-web-6.4.21.tgz", + "integrity": "sha512-v0AS7rDbdcD3aw/1pY525EJ4jmgY5ntz9CqiLmBKVBgshjng7Cza8AVR8Kvhr+ppoP/v63w4sEdxIw7jYsO5rQ==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/channel-postmessage": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/channel-postmessage": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/store": "6.4.19", + "@storybook/store": "6.4.21", "ansi-to-html": "^0.6.11", "core-js": "^3.8.2", "global": "^4.4.0", @@ -68463,11 +68423,11 @@ } }, "@storybook/router": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.4.19.tgz", - "integrity": "sha512-KWWwIzuyeEIWVezkCihwY2A76Il9tUNg0I410g9qT7NrEsKyqXGRYOijWub7c1GGyNjLqz0jtrrehtixMcJkuA==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.4.21.tgz", + "integrity": "sha512-otn3xYc017SNebeA95xLQ7P6elfyu9541QteXbLR5gFvrT+MB/8zMRZrVuD7n1xwpBgazlonzAdODC736Be9jQ==", "requires": { - "@storybook/client-logger": "6.4.19", + "@storybook/client-logger": "6.4.21", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", "global": "^4.4.0", @@ -68525,12 +68485,12 @@ } }, "@storybook/source-loader": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.4.19.tgz", - "integrity": "sha512-XqTsqddRglvfW7mhyjwoqd/B8L6samcBehhO0OEbsFp6FPWa9eXuObCxtRYIcjcSIe+ksbW3D/54ppEs1L/g1Q==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/source-loader/-/source-loader-6.4.21.tgz", + "integrity": "sha512-rRu3uWla1c73F5FKl7mdkIKcj+Of4jzIT7aHycS0j6rYKwbGpsptLgxbpMUaEdNHjSDyAzSM6Mj5XcnE5rC8nQ==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/client-logger": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/client-logger": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", "core-js": "^3.8.2", "estraverse": "^5.2.0", @@ -68549,13 +68509,13 @@ } }, "@storybook/store": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/store/-/store-6.4.19.tgz", - "integrity": "sha512-N9/ZjemRHGfT3InPIbqQqc6snkcfnf3Qh9oOr0smbfaVGJol//KOX65kzzobtzFcid0WxtTDZ3HmgFVH+GvuhQ==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/store/-/store-6.4.21.tgz", + "integrity": "sha512-j0cMo3JUs6yGc1cJi29kkzZK2zCGmx03BCMtMflnqNnMVnhuIF2iOTnwj4z01keL8/7hosUAz0OJxhvIV0JHIg==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/core-events": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/core-events": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", @@ -68571,14 +68531,14 @@ } }, "@storybook/theming": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.4.19.tgz", - "integrity": "sha512-V4pWmTvAxmbHR6B3jA4hPkaxZPyExHvCToy7b76DpUTpuHihijNDMAn85KhOQYIeL9q14zP/aiz899tOHsOidg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.4.21.tgz", + "integrity": "sha512-7pLNwmqbyqCeHXzjsacI69IdJcAZr6zoZA84iGqx+Na32OI8wtIpFczbwuYpVPN2jzgRYp23CgIv1Gz27yk/zw==", "requires": { "@emotion/core": "^10.1.1", "@emotion/is-prop-valid": "^0.8.6", "@emotion/styled": "^10.0.27", - "@storybook/client-logger": "6.4.19", + "@storybook/client-logger": "6.4.21", "core-js": "^3.8.2", "deep-object-diff": "^1.1.0", "emotion-theming": "^10.0.27", @@ -68590,20 +68550,20 @@ } }, "@storybook/ui": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-6.4.19.tgz", - "integrity": "sha512-gFwdn5LA2U6oQ4bfUFLyHZnNasGQ01YVdwjbi+l6yjmnckBNtZfJoVTZ1rzGUbxSE9rK48InJRU+latTsr7xAg==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-6.4.21.tgz", + "integrity": "sha512-jjEEFDm8PAzscn5dN+3YJap9033ce98YYC9FCQVF5sB41CIwI0PD5LUafxWbaxQdL+t/ZlRYXNz3FLNFHMwzcQ==", "requires": { "@emotion/core": "^10.1.1", - "@storybook/addons": "6.4.19", - "@storybook/api": "6.4.19", - "@storybook/channels": "6.4.19", - "@storybook/client-logger": "6.4.19", - "@storybook/components": "6.4.19", - "@storybook/core-events": "6.4.19", - "@storybook/router": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/api": "6.4.21", + "@storybook/channels": "6.4.21", + "@storybook/client-logger": "6.4.21", + "@storybook/components": "6.4.21", + "@storybook/core-events": "6.4.21", + "@storybook/router": "6.4.21", "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.4.19", + "@storybook/theming": "6.4.21", "copy-to-clipboard": "^3.3.1", "core-js": "^3.8.2", "core-js-pure": "^3.8.2", @@ -68625,15 +68585,15 @@ } }, "@storybook/vue": { - "version": "6.4.19", - "resolved": "https://registry.npmjs.org/@storybook/vue/-/vue-6.4.19.tgz", - "integrity": "sha512-Uqy2F7qIV90IQwhT7BCwDWWHwDvAgT2MFMripVmzUQfYfPoTsja54viDBS8i0uEc7R1qPrRA2CpofINKAuZM0A==", + "version": "6.4.21", + "resolved": "https://registry.npmjs.org/@storybook/vue/-/vue-6.4.21.tgz", + "integrity": "sha512-KR1uq1IBfZ6RT652Dl9HCg+QRJnDANF80/GOYwtryHmnERDJTizAvG02QOwxSgfHQf+ZmG9MxOZpAcSXGyjH7w==", "requires": { - "@storybook/addons": "6.4.19", - "@storybook/core": "6.4.19", - "@storybook/core-common": "6.4.19", + "@storybook/addons": "6.4.21", + "@storybook/core": "6.4.21", + "@storybook/core-common": "6.4.21", "@storybook/csf": "0.0.2--canary.87bc651.0", - "@storybook/store": "6.4.19", + "@storybook/store": "6.4.21", "@types/webpack-env": "^1.16.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -68667,9 +68627,9 @@ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" }, "@types/aws4": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@types/aws4/-/aws4-1.11.1.tgz", - "integrity": "sha512-yUnPMlHP5JMZJiiNZElJG5qj1ShezlaET6Bug9SBhYsxKVamh7aOwl7Q/XR1Y//cZ5PoeRb9j4hi9svb2+FLlg==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@types/aws4/-/aws4-1.11.2.tgz", + "integrity": "sha512-x0f96eBPrCCJzJxdPbUvDFRva4yPpINJzTuXXpmS2j9qLUpF2nyGzvXPlRziuGbCsPukwY4JfuO+8xwsoZLzGw==", "requires": { "@types/node": "*" } @@ -69074,9 +69034,9 @@ "integrity": "sha512-3YxO7RHRrmtYNX6Rhkr97bnXHrF1Ckfo4axENWLcBXWi+8B1WsNbqPqe5Eg6TA5survjAWWvLTu1KQesuLHVgQ==" }, "@types/lodash": { - "version": "4.14.180", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.180.tgz", - "integrity": "sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g==" + "version": "4.14.181", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.181.tgz", + "integrity": "sha512-n3tyKthHJbkiWhDZs3DkhkCzt2MexYHXlX0td5iMplyfwketaOeKboEVBqzceH7juqvEg3q5oUoBFxSLu7zFag==" }, "@types/lodash.camelcase": { "version": "4.3.6", @@ -69307,9 +69267,9 @@ } }, "@types/prettier": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.4.tgz", - "integrity": "sha512-ReVR2rLTV1kvtlWFyuot+d1pkpG2Fw/XKE3PDAdj57rbM97ttSp9JZ2UsP+2EHTylra9cUf6JA7tGwW1INzUrA==" + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.6.0.tgz", + "integrity": "sha512-G/AdOadiZhnJp0jXCaBQU449W2h716OW/EoXeYkCytxKL06X1WCXB4DZpp8TpZ8eyIJVS1cw4lrlkkSYU21cDw==" }, "@types/pretty-hrtime": { "version": "1.0.1", @@ -69333,9 +69293,9 @@ "integrity": "sha512-mqo6D4qdiJdzeqlzFwEIchQQZk2hZacjssmjoAX7nClcREmRUUsnmgbWXEfA2qK986rwOPqepfRoSu7rsjAKag==" }, "@types/prop-types": { - "version": "15.7.4", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.4.tgz", - "integrity": "sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==" + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" }, "@types/q": { "version": "1.5.5", @@ -69362,9 +69322,9 @@ "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" }, "@types/react": { - "version": "17.0.43", - "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.43.tgz", - "integrity": "sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A==", + "version": "18.0.1", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.1.tgz", + "integrity": "sha512-VnWlrVgG0dYt+NqlfMI0yUYb8Rdl4XUROyH+c6gq/iFCiZ805Vi//26UW38DHnxQkbDhnrIWTBiy6oKZqL11cw==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -69462,9 +69422,9 @@ "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==" }, "@types/ssh2": { - "version": "0.5.51", - "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.51.tgz", - "integrity": "sha512-aIq7ownezauW/+VWYaeXwd5J1Evnn4EXyeKi7bT3H6ZLBLoqsmhdvkHYPLpnZPM6unKKKsxTHIyQAVOZnPiJBw==", + "version": "0.5.52", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.52.tgz", + "integrity": "sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg==", "requires": { "@types/node": "*", "@types/ssh2-streams": "*" @@ -69558,9 +69518,9 @@ } }, "@types/uglify-js": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz", - "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==", + "version": "3.13.2", + "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.2.tgz", + "integrity": "sha512-/xFrPIo+4zOeNGtVMbf9rUm0N+i4pDf1ynExomqtokIJmVzR3962lJ1UE+MmexMkA0cmN9oTzg5Xcbwge0Ij2Q==", "requires": { "source-map": "^0.6.1" }, @@ -69683,25 +69643,17 @@ }, "dependencies": { "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -69758,25 +69710,17 @@ }, "dependencies": { "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -71811,9 +71755,9 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" }, "strip-ansi": { "version": "4.0.0", @@ -73692,14 +73636,14 @@ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, "avsc": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/avsc/-/avsc-5.7.3.tgz", - "integrity": "sha512-uUbetCWczQHbsKyX1C99XpQHBM8SWfovvaZhPIj23/1uV7SQf0WeRZbiLpw0JZm+LHTChfNgrLfDJOVoU2kU+A==" + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/avsc/-/avsc-5.7.4.tgz", + "integrity": "sha512-z4oo33lmnvvNRqfUe3YjDGGpqu/L2+wXBIhMtwq6oqZ+exOUAkQYM6zd2VWKF7AIlajOF8ZZuPFfryTG9iLC/w==" }, "aws-sdk": { - "version": "2.1101.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1101.0.tgz", - "integrity": "sha512-7lyVb7GXGl8yyu954Qxf6vU6MrcgFlmKyTLBVXJyo3Phn1OB+qOExA55WtSC6gQiQ7e5TeWOn1RUHLg30ywTBA==", + "version": "2.1111.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1111.0.tgz", + "integrity": "sha512-WRyNcCckzmu1djTAWfR2r+BuI/PbuLrhG3oa+oH39v4NZ4EecYWFL1CoCPlC2kRUML4maSba5T4zlxjcNl7ELQ==", "requires": { "buffer": "4.9.2", "events": "1.1.1", @@ -75008,20 +74952,22 @@ "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" }, "body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", + "integrity": "sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==", "requires": { "bytes": "3.1.2", "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.8.1", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.9.7", - "raw-body": "2.4.3", - "type-is": "~1.6.18" + "on-finished": "2.4.1", + "qs": "6.10.3", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "dependencies": { "debug": { @@ -75044,11 +74990,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" } } }, @@ -75409,25 +75350,17 @@ }, "dependencies": { "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -75748,9 +75681,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001320", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", - "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==" + "version": "1.0.30001327", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001327.tgz", + "integrity": "sha512-1/Cg4jlD9qjZzhbzkzEaAC2JHsP0WrOc8Rd/3a3LuajGzGWR/hD7TVyvq99VqmTy99eVh8Zkmdq213OgvgXx7w==" }, "capital-case": { "version": "1.0.4", @@ -75802,34 +75735,18 @@ "integrity": "sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==" }, "cfb": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.1.tgz", - "integrity": "sha512-wT2ScPAFGSVy7CY+aauMezZBnNrfnaLSrxHUHdea+Td/86vrk6ZquggV+ssBR88zNs0OnBkL2+lf9q0K+zVGzQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", "requires": { "adler-32": "~1.3.0", - "crc-32": "~1.2.0", - "printj": "~1.3.0" + "crc-32": "~1.2.0" }, "dependencies": { "adler-32": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.0.tgz", - "integrity": "sha512-f5nltvjl+PRUh6YNfUstRaXwJxtfnKEWhAWWlmKvh+Y3J2+98a0KKVYDEhz6NdKGqswLhjNGznxfSsZGOvOd9g==", - "requires": { - "printj": "~1.2.2" - }, - "dependencies": { - "printj": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.2.3.tgz", - "integrity": "sha512-sanczS6xOJOg7IKDvi4sGOUOe7c1tsEzjwlLFH/zgwx/uyImVM9/rgBkc8AfiQa/Vg54nRd8mkm9yI7WV/O+WA==" - } - } - }, - "printj": { "version": "1.3.1", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", - "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==" + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==" } } }, @@ -75931,15 +75848,15 @@ } }, "cheerio-select": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.5.0.tgz", - "integrity": "sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", + "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", "requires": { - "css-select": "^4.1.3", - "css-what": "^5.0.1", + "css-select": "^4.3.0", + "css-what": "^6.0.1", "domelementtype": "^2.2.0", - "domhandler": "^4.2.0", - "domutils": "^2.7.0" + "domhandler": "^4.3.1", + "domutils": "^2.8.0" } }, "chokidar": { @@ -76275,19 +76192,16 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } }, "supports-color": { @@ -76302,11 +76216,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -76564,7 +76473,8 @@ "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "optional": true }, "colorspace": { "version": "1.1.4", @@ -77991,9 +77901,9 @@ } }, "cpu-features": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.3.tgz", - "integrity": "sha512-p6C/uud4F4bDyCz9+BNU22KdV1AGxPK6L9rQG9x3x4SSzdMPyBPErP7Rxn8avT2ex1M2g5Rpjz5Us/ri/766Qg==", + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.4.tgz", + "integrity": "sha512-fKiZ/zp1mUwQbnzb9IghXtHtDoTMtNeb8oYGx6kX2SYfhnG0HNdBEBIzB9b5KlXu5DQPhfy3mInbBxFcgwAr3A==", "optional": true, "requires": { "buildcheck": "0.0.3", @@ -78231,20 +78141,9 @@ } }, "crc-32": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.1.tgz", - "integrity": "sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w==", - "requires": { - "exit-on-epipe": "~1.0.1", - "printj": "~1.3.1" - }, - "dependencies": { - "printj": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/printj/-/printj-1.3.1.tgz", - "integrity": "sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg==" - } - } + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==" }, "create-ecdh": { "version": "4.0.4", @@ -78443,13 +78342,13 @@ } }, "css-select": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz", - "integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", "requires": { "boolbase": "^1.0.0", - "css-what": "^5.1.0", - "domhandler": "^4.3.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", "domutils": "^2.8.0", "nth-check": "^2.0.1" } @@ -78476,9 +78375,9 @@ } }, "css-what": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz", - "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==" }, "cssesc": { "version": "3.0.0", @@ -78675,9 +78574,9 @@ }, "dependencies": { "es5-ext": { - "version": "0.10.59", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.59.tgz", - "integrity": "sha512-cOgyhW0tIJyQY1Kfw6Kr0viu9ZlUctVchRMZ7R0HiH3dxTSp5zJDLecwxUqPUrGKMsgBI1wd1FL+d9Jxfi4cLw==", + "version": "0.10.60", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", + "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", "requires": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", @@ -78739,9 +78638,9 @@ "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=" }, "deasync": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.24.tgz", - "integrity": "sha512-i98vg42xNfRZCymummMAN0rIcQ1gZFinSe3btvPIvy6JFTaeHcumeKybRo2HTv86nasfmT0nEgAn2ggLZhOCVA==", + "version": "0.1.26", + "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.26.tgz", + "integrity": "sha512-YKw0BmJSWxkjtQsbgn6Q9CHSWB7DKMen8vKrgyC006zy0UZ6nWyGidB0IzZgqkVRkOglAeUaFtiRTeLyel72bg==", "requires": { "bindings": "^1.5.0", "node-addon-api": "^1.7.1" @@ -79044,9 +78943,9 @@ "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" }, "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, "deprecation": { "version": "2.3.1", @@ -79064,9 +78963,9 @@ } }, "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, "detab": { "version": "2.0.4", @@ -79127,9 +79026,10 @@ } }, "dezalgo": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, "requires": { "asap": "^2.0.0", "wrappy": "1" @@ -79251,9 +79151,9 @@ } }, "dom-serializer": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", - "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "requires": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", @@ -79271,9 +79171,9 @@ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" }, "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" }, "domexception": { "version": "2.0.1", @@ -79504,9 +79404,9 @@ "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==" }, "electron-to-chromium": { - "version": "1.4.95", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.95.tgz", - "integrity": "sha512-h2VAMV/hPtmAeiDkwA8c5sjS+cWt6GlQL4ERdrOUWu7cRIG5IRk9uwR9f0utP+hPJ9ZZsADTq9HpbuT46eBYAg==" + "version": "1.4.106", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.106.tgz", + "integrity": "sha512-ZYfpVLULm67K7CaaGP7DmjyeMY4naxsbTy+syVVxT6QHI1Ww8XbJjmr9fDckrhq44WzCrcC5kH3zGpdusxwwqg==" }, "element-resize-detector": { "version": "1.2.4", @@ -79688,9 +79588,9 @@ } }, "es-abstract": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz", - "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==", + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.2.tgz", + "integrity": "sha512-gfSBJoZdlL2xRiOCy0g8gLMryhoe1TlimjzU99L/31Z8QEGIhVQI+EWwt5lT+AuU9SnorVupXFqqOGqGfsyO6w==", "requires": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", @@ -79698,15 +79598,15 @@ "get-intrinsic": "^1.1.1", "get-symbol-description": "^1.0.0", "has": "^1.0.3", - "has-symbols": "^1.0.2", + "has-symbols": "^1.0.3", "internal-slot": "^1.0.3", "is-callable": "^1.2.4", - "is-negative-zero": "^2.0.1", + "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.1", "is-string": "^1.0.7", - "is-weakref": "^1.0.1", - "object-inspect": "^1.11.0", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.0", "object-keys": "^1.1.1", "object.assign": "^4.1.2", "string.prototype.trimend": "^1.0.4", @@ -79765,9 +79665,9 @@ }, "dependencies": { "es5-ext": { - "version": "0.10.59", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.59.tgz", - "integrity": "sha512-cOgyhW0tIJyQY1Kfw6Kr0viu9ZlUctVchRMZ7R0HiH3dxTSp5zJDLecwxUqPUrGKMsgBI1wd1FL+d9Jxfi4cLw==", + "version": "0.10.60", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", + "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", "requires": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", @@ -79817,9 +79717,9 @@ }, "dependencies": { "es5-ext": { - "version": "0.10.59", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.59.tgz", - "integrity": "sha512-cOgyhW0tIJyQY1Kfw6Kr0viu9ZlUctVchRMZ7R0HiH3dxTSp5zJDLecwxUqPUrGKMsgBI1wd1FL+d9Jxfi4cLw==", + "version": "0.10.60", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.60.tgz", + "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", "requires": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", @@ -79979,12 +79879,9 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "optionator": { "version": "0.9.1", @@ -80000,11 +79897,11 @@ } }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } }, "supports-color": { @@ -80014,11 +79911,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -80231,23 +80123,23 @@ } }, "eslint-plugin-import": { - "version": "2.25.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz", - "integrity": "sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==", + "version": "2.26.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz", + "integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==", "requires": { "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.2", + "eslint-module-utils": "^2.7.3", "has": "^1.0.3", - "is-core-module": "^2.8.0", + "is-core-module": "^2.8.1", "is-glob": "^4.0.3", - "minimatch": "^3.0.4", + "minimatch": "^3.1.2", "object.values": "^1.1.5", - "resolve": "^1.20.0", - "tsconfig-paths": "^3.12.0" + "resolve": "^1.22.0", + "tsconfig-paths": "^3.14.1" }, "dependencies": { "debug": { @@ -80714,6 +80606,23 @@ "vary": "~1.1.2" }, "dependencies": { + "body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.9.7", + "raw-body": "2.4.3", + "type-is": "~1.6.18" + } + }, "cookie": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", @@ -80727,15 +80636,59 @@ "ms": "2.0.0" } }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, "qs": { "version": "6.9.7", "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" + }, + "raw-body": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", + "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "requires": { + "bytes": "3.1.2", + "http-errors": "1.8.1", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } } } }, @@ -81093,6 +81046,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } } } }, @@ -81361,9 +81322,9 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" }, "flow-parser": { - "version": "0.174.1", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.174.1.tgz", - "integrity": "sha512-nDMOvlFR+4doLpB3OJpseHZ7uEr3ENptlF6qMas/kzQmNcLzMwfQeFX0gGJ/+em7UdldB/nGsk55tDTOvjbCuw==" + "version": "0.175.1", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.175.1.tgz", + "integrity": "sha512-gYes5/nxeLYiu02MMb+WH4KaOIYrVcTVIuV9M4aP/4hqJ+zULxxS/In+WEj/tEBsQ+8/wSHo9IDWKQL1FhrLmA==" }, "flush-write-stream": { "version": "1.1.1", @@ -81661,13 +81622,10 @@ } }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "optional": true, - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==", + "optional": true }, "schema-utils": { "version": "2.7.0", @@ -81681,12 +81639,12 @@ } }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "optional": true, "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } }, "supports-color": { @@ -81709,12 +81667,6 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "optional": true - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "optional": true } } }, @@ -83291,9 +83243,9 @@ } }, "graceful-fs": { - "version": "4.2.9", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", - "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "growly": { "version": "1.3.0", @@ -83695,9 +83647,9 @@ } }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" }, "arr-diff": { "version": "4.0.0", @@ -84305,9 +84257,9 @@ } }, "html-tags": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", - "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==" }, "html-to-text": { "version": "8.0.0", @@ -84434,15 +84386,22 @@ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" }, "http-errors": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", - "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "requires": { - "depd": "~1.1.2", + "depd": "2.0.0", "inherits": "2.0.4", "setprototypeof": "1.2.0", - "statuses": ">= 1.5.0 < 2", + "statuses": "2.0.1", "toidentifier": "1.0.1" + }, + "dependencies": { + "statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" + } } }, "http-parser-js": { @@ -85195,9 +85154,9 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "is-number-object": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", - "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "requires": { "has-tostringtag": "^1.0.0" } @@ -85302,9 +85261,12 @@ "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==" }, "is-shared-array-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz", - "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "requires": { + "call-bind": "^1.0.2" + } }, "is-ssh": { "version": "1.3.3", @@ -88058,19 +88020,16 @@ } }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } }, "source-map": { @@ -88085,11 +88044,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -88487,9 +88441,9 @@ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==" }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==" }, "string-length": { "version": "2.0.0", @@ -88691,11 +88645,11 @@ "integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==" }, "js-beautify": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.0.tgz", - "integrity": "sha512-yuck9KirNSCAwyNJbqW+BxJqJ0NLJ4PwBUzQQACl5O3qHMBXVkXb/rD0ilh/Lat/tn88zSZ+CAHOlk0DsY7GuQ==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.3.tgz", + "integrity": "sha512-f1ra8PHtOEu/70EBnmiUlV8nJePS58y9qKjl4JHfYWlFH6bo7ogZBz//FAZp7jDuXtYnGYKymZPlrg2I/9Zo4g==", "requires": { - "config-chain": "^1.1.12", + "config-chain": "^1.1.13", "editorconfig": "^0.15.3", "glob": "^7.1.3", "nopt": "^5.0.0" @@ -88751,40 +88705,44 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, "jscodeshift": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.7.1.tgz", - "integrity": "sha512-YMkZSyoc8zg5woZL23cmWlnFLPH/mHilonGA7Qbzs7H6M4v4PH0Qsn4jeDyw+CHhVoAnm9UxQyB0Yw1OT+mktA==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.13.1.tgz", + "integrity": "sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ==", "requires": { - "@babel/core": "^7.1.6", - "@babel/parser": "^7.1.6", - "@babel/plugin-proposal-class-properties": "^7.1.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/preset-env": "^7.1.6", - "@babel/preset-flow": "^7.0.0", - "@babel/preset-typescript": "^7.1.0", - "@babel/register": "^7.0.0", + "@babel/core": "^7.13.16", + "@babel/parser": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/preset-flow": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/register": "^7.13.16", "babel-core": "^7.0.0-bridge.0", - "colors": "^1.1.2", + "chalk": "^4.1.2", "flow-parser": "0.*", - "graceful-fs": "^4.1.11", + "graceful-fs": "^4.2.4", "micromatch": "^3.1.10", "neo-async": "^2.5.0", "node-dir": "^0.1.17", - "recast": "^0.18.1", - "temp": "^0.8.1", + "recast": "^0.20.4", + "temp": "^0.8.4", "write-file-atomic": "^2.3.0" }, "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=" }, - "ast-types": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.3.tgz", - "integrity": "sha512-XTZ7xGML849LkQP86sWdQzfhwbt3YwIO6MqbX9mUNYY98VKaaVZP7YNNm70IpwecbkkxmfC5IYAzOQ/2p29zRA==" - }, "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", @@ -88817,6 +88775,15 @@ } } }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, "extend-shallow": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", @@ -88852,6 +88819,11 @@ } } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", @@ -88890,22 +88862,14 @@ "to-regex": "^3.0.2" } }, - "recast": { - "version": "0.18.10", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.18.10.tgz", - "integrity": "sha512-XNvYvkfdAN9QewbrxeTOjgINkdY/odTgTS56ZNEWL9Ml0weT4T3sFtvnTuF+Gxyu46ANcRm1ntrF6F5LAJPAaQ==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { - "ast-types": "0.13.3", - "esprima": "~4.0.0", - "private": "^0.1.8", - "source-map": "~0.6.1" + "has-flag": "^4.0.0" } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, "to-regex-range": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", @@ -89012,9 +88976,9 @@ }, "dependencies": { "domelementtype": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==" }, "entities": { "version": "2.2.0", @@ -91100,9 +91064,9 @@ "dev": true }, "moment": { - "version": "2.29.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", - "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + "version": "2.29.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.2.tgz", + "integrity": "sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==" }, "moment-timezone": { "version": "0.5.34", @@ -91407,9 +91371,9 @@ "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" }, "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==" + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.2.tgz", + "integrity": "sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==" }, "nanomatch": { "version": "1.2.13", @@ -91522,9 +91486,9 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "nested-error-stacks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", - "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==" + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz", + "integrity": "sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==" }, "next-tick": { "version": "1.1.0", @@ -91877,25 +91841,17 @@ }, "dependencies": { "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -92317,11 +92273,18 @@ } }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" + }, + "dependencies": { + "lru-cache": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" + } } }, "yallist": { @@ -92772,9 +92735,9 @@ "dev": true }, "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", "requires": { "ee-first": "1.1.1" } @@ -93832,11 +93795,11 @@ } }, "polished": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/polished/-/polished-4.1.4.tgz", - "integrity": "sha512-Nq5Mbza+Auo7N3sQb1QMFaQiDO+4UexWuSGR7Cjb4Sw11SZIJcrrFtiZ+L0jT9MBsUsxDboHVASbCLbE1rnECg==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.2.2.tgz", + "integrity": "sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==", "requires": { - "@babel/runtime": "^7.16.7" + "@babel/runtime": "^7.17.8" } }, "popsicle": { @@ -94109,12 +94072,9 @@ } }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "schema-utils": { "version": "3.1.1", @@ -94127,17 +94087,12 @@ } }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -94522,9 +94477,9 @@ } }, "postcss-selector-parser": { - "version": "6.0.9", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz", - "integrity": "sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -94596,9 +94551,9 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, "prettier": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.1.tgz", - "integrity": "sha512-8UVbTBYGwN37Bs9LERmxCPjdvPxlEowx2urIL6urHzdb3SDq4B/Z6xLFCblrSnE4iKWcS6ziJ3aOYrc1kz/E2A==" + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.6.2.tgz", + "integrity": "sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==" }, "prettier-linter-helpers": { "version": "1.0.0", @@ -94674,11 +94629,6 @@ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.27.0.tgz", "integrity": "sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==" }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" - }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -95459,12 +95409,12 @@ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, "raw-body": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", - "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", "requires": { "bytes": "3.1.2", - "http-errors": "1.8.1", + "http-errors": "2.0.0", "iconv-lite": "0.4.24", "unpipe": "1.0.0" }, @@ -95622,9 +95572,9 @@ } }, "react-router": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.2.2.tgz", - "integrity": "sha512-/MbxyLzd7Q7amp4gDOGaYvXwhEojkJD5BtExkuKmj39VEE0m3l/zipf6h2WIB2jyAO0lI6NGETh4RDcktRm4AQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.3.0.tgz", + "integrity": "sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==", "requires": { "history": "^5.2.0" }, @@ -95640,12 +95590,12 @@ } }, "react-router-dom": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.2.2.tgz", - "integrity": "sha512-AtYEsAST7bDD4dLSQHDnk/qxWLJdad5t1HFa1qJyUrCeGgEuCSw0VB/27ARbF9Fi/W5598ujvJOm3ujUCVzuYQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.3.0.tgz", + "integrity": "sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==", "requires": { "history": "^5.2.0", - "react-router": "6.2.2" + "react-router": "6.3.0" }, "dependencies": { "history": { @@ -96011,9 +95961,9 @@ "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" }, "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", "requires": { "@babel/runtime": "^7.8.4" } @@ -96402,9 +96352,9 @@ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" }, "yargs": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.0.tgz", - "integrity": "sha512-WJudfrk81yWFSOkZYpAZx4Nt7V4xp7S/uJkX0CnxovMCt1wCE8LNftPpNuF9X/u9gN5nsD7ycYtRcDf2pL3UiA==", + "version": "17.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.4.1.tgz", + "integrity": "sha512-WSZD9jgobAg3ZKuCQZSa3g9QOJeCCqLoLAykiWgmXnDo9EPnn4RPf5qVTtzgOx66o6/oqhcA5tHtJXpG8pMt3g==", "requires": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -96942,9 +96892,9 @@ } }, "sass": { - "version": "1.49.9", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.49.9.tgz", - "integrity": "sha512-YlYWkkHP9fbwaFRZQRXgDi3mXZShslVmmo+FVK3kHLUELHHEYrCmL1x6IUjC7wLS6VuJSAFXRQS/DxdsC4xL1A==", + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.50.0.tgz", + "integrity": "sha512-cLsD6MEZ5URXHStxApajEh7gW189kkjn4Rc8DQweMyF+o5HF5nfEz8QYLMlPsTOD88DknatTmBWkOcw5/LnJLQ==", "requires": { "chokidar": ">=3.0.0 <4.0.0", "immutable": "^4.0.0", @@ -97104,6 +97054,36 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } } } }, @@ -97183,6 +97163,11 @@ "ms": "2.0.0" } }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, "http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", @@ -97352,13 +97337,13 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "simple-git": { - "version": "2.48.0", - "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.48.0.tgz", - "integrity": "sha512-z4qtrRuaAFJS4PUd0g+xy7aN4y+RvEt/QTJpR184lhJguBA1S/LsVlvE/CM95RsYMOFJG3NGGDjqFCzKU19S/A==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.6.0.tgz", + "integrity": "sha512-2e+4QhOVO59GeLsHgwSMKNrSKCnuACeA/gMNrLCYR8ID9qwm4hViVt4WsODcUGjx//KDv6GMLC6Hs/MeosgXxg==", "requires": { "@kwsites/file-exists": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1", - "debug": "^4.3.2" + "debug": "^4.3.3" } }, "simple-lru-cache": { @@ -98170,13 +98155,13 @@ } }, "ssh2": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.8.0.tgz", - "integrity": "sha512-NVIRkIwJvWl+mcRozp+EBzHMVCcbDKBea64ToPdZEk43yAVGwmfqYZRPFRnnvGjsKC34wYCmiupTcKgCVNVNNg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.9.0.tgz", + "integrity": "sha512-rhhIZT0eMPvCBSOG8CpqZZ7gre2vgXaIqmb3Jb83t88rjsxIsFzDanqBJM9Ns8BmP1835A5IbQ199io4EUZwOA==", "requires": { "asn1": "^0.2.4", "bcrypt-pbkdf": "^1.0.2", - "cpu-features": "0.0.3", + "cpu-features": "~0.0.4", "nan": "^2.15.0" } }, @@ -98732,9 +98717,9 @@ } }, "superagent": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.1.tgz", - "integrity": "sha512-CQ2weSS6M+doIwwYFoMatklhRbx6sVNdB99OEJ5czcP3cng76Ljqus694knFWgOj3RkrtxZqIgpe6vhe0J7QWQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.2.tgz", + "integrity": "sha512-o9/fP6dww7a4xmEF5a484o2rG34UUGo8ztDlv7vbCWuqPhpndMi0f7eXxdlryk5U12Kzy46nh8eNpLAJ93Alsg==", "requires": { "component-emitter": "^1.3.0", "cookiejar": "^2.1.3", @@ -98749,6 +98734,15 @@ "semver": "^7.3.5" }, "dependencies": { + "dezalgo": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", + "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "requires": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, "formidable": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/formidable/-/formidable-2.0.1.tgz", @@ -98768,12 +98762,9 @@ } }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "mime": { "version": "2.6.0", @@ -98791,17 +98782,12 @@ } }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -99111,11 +99097,6 @@ "readable-stream": "^3.0.1" } }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, "iconv-lite": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.5.2.tgz", @@ -100015,19 +99996,16 @@ } }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } }, "supports-color": { @@ -100037,11 +100015,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -100095,12 +100068,9 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "memory-fs": { "version": "0.5.0", @@ -100131,11 +100101,11 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } }, "string_decoder": { @@ -100158,11 +100128,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -100424,9 +100389,9 @@ } }, "typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==" + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", + "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==" }, "uc.micro": { "version": "1.0.6", @@ -100434,9 +100399,9 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, "uglify-js": { - "version": "3.15.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.3.tgz", - "integrity": "sha512-6iCVm2omGJbsu3JWac+p6kUiOpg3wFO2f8lIXjfEb8RrmLjzog1wTPMmwKB7swfzzqxj9YM+sGUM++u1qN4qJg==", + "version": "3.15.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.15.4.tgz", + "integrity": "sha512-vMOPGDuvXecPs34V74qDKk4iJ/SN4vL3Ow/23ixafENYvtrNvtbcgUeugTcUGRGsOF/5fU8/NYSL5Hyb3l1OJA==", "optional": true }, "uid-number": { @@ -100848,19 +100813,16 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz", + "integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==" }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", + "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", "requires": { - "lru-cache": "^6.0.0" + "lru-cache": "^7.4.0" } }, "supports-color": { @@ -100870,11 +100832,6 @@ "requires": { "has-flag": "^4.0.0" } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -101001,9 +100958,9 @@ "integrity": "sha512-6+X1FLlIcjvFMAeAD/hcxDT8tmyrWnbSPMU0EnxQuDLIxokuFzWliXBiYZuGIx+mrAMLBw0WFfCkaPw8ebzAhw==" }, "use-isomorphic-layout-effect": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz", - "integrity": "sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz", + "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==" }, "use-latest": { "version": "1.2.0", @@ -101433,12 +101390,12 @@ } }, "vue-docgen-loader": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/vue-docgen-loader/-/vue-docgen-loader-1.5.0.tgz", - "integrity": "sha512-LKZ8mxeIQ44uSUMTplnwOXbC4bO4E2vyZDTbn7/1QlVwJPEIjk3ahL0DA1m27IEw6YTlHOwtWS0PrHmDkFgyAg==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/vue-docgen-loader/-/vue-docgen-loader-1.5.1.tgz", + "integrity": "sha512-coMmQYsg+fy18SVtBNU7/tztdqEyrneFfwQFLmx8O7jaJ11VZ//9tRWXlwGzJM07cPRwMHDKMlAdWrpuw3U46A==", "requires": { "clone": "^2.1.2", - "jscodeshift": "^0.7.0", + "jscodeshift": "^0.13.1", "loader-utils": "^1.2.3", "querystring": "^0.2.0" }, @@ -101505,9 +101462,9 @@ "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==" }, "vue-i18n": { - "version": "8.27.0", - "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.27.0.tgz", - "integrity": "sha512-SX35iJHL5PJ4Gfh0Mo/q0shyHiI2V6Zkh51c+k8E9O1RKv5BQyYrCxRzpvPrsIOJEnLaeiovet3dsUB0e/kDzw==" + "version": "8.27.1", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.27.1.tgz", + "integrity": "sha512-lWrGm4F25qReJ7XxSnFVb2h3PfW54ldnM4C+YLBGGJ75+Myt/kj4hHSTKqsyDLamvNYpvINMicSOdW+7yuqgIQ==" }, "vue-inbrowser-compiler-demi": { "version": "4.44.23", @@ -103215,9 +103172,9 @@ } }, "winston": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.6.0.tgz", - "integrity": "sha512-9j8T75p+bcN6D00sF/zjFVmPp+t8KMPB1MzbbzYjeN9VWxdsYnTB40TkbNUEXAmILEfChMvAMgidlX64OG3p6w==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.7.2.tgz", + "integrity": "sha512-QziIqtojHBoyzUOdQvQiar1DH0Xp9nF1A1y7NVy2DGEsz82SBDtOalS0ulTRGVT14xPX3WRWkCsdcJKqNflKng==", "requires": { "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", diff --git a/packages/cli/BREAKING-CHANGES.md b/packages/cli/BREAKING-CHANGES.md index 2a339c371f..53e0577a53 100644 --- a/packages/cli/BREAKING-CHANGES.md +++ b/packages/cli/BREAKING-CHANGES.md @@ -2,13 +2,27 @@ This list shows all the versions which include breaking changes and how to upgrade. +## 0.171.0 + +### What changed? + +The GraphQL node now errors when the response includes an error. + +### When is action necessary? + +If you are using the GraphQL node. + +### How to upgrade: + +Go to the workflows that use the GraphQL node and adjust them to the new behavior. If you want to continue even on error, you can set "Continue on Fail" to true. + ## 0.165.0 ### What changed? The Hive node now correctly rejects invalid SSL certificates when the "Ignore SSL Issues" option is set to False. -### When is action necassary? +### When is action necessary? If you are using a self signed certificate with The Hive. @@ -28,7 +42,7 @@ If you are using the Hubspot Trigger. ### How to upgrade: -Create an app in HubSpot, use the Client ID, Client Secret, App ID, and the Developer Key, and complete the OAuth2 flow. +Create an app in HubSpot, use the Client ID, Client Secret, App ID, and the Developer Key, and complete the OAuth2 flow. ## 0.135.0 @@ -59,15 +73,14 @@ const credentials = await this.getCredentials(myNodeCredentials); Example: ```typescript - const items = this.getInputData(); for (const i = 0; i < items.length; i++) { - const item = items[i].binary as IBinaryKeyData; - const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string; - const binaryData = item[binaryPropertyName] as IBinaryData; + const item = items[i].binary as IBinaryKeyData; + const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i) as string; + const binaryData = item[binaryPropertyName] as IBinaryData; // Before 0.135.0: - const binaryDataBuffer = Buffer.from(binaryData.data, BINARY_ENCODING); + const binaryDataBuffer = Buffer.from(binaryData.data, BINARY_ENCODING); // From 0.135.0: const binaryDataBuffer = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName); } @@ -106,17 +119,21 @@ If you are using `lead:create` with "Company" or "Address", reset the parameters ## 0.118.0 ### What changed? + The minimum Node.js version required for n8n is now v14. ### When is action necessary? + If you're using n8n via npm or PM2 or if you're contributing to n8n. ### How to upgrade: + Update the Node.js version to v14 or above. ----------------------------- +--- ### What changed? + In the Postgres, CrateDB, QuestDB and TimescaleDB nodes the `Execute Query` operation returns the result from all queries executed instead of just one of the results. ### When is action necessary? @@ -126,6 +143,7 @@ If you use any of the above mentioned nodes with the `Execute Query` operation a ## 0.117.0 ### What changed? + Removed the "Activation Trigger" node. This node was replaced by two other nodes. The "Activation Trigger" node was added on version 0.113.0 but was not fully compliant to UX, so we decided to refactor and change it ASAP so it affects the least possible users. @@ -140,7 +158,7 @@ If you use the "Activation Trigger" in any of your workflows, please replace it Remove the previous node and add the new ones according to your workflows. ----------------------------- +--- Changed the behavior for nodes that use Postgres Wire Protocol: Postgres, QuestDB, CrateDB and TimescaleDB. @@ -158,10 +176,10 @@ By default, all `insert` operations will have `Return fields: *` as the default, Previously, the node would return all information it received, without taking into account what actually happened in the database. - ## 0.113.0 ### What changed? + In the Dropbox node, both credential types (Access Token & OAuth2) have a new parameter called "APP Access Type". ### When is action necessary? @@ -175,6 +193,7 @@ Open your Dropbox node's credentials and set the "APP Access Type" parameter to ## 0.111.0 ### What changed? + In the Dropbox node, now all operations are performed relative to the user's root directory. ### When is action necessary? @@ -192,24 +211,29 @@ Also, if you are using the `folder:list` operation, make sure your logic is taki ## 0.105.0 ### What changed? + In the Hubspot Trigger, now multiple events can be provided and the field `App ID` was so moved to the credentials. ### When is action necessary? + If you are using the Hubspot Trigger node. ### How to upgrade: -Open the Hubspot Trigger and set the events again. Also open the credentials `Hubspot Developer API` and set your APP ID. +Open the Hubspot Trigger and set the events again. Also open the credentials `Hubspot Developer API` and set your APP ID. ## 0.104.0 ### What changed? + Support for MongoDB as a database for n8n has been dropped as MongoDB had problems saving large amounts of data in a document, among other issues. ### When is action necessary? + If you have been using MongoDB as a database for n8n. Please note that this is not related to the MongoDB node. ### How to upgrade: + Before upgrading, you can [export](https://docs.n8n.io/reference/start-workflows-via-cli.html#export-workflows-and-credentials) all your credentials and workflows using the CLI. ``` @@ -227,21 +251,26 @@ n8n import:credentials --separate --input=backups/latest/ ## 0.102.0 ### What changed? -- The `As User` property and the `User Name` field got combined and renamed to `Send as User`. It also got moved under “Add Options”. + +- The `As User` property and the `User Name` field got combined and renamed to `Send as User`. It also got moved under “Add Options”. - The `Ephemeral` property got removed. To send an ephemeral message, you have to select the "Post (Ephemeral)" operation. ### When is action necessary? + If you are using the following fields or properties in the Slack node: + - As User - Ephemeral - User Name ### How to upgrade: + Open the Slack node and set them again to the appropriate values. ----------------------------- +--- ### What changed? + If you have a question in Typeform that uses a previously answered question as part of its text, the question text would look like this in the Typeform Trigger node: `You have chosen {{field:23234242}} as your answer. Is this correct?` @@ -251,9 +280,11 @@ Those curly braces broke the expression editor. The change makes it now display `You have chosen [field:23234242] as your answer. Is this correct?` ### When is action necessary? + If you are using the Typeform Trigger node with questions using the [Recall information](https://help.typeform.com/hc/en-us/articles/360050447072-What-is-Recall-information-) feature. ### How to upgrade: + In workflows using the Typeform Trigger node, nodes that reference such key names (questions that use a previously answered question as part of its text) will need to be updated. ## 0.95.0 @@ -281,11 +312,11 @@ In the Segment Node, we have changed how the properties 'traits' and 'properties When the properties 'traits' or 'properties' are set, and one of the following resources/operations is used: | Resource | Operation | -|--|--| -| Identify | Create | -| Track | Event | -| Track | Page | -| Group | Add | +| -------- | --------- | +| Identify | Create | +| Track | Event | +| Track | Page | +| Group | Add | ### How to upgrade: @@ -305,7 +336,6 @@ If you had set "Basic Auth" for the "Authentication" field in the node. The "Authentication" field has been renamed to "Incoming Authentication". Please set the parameter “Incoming Authentication” to “Basic Auth” to activate it again. - ## 0.90.0 ### What changed? @@ -320,7 +350,6 @@ If you are running Node.js version older than 12.9. You can find download and install the latest version of Node.js from [here](https://nodejs.org/en/download/). - ## 0.87.0 ### What changed? @@ -335,7 +364,6 @@ If you are are actively using the link.fish node. Unfortunately, that's not possible. We'd recommend you to look for an alternative service. - ## 0.83.0 ### What changed? @@ -346,13 +374,13 @@ In the Active Campaign Node, we have changed how the `getAll` operation works wi When one of the following resources/operations is used: -| Resource | Operation | -|--|--| -| Deal | Get All | -| Connector | Get All | -| E-commerce Order | Get All | -| E-commerce Customer | Get All | -| E-commerce Order Products | Get All | +| Resource | Operation | +| ------------------------- | --------- | +| Deal | Get All | +| Connector | Get All | +| E-commerce Order | Get All | +| E-commerce Customer | Get All | +| E-commerce Order Products | Get All | ### How to upgrade: @@ -393,7 +421,6 @@ If you have used the Attachments option in your Twitter nodes. You'll need to re-create the attachments for the Twitter node. - ## 0.68.0 ### What changed? @@ -413,36 +440,39 @@ All values that get referenced which were before under the property "channel" ar This means that these expressions have to get adjusted. Meaning if the expression used before was: + ``` {{ $node["Slack"].data["channel"]["id"] }} ``` + it has to get changed to: + ``` {{ $node["Slack"].data["id"] }} ``` - ## 0.67.0 ### What changed? The names of the following nodes were not set correctly and got fixed: - - AMQP Sender - - Bitbucket-Trigger - - Coda - - Eventbrite-Trigger - - Flow - - Flow-Trigger - - Gumroad-Trigger - - Jira - - Mailchimp-Trigger - - PayPal Trigger - - Read PDF - - Rocketchat - - Shopify - - Shopify-Trigger - - Stripe-Trigger - - Toggl-Trigger + +- AMQP Sender +- Bitbucket-Trigger +- Coda +- Eventbrite-Trigger +- Flow +- Flow-Trigger +- Gumroad-Trigger +- Jira +- Mailchimp-Trigger +- PayPal Trigger +- Read PDF +- Rocketchat +- Shopify +- Shopify-Trigger +- Stripe-Trigger +- Toggl-Trigger ### When is action necessary? @@ -454,32 +484,32 @@ For the nodes mentioned above, you'll need to give them access to the credential **Simple** - - Note down the settings of the nodes before upgrading - - After upgrading, delete the nodes mentioned above from your workflow, and recreate them +- Note down the settings of the nodes before upgrading +- After upgrading, delete the nodes mentioned above from your workflow, and recreate them **Advanced** After upgrading, select the whole workflow in the editor, copy it, and paste it into a text editor. In the JSON, change the node types manually by replacing the values for "type" as follows: - - "n8n-nodes-base.amqpSender" -> "n8n-nodes-base.amqp" - - "n8n-nodes-base.bitbucket" -> "n8n-nodes-base.bitbucketTrigger" - - "n8n-nodes-base.Coda" -> "n8n-nodes-base.coda" - - "n8n-nodes-base.eventbrite" -> "n8n-nodes-base.eventbriteTrigger" - - "n8n-nodes-base.Flow" -> "n8n-nodes-base.flow" - - "n8n-nodes-base.flow" -> "n8n-nodes-base.flowTrigger" - - "n8n-nodes-base.gumroad" -> "n8n-nodes-base.gumroadTrigger" - - "n8n-nodes-base.Jira Software Cloud" -> "n8n-nodes-base.jira" - - "n8n-nodes-base.Mailchimp" -> "n8n-nodes-base.mailchimpTrigger" - - "n8n-nodes-base.PayPal" -> "n8n-nodes-base.payPalTrigger" - - "n8n-nodes-base.Read PDF" -> "n8n-nodes-base.readPDF" - - "n8n-nodes-base.Rocketchat" -> "n8n-nodes-base.rocketchat" - - "n8n-nodes-base.shopify" -> "n8n-nodes-base.shopifyTrigger" - - "n8n-nodes-base.shopifyNode" -> "n8n-nodes-base.shopify" - - "n8n-nodes-base.stripe" -> "n8n-nodes-base.stripeTrigger" - - "n8n-nodes-base.toggl" -> "n8n-nodes-base.togglTrigger" + +- "n8n-nodes-base.amqpSender" -> "n8n-nodes-base.amqp" +- "n8n-nodes-base.bitbucket" -> "n8n-nodes-base.bitbucketTrigger" +- "n8n-nodes-base.Coda" -> "n8n-nodes-base.coda" +- "n8n-nodes-base.eventbrite" -> "n8n-nodes-base.eventbriteTrigger" +- "n8n-nodes-base.Flow" -> "n8n-nodes-base.flow" +- "n8n-nodes-base.flow" -> "n8n-nodes-base.flowTrigger" +- "n8n-nodes-base.gumroad" -> "n8n-nodes-base.gumroadTrigger" +- "n8n-nodes-base.Jira Software Cloud" -> "n8n-nodes-base.jira" +- "n8n-nodes-base.Mailchimp" -> "n8n-nodes-base.mailchimpTrigger" +- "n8n-nodes-base.PayPal" -> "n8n-nodes-base.payPalTrigger" +- "n8n-nodes-base.Read PDF" -> "n8n-nodes-base.readPDF" +- "n8n-nodes-base.Rocketchat" -> "n8n-nodes-base.rocketchat" +- "n8n-nodes-base.shopify" -> "n8n-nodes-base.shopifyTrigger" +- "n8n-nodes-base.shopifyNode" -> "n8n-nodes-base.shopify" +- "n8n-nodes-base.stripe" -> "n8n-nodes-base.stripeTrigger" +- "n8n-nodes-base.toggl" -> "n8n-nodes-base.togglTrigger" Then delete all existing nodes, and then paste the changed JSON directly into n8n. It should then recreate all the nodes and connections again, this time with working nodes. - ## 0.62.0 ### What changed? @@ -496,7 +526,6 @@ If "evaluateExpression(...)" gets used in any Function or FunctionItem Node. Simply replace the "evaluateExpression(...)" with "$evaluateExpression(...)". - ## 0.52.0 ### What changed? @@ -517,7 +546,6 @@ Open the "Date & Time"-Nodes and reference the date that should be converted via an expression. Also, set the "Property Name" to the name of the property the converted date should be set on. - ## 0.37.0 ### What changed? @@ -534,7 +562,6 @@ When you currently use the Rocketchat-Node. Open the Rocketchat credentials and fill the parameter `domain`. If you had previously the subdomain "example" set you have to set now "https://example.rocket.chat". - ## 0.19.0 ### What changed? @@ -556,9 +583,7 @@ it and paste it in a text-editor, it will display all the data the node contained). Then set the "Response Format" to "File". Everything will then function again like before. - ----------------------------- - +--- ### What changed? @@ -576,7 +601,6 @@ When "HTTP Request" nodes get used which have "Response Format" set to "String". After upgrading open all workflows which contain the concerning Nodes and set "Binary Property" to "response". - ## 0.18.0 ### What changed? @@ -591,8 +615,7 @@ When Webhook-Nodes get used which have "Response Mode" set to "Last Node". After upgrading open all workflows which contain the concerning Webhook-Nodes and set "Response Mode" again manually to "Last Node". - ----------------------------- +--- ### What changed? @@ -603,6 +626,7 @@ packages with security vulnerabilities we had to switch to a different one. When you currently start n8n in your setup directly via its JavaScript file. For example like this: + ``` /usr/local/bin/node ./dist/index.js start ``` @@ -610,6 +634,7 @@ For example like this: ### How to upgrade: Change the path to its new location: + ``` /usr/local/bin/node bin/n8n start ``` diff --git a/packages/cli/commands/execute.ts b/packages/cli/commands/execute.ts index 2d647cb233..ed8737bc2b 100644 --- a/packages/cli/commands/execute.ts +++ b/packages/cli/commands/execute.ts @@ -2,12 +2,7 @@ /* eslint-disable no-console */ import { promises as fs } from 'fs'; import { Command, flags } from '@oclif/command'; -import { - BinaryDataManager, - IBinaryDataConfig, - UserSettings, - PLACEHOLDER_EMPTY_WORKFLOW_ID, -} from 'n8n-core'; +import { BinaryDataManager, UserSettings, PLACEHOLDER_EMPTY_WORKFLOW_ID } from 'n8n-core'; import { INode, LoggerProxy } from 'n8n-workflow'; import { @@ -27,7 +22,7 @@ import { } from '../src'; import { getLogger } from '../src/Logger'; -import config = require('../config'); +import config from '../config'; import { getInstanceOwner } from '../src/UserManagement/UserManagementHelper'; export class Execute extends Command { @@ -52,7 +47,7 @@ export class Execute extends Command { async run() { const logger = getLogger(); LoggerProxy.init(logger); - const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig; + const binaryDataConfig = config.getEnv('binaryDataManager'); await BinaryDataManager.init(binaryDataConfig, true); // eslint-disable-next-line @typescript-eslint/no-shadow diff --git a/packages/cli/commands/executeBatch.ts b/packages/cli/commands/executeBatch.ts index e5cb5ca1ee..26f4edb594 100644 --- a/packages/cli/commands/executeBatch.ts +++ b/packages/cli/commands/executeBatch.ts @@ -6,10 +6,10 @@ /* eslint-disable no-param-reassign */ /* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable no-console */ -import * as fs from 'fs'; +import fs from 'fs'; import { Command, flags } from '@oclif/command'; -import { BinaryDataManager, IBinaryDataConfig, UserSettings } from 'n8n-core'; +import { BinaryDataManager, UserSettings } from 'n8n-core'; // eslint-disable-next-line @typescript-eslint/no-unused-vars import { INode, ITaskData, LoggerProxy } from 'n8n-workflow'; @@ -36,7 +36,7 @@ import { NodeTypes, WorkflowRunner, } from '../src'; -import config = require('../config'); +import config from '../config'; import { User } from '../src/databases/entities/User'; import { getInstanceOwner } from '../src/UserManagement/UserManagementHelper'; @@ -196,7 +196,7 @@ export class ExecuteBatch extends Command { const logger = getLogger(); LoggerProxy.init(logger); - const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig; + const binaryDataConfig = config.getEnv('binaryDataManager'); await BinaryDataManager.init(binaryDataConfig, true); // eslint-disable-next-line @typescript-eslint/no-shadow diff --git a/packages/cli/commands/export/credentials.ts b/packages/cli/commands/export/credentials.ts index b8ebb95ec9..70cff781e1 100644 --- a/packages/cli/commands/export/credentials.ts +++ b/packages/cli/commands/export/credentials.ts @@ -7,8 +7,8 @@ import { Credentials, UserSettings } from 'n8n-core'; import { IDataObject, LoggerProxy } from 'n8n-workflow'; -import * as fs from 'fs'; -import * as path from 'path'; +import fs from 'fs'; +import path from 'path'; import { getLogger } from '../../src/Logger'; import { Db, ICredentialsDecryptedDb } from '../../src'; diff --git a/packages/cli/commands/export/workflow.ts b/packages/cli/commands/export/workflow.ts index c9591e595b..39514c0398 100644 --- a/packages/cli/commands/export/workflow.ts +++ b/packages/cli/commands/export/workflow.ts @@ -4,8 +4,8 @@ import { Command, flags } from '@oclif/command'; import { IDataObject, LoggerProxy } from 'n8n-workflow'; -import * as fs from 'fs'; -import * as path from 'path'; +import fs from 'fs'; +import path from 'path'; import { getLogger } from '../../src/Logger'; import { Db } from '../../src'; diff --git a/packages/cli/commands/import/credentials.ts b/packages/cli/commands/import/credentials.ts index be36b53771..98f735fe5d 100644 --- a/packages/cli/commands/import/credentials.ts +++ b/packages/cli/commands/import/credentials.ts @@ -12,9 +12,9 @@ import { Credentials, UserSettings } from 'n8n-core'; import { LoggerProxy } from 'n8n-workflow'; -import * as fs from 'fs'; -import * as glob from 'fast-glob'; -import * as path from 'path'; +import fs from 'fs'; +import glob from 'fast-glob'; +import path from 'path'; import { EntityManager, getConnection } from 'typeorm'; import { getLogger } from '../../src/Logger'; import { Db } from '../../src'; diff --git a/packages/cli/commands/import/workflow.ts b/packages/cli/commands/import/workflow.ts index a58f073167..f07a26c4f0 100644 --- a/packages/cli/commands/import/workflow.ts +++ b/packages/cli/commands/import/workflow.ts @@ -12,8 +12,8 @@ import { Command, flags } from '@oclif/command'; import { INode, INodeCredentialsDetails, LoggerProxy } from 'n8n-workflow'; -import * as fs from 'fs'; -import * as glob from 'fast-glob'; +import fs from 'fs'; +import glob from 'fast-glob'; import { UserSettings } from 'n8n-core'; import { EntityManager, getConnection } from 'typeorm'; import { getLogger } from '../../src/Logger'; diff --git a/packages/cli/commands/start.ts b/packages/cli/commands/start.ts index 66dcd81eb1..5eab0995e1 100644 --- a/packages/cli/commands/start.ts +++ b/packages/cli/commands/start.ts @@ -6,15 +6,15 @@ /* eslint-disable no-console */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import * as localtunnel from 'localtunnel'; -import { BinaryDataManager, IBinaryDataConfig, TUNNEL_SUBDOMAIN_ENV, UserSettings } from 'n8n-core'; +import localtunnel from 'localtunnel'; +import { BinaryDataManager, TUNNEL_SUBDOMAIN_ENV, UserSettings } from 'n8n-core'; import { Command, flags } from '@oclif/command'; // eslint-disable-next-line import/no-extraneous-dependencies -import * as Redis from 'ioredis'; +import Redis from 'ioredis'; import { IDataObject, LoggerProxy } from 'n8n-workflow'; import { createHash } from 'crypto'; -import * as config from '../config'; +import config from '../config'; import { ActiveExecutions, ActiveWorkflowRunner, @@ -100,9 +100,9 @@ export class Start extends Command { await InternalHooksManager.getInstance().onN8nStop(); - const skipWebhookDeregistration = config.get( + const skipWebhookDeregistration = config.getEnv( 'endpoints.skipWebhoooksDeregistrationOnShutdown', - ) as boolean; + ); const removePromises = []; if (activeWorkflowRunner !== undefined && !skipWebhookDeregistration) { @@ -169,7 +169,7 @@ export class Start extends Command { // Make sure the settings exist const userSettings = await UserSettings.prepareUserSettings(); - if (!config.get('userManagement.jwtSecret')) { + if (!config.getEnv('userManagement.jwtSecret')) { // If we don't have a JWT secret set, generate // one based and save to config. const encryptionKey = await UserSettings.getEncryptionKey(); @@ -222,12 +222,12 @@ export class Start extends Command { config.set(setting.key, JSON.parse(setting.value)); }); - if (config.get('executions.mode') === 'queue') { - const redisHost = config.get('queue.bull.redis.host'); - const redisPassword = config.get('queue.bull.redis.password'); - const redisPort = config.get('queue.bull.redis.port'); - const redisDB = config.get('queue.bull.redis.db'); - const redisConnectionTimeoutLimit = config.get('queue.bull.redis.timeoutThreshold'); + if (config.getEnv('executions.mode') === 'queue') { + const redisHost = config.getEnv('queue.bull.redis.host'); + const redisPassword = config.getEnv('queue.bull.redis.password'); + const redisPort = config.getEnv('queue.bull.redis.port'); + const redisDB = config.getEnv('queue.bull.redis.db'); + const redisConnectionTimeoutLimit = config.getEnv('queue.bull.redis.timeoutThreshold'); let lastTimer = 0; let cumulativeTimeout = 0; @@ -285,7 +285,7 @@ export class Start extends Command { const dbType = (await GenericHelpers.getConfigValue('database.type')) as DatabaseType; if (dbType === 'sqlite') { - const shouldRunVacuum = config.get('database.sqlite.executeVacuumOnStartup') as number; + const shouldRunVacuum = config.getEnv('database.sqlite.executeVacuumOnStartup'); if (shouldRunVacuum) { // eslint-disable-next-line @typescript-eslint/no-floating-promises, @typescript-eslint/no-non-null-assertion await Db.collections.Execution!.query('VACUUM;'); @@ -324,7 +324,7 @@ export class Start extends Command { subdomain: tunnelSubdomain, }; - const port = config.get('port'); + const port = config.getEnv('port'); // @ts-ignore const webhookTunnel = await localtunnel(port, tunnelSettings); @@ -340,7 +340,7 @@ export class Start extends Command { const { cli } = await GenericHelpers.getVersions(); InternalHooksManager.init(instanceId, cli, nodeTypes); - const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig; + const binaryDataConfig = config.getEnv('binaryDataManager'); await BinaryDataManager.init(binaryDataConfig, true); await Server.start(); @@ -354,7 +354,7 @@ export class Start extends Command { const editorUrl = GenericHelpers.getBaseUrl(); this.log(`\nEditor is now accessible via:\n${editorUrl}`); - const saveManualExecutions = config.get('executions.saveDataManualExecutions') as boolean; + const saveManualExecutions = config.getEnv('executions.saveDataManualExecutions'); if (saveManualExecutions) { this.log('\nManual executions will be visible only for the owner'); diff --git a/packages/cli/commands/webhook.ts b/packages/cli/commands/webhook.ts index 76feafdc3b..d6cca79f0c 100644 --- a/packages/cli/commands/webhook.ts +++ b/packages/cli/commands/webhook.ts @@ -3,13 +3,13 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/unbound-method */ -import { BinaryDataManager, IBinaryDataConfig, UserSettings } from 'n8n-core'; +import { BinaryDataManager, UserSettings } from 'n8n-core'; import { Command, flags } from '@oclif/command'; // eslint-disable-next-line import/no-extraneous-dependencies -import * as Redis from 'ioredis'; +import Redis from 'ioredis'; import { IDataObject, LoggerProxy } from 'n8n-workflow'; -import * as config from '../config'; +import config from '../config'; import { ActiveExecutions, ActiveWorkflowRunner, @@ -95,7 +95,7 @@ export class Webhook extends Command { // Wrap that the process does not close but we can still use async await (async () => { - if (config.get('executions.mode') !== 'queue') { + if (config.getEnv('executions.mode') !== 'queue') { /** * It is technically possible to run without queues but * there are 2 known bugs when running in this mode: @@ -152,15 +152,15 @@ export class Webhook extends Command { const { cli } = await GenericHelpers.getVersions(); InternalHooksManager.init(instanceId, cli, nodeTypes); - const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig; + const binaryDataConfig = config.getEnv('binaryDataManager'); await BinaryDataManager.init(binaryDataConfig); - if (config.get('executions.mode') === 'queue') { - const redisHost = config.get('queue.bull.redis.host'); - const redisPassword = config.get('queue.bull.redis.password'); - const redisPort = config.get('queue.bull.redis.port'); - const redisDB = config.get('queue.bull.redis.db'); - const redisConnectionTimeoutLimit = config.get('queue.bull.redis.timeoutThreshold'); + if (config.getEnv('executions.mode') === 'queue') { + const redisHost = config.getEnv('queue.bull.redis.host'); + const redisPassword = config.getEnv('queue.bull.redis.password'); + const redisPort = config.getEnv('queue.bull.redis.port'); + const redisDB = config.getEnv('queue.bull.redis.db'); + const redisConnectionTimeoutLimit = config.getEnv('queue.bull.redis.timeoutThreshold'); let lastTimer = 0; let cumulativeTimeout = 0; diff --git a/packages/cli/commands/worker.ts b/packages/cli/commands/worker.ts index 06a4f2e6fe..5da36884e4 100644 --- a/packages/cli/commands/worker.ts +++ b/packages/cli/commands/worker.ts @@ -7,9 +7,9 @@ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/no-unused-vars */ // eslint-disable-next-line import/no-extraneous-dependencies -import * as express from 'express'; -import * as http from 'http'; -import * as PCancelable from 'p-cancelable'; +import express from 'express'; +import http from 'http'; +import PCancelable from 'p-cancelable'; import { Command, flags } from '@oclif/command'; import { BinaryDataManager, IBinaryDataConfig, UserSettings, WorkflowExecute } from 'n8n-core'; @@ -18,7 +18,7 @@ import { IExecuteResponsePromiseData, INodeTypes, IRun, Workflow, LoggerProxy } import { FindOneOptions, getConnectionManager } from 'typeorm'; -import * as Bull from 'bull'; +import Bull from 'bull'; import { CredentialsOverwrites, CredentialTypes, @@ -39,7 +39,7 @@ import { import { getLogger } from '../src/Logger'; -import * as config from '../config'; +import config from '../config'; import * as Queue from '../src/Queue'; import { checkPermissionsForExecution, @@ -158,7 +158,7 @@ export class Worker extends Command { staticData = workflowData.staticData; } - let workflowTimeout = config.get('executions.timeout') as number; // initialize with default + let workflowTimeout = config.getEnv('executions.timeout'); // initialize with default if ( // eslint-disable-next-line @typescript-eslint/prefer-optional-chain currentExecutionDb.workflowData.settings && @@ -169,7 +169,7 @@ export class Worker extends Command { let executionTimeoutTimestamp: number | undefined; if (workflowTimeout > 0) { - workflowTimeout = Math.min(workflowTimeout, config.get('executions.maxTimeout') as number); + workflowTimeout = Math.min(workflowTimeout, config.getEnv('executions.maxTimeout')); executionTimeoutTimestamp = Date.now() + workflowTimeout * 1000; } @@ -288,7 +288,7 @@ export class Worker extends Command { await startDbInitPromise; // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const redisConnectionTimeoutLimit = config.get('queue.bull.redis.timeoutThreshold'); + const redisConnectionTimeoutLimit = config.getEnv('queue.bull.redis.timeoutThreshold'); Worker.jobQueue = Queue.getInstance().getBullObjectInstance(); // eslint-disable-next-line @typescript-eslint/no-floating-promises @@ -299,7 +299,7 @@ export class Worker extends Command { InternalHooksManager.init(instanceId, versions.cli, nodeTypes); - const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig; + const binaryDataConfig = config.getEnv('binaryDataManager'); await BinaryDataManager.init(binaryDataConfig); console.info('\nn8n worker is now ready'); @@ -352,8 +352,8 @@ export class Worker extends Command { } }); - if (config.get('queue.health.active')) { - const port = config.get('queue.health.port') as number; + if (config.getEnv('queue.health.active')) { + const port = config.getEnv('queue.health.port'); const app = express(); const server = http.createServer(app); diff --git a/packages/cli/config/index.ts b/packages/cli/config/index.ts index 1e5b25f933..01cb5e784b 100644 --- a/packages/cli/config/index.ts +++ b/packages/cli/config/index.ts @@ -1,890 +1,14 @@ +/* eslint-disable @typescript-eslint/unbound-method */ /* eslint-disable no-console */ -/* eslint-disable no-restricted-syntax */ -/* eslint-disable @typescript-eslint/no-unsafe-assignment */ -import * as convict from 'convict'; -import * as dotenv from 'dotenv'; -import * as path from 'path'; -import * as core from 'n8n-core'; +import convict from 'convict'; +import dotenv from 'dotenv'; +import { schema } from './schema'; dotenv.config(); -const config = convict({ - database: { - type: { - doc: 'Type of database to use', - format: ['sqlite', 'mariadb', 'mysqldb', 'postgresdb'], - default: 'sqlite', - env: 'DB_TYPE', - }, - tablePrefix: { - doc: 'Prefix for table names', - format: '*', - default: '', - env: 'DB_TABLE_PREFIX', - }, - logging: { - enabled: { - doc: 'Typeorm logging enabled flag.', - format: 'Boolean', - default: false, - env: 'DB_LOGGING_ENABLED', - }, - options: { - doc: 'Logging level options, default is "error". Possible values: query,error,schema,warn,info,log. To enable all logging, specify "all"', - format: String, - default: 'error', - env: 'DB_LOGGING_OPTIONS', - }, - maxQueryExecutionTime: { - doc: 'Maximum number of milliseconds query should be executed before logger logs a warning. Set 0 to disable long running query warning', - format: Number, - default: 1000, - env: 'DB_LOGGING_MAX_EXECUTION_TIME', - }, - }, - postgresdb: { - database: { - doc: 'PostgresDB Database', - format: String, - default: 'n8n', - env: 'DB_POSTGRESDB_DATABASE', - }, - host: { - doc: 'PostgresDB Host', - format: String, - default: 'localhost', - env: 'DB_POSTGRESDB_HOST', - }, - password: { - doc: 'PostgresDB Password', - format: String, - default: '', - env: 'DB_POSTGRESDB_PASSWORD', - }, - port: { - doc: 'PostgresDB Port', - format: Number, - default: 5432, - env: 'DB_POSTGRESDB_PORT', - }, - user: { - doc: 'PostgresDB User', - format: String, - default: 'root', - env: 'DB_POSTGRESDB_USER', - }, - schema: { - doc: 'PostgresDB Schema', - format: String, - default: 'public', - env: 'DB_POSTGRESDB_SCHEMA', - }, +const config = convict(schema); - ssl: { - ca: { - doc: 'SSL certificate authority', - format: String, - default: '', - env: 'DB_POSTGRESDB_SSL_CA', - }, - cert: { - doc: 'SSL certificate', - format: String, - default: '', - env: 'DB_POSTGRESDB_SSL_CERT', - }, - key: { - doc: 'SSL key', - format: String, - default: '', - env: 'DB_POSTGRESDB_SSL_KEY', - }, - rejectUnauthorized: { - doc: 'If unauthorized SSL connections should be rejected', - format: 'Boolean', - default: true, - env: 'DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED', - }, - }, - }, - mysqldb: { - database: { - doc: 'MySQL Database', - format: String, - default: 'n8n', - env: 'DB_MYSQLDB_DATABASE', - }, - host: { - doc: 'MySQL Host', - format: String, - default: 'localhost', - env: 'DB_MYSQLDB_HOST', - }, - password: { - doc: 'MySQL Password', - format: String, - default: '', - env: 'DB_MYSQLDB_PASSWORD', - }, - port: { - doc: 'MySQL Port', - format: Number, - default: 3306, - env: 'DB_MYSQLDB_PORT', - }, - user: { - doc: 'MySQL User', - format: String, - default: 'root', - env: 'DB_MYSQLDB_USER', - }, - }, - sqlite: { - executeVacuumOnStartup: { - doc: 'Runs VACUUM operation on startup to rebuild the database. Reduces filesize and optimizes indexes. WARNING: This is a long running blocking operation. Will increase start-up time.', - format: Boolean, - default: false, - env: 'DB_SQLITE_VACUUM_ON_STARTUP', - }, - }, - }, - - credentials: { - overwrite: { - data: { - // Allows to set default values for credentials which - // get automatically prefilled and the user does not get - // displayed and can not change. - // Format: { CREDENTIAL_NAME: { PARAMTER: VALUE }} - doc: 'Overwrites for credentials', - format: '*', - default: '{}', - env: 'CREDENTIALS_OVERWRITE_DATA', - }, - endpoint: { - doc: 'Fetch credentials from API', - format: String, - default: '', - env: 'CREDENTIALS_OVERWRITE_ENDPOINT', - }, - }, - defaultName: { - doc: 'Default name for credentials', - format: String, - default: 'My credentials', - env: 'CREDENTIALS_DEFAULT_NAME', - }, - }, - - workflows: { - defaultName: { - doc: 'Default name for workflow', - format: String, - default: 'My workflow', - env: 'WORKFLOWS_DEFAULT_NAME', - }, - }, - - executions: { - // By default workflows get always executed in their own process. - // If this option gets set to "main" it will run them in the - // main-process instead. - process: { - doc: 'In what process workflows should be executed', - format: ['main', 'own'], - default: 'own', - env: 'EXECUTIONS_PROCESS', - }, - - mode: { - doc: 'If it should run executions directly or via queue', - format: ['regular', 'queue'], - default: 'regular', - env: 'EXECUTIONS_MODE', - }, - - // A Workflow times out and gets canceled after this time (seconds). - // If the workflow is executed in the main process a soft timeout - // is executed (takes effect after the current node finishes). - // If a workflow is running in its own process is a soft timeout - // tried first, before killing the process after waiting for an - // additional fifth of the given timeout duration. - // - // To deactivate timeout set it to -1 - // - // Timeout is currently not activated by default which will change - // in a future version. - timeout: { - doc: 'Max run time (seconds) before stopping the workflow execution', - format: Number, - default: -1, - env: 'EXECUTIONS_TIMEOUT', - }, - maxTimeout: { - doc: 'Max execution time (seconds) that can be set for a workflow individually', - format: Number, - default: 3600, - env: 'EXECUTIONS_TIMEOUT_MAX', - }, - - // If a workflow executes all the data gets saved by default. This - // could be a problem when a workflow gets executed a lot and processes - // a lot of data. To not exceed the database's capacity it is possible to - // prune the database regularly or to not save the execution at all. - // Depending on if the execution did succeed or error a different - // save behaviour can be set. - saveDataOnError: { - doc: 'What workflow execution data to save on error', - format: ['all', 'none'], - default: 'all', - env: 'EXECUTIONS_DATA_SAVE_ON_ERROR', - }, - saveDataOnSuccess: { - doc: 'What workflow execution data to save on success', - format: ['all', 'none'], - default: 'all', - env: 'EXECUTIONS_DATA_SAVE_ON_SUCCESS', - }, - saveExecutionProgress: { - doc: 'Wether or not to save progress for each node executed', - format: 'Boolean', - default: false, - env: 'EXECUTIONS_DATA_SAVE_ON_PROGRESS', - }, - - // If the executions of workflows which got started via the editor - // should be saved. By default they will not be saved as this runs - // are normally only for testing and debugging. This setting can - // also be overwritten on a per workflow basis in the workflow settings - // in the editor. - saveDataManualExecutions: { - doc: 'Save data of executions when started manually via editor', - format: 'Boolean', - default: false, - env: 'EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS', - }, - - // To not exceed the database's capacity and keep its size moderate - // the execution data gets pruned regularly (default: 1 hour interval). - // All saved execution data older than the max age will be deleted. - // Pruning is currently not activated by default, which will change in - // a future version. - pruneData: { - doc: 'Delete data of past executions on a rolling basis', - format: 'Boolean', - default: false, - env: 'EXECUTIONS_DATA_PRUNE', - }, - pruneDataMaxAge: { - doc: 'How old (hours) the execution data has to be to get deleted', - format: Number, - default: 336, - env: 'EXECUTIONS_DATA_MAX_AGE', - }, - pruneDataTimeout: { - doc: 'Timeout (seconds) after execution data has been pruned', - format: Number, - default: 3600, - env: 'EXECUTIONS_DATA_PRUNE_TIMEOUT', - }, - }, - - queue: { - health: { - active: { - doc: 'If health checks should be enabled', - format: 'Boolean', - default: false, - env: 'QUEUE_HEALTH_CHECK_ACTIVE', - }, - port: { - doc: 'Port to serve health check on if activated', - format: Number, - default: 5678, - env: 'QUEUE_HEALTH_CHECK_PORT', - }, - }, - bull: { - prefix: { - doc: 'Prefix for all queue keys', - format: String, - default: '', - env: 'QUEUE_BULL_PREFIX', - }, - redis: { - db: { - doc: 'Redis DB', - format: Number, - default: 0, - env: 'QUEUE_BULL_REDIS_DB', - }, - host: { - doc: 'Redis Host', - format: String, - default: 'localhost', - env: 'QUEUE_BULL_REDIS_HOST', - }, - password: { - doc: 'Redis Password', - format: String, - default: '', - env: 'QUEUE_BULL_REDIS_PASSWORD', - }, - port: { - doc: 'Redis Port', - format: Number, - default: 6379, - env: 'QUEUE_BULL_REDIS_PORT', - }, - timeoutThreshold: { - doc: 'Redis timeout threshold', - format: Number, - default: 10000, - env: 'QUEUE_BULL_REDIS_TIMEOUT_THRESHOLD', - }, - }, - queueRecoveryInterval: { - doc: 'If > 0 enables an active polling to the queue that can recover for Redis crashes. Given in seconds; 0 is disabled. May increase Redis traffic significantly.', - format: Number, - default: 60, - env: 'QUEUE_RECOVERY_INTERVAL', - }, - }, - }, - - generic: { - // The timezone to use. Is important for nodes like "Cron" which start the - // workflow automatically at a specified time. This setting can also be - // overwritten on a per worfklow basis in the workflow settings in the - // editor. - timezone: { - doc: 'The timezone to use', - format: '*', - default: 'America/New_York', - env: 'GENERIC_TIMEZONE', - }, - }, - - // How n8n can be reached (Editor & REST-API) - path: { - format: String, - default: '/', - arg: 'path', - env: 'N8N_PATH', - doc: 'Path n8n is deployed to', - }, - host: { - format: String, - default: 'localhost', - arg: 'host', - env: 'N8N_HOST', - doc: 'Host name n8n can be reached', - }, - port: { - format: Number, - default: 5678, - arg: 'port', - env: 'N8N_PORT', - doc: 'HTTP port n8n can be reached', - }, - listen_address: { - format: String, - default: '0.0.0.0', - env: 'N8N_LISTEN_ADDRESS', - doc: 'IP address n8n should listen on', - }, - protocol: { - format: ['http', 'https'], - default: 'http', - env: 'N8N_PROTOCOL', - doc: 'HTTP Protocol via which n8n can be reached', - }, - ssl_key: { - format: String, - default: '', - env: 'N8N_SSL_KEY', - doc: 'SSL Key for HTTPS Protocol', - }, - ssl_cert: { - format: String, - default: '', - env: 'N8N_SSL_CERT', - doc: 'SSL Cert for HTTPS Protocol', - }, - editorBaseUrl: { - format: String, - default: '', - env: 'N8N_EDITOR_BASE_URL', - doc: 'Public URL where the editor is accessible. Also used for emails sent from n8n.', - }, - - security: { - excludeEndpoints: { - doc: 'Additional endpoints to exclude auth checks. Multiple endpoints can be separated by colon (":")', - format: String, - default: '', - env: 'N8N_AUTH_EXCLUDE_ENDPOINTS', - }, - basicAuth: { - active: { - format: 'Boolean', - default: false, - env: 'N8N_BASIC_AUTH_ACTIVE', - doc: 'If basic auth should be activated for editor and REST-API', - }, - user: { - format: String, - default: '', - env: 'N8N_BASIC_AUTH_USER', - doc: 'The name of the basic auth user', - }, - password: { - format: String, - default: '', - env: 'N8N_BASIC_AUTH_PASSWORD', - doc: 'The password of the basic auth user', - }, - hash: { - format: 'Boolean', - default: false, - env: 'N8N_BASIC_AUTH_HASH', - doc: 'If password for basic auth is hashed', - }, - }, - jwtAuth: { - active: { - format: 'Boolean', - default: false, - env: 'N8N_JWT_AUTH_ACTIVE', - doc: 'If JWT auth should be activated for editor and REST-API', - }, - jwtHeader: { - format: String, - default: '', - env: 'N8N_JWT_AUTH_HEADER', - doc: 'The request header containing a signed JWT', - }, - jwtHeaderValuePrefix: { - format: String, - default: '', - env: 'N8N_JWT_AUTH_HEADER_VALUE_PREFIX', - doc: 'The request header value prefix to strip (optional)', - }, - jwksUri: { - format: String, - default: '', - env: 'N8N_JWKS_URI', - doc: 'The URI to fetch JWK Set for JWT authentication', - }, - jwtIssuer: { - format: String, - default: '', - env: 'N8N_JWT_ISSUER', - doc: 'JWT issuer to expect (optional)', - }, - jwtNamespace: { - format: String, - default: '', - env: 'N8N_JWT_NAMESPACE', - doc: 'JWT namespace to expect (optional)', - }, - jwtAllowedTenantKey: { - format: String, - default: '', - env: 'N8N_JWT_ALLOWED_TENANT_KEY', - doc: 'JWT tenant key name to inspect within JWT namespace (optional)', - }, - jwtAllowedTenant: { - format: String, - default: '', - env: 'N8N_JWT_ALLOWED_TENANT', - doc: 'JWT tenant to allow (optional)', - }, - }, - }, - - endpoints: { - payloadSizeMax: { - format: Number, - default: 16, - env: 'N8N_PAYLOAD_SIZE_MAX', - doc: 'Maximum payload size in MB.', - }, - metrics: { - enable: { - format: 'Boolean', - default: false, - env: 'N8N_METRICS', - doc: 'Enable metrics endpoint', - }, - prefix: { - format: String, - default: 'n8n_', - env: 'N8N_METRICS_PREFIX', - doc: 'An optional prefix for metric names. Default: n8n_', - }, - }, - rest: { - format: String, - default: 'rest', - env: 'N8N_ENDPOINT_REST', - doc: 'Path for rest endpoint', - }, - webhook: { - format: String, - default: 'webhook', - env: 'N8N_ENDPOINT_WEBHOOK', - doc: 'Path for webhook endpoint', - }, - webhookWaiting: { - format: String, - default: 'webhook-waiting', - env: 'N8N_ENDPOINT_WEBHOOK_WAIT', - doc: 'Path for waiting-webhook endpoint', - }, - webhookTest: { - format: String, - default: 'webhook-test', - env: 'N8N_ENDPOINT_WEBHOOK_TEST', - doc: 'Path for test-webhook endpoint', - }, - disableUi: { - format: Boolean, - default: false, - env: 'N8N_DISABLE_UI', - doc: 'Disable N8N UI (Frontend).', - }, - disableProductionWebhooksOnMainProcess: { - format: Boolean, - default: false, - env: 'N8N_DISABLE_PRODUCTION_MAIN_PROCESS', - doc: 'Disable production webhooks from main process. This helps ensures no http traffic load to main process when using webhook-specific processes.', - }, - skipWebhoooksDeregistrationOnShutdown: { - /** - * Longer explanation: n8n deregisters webhooks on shutdown / deactivation - * and registers on startup / activation. If we skip - * deactivation on shutdown, webhooks will remain active on 3rd party services. - * We don't have to worry about startup as it always - * checks if webhooks already exist. - * If users want to upgrade n8n, it is possible to run - * two instances simultaneously without downtime, similar - * to blue/green deployment. - * WARNING: Trigger nodes (like Cron) will cause duplication - * of work, so be aware when using. - */ - doc: 'Deregister webhooks on external services only when workflows are deactivated.', - format: Boolean, - default: false, - env: 'N8N_SKIP_WEBHOOK_DEREGISTRATION_SHUTDOWN', - }, - }, - - workflowTagsDisabled: { - format: Boolean, - default: false, - env: 'N8N_WORKFLOW_TAGS_DISABLED', - doc: 'Disable worfklow tags.', - }, - - userManagement: { - disabled: { - doc: 'Disable user management and hide it completely.', - format: Boolean, - default: false, - env: 'N8N_USER_MANAGEMENT_DISABLED', - }, - jwtSecret: { - doc: 'Set a specific JWT secret (optional - n8n can generate one)', // Generated @ start.ts - format: String, - default: '', - env: 'N8N_USER_MANAGEMENT_JWT_SECRET', - }, - emails: { - mode: { - doc: 'How to send emails', - format: ['', 'smtp'], - default: 'smtp', - env: 'N8N_EMAIL_MODE', - }, - smtp: { - host: { - doc: 'SMTP server host', - format: String, // e.g. 'smtp.gmail.com' - default: '', - env: 'N8N_SMTP_HOST', - }, - port: { - doc: 'SMTP server port', - format: Number, - default: 465, - env: 'N8N_SMTP_PORT', - }, - secure: { - doc: 'Whether or not to use SSL for SMTP', - format: Boolean, - default: true, - env: 'N8N_SMTP_SSL', - }, - auth: { - user: { - doc: 'SMTP login username', - format: String, // e.g.'you@gmail.com' - default: '', - env: 'N8N_SMTP_USER', - }, - pass: { - doc: 'SMTP login password', - format: String, - default: '', - env: 'N8N_SMTP_PASS', - }, - }, - sender: { - doc: 'How to display sender name', - format: String, - default: '', - env: 'N8N_SMTP_SENDER', - }, - }, - templates: { - invite: { - doc: 'Overrides default HTML template for inviting new people (use full path)', - format: String, - default: '', - env: 'N8N_UM_EMAIL_TEMPLATES_INVITE', - }, - passwordReset: { - doc: 'Overrides default HTML template for resetting password (use full path)', - format: String, - default: '', - env: 'N8N_UM_EMAIL_TEMPLATES_PWRESET', - }, - }, - }, - }, - - externalHookFiles: { - doc: 'Files containing external hooks. Multiple files can be separated by colon (":")', - format: String, - default: '', - env: 'EXTERNAL_HOOK_FILES', - }, - - nodes: { - include: { - doc: 'Nodes to load', - format: function check(rawValue) { - if (rawValue === '') { - return; - } - try { - const values = JSON.parse(rawValue); - if (!Array.isArray(values)) { - throw new Error(); - } - - for (const value of values) { - if (typeof value !== 'string') { - throw new Error(); - } - } - } catch (error) { - throw new TypeError(`The Nodes to include is not a valid Array of strings.`); - } - }, - default: undefined, - env: 'NODES_INCLUDE', - }, - exclude: { - doc: 'Nodes not to load', - format: function check(rawValue) { - try { - const values = JSON.parse(rawValue); - if (!Array.isArray(values)) { - throw new Error(); - } - - for (const value of values) { - if (typeof value !== 'string') { - throw new Error(); - } - } - } catch (error) { - throw new TypeError(`The Nodes to exclude is not a valid Array of strings.`); - } - }, - default: '[]', - env: 'NODES_EXCLUDE', - }, - errorTriggerType: { - doc: 'Node Type to use as Error Trigger', - format: String, - default: 'n8n-nodes-base.errorTrigger', - env: 'NODES_ERROR_TRIGGER_TYPE', - }, - }, - - logs: { - level: { - doc: 'Log output level', - format: ['error', 'warn', 'info', 'verbose', 'debug'], - default: 'info', - env: 'N8N_LOG_LEVEL', - }, - output: { - doc: 'Where to output logs. Options are: console, file. Multiple can be separated by comma (",")', - format: String, - default: 'console', - env: 'N8N_LOG_OUTPUT', - }, - file: { - fileCountMax: { - doc: 'Maximum number of files to keep.', - format: Number, - default: 100, - env: 'N8N_LOG_FILE_COUNT_MAX', - }, - fileSizeMax: { - doc: 'Maximum size for each log file in MB.', - format: Number, - default: 16, - env: 'N8N_LOG_FILE_SIZE_MAX', - }, - location: { - doc: 'Log file location; only used if log output is set to file.', - format: String, - default: path.join(core.UserSettings.getUserN8nFolderPath(), 'logs/n8n.log'), - env: 'N8N_LOG_FILE_LOCATION', - }, - }, - }, - - versionNotifications: { - enabled: { - doc: 'Whether feature is enabled to request notifications about new versions and security updates.', - format: Boolean, - default: true, - env: 'N8N_VERSION_NOTIFICATIONS_ENABLED', - }, - endpoint: { - doc: 'Endpoint to retrieve version information from.', - format: String, - default: 'https://api.n8n.io/versions/', - env: 'N8N_VERSION_NOTIFICATIONS_ENDPOINT', - }, - infoUrl: { - doc: `Url in New Versions Panel with more information on updating one's instance.`, - format: String, - default: 'https://docs.n8n.io/getting-started/installation/updating.html', - env: 'N8N_VERSION_NOTIFICATIONS_INFO_URL', - }, - }, - - templates: { - enabled: { - doc: 'Whether templates feature is enabled to load workflow templates.', - format: Boolean, - default: true, - env: 'N8N_TEMPLATES_ENABLED', - }, - host: { - doc: 'Endpoint host to retrieve workflow templates from endpoints.', - format: String, - default: 'https://api.n8n.io/', - env: 'N8N_TEMPLATES_HOST', - }, - }, - - binaryDataManager: { - availableModes: { - format: String, - default: 'filesystem', - env: 'N8N_AVAILABLE_BINARY_DATA_MODES', - doc: 'Available modes of binary data storage, as comma separated strings', - }, - mode: { - format: ['default', 'filesystem'], - default: 'default', - env: 'N8N_DEFAULT_BINARY_DATA_MODE', - doc: 'Storage mode for binary data', - }, - localStoragePath: { - format: String, - default: path.join(core.UserSettings.getUserN8nFolderPath(), 'binaryData'), - env: 'N8N_BINARY_DATA_STORAGE_PATH', - doc: 'Path for binary data storage in "filesystem" mode', - }, - binaryDataTTL: { - format: Number, - default: 60, - env: 'N8N_BINARY_DATA_TTL', - doc: 'TTL for binary data of unsaved executions in minutes', - }, - persistedBinaryDataTTL: { - format: Number, - default: 1440, - env: 'N8N_PERSISTED_BINARY_DATA_TTL', - doc: 'TTL for persisted binary data in minutes (binary data gets deleted if not persisted before TTL expires)', - }, - }, - - deployment: { - type: { - format: String, - default: 'default', - env: 'N8N_DEPLOYMENT_TYPE', - }, - }, - - hiringBanner: { - enabled: { - doc: 'Whether hiring banner in browser console is enabled.', - format: Boolean, - default: true, - env: 'N8N_HIRING_BANNER_ENABLED', - }, - }, - - personalization: { - enabled: { - doc: 'Whether personalization is enabled.', - format: Boolean, - default: true, - env: 'N8N_PERSONALIZATION_ENABLED', - }, - }, - - diagnostics: { - enabled: { - doc: 'Whether diagnostic mode is enabled.', - format: Boolean, - default: true, - env: 'N8N_DIAGNOSTICS_ENABLED', - }, - config: { - frontend: { - doc: 'Diagnostics config for frontend.', - format: String, - default: '1zPn9bgWPzlQc0p8Gj1uiK6DOTn;https://telemetry.n8n.io', - env: 'N8N_DIAGNOSTICS_CONFIG_FRONTEND', - }, - backend: { - doc: 'Diagnostics config for backend.', - format: String, - default: '1zPn7YoGC3ZXE9zLeTKLuQCB4F6;https://telemetry.n8n.io/v1/batch', - env: 'N8N_DIAGNOSTICS_CONFIG_BACKEND', - }, - }, - }, - - defaultLocale: { - doc: 'Default locale for the UI', - format: String, - default: 'en', - env: 'N8N_DEFAULT_LOCALE', - }, -}); +config.getEnv = config.get; // Overwrite default configuration with settings which got defined in // optional configuration files diff --git a/packages/cli/config/schema.ts b/packages/cli/config/schema.ts new file mode 100644 index 0000000000..92b8dc9a12 --- /dev/null +++ b/packages/cli/config/schema.ts @@ -0,0 +1,883 @@ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ + +import path from 'path'; +import * as core from 'n8n-core'; + +export const schema = { + database: { + type: { + doc: 'Type of database to use', + format: ['sqlite', 'mariadb', 'mysqldb', 'postgresdb'] as const, + default: 'sqlite', + env: 'DB_TYPE', + }, + tablePrefix: { + doc: 'Prefix for table names', + format: '*', + default: '', + env: 'DB_TABLE_PREFIX', + }, + logging: { + enabled: { + doc: 'Typeorm logging enabled flag.', + format: Boolean, + default: false, + env: 'DB_LOGGING_ENABLED', + }, + options: { + doc: 'Logging level options, default is "error". Possible values: query,error,schema,warn,info,log. To enable all logging, specify "all"', + format: String, + default: 'error', + env: 'DB_LOGGING_OPTIONS', + }, + maxQueryExecutionTime: { + doc: 'Maximum number of milliseconds query should be executed before logger logs a warning. Set 0 to disable long running query warning', + format: Number, + default: 1000, + env: 'DB_LOGGING_MAX_EXECUTION_TIME', + }, + }, + postgresdb: { + database: { + doc: 'PostgresDB Database', + format: String, + default: 'n8n', + env: 'DB_POSTGRESDB_DATABASE', + }, + host: { + doc: 'PostgresDB Host', + format: String, + default: 'localhost', + env: 'DB_POSTGRESDB_HOST', + }, + password: { + doc: 'PostgresDB Password', + format: String, + default: '', + env: 'DB_POSTGRESDB_PASSWORD', + }, + port: { + doc: 'PostgresDB Port', + format: Number, + default: 5432, + env: 'DB_POSTGRESDB_PORT', + }, + user: { + doc: 'PostgresDB User', + format: String, + default: 'root', + env: 'DB_POSTGRESDB_USER', + }, + schema: { + doc: 'PostgresDB Schema', + format: String, + default: 'public', + env: 'DB_POSTGRESDB_SCHEMA', + }, + + ssl: { + ca: { + doc: 'SSL certificate authority', + format: String, + default: '', + env: 'DB_POSTGRESDB_SSL_CA', + }, + cert: { + doc: 'SSL certificate', + format: String, + default: '', + env: 'DB_POSTGRESDB_SSL_CERT', + }, + key: { + doc: 'SSL key', + format: String, + default: '', + env: 'DB_POSTGRESDB_SSL_KEY', + }, + rejectUnauthorized: { + doc: 'If unauthorized SSL connections should be rejected', + format: 'Boolean', + default: true, + env: 'DB_POSTGRESDB_SSL_REJECT_UNAUTHORIZED', + }, + }, + }, + mysqldb: { + database: { + doc: 'MySQL Database', + format: String, + default: 'n8n', + env: 'DB_MYSQLDB_DATABASE', + }, + host: { + doc: 'MySQL Host', + format: String, + default: 'localhost', + env: 'DB_MYSQLDB_HOST', + }, + password: { + doc: 'MySQL Password', + format: String, + default: '', + env: 'DB_MYSQLDB_PASSWORD', + }, + port: { + doc: 'MySQL Port', + format: Number, + default: 3306, + env: 'DB_MYSQLDB_PORT', + }, + user: { + doc: 'MySQL User', + format: String, + default: 'root', + env: 'DB_MYSQLDB_USER', + }, + }, + sqlite: { + executeVacuumOnStartup: { + doc: 'Runs VACUUM operation on startup to rebuild the database. Reduces filesize and optimizes indexes. WARNING: This is a long running blocking operation. Will increase start-up time.', + format: Boolean, + default: false, + env: 'DB_SQLITE_VACUUM_ON_STARTUP', + }, + }, + }, + + credentials: { + overwrite: { + data: { + // Allows to set default values for credentials which + // get automatically prefilled and the user does not get + // displayed and can not change. + // Format: { CREDENTIAL_NAME: { PARAMTER: VALUE }} + doc: 'Overwrites for credentials', + format: '*', + default: '{}', + env: 'CREDENTIALS_OVERWRITE_DATA', + }, + endpoint: { + doc: 'Fetch credentials from API', + format: String, + default: '', + env: 'CREDENTIALS_OVERWRITE_ENDPOINT', + }, + }, + defaultName: { + doc: 'Default name for credentials', + format: String, + default: 'My credentials', + env: 'CREDENTIALS_DEFAULT_NAME', + }, + }, + + workflows: { + defaultName: { + doc: 'Default name for workflow', + format: String, + default: 'My workflow', + env: 'WORKFLOWS_DEFAULT_NAME', + }, + }, + + executions: { + // By default workflows get always executed in their own process. + // If this option gets set to "main" it will run them in the + // main-process instead. + process: { + doc: 'In what process workflows should be executed', + format: ['main', 'own'] as const, + default: 'own', + env: 'EXECUTIONS_PROCESS', + }, + + mode: { + doc: 'If it should run executions directly or via queue', + format: ['regular', 'queue'] as const, + default: 'regular', + env: 'EXECUTIONS_MODE', + }, + + // A Workflow times out and gets canceled after this time (seconds). + // If the workflow is executed in the main process a soft timeout + // is executed (takes effect after the current node finishes). + // If a workflow is running in its own process is a soft timeout + // tried first, before killing the process after waiting for an + // additional fifth of the given timeout duration. + // + // To deactivate timeout set it to -1 + // + // Timeout is currently not activated by default which will change + // in a future version. + timeout: { + doc: 'Max run time (seconds) before stopping the workflow execution', + format: Number, + default: -1, + env: 'EXECUTIONS_TIMEOUT', + }, + maxTimeout: { + doc: 'Max execution time (seconds) that can be set for a workflow individually', + format: Number, + default: 3600, + env: 'EXECUTIONS_TIMEOUT_MAX', + }, + + // If a workflow executes all the data gets saved by default. This + // could be a problem when a workflow gets executed a lot and processes + // a lot of data. To not exceed the database's capacity it is possible to + // prune the database regularly or to not save the execution at all. + // Depending on if the execution did succeed or error a different + // save behaviour can be set. + saveDataOnError: { + doc: 'What workflow execution data to save on error', + format: ['all', 'none'] as const, + default: 'all', + env: 'EXECUTIONS_DATA_SAVE_ON_ERROR', + }, + saveDataOnSuccess: { + doc: 'What workflow execution data to save on success', + format: ['all', 'none'] as const, + default: 'all', + env: 'EXECUTIONS_DATA_SAVE_ON_SUCCESS', + }, + saveExecutionProgress: { + doc: 'Wether or not to save progress for each node executed', + format: 'Boolean', + default: false, + env: 'EXECUTIONS_DATA_SAVE_ON_PROGRESS', + }, + + // If the executions of workflows which got started via the editor + // should be saved. By default they will not be saved as this runs + // are normally only for testing and debugging. This setting can + // also be overwritten on a per workflow basis in the workflow settings + // in the editor. + saveDataManualExecutions: { + doc: 'Save data of executions when started manually via editor', + format: 'Boolean', + default: false, + env: 'EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS', + }, + + // To not exceed the database's capacity and keep its size moderate + // the execution data gets pruned regularly (default: 1 hour interval). + // All saved execution data older than the max age will be deleted. + // Pruning is currently not activated by default, which will change in + // a future version. + pruneData: { + doc: 'Delete data of past executions on a rolling basis', + format: 'Boolean', + default: false, + env: 'EXECUTIONS_DATA_PRUNE', + }, + pruneDataMaxAge: { + doc: 'How old (hours) the execution data has to be to get deleted', + format: Number, + default: 336, + env: 'EXECUTIONS_DATA_MAX_AGE', + }, + pruneDataTimeout: { + doc: 'Timeout (seconds) after execution data has been pruned', + format: Number, + default: 3600, + env: 'EXECUTIONS_DATA_PRUNE_TIMEOUT', + }, + }, + + queue: { + health: { + active: { + doc: 'If health checks should be enabled', + format: 'Boolean', + default: false, + env: 'QUEUE_HEALTH_CHECK_ACTIVE', + }, + port: { + doc: 'Port to serve health check on if activated', + format: Number, + default: 5678, + env: 'QUEUE_HEALTH_CHECK_PORT', + }, + }, + bull: { + prefix: { + doc: 'Prefix for all queue keys', + format: String, + default: '', + env: 'QUEUE_BULL_PREFIX', + }, + redis: { + db: { + doc: 'Redis DB', + format: Number, + default: 0, + env: 'QUEUE_BULL_REDIS_DB', + }, + host: { + doc: 'Redis Host', + format: String, + default: 'localhost', + env: 'QUEUE_BULL_REDIS_HOST', + }, + password: { + doc: 'Redis Password', + format: String, + default: '', + env: 'QUEUE_BULL_REDIS_PASSWORD', + }, + port: { + doc: 'Redis Port', + format: Number, + default: 6379, + env: 'QUEUE_BULL_REDIS_PORT', + }, + timeoutThreshold: { + doc: 'Redis timeout threshold', + format: Number, + default: 10000, + env: 'QUEUE_BULL_REDIS_TIMEOUT_THRESHOLD', + }, + }, + queueRecoveryInterval: { + doc: 'If > 0 enables an active polling to the queue that can recover for Redis crashes. Given in seconds; 0 is disabled. May increase Redis traffic significantly.', + format: Number, + default: 60, + env: 'QUEUE_RECOVERY_INTERVAL', + }, + }, + }, + + generic: { + // The timezone to use. Is important for nodes like "Cron" which start the + // workflow automatically at a specified time. This setting can also be + // overwritten on a per worfklow basis in the workflow settings in the + // editor. + timezone: { + doc: 'The timezone to use', + format: '*', + default: 'America/New_York', + env: 'GENERIC_TIMEZONE', + }, + }, + + // How n8n can be reached (Editor & REST-API) + path: { + format: String, + default: '/', + arg: 'path', + env: 'N8N_PATH', + doc: 'Path n8n is deployed to', + }, + host: { + format: String, + default: 'localhost', + arg: 'host', + env: 'N8N_HOST', + doc: 'Host name n8n can be reached', + }, + port: { + format: Number, + default: 5678, + arg: 'port', + env: 'N8N_PORT', + doc: 'HTTP port n8n can be reached', + }, + listen_address: { + format: String, + default: '0.0.0.0', + env: 'N8N_LISTEN_ADDRESS', + doc: 'IP address n8n should listen on', + }, + protocol: { + format: ['http', 'https'] as const, + default: 'http', + env: 'N8N_PROTOCOL', + doc: 'HTTP Protocol via which n8n can be reached', + }, + ssl_key: { + format: String, + default: '', + env: 'N8N_SSL_KEY', + doc: 'SSL Key for HTTPS Protocol', + }, + ssl_cert: { + format: String, + default: '', + env: 'N8N_SSL_CERT', + doc: 'SSL Cert for HTTPS Protocol', + }, + editorBaseUrl: { + format: String, + default: '', + env: 'N8N_EDITOR_BASE_URL', + doc: 'Public URL where the editor is accessible. Also used for emails sent from n8n.', + }, + + security: { + excludeEndpoints: { + doc: 'Additional endpoints to exclude auth checks. Multiple endpoints can be separated by colon (":")', + format: String, + default: '', + env: 'N8N_AUTH_EXCLUDE_ENDPOINTS', + }, + basicAuth: { + active: { + format: 'Boolean', + default: false, + env: 'N8N_BASIC_AUTH_ACTIVE', + doc: 'If basic auth should be activated for editor and REST-API', + }, + user: { + format: String, + default: '', + env: 'N8N_BASIC_AUTH_USER', + doc: 'The name of the basic auth user', + }, + password: { + format: String, + default: '', + env: 'N8N_BASIC_AUTH_PASSWORD', + doc: 'The password of the basic auth user', + }, + hash: { + format: 'Boolean', + default: false, + env: 'N8N_BASIC_AUTH_HASH', + doc: 'If password for basic auth is hashed', + }, + }, + jwtAuth: { + active: { + format: 'Boolean', + default: false, + env: 'N8N_JWT_AUTH_ACTIVE', + doc: 'If JWT auth should be activated for editor and REST-API', + }, + jwtHeader: { + format: String, + default: '', + env: 'N8N_JWT_AUTH_HEADER', + doc: 'The request header containing a signed JWT', + }, + jwtHeaderValuePrefix: { + format: String, + default: '', + env: 'N8N_JWT_AUTH_HEADER_VALUE_PREFIX', + doc: 'The request header value prefix to strip (optional)', + }, + jwksUri: { + format: String, + default: '', + env: 'N8N_JWKS_URI', + doc: 'The URI to fetch JWK Set for JWT authentication', + }, + jwtIssuer: { + format: String, + default: '', + env: 'N8N_JWT_ISSUER', + doc: 'JWT issuer to expect (optional)', + }, + jwtNamespace: { + format: String, + default: '', + env: 'N8N_JWT_NAMESPACE', + doc: 'JWT namespace to expect (optional)', + }, + jwtAllowedTenantKey: { + format: String, + default: '', + env: 'N8N_JWT_ALLOWED_TENANT_KEY', + doc: 'JWT tenant key name to inspect within JWT namespace (optional)', + }, + jwtAllowedTenant: { + format: String, + default: '', + env: 'N8N_JWT_ALLOWED_TENANT', + doc: 'JWT tenant to allow (optional)', + }, + }, + }, + + endpoints: { + payloadSizeMax: { + format: Number, + default: 16, + env: 'N8N_PAYLOAD_SIZE_MAX', + doc: 'Maximum payload size in MB.', + }, + metrics: { + enable: { + format: 'Boolean', + default: false, + env: 'N8N_METRICS', + doc: 'Enable metrics endpoint', + }, + prefix: { + format: String, + default: 'n8n_', + env: 'N8N_METRICS_PREFIX', + doc: 'An optional prefix for metric names. Default: n8n_', + }, + }, + rest: { + format: String, + default: 'rest', + env: 'N8N_ENDPOINT_REST', + doc: 'Path for rest endpoint', + }, + webhook: { + format: String, + default: 'webhook', + env: 'N8N_ENDPOINT_WEBHOOK', + doc: 'Path for webhook endpoint', + }, + webhookWaiting: { + format: String, + default: 'webhook-waiting', + env: 'N8N_ENDPOINT_WEBHOOK_WAIT', + doc: 'Path for waiting-webhook endpoint', + }, + webhookTest: { + format: String, + default: 'webhook-test', + env: 'N8N_ENDPOINT_WEBHOOK_TEST', + doc: 'Path for test-webhook endpoint', + }, + disableUi: { + format: Boolean, + default: false, + env: 'N8N_DISABLE_UI', + doc: 'Disable N8N UI (Frontend).', + }, + disableProductionWebhooksOnMainProcess: { + format: Boolean, + default: false, + env: 'N8N_DISABLE_PRODUCTION_MAIN_PROCESS', + doc: 'Disable production webhooks from main process. This helps ensures no http traffic load to main process when using webhook-specific processes.', + }, + skipWebhoooksDeregistrationOnShutdown: { + /** + * Longer explanation: n8n deregisters webhooks on shutdown / deactivation + * and registers on startup / activation. If we skip + * deactivation on shutdown, webhooks will remain active on 3rd party services. + * We don't have to worry about startup as it always + * checks if webhooks already exist. + * If users want to upgrade n8n, it is possible to run + * two instances simultaneously without downtime, similar + * to blue/green deployment. + * WARNING: Trigger nodes (like Cron) will cause duplication + * of work, so be aware when using. + */ + doc: 'Deregister webhooks on external services only when workflows are deactivated.', + format: Boolean, + default: false, + env: 'N8N_SKIP_WEBHOOK_DEREGISTRATION_SHUTDOWN', + }, + }, + + workflowTagsDisabled: { + format: Boolean, + default: false, + env: 'N8N_WORKFLOW_TAGS_DISABLED', + doc: 'Disable worfklow tags.', + }, + + userManagement: { + disabled: { + doc: 'Disable user management and hide it completely.', + format: Boolean, + default: false, + env: 'N8N_USER_MANAGEMENT_DISABLED', + }, + jwtSecret: { + doc: 'Set a specific JWT secret (optional - n8n can generate one)', // Generated @ start.ts + format: String, + default: '', + env: 'N8N_USER_MANAGEMENT_JWT_SECRET', + }, + emails: { + mode: { + doc: 'How to send emails', + format: ['', 'smtp'] as const, + default: 'smtp', + env: 'N8N_EMAIL_MODE', + }, + smtp: { + host: { + doc: 'SMTP server host', + format: String, // e.g. 'smtp.gmail.com' + default: '', + env: 'N8N_SMTP_HOST', + }, + port: { + doc: 'SMTP server port', + format: Number, + default: 465, + env: 'N8N_SMTP_PORT', + }, + secure: { + doc: 'Whether or not to use SSL for SMTP', + format: Boolean, + default: true, + env: 'N8N_SMTP_SSL', + }, + auth: { + user: { + doc: 'SMTP login username', + format: String, // e.g.'you@gmail.com' + default: '', + env: 'N8N_SMTP_USER', + }, + pass: { + doc: 'SMTP login password', + format: String, + default: '', + env: 'N8N_SMTP_PASS', + }, + }, + sender: { + doc: 'How to display sender name', + format: String, + default: '', + env: 'N8N_SMTP_SENDER', + }, + }, + templates: { + invite: { + doc: 'Overrides default HTML template for inviting new people (use full path)', + format: String, + default: '', + env: 'N8N_UM_EMAIL_TEMPLATES_INVITE', + }, + passwordReset: { + doc: 'Overrides default HTML template for resetting password (use full path)', + format: String, + default: '', + env: 'N8N_UM_EMAIL_TEMPLATES_PWRESET', + }, + }, + }, + }, + + externalHookFiles: { + doc: 'Files containing external hooks. Multiple files can be separated by colon (":")', + format: String, + default: '', + env: 'EXTERNAL_HOOK_FILES', + }, + + nodes: { + include: { + doc: 'Nodes to load', + format: function check(rawValue: string): void { + if (rawValue === '') { + return; + } + try { + const values = JSON.parse(rawValue); + if (!Array.isArray(values)) { + throw new Error(); + } + + for (const value of values) { + if (typeof value !== 'string') { + throw new Error(); + } + } + } catch (error) { + throw new TypeError(`The Nodes to include is not a valid Array of strings.`); + } + }, + default: undefined, + env: 'NODES_INCLUDE', + }, + exclude: { + doc: 'Nodes not to load', + format: function check(rawValue: string): void { + try { + const values = JSON.parse(rawValue); + if (!Array.isArray(values)) { + throw new Error(); + } + + for (const value of values) { + if (typeof value !== 'string') { + throw new Error(); + } + } + } catch (error) { + throw new TypeError(`The Nodes to exclude is not a valid Array of strings.`); + } + }, + default: '[]', + env: 'NODES_EXCLUDE', + }, + errorTriggerType: { + doc: 'Node Type to use as Error Trigger', + format: String, + default: 'n8n-nodes-base.errorTrigger', + env: 'NODES_ERROR_TRIGGER_TYPE', + }, + }, + + logs: { + level: { + doc: 'Log output level', + format: ['error', 'warn', 'info', 'verbose', 'debug', 'silent'] as const, + default: 'info', + env: 'N8N_LOG_LEVEL', + }, + output: { + doc: 'Where to output logs. Options are: console, file. Multiple can be separated by comma (",")', + format: String, + default: 'console', + env: 'N8N_LOG_OUTPUT', + }, + file: { + fileCountMax: { + doc: 'Maximum number of files to keep.', + format: Number, + default: 100, + env: 'N8N_LOG_FILE_COUNT_MAX', + }, + fileSizeMax: { + doc: 'Maximum size for each log file in MB.', + format: Number, + default: 16, + env: 'N8N_LOG_FILE_SIZE_MAX', + }, + location: { + doc: 'Log file location; only used if log output is set to file.', + format: String, + default: path.join(core.UserSettings.getUserN8nFolderPath(), 'logs/n8n.log'), + env: 'N8N_LOG_FILE_LOCATION', + }, + }, + }, + + versionNotifications: { + enabled: { + doc: 'Whether feature is enabled to request notifications about new versions and security updates.', + format: Boolean, + default: true, + env: 'N8N_VERSION_NOTIFICATIONS_ENABLED', + }, + endpoint: { + doc: 'Endpoint to retrieve version information from.', + format: String, + default: 'https://api.n8n.io/versions/', + env: 'N8N_VERSION_NOTIFICATIONS_ENDPOINT', + }, + infoUrl: { + doc: `Url in New Versions Panel with more information on updating one's instance.`, + format: String, + default: 'https://docs.n8n.io/getting-started/installation/updating.html', + env: 'N8N_VERSION_NOTIFICATIONS_INFO_URL', + }, + }, + + templates: { + enabled: { + doc: 'Whether templates feature is enabled to load workflow templates.', + format: Boolean, + default: true, + env: 'N8N_TEMPLATES_ENABLED', + }, + host: { + doc: 'Endpoint host to retrieve workflow templates from endpoints.', + format: String, + default: 'https://api.n8n.io/', + env: 'N8N_TEMPLATES_HOST', + }, + }, + + binaryDataManager: { + availableModes: { + format: String, + default: 'filesystem', + env: 'N8N_AVAILABLE_BINARY_DATA_MODES', + doc: 'Available modes of binary data storage, as comma separated strings', + }, + mode: { + format: ['default', 'filesystem'] as const, + default: 'default', + env: 'N8N_DEFAULT_BINARY_DATA_MODE', + doc: 'Storage mode for binary data', + }, + localStoragePath: { + format: String, + default: path.join(core.UserSettings.getUserN8nFolderPath(), 'binaryData'), + env: 'N8N_BINARY_DATA_STORAGE_PATH', + doc: 'Path for binary data storage in "filesystem" mode', + }, + binaryDataTTL: { + format: Number, + default: 60, + env: 'N8N_BINARY_DATA_TTL', + doc: 'TTL for binary data of unsaved executions in minutes', + }, + persistedBinaryDataTTL: { + format: Number, + default: 1440, + env: 'N8N_PERSISTED_BINARY_DATA_TTL', + doc: 'TTL for persisted binary data in minutes (binary data gets deleted if not persisted before TTL expires)', + }, + }, + + deployment: { + type: { + format: String, + default: 'default', + env: 'N8N_DEPLOYMENT_TYPE', + }, + }, + + hiringBanner: { + enabled: { + doc: 'Whether hiring banner in browser console is enabled.', + format: Boolean, + default: true, + env: 'N8N_HIRING_BANNER_ENABLED', + }, + }, + + personalization: { + enabled: { + doc: 'Whether personalization is enabled.', + format: Boolean, + default: true, + env: 'N8N_PERSONALIZATION_ENABLED', + }, + }, + + diagnostics: { + enabled: { + doc: 'Whether diagnostic mode is enabled.', + format: Boolean, + default: true, + env: 'N8N_DIAGNOSTICS_ENABLED', + }, + config: { + frontend: { + doc: 'Diagnostics config for frontend.', + format: String, + default: '1zPn9bgWPzlQc0p8Gj1uiK6DOTn;https://telemetry.n8n.io', + env: 'N8N_DIAGNOSTICS_CONFIG_FRONTEND', + }, + backend: { + doc: 'Diagnostics config for backend.', + format: String, + default: '1zPn7YoGC3ZXE9zLeTKLuQCB4F6;https://telemetry.n8n.io/v1/batch', + env: 'N8N_DIAGNOSTICS_CONFIG_BACKEND', + }, + }, + }, + + defaultLocale: { + doc: 'Default locale for the UI', + format: String, + default: 'en', + env: 'N8N_DEFAULT_LOCALE', + }, +}; diff --git a/packages/cli/config/types.d.ts b/packages/cli/config/types.d.ts new file mode 100644 index 0000000000..7009dce746 --- /dev/null +++ b/packages/cli/config/types.d.ts @@ -0,0 +1,132 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import { IBinaryDataConfig } from '../../core/dist/src'; +import { schema } from './schema'; + +// ----------------------------------- +// transformers +// ----------------------------------- + +/** + * Transform an object (convict schema) into a union of string arrays (path segments), + * one for every valid path in the schema object, filtered by type. + * + * ```ts + * ["port", "default"] | ["queue", "bull", "redis", "port", "default"] | ["queue", "bull", "redis", "db", "default"] | ["queue", "bull", "redis", "timeoutThreshold", "default"] | etc + * ``` + */ +type GetPathSegments = Traversable extends Filter + ? [] + : { + [K in ValidKeys]: [K, ...GetPathSegments]; + }[ValidKeys]; + +/** + * Transform a union of string arrays (path segments) into a union of strings (dotted paths). + * + * ```ts + * "port" | "queue.bull.redis.port" | "queue.bull.redis.db" | "queue.bull.redis.timeoutThreshold" | etc + * ``` + */ +type JoinByDotting = T extends [infer F] + ? F + : T extends [infer F, ...infer R] + ? F extends string + ? R extends string[] + ? `${F}.${JoinByDotting}` + : never + : never + : string; + +type ToDottedPath = JoinByDotting>; + +type CollectPathsByType = ToDottedPath>; + +// ----------------------------------- +// path-to-return-type mapper +// ----------------------------------- + +type NumericPath = CollectPathsByType; + +type BooleanPath = CollectPathsByType; + +type StringLiteralArrayPath = CollectPathsByType>; + +type StringPath = CollectPathsByType; + +type ConfigOptionPath = + | NumericPath + | BooleanPath + | StringPath + | StringLiteralArrayPath + | keyof ExceptionPaths; + +type ToReturnType = T extends NumericPath + ? number + : T extends BooleanPath + ? boolean + : T extends StringLiteralArrayPath + ? StringLiteralMap[T] + : T extends keyof ExceptionPaths + ? ExceptionPaths[T] + : T extends StringPath + ? string + : unknown; + +type ExceptionPaths = { + 'queue.bull.redis': object; + binaryDataManager: IBinaryDataConfig; + 'nodes.include': undefined; + 'userManagement.isInstanceOwnerSetUp': boolean; + 'userManagement.skipInstanceOwnerSetup': boolean; +}; + +// ----------------------------------- +// string literals map +// ----------------------------------- + +type GetPathSegmentsWithUnions = T extends ReadonlyArray + ? [C] + : { + [K in ValidKeys]: [K, ...GetPathSegmentsWithUnions]; + }[ValidKeys]; + +type ToPathUnionPair = T extends [...infer Path, infer Union] + ? Path extends string[] + ? { path: ToDottedPath; union: Union } + : never + : never; + +type ToStringLiteralMap = { + [Path in T['path']]: Extract['union']; +}; + +type StringLiteralMap = ToStringLiteralMap< + ToPathUnionPair> +>; + +// ----------------------------------- +// utils +// ----------------------------------- + +type ValidKeys = keyof T extends string + ? keyof T extends keyof NumberConstructor + ? never + : keyof T + : never; + +type RemoveExcess = T extends [...infer Path, 'format' | 'default'] + ? Path extends string[] + ? Path + : never + : never; + +// ----------------------------------- +// module augmentation +// ----------------------------------- + +declare module 'convict' { + interface Config { + getEnv(path: Path): ToReturnType; + } +} diff --git a/packages/cli/migrations/ormconfig.ts b/packages/cli/migrations/ormconfig.ts index 1b83c806e1..2ca697e88e 100644 --- a/packages/cli/migrations/ormconfig.ts +++ b/packages/cli/migrations/ormconfig.ts @@ -1,4 +1,4 @@ -import * as path from 'path'; +import path from 'path'; import { UserSettings } from 'n8n-core'; import { entities } from '../src/databases/entities'; diff --git a/packages/cli/package.json b/packages/cli/package.json index 25c28a60ad..7ee8937c8c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "n8n", - "version": "0.170.0", + "version": "0.171.1", "description": "n8n Workflow Automation Tool", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", @@ -30,9 +30,9 @@ "start:default": "cd bin && ./n8n", "start:windows": "cd bin && n8n", "test": "npm run test:sqlite", - "test:sqlite": "export DB_TYPE=sqlite && jest --forceExit", - "test:postgres": "export DB_TYPE=postgresdb && jest", - "test:mysql": "export DB_TYPE=mysqldb && jest", + "test:sqlite": "export N8N_LOG_LEVEL='silent'; export DB_TYPE=sqlite; jest", + "test:postgres": "export N8N_LOG_LEVEL='silent'; export DB_TYPE=postgresdb && jest", + "test:mysql": "export N8N_LOG_LEVEL='silent'; export DB_TYPE=mysqldb && jest", "watch": "tsc --watch", "typeorm": "ts-node ../../node_modules/typeorm/cli.js" }, @@ -89,7 +89,7 @@ "ts-jest": "^27.1.3", "ts-node": "^8.9.1", "tslint": "^6.1.2", - "typescript": "~4.3.5" + "typescript": "~4.6.0" }, "dependencies": { "@oclif/command": "^1.5.18", @@ -125,10 +125,10 @@ "lodash.get": "^4.4.2", "lodash.merge": "^4.6.2", "mysql2": "~2.3.0", - "n8n-core": "~0.111.0", - "n8n-editor-ui": "~0.137.0", - "n8n-nodes-base": "~0.168.0", - "n8n-workflow": "~0.93.0", + "n8n-core": "~0.112.0", + "n8n-editor-ui": "~0.138.0", + "n8n-nodes-base": "~0.169.1", + "n8n-workflow": "~0.94.0", "nodemailer": "^6.7.1", "oauth-1.0a": "^2.2.6", "open": "^7.0.0", diff --git a/packages/cli/src/ActiveExecutions.ts b/packages/cli/src/ActiveExecutions.ts index cebcd8535d..cc2f99f388 100644 --- a/packages/cli/src/ActiveExecutions.ts +++ b/packages/cli/src/ActiveExecutions.ts @@ -15,7 +15,7 @@ import { import { ChildProcess } from 'child_process'; import { stringify } from 'flatted'; // eslint-disable-next-line import/no-extraneous-dependencies -import * as PCancelable from 'p-cancelable'; +import PCancelable from 'p-cancelable'; // eslint-disable-next-line import/no-cycle import { Db, diff --git a/packages/cli/src/ActiveWorkflowRunner.ts b/packages/cli/src/ActiveWorkflowRunner.ts index bc24be4019..d24671a8b3 100644 --- a/packages/cli/src/ActiveWorkflowRunner.ts +++ b/packages/cli/src/ActiveWorkflowRunner.ts @@ -30,7 +30,7 @@ import { LoggerProxy as Logger, } from 'n8n-workflow'; -import * as express from 'express'; +import express from 'express'; // eslint-disable-next-line import/no-cycle import { @@ -48,7 +48,7 @@ import { WorkflowRunner, ExternalHooks, } from '.'; -import config = require('../config'); +import config from '../config'; import { User } from './databases/entities/User'; import { whereClause } from './WorkflowHelpers'; import { WorkflowEntity } from './databases/entities/WorkflowEntity'; @@ -74,7 +74,7 @@ export class ActiveWorkflowRunner { relations: ['shared', 'shared.user', 'shared.user.globalRole'], })) as IWorkflowDb[]; - if (!config.get('endpoints.skipWebhoooksDeregistrationOnShutdown')) { + if (!config.getEnv('endpoints.skipWebhoooksDeregistrationOnShutdown')) { // Do not clean up database when skip registration is done. // This flag is set when n8n is running in scaled mode. // Impact is minimal, but for a short while, n8n will stop accepting requests. @@ -466,7 +466,7 @@ export class ActiveWorkflowRunner { } catch (error) { if ( activation === 'init' && - config.get('endpoints.skipWebhoooksDeregistrationOnShutdown') && + config.getEnv('endpoints.skipWebhoooksDeregistrationOnShutdown') && error.name === 'QueryFailedError' ) { // When skipWebhoooksDeregistrationOnShutdown is enabled, @@ -682,6 +682,15 @@ export class ActiveWorkflowRunner { (error) => console.error(error), ); }; + returnFunctions.emitError = async (error: Error): Promise => { + await this.activeWorkflows?.remove(workflowData.id.toString()); + this.activationErrors[workflowData.id.toString()] = { + time: new Date().getTime(), + error: { + message: error.message, + }, + }; + }; return returnFunctions; }; } diff --git a/packages/cli/src/CredentialsHelper.ts b/packages/cli/src/CredentialsHelper.ts index 6806dd0294..27f838fffe 100644 --- a/packages/cli/src/CredentialsHelper.ts +++ b/packages/cli/src/CredentialsHelper.ts @@ -79,6 +79,7 @@ export class CredentialsHelper extends ICredentialsHelper { incomingRequestOptions: IHttpRequestOptions | IRequestOptionsSimplified, workflow: Workflow, node: INode, + defaultTimezone: string, ): Promise { const requestOptions = incomingRequestOptions; const credentialType = this.credentialTypes.getByName(typeName); @@ -127,6 +128,7 @@ export class CredentialsHelper extends ICredentialsHelper { { $credentials: credentials }, workflow, node, + defaultTimezone, ); const value = this.resolveValue( @@ -135,6 +137,7 @@ export class CredentialsHelper extends ICredentialsHelper { { $credentials: credentials }, workflow, node, + defaultTimezone, ); requestOptions.headers[key] = value; } else if (authenticate.type === 'queryAuth') { @@ -144,6 +147,7 @@ export class CredentialsHelper extends ICredentialsHelper { { $credentials: credentials }, workflow, node, + defaultTimezone, ); const value = this.resolveValue( @@ -152,6 +156,7 @@ export class CredentialsHelper extends ICredentialsHelper { { $credentials: credentials }, workflow, node, + defaultTimezone, ); if (!requestOptions.qs) { requestOptions.qs = {}; @@ -172,6 +177,7 @@ export class CredentialsHelper extends ICredentialsHelper { additionalKeys: IWorkflowDataProxyAdditionalKeys, workflow: Workflow, node: INode, + defaultTimezone: string, ): string { if (parameterValue.charAt(0) !== '=') { return parameterValue; @@ -181,6 +187,7 @@ export class CredentialsHelper extends ICredentialsHelper { node, parameterValue, 'internal', + defaultTimezone, additionalKeys, '', ); @@ -293,6 +300,7 @@ export class CredentialsHelper extends ICredentialsHelper { nodeCredentials: INodeCredentialsDetails, type: string, mode: WorkflowExecuteMode, + defaultTimezone: string, raw?: boolean, expressionResolveValues?: ICredentialsExpressionResolveValues, ): Promise { @@ -307,6 +315,7 @@ export class CredentialsHelper extends ICredentialsHelper { decryptedDataOriginal, type, mode, + defaultTimezone, expressionResolveValues, ); } @@ -323,6 +332,7 @@ export class CredentialsHelper extends ICredentialsHelper { decryptedDataOriginal: ICredentialDataDecryptedObject, type: string, mode: WorkflowExecuteMode, + defaultTimezone: string, expressionResolveValues?: ICredentialsExpressionResolveValues, ): ICredentialDataDecryptedObject { const credentialsProperties = this.getCredentialsProperties(type); @@ -342,14 +352,11 @@ export class CredentialsHelper extends ICredentialsHelper { } if (expressionResolveValues) { + const timezone = + (expressionResolveValues.workflow.settings.timezone as string) || defaultTimezone; + try { - const workflow = new Workflow({ - nodes: Object.values(expressionResolveValues.workflow.nodes), - connections: expressionResolveValues.workflow.connectionsBySourceNode, - active: false, - nodeTypes: expressionResolveValues.workflow.nodeTypes, - }); - decryptedData = workflow.expression.getParameterValue( + decryptedData = expressionResolveValues.workflow.expression.getParameterValue( decryptedData as INodeParameters, expressionResolveValues.runExecutionData, expressionResolveValues.runIndex, @@ -357,6 +364,7 @@ export class CredentialsHelper extends ICredentialsHelper { expressionResolveValues.node.name, expressionResolveValues.connectionInputData, mode, + timezone, {}, false, decryptedData, @@ -387,6 +395,7 @@ export class CredentialsHelper extends ICredentialsHelper { node, decryptedData as INodeParameters, mode, + defaultTimezone, {}, undefined, decryptedData, diff --git a/packages/cli/src/Db.ts b/packages/cli/src/Db.ts index db788c521b..3ce8b993f9 100644 --- a/packages/cli/src/Db.ts +++ b/packages/cli/src/Db.ts @@ -15,11 +15,11 @@ import { Repository, } from 'typeorm'; import { TlsOptions } from 'tls'; -import * as path from 'path'; +import path from 'path'; // eslint-disable-next-line import/no-cycle import { DatabaseType, GenericHelpers, IDatabaseCollections } from '.'; -import * as config from '../config'; +import config from '../config'; // eslint-disable-next-line import/no-cycle import { entities } from './databases/entities'; @@ -59,7 +59,7 @@ export async function init( let connectionOptions: ConnectionOptions; - const entityPrefix = config.get('database.tablePrefix'); + const entityPrefix = config.getEnv('database.tablePrefix'); if (testConnectionOptions) { connectionOptions = testConnectionOptions; @@ -95,7 +95,7 @@ export async function init( password: (await GenericHelpers.getConfigValue('database.postgresdb.password')) as string, port: (await GenericHelpers.getConfigValue('database.postgresdb.port')) as number, username: (await GenericHelpers.getConfigValue('database.postgresdb.user')) as string, - schema: config.get('database.postgresdb.schema'), + schema: config.getEnv('database.postgresdb.schema'), migrations: postgresMigrations, migrationsRun: true, migrationsTableName: `${entityPrefix}migrations`, diff --git a/packages/cli/src/ExternalHooks.ts b/packages/cli/src/ExternalHooks.ts index 8578f61bc8..d4f905f57f 100644 --- a/packages/cli/src/ExternalHooks.ts +++ b/packages/cli/src/ExternalHooks.ts @@ -4,7 +4,7 @@ // eslint-disable-next-line import/no-cycle import { Db, IExternalHooksClass, IExternalHooksFileData, IExternalHooksFunctions } from '.'; -import * as config from '../config'; +import config from '../config'; class ExternalHooksClass implements IExternalHooksClass { externalHooks: { @@ -34,7 +34,7 @@ class ExternalHooksClass implements IExternalHooksClass { } async loadHooksFiles(reload = false) { - const externalHookFiles = config.get('externalHookFiles').split(':'); + const externalHookFiles = config.getEnv('externalHookFiles').split(':'); // Load all the provided hook-files for (let hookFilePath of externalHookFiles) { diff --git a/packages/cli/src/GenericHelpers.ts b/packages/cli/src/GenericHelpers.ts index 9514c202d1..82b24af246 100644 --- a/packages/cli/src/GenericHelpers.ts +++ b/packages/cli/src/GenericHelpers.ts @@ -5,12 +5,12 @@ /* eslint-disable no-param-reassign */ /* eslint-disable no-underscore-dangle */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import * as express from 'express'; +import express from 'express'; import { join as pathJoin } from 'path'; import { readFile as fsReadFile } from 'fs/promises'; import { IDataObject } from 'n8n-workflow'; import { validate } from 'class-validator'; -import * as config from '../config'; +import config from '../config'; // eslint-disable-next-line import/no-cycle import { Db, ICredentialsDb, IPackageVersions, ResponseHelper } from '.'; @@ -31,10 +31,10 @@ let versionCache: IPackageVersions | undefined; * @returns {string} */ export function getBaseUrl(): string { - const protocol = config.get('protocol'); - const host = config.get('host'); - const port = config.get('port'); - const path = config.get('path'); + const protocol = config.getEnv('protocol'); + const host = config.getEnv('host'); + const port = config.getEnv('port'); + const path = config.getEnv('path'); if ((protocol === 'http' && port === 80) || (protocol === 'https' && port === 443)) { return `${protocol}://${host}${path}`; @@ -117,14 +117,16 @@ export async function getConfigValue( // Check if environment variable is defined for config key if (currentSchema.env === undefined) { // No environment variable defined, so return value from config - return config.get(configKey); + // @ts-ignore + return config.getEnv(configKey); } // Check if special file enviroment variable exists const fileEnvironmentVariable = process.env[`${currentSchema.env}_FILE`]; if (fileEnvironmentVariable === undefined) { // Does not exist, so return value from config - return config.get(configKey); + // @ts-ignore + return config.getEnv(configKey); } let data; diff --git a/packages/cli/src/Interfaces.ts b/packages/cli/src/Interfaces.ts index ac8290140c..cf8362838a 100644 --- a/packages/cli/src/Interfaces.ts +++ b/packages/cli/src/Interfaces.ts @@ -21,7 +21,7 @@ import { import { WorkflowExecute } from 'n8n-core'; // eslint-disable-next-line import/no-extraneous-dependencies -import * as PCancelable from 'p-cancelable'; +import PCancelable from 'p-cancelable'; import { Repository } from 'typeorm'; import { ChildProcess } from 'child_process'; @@ -329,7 +329,7 @@ export interface IDiagnosticInfo { }; }; executionVariables: { - [key: string]: string | number | undefined; + [key: string]: string | number | boolean | undefined; }; deploymentType: string; binaryDataMode: string; @@ -458,7 +458,7 @@ export interface IN8nUISettings { defaultLocale: string; userManagement: IUserManagementSettings; workflowTagsDisabled: boolean; - logLevel: 'info' | 'debug' | 'warn' | 'error' | 'verbose'; + logLevel: 'info' | 'debug' | 'warn' | 'error' | 'verbose' | 'silent'; hiringBannerEnabled: boolean; templates: { enabled: boolean; diff --git a/packages/cli/src/LoadNodesAndCredentials.ts b/packages/cli/src/LoadNodesAndCredentials.ts index ae9d58be17..c1178c9058 100644 --- a/packages/cli/src/LoadNodesAndCredentials.ts +++ b/packages/cli/src/LoadNodesAndCredentials.ts @@ -26,10 +26,10 @@ import { readFile as fsReadFile, stat as fsStat, } from 'fs/promises'; -import * as glob from 'fast-glob'; -import * as path from 'path'; +import glob from 'fast-glob'; +import path from 'path'; import { getLogger } from './Logger'; -import * as config from '../config'; +import config from '../config'; const CUSTOM_NODES_CATEGORY = 'Custom Nodes'; @@ -38,9 +38,9 @@ class LoadNodesAndCredentialsClass { credentialTypes: ICredentialTypeData = {}; - excludeNodes: string[] | undefined = undefined; + excludeNodes: string | undefined = undefined; - includeNodes: string[] | undefined = undefined; + includeNodes: string | undefined = undefined; nodeModulesPath = ''; @@ -76,8 +76,8 @@ class LoadNodesAndCredentialsClass { throw new Error('Could not find "node_modules" folder!'); } - this.excludeNodes = config.get('nodes.exclude'); - this.includeNodes = config.get('nodes.include'); + this.excludeNodes = config.getEnv('nodes.exclude'); + this.includeNodes = config.getEnv('nodes.include'); // Get all the installed packages which contain n8n nodes const packages = await this.getN8nNodePackages(); diff --git a/packages/cli/src/Logger.ts b/packages/cli/src/Logger.ts index b5c7844378..c5a9cb1654 100644 --- a/packages/cli/src/Logger.ts +++ b/packages/cli/src/Logger.ts @@ -1,24 +1,28 @@ +/* eslint-disable @typescript-eslint/no-shadow */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ -import * as winston from 'winston'; +import winston from 'winston'; import { IDataObject, ILogger, LogTypes } from 'n8n-workflow'; -import * as callsites from 'callsites'; +import callsites from 'callsites'; import { basename } from 'path'; -import config = require('../config'); +import config from '../config'; class Logger implements ILogger { private logger: winston.Logger; constructor() { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const level = config.get('logs.level'); - // eslint-disable-next-line @typescript-eslint/no-shadow - const output = (config.get('logs.output') as string).split(',').map((output) => output.trim()); + const level = config.getEnv('logs.level'); + + const output = config + .getEnv('logs.output') + .split(',') + .map((output) => output.trim()); this.logger = winston.createLogger({ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment level, + silent: level === 'silent', }); if (output.includes('console')) { @@ -55,10 +59,10 @@ class Logger implements ILogger { ); this.logger.add( new winston.transports.File({ - filename: config.get('logs.file.location'), + filename: config.getEnv('logs.file.location'), format: fileLogFormat, - maxsize: (config.get('logs.file.fileSizeMax') as number) * 1048576, // config * 1mb - maxFiles: config.get('logs.file.fileCountMax'), + maxsize: config.getEnv('logs.file.fileSizeMax') * 1048576, // config * 1mb + maxFiles: config.getEnv('logs.file.fileCountMax'), }), ); } diff --git a/packages/cli/src/Push.ts b/packages/cli/src/Push.ts index 2ebac7768b..c982ce6a54 100644 --- a/packages/cli/src/Push.ts +++ b/packages/cli/src/Push.ts @@ -1,8 +1,8 @@ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ // @ts-ignore -import * as sseChannel from 'sse-channel'; -import * as express from 'express'; +import sseChannel from 'sse-channel'; +import express from 'express'; import { LoggerProxy as Logger } from 'n8n-workflow'; // eslint-disable-next-line import/no-cycle diff --git a/packages/cli/src/Queue.ts b/packages/cli/src/Queue.ts index 5d215a2bd6..9d4314e645 100644 --- a/packages/cli/src/Queue.ts +++ b/packages/cli/src/Queue.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import * as Bull from 'bull'; -import * as config from '../config'; +import Bull from 'bull'; +import config from '../config'; // eslint-disable-next-line import/no-cycle import { IBullJobData, IBullWebhookResponse } from './Interfaces'; // eslint-disable-next-line import/no-cycle @@ -16,8 +16,8 @@ export class Queue { constructor() { this.activeExecutions = ActiveExecutions.getInstance(); - const prefix = config.get('queue.bull.prefix') as string; - const redisOptions = config.get('queue.bull.redis') as object; + const prefix = config.getEnv('queue.bull.prefix'); + const redisOptions = config.getEnv('queue.bull.redis'); // Disabling ready check is necessary as it allows worker to // quickly reconnect to Redis if Redis crashes or is unreachable // for some time. With it enabled, worker might take minutes to realize diff --git a/packages/cli/src/ResponseHelper.ts b/packages/cli/src/ResponseHelper.ts index 747ca0211d..3eae444995 100644 --- a/packages/cli/src/ResponseHelper.ts +++ b/packages/cli/src/ResponseHelper.ts @@ -96,15 +96,13 @@ export function sendSuccessResponse( } } -export function sendErrorResponse(res: Response, error: ResponseError, shouldLog = true) { +export function sendErrorResponse(res: Response, error: ResponseError) { let httpStatusCode = 500; if (error.httpStatusCode) { httpStatusCode = error.httpStatusCode; } - shouldLog = !process.argv[1].split('/').includes('jest'); - - if (process.env.NODE_ENV !== 'production' && shouldLog) { + if (!process.env.NODE_ENV || process.env.NODE_ENV === 'development') { console.error('ERROR RESPONSE'); console.error(error); } diff --git a/packages/cli/src/Server.ts b/packages/cli/src/Server.ts index 33a8918d60..e104440d9e 100644 --- a/packages/cli/src/Server.ts +++ b/packages/cli/src/Server.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-unnecessary-boolean-literal-compare */ /* eslint-disable @typescript-eslint/no-unnecessary-type-assertion */ /* eslint-disable @typescript-eslint/no-use-before-define */ /* eslint-disable @typescript-eslint/await-thenable */ @@ -28,10 +29,10 @@ /* eslint-disable import/no-dynamic-require */ /* eslint-disable no-await-in-loop */ -import * as express from 'express'; -import { existsSync, readFileSync } from 'fs'; +import express from 'express'; +import { readFileSync } from 'fs'; import { readFile } from 'fs/promises'; -import { cloneDeep } from 'lodash'; +import _, { cloneDeep } from 'lodash'; import { dirname as pathDirname, join as pathJoin, resolve as pathResolve } from 'path'; import { FindConditions, @@ -46,22 +47,19 @@ import { Not, Raw, } from 'typeorm'; -import * as bodyParser from 'body-parser'; -import * as cookieParser from 'cookie-parser'; -import * as history from 'connect-history-api-fallback'; -import * as os from 'os'; +import bodyParser from 'body-parser'; +import cookieParser from 'cookie-parser'; +import history from 'connect-history-api-fallback'; +import os from 'os'; // eslint-disable-next-line import/no-extraneous-dependencies -import * as _ from 'lodash'; -import * as clientOAuth2 from 'client-oauth2'; -import * as clientOAuth1 from 'oauth-1.0a'; -import { RequestOptions } from 'oauth-1.0a'; -import * as csrf from 'csrf'; -import * as requestPromise from 'request-promise-native'; +import clientOAuth2 from 'client-oauth2'; +import clientOAuth1, { RequestOptions } from 'oauth-1.0a'; +import csrf from 'csrf'; +import requestPromise, { OptionsWithUrl } from 'request-promise-native'; import { createHmac } from 'crypto'; // IMPORTANT! Do not switch to anther bcrypt library unless really necessary and // tested with all possible systems like Windows, Alpine on ARM, FreeBSD, ... import { compare } from 'bcryptjs'; -import * as promClient from 'prom-client'; import { BinaryDataManager, @@ -90,16 +88,15 @@ import { WorkflowExecuteMode, } from 'n8n-workflow'; -import * as basicAuth from 'basic-auth'; -import * as compression from 'compression'; -import * as jwt from 'jsonwebtoken'; -import * as jwks from 'jwks-rsa'; +import basicAuth from 'basic-auth'; +import compression from 'compression'; +import jwt from 'jsonwebtoken'; +import jwks from 'jwks-rsa'; // @ts-ignore -import * as timezones from 'google-timezones-json'; -import * as parseUrl from 'parseurl'; -import * as querystring from 'querystring'; -import { OptionsWithUrl } from 'request-promise-native'; -import { Registry } from 'prom-client'; +import timezones from 'google-timezones-json'; +import parseUrl from 'parseurl'; +import querystring from 'querystring'; +import promClient, { Registry } from 'prom-client'; import * as Queue from './Queue'; import { ActiveExecutions, @@ -142,7 +139,7 @@ import { getCredentialForUser, } from '.'; -import * as config from '../config'; +import config from '../config'; import * as TagHelpers from './TagHelpers'; @@ -200,9 +197,9 @@ class App { defaultCredentialsName: string; - saveDataErrorExecution: string; + saveDataErrorExecution: 'all' | 'none'; - saveDataSuccessExecution: string; + saveDataSuccessExecution: 'all' | 'none'; saveManualExecutions: boolean; @@ -237,21 +234,21 @@ class App { constructor() { this.app = express(); - this.endpointWebhook = config.get('endpoints.webhook') as string; - this.endpointWebhookWaiting = config.get('endpoints.webhookWaiting') as string; - this.endpointWebhookTest = config.get('endpoints.webhookTest') as string; + this.endpointWebhook = config.getEnv('endpoints.webhook'); + this.endpointWebhookWaiting = config.getEnv('endpoints.webhookWaiting'); + this.endpointWebhookTest = config.getEnv('endpoints.webhookTest'); - this.defaultWorkflowName = config.get('workflows.defaultName') as string; - this.defaultCredentialsName = config.get('credentials.defaultName') as string; + this.defaultWorkflowName = config.getEnv('workflows.defaultName'); + this.defaultCredentialsName = config.getEnv('credentials.defaultName'); - this.saveDataErrorExecution = config.get('executions.saveDataOnError') as string; - this.saveDataSuccessExecution = config.get('executions.saveDataOnSuccess') as string; - this.saveManualExecutions = config.get('executions.saveDataManualExecutions') as boolean; - this.executionTimeout = config.get('executions.timeout') as number; - this.maxExecutionTimeout = config.get('executions.maxTimeout') as number; - this.payloadSizeMax = config.get('endpoints.payloadSizeMax') as number; - this.timezone = config.get('generic.timezone') as string; - this.restEndpoint = config.get('endpoints.rest') as string; + this.saveDataErrorExecution = config.getEnv('executions.saveDataOnError'); + this.saveDataSuccessExecution = config.getEnv('executions.saveDataOnSuccess'); + this.saveManualExecutions = config.getEnv('executions.saveDataManualExecutions'); + this.executionTimeout = config.getEnv('executions.timeout'); + this.maxExecutionTimeout = config.getEnv('executions.maxTimeout'); + this.payloadSizeMax = config.getEnv('endpoints.payloadSizeMax'); + this.timezone = config.getEnv('generic.timezone'); + this.restEndpoint = config.getEnv('endpoints.rest'); this.activeWorkflowRunner = ActiveWorkflowRunner.getInstance(); this.testWebhooks = TestWebhooks.getInstance(); @@ -260,22 +257,22 @@ class App { this.activeExecutionsInstance = ActiveExecutions.getInstance(); this.waitTracker = WaitTracker(); - this.protocol = config.get('protocol'); - this.sslKey = config.get('ssl_key'); - this.sslCert = config.get('ssl_cert'); + this.protocol = config.getEnv('protocol'); + this.sslKey = config.getEnv('ssl_key'); + this.sslCert = config.getEnv('ssl_cert'); this.externalHooks = externalHooks; this.presetCredentialsLoaded = false; - this.endpointPresetCredentials = config.get('credentials.overwrite.endpoint') as string; + this.endpointPresetCredentials = config.getEnv('credentials.overwrite.endpoint'); const urlBaseWebhook = WebhookHelpers.getWebhookBaseUrl(); const telemetrySettings: ITelemetrySettings = { - enabled: config.get('diagnostics.enabled') as boolean, + enabled: config.getEnv('diagnostics.enabled'), }; if (telemetrySettings.enabled) { - const conf = config.get('diagnostics.config.frontend') as string; + const conf = config.getEnv('diagnostics.config.frontend'); const [key, url] = conf.split(';'); if (!key || !url) { @@ -303,31 +300,31 @@ class App { oauth2: `${urlBaseWebhook}${this.restEndpoint}/oauth2-credential/callback`, }, versionNotifications: { - enabled: config.get('versionNotifications.enabled'), - endpoint: config.get('versionNotifications.endpoint'), - infoUrl: config.get('versionNotifications.infoUrl'), + enabled: config.getEnv('versionNotifications.enabled'), + endpoint: config.getEnv('versionNotifications.endpoint'), + infoUrl: config.getEnv('versionNotifications.infoUrl'), }, instanceId: '', telemetry: telemetrySettings, personalizationSurveyEnabled: - config.get('personalization.enabled') && config.get('diagnostics.enabled'), - defaultLocale: config.get('defaultLocale'), + config.getEnv('personalization.enabled') && config.getEnv('diagnostics.enabled'), + defaultLocale: config.getEnv('defaultLocale'), userManagement: { enabled: - config.get('userManagement.disabled') === false || - config.get('userManagement.isInstanceOwnerSetUp') === true, + config.getEnv('userManagement.disabled') === false || + config.getEnv('userManagement.isInstanceOwnerSetUp') === true, showSetupOnFirstLoad: - config.get('userManagement.disabled') === false && - config.get('userManagement.isInstanceOwnerSetUp') === false && - config.get('userManagement.skipInstanceOwnerSetup') === false, + config.getEnv('userManagement.disabled') === false && + config.getEnv('userManagement.isInstanceOwnerSetUp') === false && + config.getEnv('userManagement.skipInstanceOwnerSetup') === false, smtpSetup: isEmailSetUp(), }, - workflowTagsDisabled: config.get('workflowTagsDisabled'), - logLevel: config.get('logs.level'), - hiringBannerEnabled: config.get('hiringBanner.enabled'), + workflowTagsDisabled: config.getEnv('workflowTagsDisabled'), + logLevel: config.getEnv('logs.level'), + hiringBannerEnabled: config.getEnv('hiringBanner.enabled'), templates: { - enabled: config.get('templates.enabled'), - host: config.get('templates.host'), + enabled: config.getEnv('templates.enabled'), + host: config.getEnv('templates.host'), }, }; } @@ -349,23 +346,23 @@ class App { // refresh user management status Object.assign(this.frontendSettings.userManagement, { enabled: - config.get('userManagement.disabled') === false || - config.get('userManagement.isInstanceOwnerSetUp') === true, + config.getEnv('userManagement.disabled') === false || + config.getEnv('userManagement.isInstanceOwnerSetUp') === true, showSetupOnFirstLoad: - config.get('userManagement.disabled') === false && - config.get('userManagement.isInstanceOwnerSetUp') === false && - config.get('userManagement.skipInstanceOwnerSetup') === false, + config.getEnv('userManagement.disabled') === false && + config.getEnv('userManagement.isInstanceOwnerSetUp') === false && + config.getEnv('userManagement.skipInstanceOwnerSetup') === false, }); return this.frontendSettings; } async config(): Promise { - const enableMetrics = config.get('endpoints.metrics.enable') as boolean; + const enableMetrics = config.getEnv('endpoints.metrics.enable'); let register: Registry; if (enableMetrics) { - const prefix = config.get('endpoints.metrics.prefix') as string; + const prefix = config.getEnv('endpoints.metrics.prefix'); register = new promClient.Registry(); register.setDefaultLabels({ prefix }); promClient.collectDefaultMetrics({ register }); @@ -378,7 +375,7 @@ class App { await this.externalHooks.run('frontend.settings', [this.frontendSettings]); - const excludeEndpoints = config.get('security.excludeEndpoints') as string; + const excludeEndpoints = config.getEnv('security.excludeEndpoints'); const ignoredEndpoints = [ 'healthz', @@ -394,7 +391,7 @@ class App { const authIgnoreRegex = new RegExp(`^\/(${_(ignoredEndpoints).compact().join('|')})\/?.*$`); // Check for basic auth credentials if activated - const basicAuthActive = config.get('security.basicAuth.active') as boolean; + const basicAuthActive = config.getEnv('security.basicAuth.active'); if (basicAuthActive) { const basicAuthUser = (await GenericHelpers.getConfigValue( 'security.basicAuth.user', @@ -419,7 +416,10 @@ class App { this.app.use( async (req: express.Request, res: express.Response, next: express.NextFunction) => { // Skip basic auth for a few listed endpoints or when instance owner has been setup - if (authIgnoreRegex.exec(req.url) || config.get('userManagement.isInstanceOwnerSetUp')) { + if ( + authIgnoreRegex.exec(req.url) || + config.getEnv('userManagement.isInstanceOwnerSetUp') + ) { return next(); } const realm = 'n8n - Editor UI'; @@ -465,7 +465,7 @@ class App { } // Check for and validate JWT if configured - const jwtAuthActive = config.get('security.jwtAuth.active') as boolean; + const jwtAuthActive = config.getEnv('security.jwtAuth.active'); if (jwtAuthActive) { const jwtAuthHeader = (await GenericHelpers.getConfigValue( 'security.jwtAuth.jwtHeader', @@ -750,7 +750,7 @@ class App { const { tags: tagIds } = req.body; - if (tagIds?.length && !config.get('workflowTagsDisabled')) { + if (tagIds?.length && !config.getEnv('workflowTagsDisabled')) { newWorkflow.tags = await Db.collections.Tag!.findByIds(tagIds, { select: ['id', 'name'], }); @@ -784,7 +784,7 @@ class App { throw new ResponseHelper.ResponseError('Failed to save workflow'); } - if (tagIds && !config.get('workflowTagsDisabled')) { + if (tagIds && !config.getEnv('workflowTagsDisabled')) { savedWorkflow.tags = TagHelpers.sortByRequestOrder(savedWorkflow.tags, { requestOrder: tagIds, }); @@ -868,7 +868,7 @@ class App { relations: ['tags'], }; - if (config.get('workflowTagsDisabled')) { + if (config.getEnv('workflowTagsDisabled')) { delete query.relations; } @@ -928,7 +928,7 @@ class App { let relations = ['workflow', 'workflow.tags']; - if (config.get('workflowTagsDisabled')) { + if (config.getEnv('workflowTagsDisabled')) { relations = relations.filter((relation) => relation !== 'workflow.tags'); } @@ -1038,8 +1038,8 @@ class App { await Db.collections.Workflow!.update(workflowId, updateData); - if (tags && !config.get('workflowTagsDisabled')) { - const tablePrefix = config.get('database.tablePrefix'); + if (tags && !config.getEnv('workflowTagsDisabled')) { + const tablePrefix = config.getEnv('database.tablePrefix'); await TagHelpers.removeRelations(workflowId, tablePrefix); if (tags.length) { @@ -1051,7 +1051,7 @@ class App { relations: ['tags'], }; - if (config.get('workflowTagsDisabled')) { + if (config.getEnv('workflowTagsDisabled')) { delete options.relations; } @@ -1233,11 +1233,11 @@ class App { req: express.Request, res: express.Response, ): Promise => { - if (config.get('workflowTagsDisabled')) { + if (config.getEnv('workflowTagsDisabled')) { throw new ResponseHelper.ResponseError('Workflow tags are disabled'); } if (req.query.withUsageCount === 'true') { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); return TagHelpers.getTagsWithCountDb(tablePrefix); } @@ -1251,7 +1251,7 @@ class App { `/${this.restEndpoint}/tags`, ResponseHelper.send( async (req: express.Request, res: express.Response): Promise => { - if (config.get('workflowTagsDisabled')) { + if (config.getEnv('workflowTagsDisabled')) { throw new ResponseHelper.ResponseError('Workflow tags are disabled'); } const newTag = new TagEntity(); @@ -1274,7 +1274,7 @@ class App { `/${this.restEndpoint}/tags/:id`, ResponseHelper.send( async (req: express.Request, res: express.Response): Promise => { - if (config.get('workflowTagsDisabled')) { + if (config.getEnv('workflowTagsDisabled')) { throw new ResponseHelper.ResponseError('Workflow tags are disabled'); } @@ -1303,11 +1303,11 @@ class App { `/${this.restEndpoint}/tags/:id`, ResponseHelper.send( async (req: TagsRequest.Delete, res: express.Response): Promise => { - if (config.get('workflowTagsDisabled')) { + if (config.getEnv('workflowTagsDisabled')) { throw new ResponseHelper.ResponseError('Workflow tags are disabled'); } if ( - config.get('userManagement.isInstanceOwnerSetUp') === true && + config.getEnv('userManagement.isInstanceOwnerSetUp') === true && req.user.globalRole.name !== 'owner' ) { throw new ResponseHelper.ResponseError( @@ -1709,11 +1709,13 @@ class App { } const mode: WorkflowExecuteMode = 'internal'; + const timezone = config.getEnv('generic.timezone'); const credentialsHelper = new CredentialsHelper(encryptionKey); const decryptedDataOriginal = await credentialsHelper.getDecrypted( credential as INodeCredentialsDetails, credential.type, mode, + timezone, true, ); @@ -1721,6 +1723,7 @@ class App { decryptedDataOriginal, credential.type, mode, + timezone, ); const signatureMethod = _.get(oauthCredentials, 'signatureMethod') as string; @@ -1847,17 +1850,20 @@ class App { } const mode: WorkflowExecuteMode = 'internal'; + const timezone = config.getEnv('generic.timezone'); const credentialsHelper = new CredentialsHelper(encryptionKey); const decryptedDataOriginal = await credentialsHelper.getDecrypted( credential as INodeCredentialsDetails, credential.type, mode, + timezone, true, ); const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites( decryptedDataOriginal, credential.type, mode, + timezone, ); const options: OptionsWithUrl = { @@ -1962,11 +1968,13 @@ class App { } const mode: WorkflowExecuteMode = 'internal'; + const timezone = config.getEnv('generic.timezone'); const credentialsHelper = new CredentialsHelper(encryptionKey); const decryptedDataOriginal = await credentialsHelper.getDecrypted( credential as INodeCredentialsDetails, credential.type, mode, + timezone, true, ); @@ -1974,6 +1982,7 @@ class App { decryptedDataOriginal, credential.type, mode, + timezone, ); const token = new csrf(); @@ -2102,17 +2111,20 @@ class App { } const mode: WorkflowExecuteMode = 'internal'; + const timezone = config.getEnv('generic.timezone'); const credentialsHelper = new CredentialsHelper(encryptionKey); const decryptedDataOriginal = await credentialsHelper.getDecrypted( credential as INodeCredentialsDetails, credential.type, mode, + timezone, true, ); const oauthCredentials = credentialsHelper.applyDefaultsAndOverwrites( decryptedDataOriginal, credential.type, mode, + timezone, ); const token = new csrf(); @@ -2235,7 +2247,7 @@ class App { const executingWorkflowIds: string[] = []; - if (config.get('executions.mode') === 'queue') { + if (config.getEnv('executions.mode') === 'queue') { const currentJobs = await Queue.getInstance().getJobs(['active', 'waiting']); executingWorkflowIds.push(...currentJobs.map(({ data }) => data.executionId)); } @@ -2598,7 +2610,7 @@ class App { `/${this.restEndpoint}/executions-current`, ResponseHelper.send( async (req: ExecutionRequest.GetAllCurrent): Promise => { - if (config.get('executions.mode') === 'queue') { + if (config.getEnv('executions.mode') === 'queue') { const currentJobs = await Queue.getInstance().getJobs(['active', 'waiting']); const currentlyRunningQueueIds = currentJobs.map((job) => job.data.executionId); @@ -2663,7 +2675,7 @@ class App { for (const data of executingWorkflows) { if ( (filter.workflowId !== undefined && filter.workflowId !== data.workflowId) || - !sharedWorkflowIds.includes(data.workflowId) + !sharedWorkflowIds.includes(data.workflowId.toString()) ) { continue; } @@ -2707,7 +2719,7 @@ class App { throw new ResponseHelper.ResponseError('Execution not found', undefined, 404); } - if (config.get('executions.mode') === 'queue') { + if (config.getEnv('executions.mode') === 'queue') { // Manual executions should still be stoppable, so // try notifying the `activeExecutions` to stop it. const result = await this.activeExecutionsInstance.stopExecution(req.params.id); @@ -2834,7 +2846,7 @@ class App { // Webhooks // ---------------------------------------- - if (config.get('endpoints.disableProductionWebhooksOnMainProcess') !== true) { + if (!config.getEnv('endpoints.disableProductionWebhooksOnMainProcess')) { WebhookServer.registerProductionWebhooks.apply(this); } @@ -2929,11 +2941,11 @@ class App { ); } - if (config.get('endpoints.disableUi') !== true) { + if (!config.getEnv('endpoints.disableUi')) { // Read the index file and replace the path placeholder const editorUiPath = require.resolve('n8n-editor-ui'); const filePath = pathJoin(pathDirname(editorUiPath), 'dist', 'index.html'); - const n8nPath = config.get('path'); + const n8nPath = config.getEnv('path'); let readIndexFile = readFileSync(filePath, 'utf8'); readIndexFile = readIndexFile.replace(/\/%BASE_PATH%\//g, n8nPath); @@ -2965,8 +2977,8 @@ class App { } export async function start(): Promise { - const PORT = config.get('port'); - const ADDRESS = config.get('listen_address'); + const PORT = config.getEnv('port'); + const ADDRESS = config.getEnv('listen_address'); const app = new App(); @@ -2990,7 +3002,7 @@ export async function start(): Promise { console.log(`n8n ready on ${ADDRESS}, port ${PORT}`); console.log(`Version: ${versions.cli}`); - const defaultLocale = config.get('defaultLocale'); + const defaultLocale = config.getEnv('defaultLocale'); if (defaultLocale !== 'en') { console.log(`Locale: ${defaultLocale}`); @@ -2998,13 +3010,14 @@ export async function start(): Promise { await app.externalHooks.run('n8n.ready', [app]); const cpus = os.cpus(); - const binarDataConfig = config.get('binaryDataManager') as IBinaryDataConfig; + const binarDataConfig = config.getEnv('binaryDataManager'); const diagnosticInfo: IDiagnosticInfo = { - basicAuthActive: config.get('security.basicAuth.active') as boolean, + basicAuthActive: config.getEnv('security.basicAuth.active'), databaseType: (await GenericHelpers.getConfigValue('database.type')) as DatabaseType, - disableProductionWebhooksOnMainProcess: - config.get('endpoints.disableProductionWebhooksOnMainProcess') === true, - notificationsEnabled: config.get('versionNotifications.enabled') === true, + disableProductionWebhooksOnMainProcess: config.getEnv( + 'endpoints.disableProductionWebhooksOnMainProcess', + ), + notificationsEnabled: config.getEnv('versionNotifications.enabled'), versionCli: versions.cli, systemInfo: { os: { @@ -3019,24 +3032,26 @@ export async function start(): Promise { }, }, executionVariables: { - executions_process: config.get('executions.process'), - executions_mode: config.get('executions.mode'), - executions_timeout: config.get('executions.timeout'), - executions_timeout_max: config.get('executions.maxTimeout'), - executions_data_save_on_error: config.get('executions.saveDataOnError'), - executions_data_save_on_success: config.get('executions.saveDataOnSuccess'), - executions_data_save_on_progress: config.get('executions.saveExecutionProgress'), - executions_data_save_manual_executions: config.get('executions.saveDataManualExecutions'), - executions_data_prune: config.get('executions.pruneData'), - executions_data_max_age: config.get('executions.pruneDataMaxAge'), - executions_data_prune_timeout: config.get('executions.pruneDataTimeout'), + executions_process: config.getEnv('executions.process'), + executions_mode: config.getEnv('executions.mode'), + executions_timeout: config.getEnv('executions.timeout'), + executions_timeout_max: config.getEnv('executions.maxTimeout'), + executions_data_save_on_error: config.getEnv('executions.saveDataOnError'), + executions_data_save_on_success: config.getEnv('executions.saveDataOnSuccess'), + executions_data_save_on_progress: config.getEnv('executions.saveExecutionProgress'), + executions_data_save_manual_executions: config.getEnv( + 'executions.saveDataManualExecutions', + ), + executions_data_prune: config.getEnv('executions.pruneData'), + executions_data_max_age: config.getEnv('executions.pruneDataMaxAge'), + executions_data_prune_timeout: config.getEnv('executions.pruneDataTimeout'), }, - deploymentType: config.get('deployment.type'), + deploymentType: config.getEnv('deployment.type'), binaryDataMode: binarDataConfig.mode, n8n_multi_user_allowed: - config.get('userManagement.disabled') === false || - config.get('userManagement.isInstanceOwnerSetUp') === true, - smtp_set_up: config.get('userManagement.emails.mode') === 'smtp', + config.getEnv('userManagement.disabled') === false || + config.getEnv('userManagement.isInstanceOwnerSetUp') === true, + smtp_set_up: config.getEnv('userManagement.emails.mode') === 'smtp', }; void Db.collections diff --git a/packages/cli/src/TestWebhooks.ts b/packages/cli/src/TestWebhooks.ts index 93048e3c29..6651660ad5 100644 --- a/packages/cli/src/TestWebhooks.ts +++ b/packages/cli/src/TestWebhooks.ts @@ -1,7 +1,7 @@ /* eslint-disable consistent-return */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable no-param-reassign */ -import * as express from 'express'; +import express from 'express'; import { ActiveWebhooks } from 'n8n-core'; diff --git a/packages/cli/src/UserManagement/UserManagementHelper.ts b/packages/cli/src/UserManagement/UserManagementHelper.ts index 332a0efb77..6c8defa448 100644 --- a/packages/cli/src/UserManagement/UserManagementHelper.ts +++ b/packages/cli/src/UserManagement/UserManagementHelper.ts @@ -2,14 +2,16 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable import/no-cycle */ import { Workflow } from 'n8n-workflow'; -import { In, IsNull, Not } from 'typeorm'; -import express = require('express'); +import { In } from 'typeorm'; +import express from 'express'; +import { compare, genSaltSync, hash } from 'bcryptjs'; + import { PublicUser } from './Interfaces'; -import { Db, GenericHelpers, ResponseHelper } from '..'; +import { Db, ResponseHelper } from '..'; import { MAX_PASSWORD_LENGTH, MIN_PASSWORD_LENGTH, User } from '../databases/entities/User'; import { Role } from '../databases/entities/Role'; import { AuthenticatedRequest } from '../requests'; -import config = require('../../config'); +import * as config from '../../config'; import { getWebhookBaseUrl } from '../WebhookHelpers'; export async function getWorkflowOwner(workflowId: string | number): Promise { @@ -22,10 +24,10 @@ export async function getWorkflowOwner(workflowId: string | number): Promise { * Return the n8n instance base URL without trailing slash. */ export function getInstanceBaseUrl(): string { - const n8nBaseUrl = config.get('editorBaseUrl') || getWebhookBaseUrl(); + const n8nBaseUrl = config.getEnv('editorBaseUrl') || getWebhookBaseUrl(); return n8nBaseUrl.endsWith('/') ? n8nBaseUrl.slice(0, n8nBaseUrl.length - 1) : n8nBaseUrl; } -export async function isInstanceOwnerSetup(): Promise { - const users = await Db.collections.User!.find({ email: Not(IsNull()) }); - return users.length !== 0; -} - // TODO: Enforce at model level export function validatePassword(password?: string): string { if (!password) { @@ -199,7 +196,7 @@ export async function checkPermissionsForExecution( export function isAuthExcluded(url: string, ignoredEndpoints: string[]): boolean { return !!ignoredEndpoints .filter(Boolean) // skip empty paths - .find((ignoredEndpoint) => url.includes(ignoredEndpoint)); + .find((ignoredEndpoint) => url.startsWith(`/${ignoredEndpoint}`)); } /** @@ -216,3 +213,23 @@ export function isPostUsersId(req: express.Request, restEndpoint: string): boole export function isAuthenticatedRequest(request: express.Request): request is AuthenticatedRequest { return request.user !== undefined; } + +// ---------------------------------- +// hashing +// ---------------------------------- + +export const hashPassword = async (validPassword: string): Promise => + hash(validPassword, genSaltSync(10)); + +export async function compareHash(plaintext: string, hashed: string): Promise { + try { + return await compare(plaintext, hashed); + } catch (error) { + if (error instanceof Error && error.message.includes('Invalid salt version')) { + error.message += + '. Comparison against unhashed string. Please check that the value compared against has been hashed.'; + } + + throw new Error(error); + } +} diff --git a/packages/cli/src/UserManagement/auth/jwt.ts b/packages/cli/src/UserManagement/auth/jwt.ts index 2dca697801..a247ad62b5 100644 --- a/packages/cli/src/UserManagement/auth/jwt.ts +++ b/packages/cli/src/UserManagement/auth/jwt.ts @@ -1,14 +1,14 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable import/no-cycle */ -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; import { Response } from 'express'; import { createHash } from 'crypto'; import { Db } from '../..'; import { AUTH_COOKIE_NAME } from '../../constants'; import { JwtToken, JwtPayload } from '../Interfaces'; import { User } from '../../databases/entities/User'; -import config = require('../../../config'); +import * as config from '../../../config'; export function issueJWT(user: User): JwtToken { const { id, email, password } = user; @@ -26,7 +26,7 @@ export function issueJWT(user: User): JwtToken { .digest('hex'); } - const signedToken = jwt.sign(payload, config.get('userManagement.jwtSecret'), { + const signedToken = jwt.sign(payload, config.getEnv('userManagement.jwtSecret'), { expiresIn: expiresIn / 1000 /* in seconds */, }); @@ -57,7 +57,7 @@ export async function resolveJwtContent(jwtPayload: JwtPayload): Promise { } export async function resolveJwt(token: string): Promise { - const jwtPayload = jwt.verify(token, config.get('userManagement.jwtSecret')) as JwtPayload; + const jwtPayload = jwt.verify(token, config.getEnv('userManagement.jwtSecret')) as JwtPayload; return resolveJwtContent(jwtPayload); } diff --git a/packages/cli/src/UserManagement/email/NodeMailer.ts b/packages/cli/src/UserManagement/email/NodeMailer.ts index 8ea708a2f3..c73f2803f2 100644 --- a/packages/cli/src/UserManagement/email/NodeMailer.ts +++ b/packages/cli/src/UserManagement/email/NodeMailer.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ import { createTransport, Transporter } from 'nodemailer'; import { LoggerProxy as Logger } from 'n8n-workflow'; -import config = require('../../../config'); +import * as config from '../../../config'; import { MailData, SendEmailResult, UserManagementMailerImplementation } from './Interfaces'; export class NodeMailer implements UserManagementMailerImplementation { @@ -9,20 +9,20 @@ export class NodeMailer implements UserManagementMailerImplementation { constructor() { this.transport = createTransport({ - host: config.get('userManagement.emails.smtp.host'), - port: config.get('userManagement.emails.smtp.port'), - secure: config.get('userManagement.emails.smtp.secure'), + host: config.getEnv('userManagement.emails.smtp.host'), + port: config.getEnv('userManagement.emails.smtp.port'), + secure: config.getEnv('userManagement.emails.smtp.secure'), auth: { - user: config.get('userManagement.emails.smtp.auth.user'), - pass: config.get('userManagement.emails.smtp.auth.pass'), + user: config.getEnv('userManagement.emails.smtp.auth.user'), + pass: config.getEnv('userManagement.emails.smtp.auth.pass'), }, }); } async verifyConnection(): Promise { - const host = config.get('userManagement.emails.smtp.host') as string; - const user = config.get('userManagement.emails.smtp.auth.user') as string; - const pass = config.get('userManagement.emails.smtp.auth.pass') as string; + const host = config.getEnv('userManagement.emails.smtp.host'); + const user = config.getEnv('userManagement.emails.smtp.auth.user'); + const pass = config.getEnv('userManagement.emails.smtp.auth.pass'); return new Promise((resolve, reject) => { this.transport.verify((error: Error) => { @@ -43,8 +43,8 @@ export class NodeMailer implements UserManagementMailerImplementation { } async sendMail(mailData: MailData): Promise { - let sender = config.get('userManagement.emails.smtp.sender'); - const user = config.get('userManagement.emails.smtp.auth.user') as string; + let sender = config.getEnv('userManagement.emails.smtp.sender'); + const user = config.getEnv('userManagement.emails.smtp.auth.user'); if (!sender && user.includes('@')) { sender = user; diff --git a/packages/cli/src/UserManagement/email/UserManagementMailer.ts b/packages/cli/src/UserManagement/email/UserManagementMailer.ts index 525f5397d3..5b706aadfc 100644 --- a/packages/cli/src/UserManagement/email/UserManagementMailer.ts +++ b/packages/cli/src/UserManagement/email/UserManagementMailer.ts @@ -3,7 +3,7 @@ import { existsSync, readFileSync } from 'fs'; import { IDataObject } from 'n8n-workflow'; import { join as pathJoin } from 'path'; import { GenericHelpers } from '../..'; -import config = require('../../../config'); +import * as config from '../../../config'; import { InviteEmailData, PasswordResetData, @@ -45,7 +45,7 @@ export class UserManagementMailer { constructor() { // Other implementations can be used in the future. - if (config.get('userManagement.emails.mode') === 'smtp') { + if (config.getEnv('userManagement.emails.mode') === 'smtp') { this.mailer = new NodeMailer(); } } diff --git a/packages/cli/src/UserManagement/routes/auth.ts b/packages/cli/src/UserManagement/routes/auth.ts index a91e46497a..628bade65d 100644 --- a/packages/cli/src/UserManagement/routes/auth.ts +++ b/packages/cli/src/UserManagement/routes/auth.ts @@ -3,15 +3,15 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ import { Request, Response } from 'express'; -import { compare } from 'bcryptjs'; import { IDataObject } from 'n8n-workflow'; import { Db, ResponseHelper } from '../..'; import { AUTH_COOKIE_NAME } from '../../constants'; import { issueCookie, resolveJwt } from '../auth/jwt'; import { N8nApp, PublicUser } from '../Interfaces'; -import { isInstanceOwnerSetup, sanitizeUser } from '../UserManagementHelper'; +import { compareHash, sanitizeUser } from '../UserManagementHelper'; import { User } from '../../databases/entities/User'; import type { LoginRequest } from '../../requests'; +import config = require('../../../config'); export function authenticationMethods(this: N8nApp): void { /** @@ -43,7 +43,8 @@ export function authenticationMethods(this: N8nApp): void { } catch (error) { throw new Error('Unable to access database.'); } - if (!user || !user.password || !(await compare(req.body.password, user.password))) { + + if (!user || !user.password || !(await compareHash(req.body.password, user.password))) { // password is empty until user signs up const error = new Error('Wrong username or password. Do you have caps lock on?'); // @ts-ignore @@ -71,13 +72,18 @@ export function authenticationMethods(this: N8nApp): void { // If logged in, return user try { user = await resolveJwt(cookieContents); + + if (!config.get('userManagement.isInstanceOwnerSetUp')) { + res.cookie(AUTH_COOKIE_NAME, cookieContents); + } + return sanitizeUser(user); } catch (error) { res.clearCookie(AUTH_COOKIE_NAME); } } - if (await isInstanceOwnerSetup()) { + if (config.get('userManagement.isInstanceOwnerSetUp')) { const error = new Error('Not logged in'); // @ts-ignore error.httpStatusCode = 401; diff --git a/packages/cli/src/UserManagement/routes/index.ts b/packages/cli/src/UserManagement/routes/index.ts index 95420ef8d6..78534c106e 100644 --- a/packages/cli/src/UserManagement/routes/index.ts +++ b/packages/cli/src/UserManagement/routes/index.ts @@ -2,16 +2,16 @@ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable import/no-cycle */ -import cookieParser = require('cookie-parser'); -import * as passport from 'passport'; +import cookieParser from 'cookie-parser'; +import passport from 'passport'; import { Strategy } from 'passport-jwt'; import { NextFunction, Request, Response } from 'express'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; import { LoggerProxy as Logger } from 'n8n-workflow'; import { JwtPayload, N8nApp } from '../Interfaces'; import { authenticationMethods } from './auth'; -import config = require('../../../config'); +import * as config from '../../../config'; import { AUTH_COOKIE_NAME } from '../../constants'; import { issueCookie, resolveJwtContent } from '../auth/jwt'; import { meNamespace } from './me'; @@ -30,7 +30,7 @@ export function addRoutes(this: N8nApp, ignoredEndpoints: string[], restEndpoint // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access return (req.cookies?.[AUTH_COOKIE_NAME] as string | undefined) ?? null; }, - secretOrKey: config.get('userManagement.jwtSecret') as string, + secretOrKey: config.getEnv('userManagement.jwtSecret'), }; passport.use( diff --git a/packages/cli/src/UserManagement/routes/me.ts b/packages/cli/src/UserManagement/routes/me.ts index 1c4ed9f427..dbe3e1e952 100644 --- a/packages/cli/src/UserManagement/routes/me.ts +++ b/packages/cli/src/UserManagement/routes/me.ts @@ -1,15 +1,14 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable import/no-cycle */ -import { compare, genSaltSync, hashSync } from 'bcryptjs'; -import express = require('express'); +import express from 'express'; import validator from 'validator'; import { LoggerProxy as Logger } from 'n8n-workflow'; import { Db, InternalHooksManager, ResponseHelper } from '../..'; import { issueCookie } from '../auth/jwt'; import { N8nApp, PublicUser } from '../Interfaces'; -import { validatePassword, sanitizeUser } from '../UserManagementHelper'; +import { validatePassword, sanitizeUser, compareHash, hashPassword } from '../UserManagementHelper'; import type { AuthenticatedRequest, MeRequest } from '../../requests'; import { validateEntity } from '../../GenericHelpers'; import { User } from '../../databases/entities/User'; @@ -87,7 +86,7 @@ export function meNamespace(this: N8nApp): void { throw new ResponseHelper.ResponseError('Requesting user not set up.'); } - const isCurrentPwCorrect = await compare(currentPassword, req.user.password); + const isCurrentPwCorrect = await compareHash(currentPassword, req.user.password); if (!isCurrentPwCorrect) { throw new ResponseHelper.ResponseError( 'Provided current password is incorrect.', @@ -98,7 +97,7 @@ export function meNamespace(this: N8nApp): void { const validPassword = validatePassword(newPassword); - req.user.password = hashSync(validPassword, genSaltSync(10)); + req.user.password = await hashPassword(validPassword); const user = await Db.collections.User!.save(req.user); Logger.info('Password updated successfully', { userId: user.id }); diff --git a/packages/cli/src/UserManagement/routes/owner.ts b/packages/cli/src/UserManagement/routes/owner.ts index a526afc948..06c8605a49 100644 --- a/packages/cli/src/UserManagement/routes/owner.ts +++ b/packages/cli/src/UserManagement/routes/owner.ts @@ -1,17 +1,16 @@ /* eslint-disable import/no-cycle */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { hashSync, genSaltSync } from 'bcryptjs'; -import * as express from 'express'; +import express from 'express'; import validator from 'validator'; import { LoggerProxy as Logger } from 'n8n-workflow'; import { Db, InternalHooksManager, ResponseHelper } from '../..'; -import config = require('../../../config'); +import * as config from '../../../config'; import { validateEntity } from '../../GenericHelpers'; import { AuthenticatedRequest, OwnerRequest } from '../../requests'; import { issueCookie } from '../auth/jwt'; import { N8nApp } from '../Interfaces'; -import { sanitizeUser, validatePassword } from '../UserManagementHelper'; +import { hashPassword, sanitizeUser, validatePassword } from '../UserManagementHelper'; export function ownerNamespace(this: N8nApp): void { /** @@ -24,7 +23,7 @@ export function ownerNamespace(this: N8nApp): void { const { email, firstName, lastName, password } = req.body; const { id: userId } = req.user; - if (config.get('userManagement.isInstanceOwnerSetUp')) { + if (config.getEnv('userManagement.isInstanceOwnerSetUp')) { Logger.debug( 'Request to claim instance ownership failed because instance owner already exists', { @@ -74,7 +73,7 @@ export function ownerNamespace(this: N8nApp): void { email, firstName, lastName, - password: hashSync(validPassword, genSaltSync(10)), + password: await hashPassword(validPassword), }); await validateEntity(owner); diff --git a/packages/cli/src/UserManagement/routes/passwordReset.ts b/packages/cli/src/UserManagement/routes/passwordReset.ts index 574551e142..1217786079 100644 --- a/packages/cli/src/UserManagement/routes/passwordReset.ts +++ b/packages/cli/src/UserManagement/routes/passwordReset.ts @@ -1,21 +1,20 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable import/no-cycle */ -import express = require('express'); +import express from 'express'; import { v4 as uuid } from 'uuid'; import { URL } from 'url'; -import { genSaltSync, hashSync } from 'bcryptjs'; import validator from 'validator'; import { IsNull, MoreThanOrEqual, Not } from 'typeorm'; import { LoggerProxy as Logger } from 'n8n-workflow'; import { Db, InternalHooksManager, ResponseHelper } from '../..'; import { N8nApp } from '../Interfaces'; -import { getInstanceBaseUrl, validatePassword } from '../UserManagementHelper'; +import { getInstanceBaseUrl, hashPassword, validatePassword } from '../UserManagementHelper'; import * as UserManagementMailer from '../email'; import type { PasswordResetRequest } from '../../requests'; import { issueCookie } from '../auth/jwt'; -import config = require('../../../config'); +import * as config from '../../../config'; export function passwordResetNamespace(this: N8nApp): void { /** @@ -26,7 +25,7 @@ export function passwordResetNamespace(this: N8nApp): void { this.app.post( `/${this.restEndpoint}/forgot-password`, ResponseHelper.send(async (req: PasswordResetRequest.Email) => { - if (config.get('userManagement.emails.mode') === '') { + if (config.getEnv('userManagement.emails.mode') === '') { Logger.debug('Request to send password reset email failed because emailing was not set up'); throw new ResponseHelper.ResponseError( 'Email sending must be set up in order to request a password reset email', @@ -206,7 +205,7 @@ export function passwordResetNamespace(this: N8nApp): void { } await Db.collections.User!.update(userId, { - password: hashSync(validPassword, genSaltSync(10)), + password: await hashPassword(validPassword), resetPasswordToken: null, resetPasswordTokenExpiration: null, }); diff --git a/packages/cli/src/UserManagement/routes/users.ts b/packages/cli/src/UserManagement/routes/users.ts index 7711150c4b..8f3a794d8f 100644 --- a/packages/cli/src/UserManagement/routes/users.ts +++ b/packages/cli/src/UserManagement/routes/users.ts @@ -3,7 +3,6 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ import { Response } from 'express'; import { In } from 'typeorm'; -import { genSaltSync, hashSync } from 'bcryptjs'; import validator from 'validator'; import { LoggerProxy as Logger } from 'n8n-workflow'; @@ -12,6 +11,7 @@ import { N8nApp, PublicUser } from '../Interfaces'; import { UserRequest } from '../../requests'; import { getInstanceBaseUrl, + hashPassword, isEmailSetUp, sanitizeUser, validatePassword, @@ -21,7 +21,7 @@ import { SharedWorkflow } from '../../databases/entities/SharedWorkflow'; import { SharedCredentials } from '../../databases/entities/SharedCredentials'; import * as UserManagementMailer from '../email/UserManagementMailer'; -import config = require('../../../config'); +import * as config from '../../../config'; import { issueCookie } from '../auth/jwt'; export function usersNamespace(this: N8nApp): void { @@ -31,7 +31,7 @@ export function usersNamespace(this: N8nApp): void { this.app.post( `/${this.restEndpoint}/users`, ResponseHelper.send(async (req: UserRequest.Invite) => { - if (config.get('userManagement.emails.mode') === '') { + if (config.getEnv('userManagement.emails.mode') === '') { Logger.debug( 'Request to send email invite(s) to user(s) failed because emailing was not set up', ); @@ -56,14 +56,14 @@ export function usersNamespace(this: N8nApp): void { } // TODO: this should be checked in the middleware rather than here - if (config.get('userManagement.disabled')) { + if (config.getEnv('userManagement.disabled')) { Logger.debug( 'Request to send email invite(s) to user(s) failed because user management is disabled', ); throw new ResponseHelper.ResponseError('User management is disabled'); } - if (!config.get('userManagement.isInstanceOwnerSetUp')) { + if (!config.getEnv('userManagement.isInstanceOwnerSetUp')) { Logger.debug( 'Request to send email invite(s) to user(s) failed because the owner account is not set up', ); @@ -349,7 +349,7 @@ export function usersNamespace(this: N8nApp): void { invitee.firstName = firstName; invitee.lastName = lastName; - invitee.password = hashSync(validPassword, genSaltSync(10)); + invitee.password = await hashPassword(validPassword); const updatedUser = await Db.collections.User!.save(invitee); diff --git a/packages/cli/src/WaitingWebhooks.ts b/packages/cli/src/WaitingWebhooks.ts index 71e7b88a12..9d313cc5ac 100644 --- a/packages/cli/src/WaitingWebhooks.ts +++ b/packages/cli/src/WaitingWebhooks.ts @@ -12,7 +12,7 @@ import { LoggerProxy as Logger, } from 'n8n-workflow'; -import * as express from 'express'; +import express from 'express'; import { Db, diff --git a/packages/cli/src/WebhookHelpers.ts b/packages/cli/src/WebhookHelpers.ts index 7b1e0b650b..ad177e57e7 100644 --- a/packages/cli/src/WebhookHelpers.ts +++ b/packages/cli/src/WebhookHelpers.ts @@ -13,7 +13,7 @@ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable prefer-destructuring */ -import * as express from 'express'; +import express from 'express'; // eslint-disable-next-line import/no-extraneous-dependencies import { get } from 'lodash'; @@ -132,26 +132,6 @@ export function encodeWebhookResponse( return response; } -/** - * Returns all the webhooks which should be created for the give workflow - * - * @export - * @param {string} workflowId - * @param {Workflow} workflow - * @returns {IWebhookData[]} - */ -export function getWorkflowWebhooksBasic(workflow: Workflow): IWebhookData[] { - // Check all the nodes in the workflow if they have webhooks - - const returnData: IWebhookData[] = []; - - for (const node of Object.values(workflow.nodes)) { - returnData.push.apply(returnData, NodeHelpers.getNodeWebhooksBasic(workflow, node)); - } - - return returnData; -} - /** * Executes a webhook * @@ -194,39 +174,6 @@ export async function executeWebhook( $executionId: executionId, }; - // Get the responseMode - const responseMode = workflow.expression.getSimpleParameterValue( - workflowStartNode, - webhookData.webhookDescription.responseMode, - executionMode, - additionalKeys, - 'onReceived', - ); - const responseCode = workflow.expression.getSimpleParameterValue( - workflowStartNode, - webhookData.webhookDescription.responseCode, - executionMode, - additionalKeys, - 200, - ) as number; - - const responseData = workflow.expression.getSimpleParameterValue( - workflowStartNode, - webhookData.webhookDescription.responseData, - executionMode, - additionalKeys, - 'firstEntryJson', - ); - - if (!['onReceived', 'lastNode', 'responseNode'].includes(responseMode as string)) { - // If the mode is not known we error. Is probably best like that instead of using - // the default that people know as early as possible (probably already testing phase) - // that something does not resolve properly. - const errorMessage = `The response mode ${responseMode} is not valid!`; - responseCallback(new Error(errorMessage), {}); - throw new ResponseHelper.ResponseError(errorMessage, 500, 500); - } - let user: User; if ( (workflowData as WorkflowEntity).shared?.length && @@ -244,6 +191,42 @@ export async function executeWebhook( // Prepare everything that is needed to run the workflow const additionalData = await WorkflowExecuteAdditionalData.getBase(user.id); + // Get the responseMode + const responseMode = workflow.expression.getSimpleParameterValue( + workflowStartNode, + webhookData.webhookDescription.responseMode, + executionMode, + additionalData.timezone, + additionalKeys, + 'onReceived', + ); + const responseCode = workflow.expression.getSimpleParameterValue( + workflowStartNode, + webhookData.webhookDescription.responseCode, + executionMode, + additionalData.timezone, + additionalKeys, + 200, + ) as number; + + const responseData = workflow.expression.getSimpleParameterValue( + workflowStartNode, + webhookData.webhookDescription.responseData, + executionMode, + additionalData.timezone, + additionalKeys, + 'firstEntryJson', + ); + + if (!['onReceived', 'lastNode', 'responseNode'].includes(responseMode as string)) { + // If the mode is not known we error. Is probably best like that instead of using + // the default that people know as early as possible (probably already testing phase) + // that something does not resolve properly. + const errorMessage = `The response mode ${responseMode} is not valid!`; + responseCallback(new Error(errorMessage), {}); + throw new ResponseHelper.ResponseError(errorMessage, 500, 500); + } + // Add the Response and Request so that this data can be accessed in the node additionalData.httpRequest = req; additionalData.httpResponse = res; @@ -302,6 +285,7 @@ export async function executeWebhook( workflowStartNode, webhookData.webhookDescription.responseHeaders, executionMode, + additionalData.timezone, additionalKeys, undefined, ) as { @@ -551,6 +535,7 @@ export async function executeWebhook( if (returnData.data!.main[0]![0] === undefined) { responseCallback(new Error('No item to return got found.'), {}); didSendResponse = true; + return undefined; } data = returnData.data!.main[0]![0].json; @@ -559,6 +544,7 @@ export async function executeWebhook( workflowStartNode, webhookData.webhookDescription.responsePropertyName, executionMode, + additionalData.timezone, additionalKeys, undefined, ); @@ -571,6 +557,7 @@ export async function executeWebhook( workflowStartNode, webhookData.webhookDescription.responseContentType, executionMode, + additionalData.timezone, additionalKeys, undefined, ); @@ -602,17 +589,20 @@ export async function executeWebhook( if (data === undefined) { responseCallback(new Error('No item to return got found.'), {}); didSendResponse = true; + return undefined; } if (data.binary === undefined) { responseCallback(new Error('No binary data to return got found.'), {}); didSendResponse = true; + return undefined; } const responseBinaryPropertyName = workflow.expression.getSimpleParameterValue( workflowStartNode, webhookData.webhookDescription.responseBinaryPropertyName, executionMode, + additionalData.timezone, additionalKeys, 'data', ); diff --git a/packages/cli/src/WebhookServer.ts b/packages/cli/src/WebhookServer.ts index 0a11e18c41..700cadaa52 100644 --- a/packages/cli/src/WebhookServer.ts +++ b/packages/cli/src/WebhookServer.ts @@ -6,16 +6,16 @@ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import * as express from 'express'; +import express from 'express'; import { readFileSync } from 'fs'; import { getConnectionManager } from 'typeorm'; -import * as bodyParser from 'body-parser'; +import bodyParser from 'body-parser'; // eslint-disable-next-line import/no-extraneous-dependencies, @typescript-eslint/no-unused-vars -import * as _ from 'lodash'; +import _ from 'lodash'; -import * as compression from 'compression'; +import compression from 'compression'; // eslint-disable-next-line import/no-extraneous-dependencies -import * as parseUrl from 'parseurl'; +import parseUrl from 'parseurl'; import { WebhookHttpMethod } from 'n8n-workflow'; // eslint-disable-next-line import/no-cycle import { @@ -31,7 +31,7 @@ import { WaitingWebhooks, } from '.'; -import * as config from '../config'; +import config from '../config'; // eslint-disable-next-line import/no-cycle import { WEBHOOK_METHODS } from './WebhookHelpers'; @@ -193,28 +193,28 @@ class App { constructor() { this.app = express(); - this.endpointWebhook = config.get('endpoints.webhook') as string; - this.endpointWebhookWaiting = config.get('endpoints.webhookWaiting') as string; - this.saveDataErrorExecution = config.get('executions.saveDataOnError') as string; - this.saveDataSuccessExecution = config.get('executions.saveDataOnSuccess') as string; - this.saveManualExecutions = config.get('executions.saveDataManualExecutions') as boolean; - this.executionTimeout = config.get('executions.timeout') as number; - this.maxExecutionTimeout = config.get('executions.maxTimeout') as number; - this.timezone = config.get('generic.timezone') as string; - this.restEndpoint = config.get('endpoints.rest') as string; + this.endpointWebhook = config.getEnv('endpoints.webhook'); + this.endpointWebhookWaiting = config.getEnv('endpoints.webhookWaiting'); + this.saveDataErrorExecution = config.getEnv('executions.saveDataOnError'); + this.saveDataSuccessExecution = config.getEnv('executions.saveDataOnSuccess'); + this.saveManualExecutions = config.getEnv('executions.saveDataManualExecutions'); + this.executionTimeout = config.getEnv('executions.timeout'); + this.maxExecutionTimeout = config.getEnv('executions.maxTimeout'); + this.timezone = config.getEnv('generic.timezone'); + this.restEndpoint = config.getEnv('endpoints.rest'); this.activeWorkflowRunner = ActiveWorkflowRunner.getInstance(); this.activeExecutionsInstance = ActiveExecutions.getInstance(); - this.protocol = config.get('protocol'); - this.sslKey = config.get('ssl_key'); - this.sslCert = config.get('ssl_cert'); + this.protocol = config.getEnv('protocol'); + this.sslKey = config.getEnv('ssl_key'); + this.sslCert = config.getEnv('ssl_cert'); this.externalHooks = ExternalHooks(); this.presetCredentialsLoaded = false; - this.endpointPresetCredentials = config.get('credentials.overwrite.endpoint') as string; + this.endpointPresetCredentials = config.getEnv('credentials.overwrite.endpoint'); } /** @@ -342,8 +342,8 @@ class App { } export async function start(): Promise { - const PORT = config.get('port'); - const ADDRESS = config.get('listen_address'); + const PORT = config.getEnv('port'); + const ADDRESS = config.getEnv('listen_address'); const app = new App(); diff --git a/packages/cli/src/WorkflowExecuteAdditionalData.ts b/packages/cli/src/WorkflowExecuteAdditionalData.ts index ee2b227744..c603ff7e15 100644 --- a/packages/cli/src/WorkflowExecuteAdditionalData.ts +++ b/packages/cli/src/WorkflowExecuteAdditionalData.ts @@ -39,7 +39,7 @@ import { import { LessThanOrEqual } from 'typeorm'; import { DateUtils } from 'typeorm/util/DateUtils'; -import * as config from '../config'; +import config from '../config'; import { ActiveExecutions, CredentialsHelper, @@ -67,7 +67,7 @@ import { } from './UserManagement/UserManagementHelper'; import { whereClause } from './WorkflowHelpers'; -const ERROR_TRIGGER_TYPE = config.get('nodes.errorTriggerType') as string; +const ERROR_TRIGGER_TYPE = config.getEnv('nodes.errorTriggerType'); /** * Checks if there was an error and if errorWorkflow or a trigger is defined. If so it collects @@ -171,8 +171,8 @@ function pruneExecutionData(this: WorkflowHooks): void { Logger.verbose('Pruning execution data from database'); throttling = true; - const timeout = config.get('executions.pruneDataTimeout') as number; // in seconds - const maxAge = config.get('executions.pruneDataMaxAge') as number; // in h + const timeout = config.getEnv('executions.pruneDataTimeout'); // in seconds + const maxAge = config.getEnv('executions.pruneDataMaxAge'); // in h const date = new Date(); // today date.setHours(date.getHours() - maxAge); @@ -357,11 +357,11 @@ export function hookFunctionsPreExecute(parentProcessMode?: string): IWorkflowEx } if ( this.workflowData.settings.saveExecutionProgress !== true && - !config.get('executions.saveExecutionProgress') + !config.getEnv('executions.saveExecutionProgress') ) { return; } - } else if (!config.get('executions.saveExecutionProgress')) { + } else if (!config.getEnv('executions.saveExecutionProgress')) { return; } @@ -466,7 +466,7 @@ function hookFunctionsSave(parentProcessMode?: string): IWorkflowExecuteHooks { }); // Prune old execution data - if (config.get('executions.pruneData')) { + if (config.getEnv('executions.pruneData')) { pruneExecutionData.call(this); } @@ -492,7 +492,7 @@ function hookFunctionsSave(parentProcessMode?: string): IWorkflowExecuteHooks { } } - let saveManualExecutions = config.get('executions.saveDataManualExecutions') as boolean; + let saveManualExecutions = config.getEnv('executions.saveDataManualExecutions'); if ( this.workflowData.settings !== undefined && this.workflowData.settings.saveManualExecutions !== undefined @@ -512,8 +512,8 @@ function hookFunctionsSave(parentProcessMode?: string): IWorkflowExecuteHooks { } // Check config to know if execution should be saved or not - let saveDataErrorExecution = config.get('executions.saveDataOnError') as string; - let saveDataSuccessExecution = config.get('executions.saveDataOnSuccess') as string; + let saveDataErrorExecution = config.getEnv('executions.saveDataOnError') as string; + let saveDataSuccessExecution = config.getEnv('executions.saveDataOnSuccess') as string; if (this.workflowData.settings !== undefined) { saveDataErrorExecution = (this.workflowData.settings.saveDataErrorExecution as string) || @@ -800,7 +800,7 @@ export async function getWorkflowData( const user = await getUserById(userId); let relations = ['workflow', 'workflow.tags']; - if (config.get('workflowTagsDisabled')) { + if (config.getEnv('workflowTagsDisabled')) { relations = relations.filter((relation) => relation !== 'workflow.tags'); } @@ -1028,10 +1028,10 @@ export async function getBase( ): Promise { const urlBaseWebhook = WebhookHelpers.getWebhookBaseUrl(); - const timezone = config.get('generic.timezone') as string; - const webhookBaseUrl = urlBaseWebhook + config.get('endpoints.webhook'); - const webhookWaitingBaseUrl = urlBaseWebhook + config.get('endpoints.webhookWaiting'); - const webhookTestBaseUrl = urlBaseWebhook + config.get('endpoints.webhookTest'); + const timezone = config.getEnv('generic.timezone'); + const webhookBaseUrl = urlBaseWebhook + config.getEnv('endpoints.webhook'); + const webhookWaitingBaseUrl = urlBaseWebhook + config.getEnv('endpoints.webhookWaiting'); + const webhookTestBaseUrl = urlBaseWebhook + config.getEnv('endpoints.webhookTest'); const encryptionKey = await UserSettings.getEncryptionKey(); if (encryptionKey === undefined) { @@ -1042,7 +1042,7 @@ export async function getBase( credentialsHelper: new CredentialsHelper(encryptionKey), encryptionKey, executeWorkflow, - restApiUrl: urlBaseWebhook + config.get('endpoints.rest'), + restApiUrl: urlBaseWebhook + config.getEnv('endpoints.rest'), timezone, webhookBaseUrl, webhookWaitingBaseUrl, diff --git a/packages/cli/src/WorkflowHelpers.ts b/packages/cli/src/WorkflowHelpers.ts index d5a0f60e87..72f7cf2eb5 100644 --- a/packages/cli/src/WorkflowHelpers.ts +++ b/packages/cli/src/WorkflowHelpers.ts @@ -33,13 +33,13 @@ import { WorkflowRunner, } from '.'; -import * as config from '../config'; +import config from '../config'; // eslint-disable-next-line import/no-cycle import { WorkflowEntity } from './databases/entities/WorkflowEntity'; import { User } from './databases/entities/User'; import { getWorkflowOwner } from './UserManagement/UserManagementHelper'; -const ERROR_TRIGGER_TYPE = config.get('nodes.errorTriggerType') as string; +const ERROR_TRIGGER_TYPE = config.getEnv('nodes.errorTriggerType'); /** * Returns the data of the last executed node diff --git a/packages/cli/src/WorkflowRunner.ts b/packages/cli/src/WorkflowRunner.ts index 6d4abbaaaf..b88ee57a53 100644 --- a/packages/cli/src/WorkflowRunner.ts +++ b/packages/cli/src/WorkflowRunner.ts @@ -26,12 +26,12 @@ import { } from 'n8n-workflow'; // eslint-disable-next-line import/no-extraneous-dependencies -import * as PCancelable from 'p-cancelable'; +import PCancelable from 'p-cancelable'; import { join as pathJoin } from 'path'; import { fork } from 'child_process'; -import * as Bull from 'bull'; -import * as config from '../config'; +import Bull from 'bull'; +import config from '../config'; // eslint-disable-next-line import/no-cycle import { ActiveExecutions, @@ -73,7 +73,7 @@ export class WorkflowRunner { this.activeExecutions = ActiveExecutions.getInstance(); this.credentialsOverwrites = CredentialsOverwrites().getAll(); - const executionsMode = config.get('executions.mode') as string; + const executionsMode = config.getEnv('executions.mode'); if (executionsMode === 'queue') { this.jobQueue = Queue.getInstance().getBullObjectInstance(); @@ -150,8 +150,8 @@ export class WorkflowRunner { executionId?: string, responsePromise?: IDeferredPromise, ): Promise { - const executionsProcess = config.get('executions.process') as string; - const executionsMode = config.get('executions.mode') as string; + const executionsProcess = config.getEnv('executions.process'); + const executionsMode = config.getEnv('executions.mode'); if (executionsMode === 'queue' && data.executionMode !== 'manual') { // Do not run "manual" executions in bull because sending events to the @@ -229,13 +229,13 @@ export class WorkflowRunner { // Changes were made by adding the `workflowTimeout` to the `additionalData` // So that the timeout will also work for executions with nested workflows. let executionTimeout: NodeJS.Timeout; - let workflowTimeout = config.get('executions.timeout') as number; // initialize with default + let workflowTimeout = config.getEnv('executions.timeout'); // initialize with default if (data.workflowData.settings && data.workflowData.settings.executionTimeout) { workflowTimeout = data.workflowData.settings.executionTimeout as number; // preference on workflow setting } if (workflowTimeout > 0) { - workflowTimeout = Math.min(workflowTimeout, config.get('executions.maxTimeout') as number); + workflowTimeout = Math.min(workflowTimeout, config.getEnv('executions.maxTimeout')); } const workflow = new Workflow({ @@ -326,8 +326,7 @@ export class WorkflowRunner { this.activeExecutions.attachWorkflowExecution(executionId, workflowExecution); if (workflowTimeout > 0) { - const timeout = - Math.min(workflowTimeout, config.get('executions.maxTimeout') as number) * 1000; // as seconds + const timeout = Math.min(workflowTimeout, config.getEnv('executions.maxTimeout')) * 1000; // as seconds executionTimeout = setTimeout(() => { this.activeExecutions.stopExecution(executionId, 'timeout'); }, timeout); @@ -450,7 +449,7 @@ export class WorkflowRunner { const jobData: Promise = job.finished(); - const queueRecoveryInterval = config.get('queue.bull.queueRecoveryInterval') as number; + const queueRecoveryInterval = config.getEnv('queue.bull.queueRecoveryInterval'); const racingPromises: Array> = [jobData]; @@ -533,8 +532,8 @@ export class WorkflowRunner { try { // Check if this execution data has to be removed from database // based on workflow settings. - let saveDataErrorExecution = config.get('executions.saveDataOnError') as string; - let saveDataSuccessExecution = config.get('executions.saveDataOnSuccess') as string; + let saveDataErrorExecution = config.getEnv('executions.saveDataOnError') as string; + let saveDataSuccessExecution = config.getEnv('executions.saveDataOnSuccess') as string; if (data.workflowData.settings !== undefined) { saveDataErrorExecution = (data.workflowData.settings.saveDataErrorExecution as string) || @@ -643,7 +642,7 @@ export class WorkflowRunner { // Start timeout for the execution let executionTimeout: NodeJS.Timeout; - let workflowTimeout = config.get('executions.timeout') as number; // initialize with default + let workflowTimeout = config.getEnv('executions.timeout'); // initialize with default if (data.workflowData.settings && data.workflowData.settings.executionTimeout) { workflowTimeout = data.workflowData.settings.executionTimeout as number; // preference on workflow setting } @@ -654,8 +653,7 @@ export class WorkflowRunner { }; if (workflowTimeout > 0) { - workflowTimeout = - Math.min(workflowTimeout, config.get('executions.maxTimeout') as number) * 1000; // as seconds + workflowTimeout = Math.min(workflowTimeout, config.getEnv('executions.maxTimeout')) * 1000; // as seconds // Start timeout already now but give process at least 5 seconds to start. // Without it could would it be possible that the workflow executions times out before it even got started if // the timeout time is very short as the process start time can be quite long. diff --git a/packages/cli/src/WorkflowRunnerProcess.ts b/packages/cli/src/WorkflowRunnerProcess.ts index 8c2d457c4f..d77f5d329f 100644 --- a/packages/cli/src/WorkflowRunnerProcess.ts +++ b/packages/cli/src/WorkflowRunnerProcess.ts @@ -5,13 +5,7 @@ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-use-before-define */ /* eslint-disable @typescript-eslint/unbound-method */ -import { - BinaryDataManager, - IBinaryDataConfig, - IProcessMessage, - UserSettings, - WorkflowExecute, -} from 'n8n-core'; +import { BinaryDataManager, IProcessMessage, UserSettings, WorkflowExecute } from 'n8n-core'; import { ExecutionError, @@ -50,7 +44,7 @@ import { import { getLogger } from './Logger'; -import * as config from '../config'; +import config from '../config'; import { InternalHooksManager } from './InternalHooksManager'; import { checkPermissionsForExecution } from './UserManagement/UserManagementHelper'; @@ -176,7 +170,7 @@ export class WorkflowRunnerProcess { const { cli } = await GenericHelpers.getVersions(); InternalHooksManager.init(instanceId, cli, nodeTypes); - const binaryDataConfig = config.get('binaryDataManager') as IBinaryDataConfig; + const binaryDataConfig = config.getEnv('binaryDataManager'); await BinaryDataManager.init(binaryDataConfig); // Credentials should now be loaded from database. @@ -204,27 +198,27 @@ export class WorkflowRunnerProcess { } else if ( inputData.workflowData.settings !== undefined && inputData.workflowData.settings.saveExecutionProgress !== false && - (config.get('executions.saveExecutionProgress') as boolean) + config.getEnv('executions.saveExecutionProgress') ) { // Workflow settings not saying anything about saving but default settings says so await Db.init(); } else if ( inputData.workflowData.settings === undefined && - (config.get('executions.saveExecutionProgress') as boolean) + config.getEnv('executions.saveExecutionProgress') ) { // Workflow settings not saying anything about saving but default settings says so await Db.init(); } // Start timeout for the execution - let workflowTimeout = config.get('executions.timeout') as number; // initialize with default + let workflowTimeout = config.getEnv('executions.timeout'); // initialize with default // eslint-disable-next-line @typescript-eslint/prefer-optional-chain if (this.data.workflowData.settings && this.data.workflowData.settings.executionTimeout) { workflowTimeout = this.data.workflowData.settings.executionTimeout as number; // preference on workflow setting } if (workflowTimeout > 0) { - workflowTimeout = Math.min(workflowTimeout, config.get('executions.maxTimeout') as number); + workflowTimeout = Math.min(workflowTimeout, config.getEnv('executions.maxTimeout')); } this.workflow = new Workflow({ diff --git a/packages/cli/src/api/credentials.api.ts b/packages/cli/src/api/credentials.api.ts index e1e6727119..f6d054782d 100644 --- a/packages/cli/src/api/credentials.api.ts +++ b/packages/cli/src/api/credentials.api.ts @@ -3,7 +3,7 @@ /* eslint-disable no-restricted-syntax */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable import/no-cycle */ -import express = require('express'); +import express from 'express'; import { In } from 'typeorm'; import { UserSettings, Credentials } from 'n8n-core'; import { INodeCredentialTestResult, LoggerProxy } from 'n8n-workflow'; @@ -24,7 +24,7 @@ import { CredentialsEntity } from '../databases/entities/CredentialsEntity'; import { SharedCredentials } from '../databases/entities/SharedCredentials'; import { validateEntity } from '../GenericHelpers'; import type { CredentialRequest } from '../requests'; -import config = require('../../config'); +import * as config from '../../config'; import { externalHooks } from '../Server'; export const credentialsController = express.Router(); @@ -99,7 +99,7 @@ credentialsController.get( const { name: newName } = req.query; return GenericHelpers.generateUniqueName( - newName ?? config.get('credentials.defaultName'), + newName ?? config.getEnv('credentials.defaultName'), 'credentials', ); }), diff --git a/packages/cli/src/databases/entities/CredentialsEntity.ts b/packages/cli/src/databases/entities/CredentialsEntity.ts index d67361114d..d61c5e0f2f 100644 --- a/packages/cli/src/databases/entities/CredentialsEntity.ts +++ b/packages/cli/src/databases/entities/CredentialsEntity.ts @@ -14,12 +14,12 @@ import { } from 'typeorm'; import { IsArray, IsObject, IsString, Length } from 'class-validator'; -import config = require('../../../config'); +import * as config from '../../../config'; import { DatabaseType, ICredentialsDb } from '../..'; import { SharedCredentials } from './SharedCredentials'; function resolveDataType(dataType: string) { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); const typeMap: { [key in DatabaseType]: { [key: string]: string } } = { sqlite: { @@ -37,7 +37,7 @@ function resolveDataType(dataType: string) { // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types function getTimestampSyntax() { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); const map: { [key in DatabaseType]: string } = { sqlite: `STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')`, diff --git a/packages/cli/src/databases/entities/ExecutionEntity.ts b/packages/cli/src/databases/entities/ExecutionEntity.ts index 2c56975cb2..590280496c 100644 --- a/packages/cli/src/databases/entities/ExecutionEntity.ts +++ b/packages/cli/src/databases/entities/ExecutionEntity.ts @@ -2,11 +2,11 @@ import { WorkflowExecuteMode } from 'n8n-workflow'; import { Column, ColumnOptions, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'; -import config = require('../../../config'); +import * as config from '../../../config'; import { DatabaseType, IExecutionFlattedDb, IWorkflowDb } from '../..'; function resolveDataType(dataType: string) { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); const typeMap: { [key in DatabaseType]: { [key: string]: string } } = { sqlite: { diff --git a/packages/cli/src/databases/entities/Role.ts b/packages/cli/src/databases/entities/Role.ts index ddc8aca31b..331e274754 100644 --- a/packages/cli/src/databases/entities/Role.ts +++ b/packages/cli/src/databases/entities/Role.ts @@ -11,7 +11,7 @@ import { } from 'typeorm'; import { IsDate, IsOptional, IsString, Length } from 'class-validator'; -import config = require('../../../config'); +import * as config from '../../../config'; import { DatabaseType } from '../../index'; import { User } from './User'; import { SharedWorkflow } from './SharedWorkflow'; @@ -21,7 +21,7 @@ type RoleScopes = 'global' | 'workflow' | 'credential'; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types function getTimestampSyntax() { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); const map: { [key in DatabaseType]: string } = { sqlite: "STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')", diff --git a/packages/cli/src/databases/entities/SharedCredentials.ts b/packages/cli/src/databases/entities/SharedCredentials.ts index 43bbc4e924..e7d4a8e6cf 100644 --- a/packages/cli/src/databases/entities/SharedCredentials.ts +++ b/packages/cli/src/databases/entities/SharedCredentials.ts @@ -9,7 +9,7 @@ import { } from 'typeorm'; import { IsDate, IsOptional } from 'class-validator'; -import config = require('../../../config'); +import * as config from '../../../config'; import { DatabaseType } from '../../index'; import { CredentialsEntity } from './CredentialsEntity'; import { User } from './User'; @@ -17,7 +17,7 @@ import { Role } from './Role'; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types function getTimestampSyntax() { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); const map: { [key in DatabaseType]: string } = { sqlite: "STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')", diff --git a/packages/cli/src/databases/entities/SharedWorkflow.ts b/packages/cli/src/databases/entities/SharedWorkflow.ts index 5e20477e36..669e0c1643 100644 --- a/packages/cli/src/databases/entities/SharedWorkflow.ts +++ b/packages/cli/src/databases/entities/SharedWorkflow.ts @@ -9,7 +9,7 @@ import { } from 'typeorm'; import { IsDate, IsOptional } from 'class-validator'; -import config = require('../../../config'); +import * as config from '../../../config'; import { DatabaseType } from '../../index'; import { WorkflowEntity } from './WorkflowEntity'; import { User } from './User'; @@ -17,7 +17,7 @@ import { Role } from './Role'; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types function getTimestampSyntax() { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); const map: { [key in DatabaseType]: string } = { sqlite: "STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')", diff --git a/packages/cli/src/databases/entities/TagEntity.ts b/packages/cli/src/databases/entities/TagEntity.ts index 0af6512399..1d61a0a595 100644 --- a/packages/cli/src/databases/entities/TagEntity.ts +++ b/packages/cli/src/databases/entities/TagEntity.ts @@ -13,7 +13,7 @@ import { } from 'typeorm'; import { IsDate, IsOptional, IsString, Length } from 'class-validator'; -import config = require('../../../config'); +import * as config from '../../../config'; import { DatabaseType } from '../../index'; import { ITagDb } from '../../Interfaces'; import { idStringifier } from '../utils/transformers'; @@ -21,7 +21,7 @@ import { WorkflowEntity } from './WorkflowEntity'; // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types function getTimestampSyntax() { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); const map: { [key in DatabaseType]: string } = { sqlite: "STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')", diff --git a/packages/cli/src/databases/entities/User.ts b/packages/cli/src/databases/entities/User.ts index b345b26534..ee539c4f65 100644 --- a/packages/cli/src/databases/entities/User.ts +++ b/packages/cli/src/databases/entities/User.ts @@ -14,7 +14,7 @@ import { UpdateDateColumn, } from 'typeorm'; import { IsEmail, IsString, Length } from 'class-validator'; -import config = require('../../../config'); +import * as config from '../../../config'; import { DatabaseType, IPersonalizationSurveyAnswers } from '../..'; import { Role } from './Role'; import { SharedWorkflow } from './SharedWorkflow'; @@ -27,7 +27,7 @@ export const MIN_PASSWORD_LENGTH = 8; export const MAX_PASSWORD_LENGTH = 64; function resolveDataType(dataType: string) { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); const typeMap: { [key in DatabaseType]: { [key: string]: string } } = { sqlite: { @@ -45,7 +45,7 @@ function resolveDataType(dataType: string) { // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types function getTimestampSyntax() { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); const map: { [key in DatabaseType]: string } = { sqlite: "STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')", @@ -62,7 +62,7 @@ export class User { @PrimaryGeneratedColumn('uuid') id: string; - @Column({ length: 254 }) + @Column({ length: 254, nullable: true }) @Index({ unique: true }) @IsEmail() email: string; @@ -81,7 +81,7 @@ export class User { @Column({ nullable: true }) @IsString({ message: 'Password must be of type string.' }) - password?: string; + password: string; @Column({ type: String, nullable: true }) resetPasswordToken?: string | null; diff --git a/packages/cli/src/databases/entities/WorkflowEntity.ts b/packages/cli/src/databases/entities/WorkflowEntity.ts index 097ae84229..f85e8625ab 100644 --- a/packages/cli/src/databases/entities/WorkflowEntity.ts +++ b/packages/cli/src/databases/entities/WorkflowEntity.ts @@ -18,13 +18,13 @@ import { UpdateDateColumn, } from 'typeorm'; -import config = require('../../../config'); +import * as config from '../../../config'; import { DatabaseType, IWorkflowDb } from '../..'; import { TagEntity } from './TagEntity'; import { SharedWorkflow } from './SharedWorkflow'; function resolveDataType(dataType: string) { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); const typeMap: { [key in DatabaseType]: { [key: string]: string } } = { sqlite: { @@ -42,7 +42,7 @@ function resolveDataType(dataType: string) { // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types function getTimestampSyntax() { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); const map: { [key in DatabaseType]: string } = { sqlite: "STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')", diff --git a/packages/cli/src/databases/mysqldb/migrations/1588157391238-InitialMigration.ts b/packages/cli/src/databases/mysqldb/migrations/1588157391238-InitialMigration.ts index 1d1d4d8cc5..8d41f70712 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1588157391238-InitialMigration.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1588157391238-InitialMigration.ts @@ -6,7 +6,7 @@ export class InitialMigration1588157391238 implements MigrationInterface { name = 'InitialMigration1588157391238'; async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('CREATE TABLE IF NOT EXISTS `' + tablePrefix + 'credentials_entity` (`id` int NOT NULL AUTO_INCREMENT, `name` varchar(128) NOT NULL, `data` text NOT NULL, `type` varchar(32) NOT NULL, `nodesAccess` json NOT NULL, `createdAt` datetime NOT NULL, `updatedAt` datetime NOT NULL, INDEX `IDX_' + tablePrefix + '07fde106c0b471d8cc80a64fc8` (`type`), PRIMARY KEY (`id`)) ENGINE=InnoDB', undefined); await queryRunner.query('CREATE TABLE IF NOT EXISTS `' + tablePrefix + 'execution_entity` (`id` int NOT NULL AUTO_INCREMENT, `data` text NOT NULL, `finished` tinyint NOT NULL, `mode` varchar(255) NOT NULL, `retryOf` varchar(255) NULL, `retrySuccessId` varchar(255) NULL, `startedAt` datetime NOT NULL, `stoppedAt` datetime NOT NULL, `workflowData` json NOT NULL, `workflowId` varchar(255) NULL, INDEX `IDX_' + tablePrefix + 'c4d999a5e90784e8caccf5589d` (`workflowId`), PRIMARY KEY (`id`)) ENGINE=InnoDB', undefined); @@ -14,7 +14,7 @@ export class InitialMigration1588157391238 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('DROP TABLE `' + tablePrefix + 'workflow_entity`', undefined); await queryRunner.query('DROP INDEX `IDX_' + tablePrefix + 'c4d999a5e90784e8caccf5589d` ON `' + tablePrefix + 'execution_entity`', undefined); diff --git a/packages/cli/src/databases/mysqldb/migrations/1592447867632-WebhookModel.ts b/packages/cli/src/databases/mysqldb/migrations/1592447867632-WebhookModel.ts index 13969d72ef..2f7be5576a 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1592447867632-WebhookModel.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1592447867632-WebhookModel.ts @@ -9,13 +9,13 @@ export class WebhookModel1592447867632 implements MigrationInterface { name = 'WebhookModel1592447867632'; async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`CREATE TABLE IF NOT EXISTS ${tablePrefix}webhook_entity (workflowId int NOT NULL, webhookPath varchar(255) NOT NULL, method varchar(255) NOT NULL, node varchar(255) NOT NULL, PRIMARY KEY (webhookPath, method)) ENGINE=InnoDB`); } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`DROP TABLE ${tablePrefix}webhook_entity`); } } diff --git a/packages/cli/src/databases/mysqldb/migrations/1594902918301-CreateIndexStoppedAt.ts b/packages/cli/src/databases/mysqldb/migrations/1594902918301-CreateIndexStoppedAt.ts index 24556ea6bd..1b2777f4b5 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1594902918301-CreateIndexStoppedAt.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1594902918301-CreateIndexStoppedAt.ts @@ -6,13 +6,13 @@ export class CreateIndexStoppedAt1594902918301 implements MigrationInterface { name = 'CreateIndexStoppedAt1594902918301'; async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('CREATE INDEX `IDX_' + tablePrefix + 'cefb067df2402f6aed0638a6c1` ON `' + tablePrefix + 'execution_entity` (`stoppedAt`)'); } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('DROP INDEX `IDX_' + tablePrefix + 'cefb067df2402f6aed0638a6c1` ON `' + tablePrefix + 'execution_entity`'); } diff --git a/packages/cli/src/databases/mysqldb/migrations/1607431743767-MakeStoppedAtNullable.ts b/packages/cli/src/databases/mysqldb/migrations/1607431743767-MakeStoppedAtNullable.ts index dd261b6620..6c7930cd3f 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1607431743767-MakeStoppedAtNullable.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1607431743767-MakeStoppedAtNullable.ts @@ -5,12 +5,12 @@ import * as config from '../../../../config'; export class MakeStoppedAtNullable1607431743767 implements MigrationInterface { async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('ALTER TABLE `' + tablePrefix + 'execution_entity` MODIFY `stoppedAt` datetime', undefined); } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('ALTER TABLE `' + tablePrefix + 'execution_entity` MODIFY `stoppedAt` datetime NOT NULL', undefined); } diff --git a/packages/cli/src/databases/mysqldb/migrations/1611149998770-AddWebhookId.ts b/packages/cli/src/databases/mysqldb/migrations/1611149998770-AddWebhookId.ts index 7eb1e7aee7..d3a5ceac9a 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1611149998770-AddWebhookId.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1611149998770-AddWebhookId.ts @@ -5,7 +5,7 @@ export class AddWebhookId1611149998770 implements MigrationInterface { name = 'AddWebhookId1611149998770'; async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('ALTER TABLE `' + tablePrefix + 'webhook_entity` ADD `webhookId` varchar(255) NULL'); await queryRunner.query('ALTER TABLE `' + tablePrefix + 'webhook_entity` ADD `pathLength` int NULL'); @@ -13,7 +13,7 @@ export class AddWebhookId1611149998770 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( 'DROP INDEX `IDX_' + tablePrefix + '742496f199721a057051acf4c2` ON `' + tablePrefix + 'webhook_entity`' diff --git a/packages/cli/src/databases/mysqldb/migrations/1615306975123-ChangeDataSize.ts b/packages/cli/src/databases/mysqldb/migrations/1615306975123-ChangeDataSize.ts index 793b178ef3..fbb63069c4 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1615306975123-ChangeDataSize.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1615306975123-ChangeDataSize.ts @@ -5,13 +5,13 @@ export class ChangeDataSize1615306975123 implements MigrationInterface { name = 'ChangeDataSize1615306975123'; async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('ALTER TABLE `' + tablePrefix + 'execution_entity` MODIFY COLUMN `data` MEDIUMTEXT NOT NULL'); } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('ALTER TABLE `' + tablePrefix + 'execution_entity` MODIFY COLUMN `data` TEXT NOT NULL'); } diff --git a/packages/cli/src/databases/mysqldb/migrations/1617268711084-CreateTagEntity.ts b/packages/cli/src/databases/mysqldb/migrations/1617268711084-CreateTagEntity.ts index cd2ec52c5b..738905d45e 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1617268711084-CreateTagEntity.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1617268711084-CreateTagEntity.ts @@ -5,7 +5,7 @@ export class CreateTagEntity1617268711084 implements MigrationInterface { name = 'CreateTagEntity1617268711084'; async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); // create tags table + relationship with workflow entity @@ -25,7 +25,7 @@ export class CreateTagEntity1617268711084 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); // `createdAt` and `updatedAt` diff --git a/packages/cli/src/databases/mysqldb/migrations/1620729500000-ChangeCredentialDataSize.ts b/packages/cli/src/databases/mysqldb/migrations/1620729500000-ChangeCredentialDataSize.ts index ea1bd42049..0869e00a75 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1620729500000-ChangeCredentialDataSize.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1620729500000-ChangeCredentialDataSize.ts @@ -5,13 +5,13 @@ export class ChangeCredentialDataSize1620729500000 implements MigrationInterface name = 'ChangeCredentialDataSize1620729500000'; async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('ALTER TABLE `' + tablePrefix + 'credentials_entity` MODIFY COLUMN `type` varchar(128) NOT NULL'); } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('ALTER TABLE `' + tablePrefix + 'credentials_entity` MODIFY COLUMN `type` varchar(32) NOT NULL'); } diff --git a/packages/cli/src/databases/mysqldb/migrations/1620826335440-UniqueWorkflowNames.ts b/packages/cli/src/databases/mysqldb/migrations/1620826335440-UniqueWorkflowNames.ts index 3dcf379028..954f6bab69 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1620826335440-UniqueWorkflowNames.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1620826335440-UniqueWorkflowNames.ts @@ -1,11 +1,11 @@ import {MigrationInterface, QueryRunner} from "typeorm"; -import config = require("../../../../config"); +import * as config from '../../../../config'; export class UniqueWorkflowNames1620826335440 implements MigrationInterface { name = 'UniqueWorkflowNames1620826335440'; async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); const workflowNames = await queryRunner.query(` SELECT name @@ -40,7 +40,7 @@ export class UniqueWorkflowNames1620826335440 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('ALTER TABLE `' + tablePrefix + 'workflow_entity` DROP INDEX `IDX_' + tablePrefix + '943d8f922be094eb507cb9a7f9`'); } diff --git a/packages/cli/src/databases/mysqldb/migrations/1623936588000-CertifyCorrectCollation.ts b/packages/cli/src/databases/mysqldb/migrations/1623936588000-CertifyCorrectCollation.ts index 079cd9cc70..33875cb18b 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1623936588000-CertifyCorrectCollation.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1623936588000-CertifyCorrectCollation.ts @@ -1,12 +1,12 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -import config = require('../../../../config'); +import * as config from '../../../../config'; export class CertifyCorrectCollation1623936588000 implements MigrationInterface { name = 'CertifyCorrectCollation1623936588000'; async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); - const databaseType = config.get('database.type'); + const tablePrefix = config.getEnv('database.tablePrefix'); + const databaseType = config.getEnv('database.type'); if (databaseType === 'mariadb') { // This applies to MySQL only. @@ -19,7 +19,7 @@ export class CertifyCorrectCollation1623936588000 implements MigrationInterface collation = 'utf8mb4_0900_ai_ci'; } - const databaseName = config.get(`database.mysqldb.database`); + const databaseName = config.getEnv(`database.mysqldb.database`); await queryRunner.query(`ALTER DATABASE \`${databaseName}\` CHARACTER SET utf8mb4 COLLATE ${collation};`); diff --git a/packages/cli/src/databases/mysqldb/migrations/1626183952959-AddWaitColumn.ts b/packages/cli/src/databases/mysqldb/migrations/1626183952959-AddWaitColumn.ts index ee2aa560e1..052343237f 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1626183952959-AddWaitColumn.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1626183952959-AddWaitColumn.ts @@ -5,14 +5,14 @@ export class AddWaitColumnId1626183952959 implements MigrationInterface { name = 'AddWaitColumnId1626183952959'; async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query('ALTER TABLE `' + tablePrefix + 'execution_entity` ADD `waitTill` DATETIME NULL'); await queryRunner.query('CREATE INDEX `IDX_' + tablePrefix + 'ca4a71b47f28ac6ea88293a8e2` ON `' + tablePrefix + 'execution_entity` (`waitTill`)'); } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( 'DROP INDEX `IDX_' + tablePrefix + 'ca4a71b47f28ac6ea88293a8e2` ON `' + tablePrefix + 'execution_entity`' diff --git a/packages/cli/src/databases/mysqldb/migrations/1630451444017-UpdateWorkflowCredentials.ts b/packages/cli/src/databases/mysqldb/migrations/1630451444017-UpdateWorkflowCredentials.ts index 3357f86853..15bee7fafe 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1630451444017-UpdateWorkflowCredentials.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1630451444017-UpdateWorkflowCredentials.ts @@ -1,5 +1,5 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -import config = require('../../../../config'); +import * as config from '../../../../config'; import { MigrationHelpers } from '../../MigrationHelpers'; // replacing the credentials in workflows and execution @@ -9,7 +9,7 @@ export class UpdateWorkflowCredentials1630451444017 implements MigrationInterfac name = 'UpdateWorkflowCredentials1630451444017'; public async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); const helpers = new MigrationHelpers(queryRunner); const credentialsEntities = await queryRunner.query(` @@ -146,7 +146,7 @@ export class UpdateWorkflowCredentials1630451444017 implements MigrationInterfac } public async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); const helpers = new MigrationHelpers(queryRunner); const credentialsEntities = await queryRunner.query(` diff --git a/packages/cli/src/databases/mysqldb/migrations/1644424784709-AddExecutionEntityIndexes.ts b/packages/cli/src/databases/mysqldb/migrations/1644424784709-AddExecutionEntityIndexes.ts index 7f7ce7285f..74215b2995 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1644424784709-AddExecutionEntityIndexes.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1644424784709-AddExecutionEntityIndexes.ts @@ -5,7 +5,7 @@ export class AddExecutionEntityIndexes1644424784709 implements MigrationInterfac name = 'AddExecutionEntityIndexes1644424784709'; public async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( 'DROP INDEX `IDX_c4d999a5e90784e8caccf5589d` ON `' + tablePrefix + 'execution_entity`', @@ -41,7 +41,7 @@ export class AddExecutionEntityIndexes1644424784709 implements MigrationInterfac } public async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( 'DROP INDEX `IDX_81fc04c8a17de15835713505e4` ON `' + tablePrefix + 'execution_entity`', ); diff --git a/packages/cli/src/databases/mysqldb/migrations/1646992772331-CreateUserManagement.ts b/packages/cli/src/databases/mysqldb/migrations/1646992772331-CreateUserManagement.ts index f0fd8a047c..004aae18e8 100644 --- a/packages/cli/src/databases/mysqldb/migrations/1646992772331-CreateUserManagement.ts +++ b/packages/cli/src/databases/mysqldb/migrations/1646992772331-CreateUserManagement.ts @@ -1,13 +1,13 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; import { v4 as uuid } from 'uuid'; -import config = require('../../../../config'); +import * as config from '../../../../config'; import { loadSurveyFromDisk } from '../../utils/migrationHelpers'; export class CreateUserManagement1646992772331 implements MigrationInterface { name = 'CreateUserManagement1646992772331'; public async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( `CREATE TABLE ${tablePrefix}role ( @@ -156,7 +156,7 @@ export class CreateUserManagement1646992772331 implements MigrationInterface { } public async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( `ALTER TABLE ${tablePrefix}workflow_entity ADD UNIQUE INDEX \`IDX_${tablePrefix}943d8f922be094eb507cb9a7f9\` (\`name\`)`, diff --git a/packages/cli/src/databases/postgresdb/migrations/1587669153312-InitialMigration.ts b/packages/cli/src/databases/postgresdb/migrations/1587669153312-InitialMigration.ts index eace7a92fb..4f2bb8ce64 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1587669153312-InitialMigration.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1587669153312-InitialMigration.ts @@ -7,9 +7,9 @@ export class InitialMigration1587669153312 implements MigrationInterface { name = 'InitialMigration1587669153312'; async up(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixIndex = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } @@ -22,9 +22,9 @@ export class InitialMigration1587669153312 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixIndex = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } diff --git a/packages/cli/src/databases/postgresdb/migrations/1589476000887-WebhookModel.ts b/packages/cli/src/databases/postgresdb/migrations/1589476000887-WebhookModel.ts index cbc0de279d..0162b78dcf 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1589476000887-WebhookModel.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1589476000887-WebhookModel.ts @@ -9,9 +9,9 @@ export class WebhookModel1589476000887 implements MigrationInterface { name = 'WebhookModel1589476000887'; async up(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixIndex = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } @@ -20,8 +20,8 @@ export class WebhookModel1589476000887 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); - const schema = config.get('database.postgresdb.schema'); + let tablePrefix = config.getEnv('database.tablePrefix'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } diff --git a/packages/cli/src/databases/postgresdb/migrations/1594828256133-CreateIndexStoppedAt.ts b/packages/cli/src/databases/postgresdb/migrations/1594828256133-CreateIndexStoppedAt.ts index 664834082e..3874ee03d0 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1594828256133-CreateIndexStoppedAt.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1594828256133-CreateIndexStoppedAt.ts @@ -6,9 +6,9 @@ export class CreateIndexStoppedAt1594828256133 implements MigrationInterface { name = 'CreateIndexStoppedAt1594828256133'; async up(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } @@ -17,7 +17,7 @@ export class CreateIndexStoppedAt1594828256133 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`DROP INDEX IDX_${tablePrefix}33228da131bb1112247cf52a42`); } diff --git a/packages/cli/src/databases/postgresdb/migrations/1607431743768-MakeStoppedAtNullable.ts b/packages/cli/src/databases/postgresdb/migrations/1607431743768-MakeStoppedAtNullable.ts index 5f0a05c02c..0baaf34256 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1607431743768-MakeStoppedAtNullable.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1607431743768-MakeStoppedAtNullable.ts @@ -6,8 +6,8 @@ export class MakeStoppedAtNullable1607431743768 implements MigrationInterface { name = 'MakeStoppedAtNullable1607431743768'; async up(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); - const schema = config.get('database.postgresdb.schema'); + let tablePrefix = config.getEnv('database.tablePrefix'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } diff --git a/packages/cli/src/databases/postgresdb/migrations/1611144599516-AddWebhookId.ts b/packages/cli/src/databases/postgresdb/migrations/1611144599516-AddWebhookId.ts index b6f4d1a684..a2d4a47baa 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1611144599516-AddWebhookId.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1611144599516-AddWebhookId.ts @@ -5,9 +5,9 @@ export class AddWebhookId1611144599516 implements MigrationInterface { name = 'AddWebhookId1611144599516'; async up(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } @@ -18,9 +18,9 @@ export class AddWebhookId1611144599516 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } diff --git a/packages/cli/src/databases/postgresdb/migrations/1617270242566-CreateTagEntity.ts b/packages/cli/src/databases/postgresdb/migrations/1617270242566-CreateTagEntity.ts index 7ccdcd3181..d5f2246d37 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1617270242566-CreateTagEntity.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1617270242566-CreateTagEntity.ts @@ -5,9 +5,9 @@ export class CreateTagEntity1617270242566 implements MigrationInterface { name = 'CreateTagEntity1617270242566'; async up(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } @@ -40,9 +40,9 @@ export class CreateTagEntity1617270242566 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } diff --git a/packages/cli/src/databases/postgresdb/migrations/1620824779533-UniqueWorkflowNames.ts b/packages/cli/src/databases/postgresdb/migrations/1620824779533-UniqueWorkflowNames.ts index 620dcffb79..e57a7adf6b 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1620824779533-UniqueWorkflowNames.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1620824779533-UniqueWorkflowNames.ts @@ -1,13 +1,13 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -import config = require('../../../../config'); +import * as config from '../../../../config'; export class UniqueWorkflowNames1620824779533 implements MigrationInterface { name = 'UniqueWorkflowNames1620824779533'; async up(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } @@ -58,9 +58,9 @@ export class UniqueWorkflowNames1620824779533 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } diff --git a/packages/cli/src/databases/postgresdb/migrations/1626176912946-AddwaitTill.ts b/packages/cli/src/databases/postgresdb/migrations/1626176912946-AddwaitTill.ts index b37834fa75..22414ff0df 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1626176912946-AddwaitTill.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1626176912946-AddwaitTill.ts @@ -5,9 +5,9 @@ export class AddwaitTill1626176912946 implements MigrationInterface { name = 'AddwaitTill1626176912946'; async up(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } @@ -17,9 +17,9 @@ export class AddwaitTill1626176912946 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } diff --git a/packages/cli/src/databases/postgresdb/migrations/1630419189837-UpdateWorkflowCredentials.ts b/packages/cli/src/databases/postgresdb/migrations/1630419189837-UpdateWorkflowCredentials.ts index 2061241ce0..df58994d25 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1630419189837-UpdateWorkflowCredentials.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1630419189837-UpdateWorkflowCredentials.ts @@ -1,5 +1,5 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -import config = require('../../../../config'); +import * as config from '../../../../config'; import { MigrationHelpers } from '../../MigrationHelpers'; // replacing the credentials in workflows and execution @@ -9,8 +9,8 @@ export class UpdateWorkflowCredentials1630419189837 implements MigrationInterfac name = 'UpdateWorkflowCredentials1630419189837'; public async up(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); - const schema = config.get('database.postgresdb.schema'); + let tablePrefix = config.getEnv('database.tablePrefix'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } @@ -152,8 +152,8 @@ export class UpdateWorkflowCredentials1630419189837 implements MigrationInterfac } public async down(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); - const schema = config.get('database.postgresdb.schema'); + let tablePrefix = config.getEnv('database.tablePrefix'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } diff --git a/packages/cli/src/databases/postgresdb/migrations/1644422880309-AddExecutionEntityIndexes.ts b/packages/cli/src/databases/postgresdb/migrations/1644422880309-AddExecutionEntityIndexes.ts index 933eb2131e..777609a366 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1644422880309-AddExecutionEntityIndexes.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1644422880309-AddExecutionEntityIndexes.ts @@ -5,44 +5,44 @@ export class AddExecutionEntityIndexes1644422880309 implements MigrationInterfac name = 'AddExecutionEntityIndexes1644422880309'; public async up(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } await queryRunner.query( - `DROP INDEX "${schema}".IDX_${tablePrefixPure}c4d999a5e90784e8caccf5589d`, + `DROP INDEX IF EXISTS "${schema}".IDX_${tablePrefixPure}c4d999a5e90784e8caccf5589d`, ); await queryRunner.query( - `DROP INDEX "${schema}".IDX_${tablePrefixPure}ca4a71b47f28ac6ea88293a8e2`, + `DROP INDEX IF EXISTS "${schema}".IDX_${tablePrefixPure}ca4a71b47f28ac6ea88293a8e2`, ); await queryRunner.query( - `CREATE INDEX "IDX_${tablePrefixPure}33228da131bb1112247cf52a42" ON ${tablePrefix}execution_entity ("stoppedAt") `, + `CREATE INDEX IF NOT EXISTS "IDX_${tablePrefixPure}33228da131bb1112247cf52a42" ON ${tablePrefix}execution_entity ("stoppedAt") `, ); await queryRunner.query( - `CREATE INDEX "IDX_${tablePrefixPure}58154df94c686818c99fb754ce" ON ${tablePrefix}execution_entity ("workflowId", "waitTill", "id") `, + `CREATE INDEX IF NOT EXISTS "IDX_${tablePrefixPure}58154df94c686818c99fb754ce" ON ${tablePrefix}execution_entity ("workflowId", "waitTill", "id") `, ); await queryRunner.query( - `CREATE INDEX "IDX_${tablePrefixPure}4f474ac92be81610439aaad61e" ON ${tablePrefix}execution_entity ("workflowId", "finished", "id") `, + `CREATE INDEX IF NOT EXISTS "IDX_${tablePrefixPure}4f474ac92be81610439aaad61e" ON ${tablePrefix}execution_entity ("workflowId", "finished", "id") `, ); await queryRunner.query( - `CREATE INDEX "IDX_${tablePrefixPure}72ffaaab9f04c2c1f1ea86e662" ON ${tablePrefix}execution_entity ("finished", "id") `, + `CREATE INDEX IF NOT EXISTS "IDX_${tablePrefixPure}72ffaaab9f04c2c1f1ea86e662" ON ${tablePrefix}execution_entity ("finished", "id") `, ); await queryRunner.query( - `CREATE INDEX "IDX_${tablePrefixPure}85b981df7b444f905f8bf50747" ON ${tablePrefix}execution_entity ("waitTill", "id") `, + `CREATE INDEX IF NOT EXISTS "IDX_${tablePrefixPure}85b981df7b444f905f8bf50747" ON ${tablePrefix}execution_entity ("waitTill", "id") `, ); await queryRunner.query( - `CREATE INDEX "IDX_${tablePrefixPure}d160d4771aba5a0d78943edbe3" ON ${tablePrefix}execution_entity ("workflowId", "id") `, + `CREATE INDEX IF NOT EXISTS "IDX_${tablePrefixPure}d160d4771aba5a0d78943edbe3" ON ${tablePrefix}execution_entity ("workflowId", "id") `, ); } public async down(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; diff --git a/packages/cli/src/databases/postgresdb/migrations/1646834195327-IncreaseTypeVarcharLimit.ts b/packages/cli/src/databases/postgresdb/migrations/1646834195327-IncreaseTypeVarcharLimit.ts index 3e3250e661..c09ce161d1 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1646834195327-IncreaseTypeVarcharLimit.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1646834195327-IncreaseTypeVarcharLimit.ts @@ -3,13 +3,13 @@ import { QueryRunner, } from 'typeorm'; -import config = require('../../../../config'); +import * as config from '../../../../config'; export class IncreaseTypeVarcharLimit1646834195327 implements MigrationInterface { name = 'IncreaseTypeVarcharLimit1646834195327'; async up(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`ALTER TABLE ${tablePrefix}credentials_entity ALTER COLUMN "type" TYPE VARCHAR(128)`); } diff --git a/packages/cli/src/databases/postgresdb/migrations/1646992772331-CreateUserManagement.ts b/packages/cli/src/databases/postgresdb/migrations/1646992772331-CreateUserManagement.ts index 5550f4d464..109c7476e7 100644 --- a/packages/cli/src/databases/postgresdb/migrations/1646992772331-CreateUserManagement.ts +++ b/packages/cli/src/databases/postgresdb/migrations/1646992772331-CreateUserManagement.ts @@ -1,15 +1,15 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; import { v4 as uuid } from 'uuid'; -import config = require('../../../../config'); +import config from '../../../../config'; import { loadSurveyFromDisk } from '../../utils/migrationHelpers'; export class CreateUserManagement1646992772331 implements MigrationInterface { name = 'CreateUserManagement1646992772331'; public async up(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } @@ -140,9 +140,9 @@ export class CreateUserManagement1646992772331 implements MigrationInterface { } public async down(queryRunner: QueryRunner): Promise { - let tablePrefix = config.get('database.tablePrefix'); + let tablePrefix = config.getEnv('database.tablePrefix'); const tablePrefixPure = tablePrefix; - const schema = config.get('database.postgresdb.schema'); + const schema = config.getEnv('database.postgresdb.schema'); if (schema) { tablePrefix = schema + '.' + tablePrefix; } diff --git a/packages/cli/src/databases/sqlite/migrations/1588102412422-InitialMigration.ts b/packages/cli/src/databases/sqlite/migrations/1588102412422-InitialMigration.ts index e0d192c65c..6825c4ac11 100644 --- a/packages/cli/src/databases/sqlite/migrations/1588102412422-InitialMigration.ts +++ b/packages/cli/src/databases/sqlite/migrations/1588102412422-InitialMigration.ts @@ -8,7 +8,7 @@ export class InitialMigration1588102412422 implements MigrationInterface { async up(queryRunner: QueryRunner): Promise { logMigrationStart(this.name); - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( `CREATE TABLE IF NOT EXISTS "${tablePrefix}credentials_entity" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(128) NOT NULL, "data" text NOT NULL, "type" varchar(128) NOT NULL, "nodesAccess" text NOT NULL, "createdAt" datetime NOT NULL, "updatedAt" datetime NOT NULL)`, @@ -35,7 +35,7 @@ export class InitialMigration1588102412422 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`DROP TABLE "${tablePrefix}workflow_entity"`, undefined); await queryRunner.query(`DROP INDEX "IDX_${tablePrefix}c4d999a5e90784e8caccf5589d"`, undefined); diff --git a/packages/cli/src/databases/sqlite/migrations/1592445003908-WebhookModel.ts b/packages/cli/src/databases/sqlite/migrations/1592445003908-WebhookModel.ts index 43d38bd50c..be9e1186dc 100644 --- a/packages/cli/src/databases/sqlite/migrations/1592445003908-WebhookModel.ts +++ b/packages/cli/src/databases/sqlite/migrations/1592445003908-WebhookModel.ts @@ -8,7 +8,7 @@ export class WebhookModel1592445003908 implements MigrationInterface { async up(queryRunner: QueryRunner): Promise { logMigrationStart(this.name); - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( `CREATE TABLE IF NOT EXISTS ${tablePrefix}webhook_entity ("workflowId" integer NOT NULL, "webhookPath" varchar NOT NULL, "method" varchar NOT NULL, "node" varchar NOT NULL, PRIMARY KEY ("webhookPath", "method"))`, @@ -18,7 +18,7 @@ export class WebhookModel1592445003908 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`DROP TABLE ${tablePrefix}webhook_entity`); } } diff --git a/packages/cli/src/databases/sqlite/migrations/1594825041918-CreateIndexStoppedAt.ts b/packages/cli/src/databases/sqlite/migrations/1594825041918-CreateIndexStoppedAt.ts index 92fe62984e..b620f9455e 100644 --- a/packages/cli/src/databases/sqlite/migrations/1594825041918-CreateIndexStoppedAt.ts +++ b/packages/cli/src/databases/sqlite/migrations/1594825041918-CreateIndexStoppedAt.ts @@ -8,7 +8,7 @@ export class CreateIndexStoppedAt1594825041918 implements MigrationInterface { async up(queryRunner: QueryRunner): Promise { logMigrationStart(this.name); - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( `CREATE INDEX "IDX_${tablePrefix}cefb067df2402f6aed0638a6c1" ON "${tablePrefix}execution_entity" ("stoppedAt") `, @@ -18,7 +18,7 @@ export class CreateIndexStoppedAt1594825041918 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`DROP INDEX "IDX_${tablePrefix}cefb067df2402f6aed0638a6c1"`); } diff --git a/packages/cli/src/databases/sqlite/migrations/1607431743769-MakeStoppedAtNullable.ts b/packages/cli/src/databases/sqlite/migrations/1607431743769-MakeStoppedAtNullable.ts index a2aee48c64..154c554e8a 100644 --- a/packages/cli/src/databases/sqlite/migrations/1607431743769-MakeStoppedAtNullable.ts +++ b/packages/cli/src/databases/sqlite/migrations/1607431743769-MakeStoppedAtNullable.ts @@ -8,7 +8,7 @@ export class MakeStoppedAtNullable1607431743769 implements MigrationInterface { async up(queryRunner: QueryRunner): Promise { logMigrationStart(this.name); - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); // SQLite does not allow us to simply "alter column" // We're hacking the way sqlite identifies tables // Allowing a column to become nullable diff --git a/packages/cli/src/databases/sqlite/migrations/1611071044839-AddWebhookId.ts b/packages/cli/src/databases/sqlite/migrations/1611071044839-AddWebhookId.ts index adf62f76c9..51d92858ec 100644 --- a/packages/cli/src/databases/sqlite/migrations/1611071044839-AddWebhookId.ts +++ b/packages/cli/src/databases/sqlite/migrations/1611071044839-AddWebhookId.ts @@ -8,7 +8,7 @@ export class AddWebhookId1611071044839 implements MigrationInterface { async up(queryRunner: QueryRunner): Promise { logMigrationStart(this.name); - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( `CREATE TABLE "temporary_webhook_entity" ("workflowId" integer NOT NULL, "webhookPath" varchar NOT NULL, "method" varchar NOT NULL, "node" varchar NOT NULL, "webhookId" varchar, "pathLength" integer, PRIMARY KEY ("webhookPath", "method"))`, @@ -28,7 +28,7 @@ export class AddWebhookId1611071044839 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`DROP INDEX "IDX_${tablePrefix}742496f199721a057051acf4c2"`); await queryRunner.query( diff --git a/packages/cli/src/databases/sqlite/migrations/1617213344594-CreateTagEntity.ts b/packages/cli/src/databases/sqlite/migrations/1617213344594-CreateTagEntity.ts index 547cc31127..20439b370f 100644 --- a/packages/cli/src/databases/sqlite/migrations/1617213344594-CreateTagEntity.ts +++ b/packages/cli/src/databases/sqlite/migrations/1617213344594-CreateTagEntity.ts @@ -8,7 +8,7 @@ export class CreateTagEntity1617213344594 implements MigrationInterface { async up(queryRunner: QueryRunner): Promise { logMigrationStart(this.name); - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); // create tags table + relationship with workflow entity @@ -73,7 +73,7 @@ export class CreateTagEntity1617213344594 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); // `createdAt` and `updatedAt` diff --git a/packages/cli/src/databases/sqlite/migrations/1620821879465-UniqueWorkflowNames.ts b/packages/cli/src/databases/sqlite/migrations/1620821879465-UniqueWorkflowNames.ts index 6b50d94012..93d456e710 100644 --- a/packages/cli/src/databases/sqlite/migrations/1620821879465-UniqueWorkflowNames.ts +++ b/packages/cli/src/databases/sqlite/migrations/1620821879465-UniqueWorkflowNames.ts @@ -1,5 +1,5 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -import config = require('../../../../config'); +import * as config from '../../../../config'; import { logMigrationEnd, logMigrationStart } from '../../utils/migrationHelpers'; export class UniqueWorkflowNames1620821879465 implements MigrationInterface { @@ -8,7 +8,7 @@ export class UniqueWorkflowNames1620821879465 implements MigrationInterface { async up(queryRunner: QueryRunner): Promise { logMigrationStart(this.name); - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); const workflowNames = await queryRunner.query(` SELECT name @@ -58,7 +58,7 @@ export class UniqueWorkflowNames1620821879465 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`DROP INDEX "IDX_${tablePrefix}943d8f922be094eb507cb9a7f9"`); } } diff --git a/packages/cli/src/databases/sqlite/migrations/1621707690587-AddWaitColumn.ts b/packages/cli/src/databases/sqlite/migrations/1621707690587-AddWaitColumn.ts index 0c5c2b28c2..502c3b86f1 100644 --- a/packages/cli/src/databases/sqlite/migrations/1621707690587-AddWaitColumn.ts +++ b/packages/cli/src/databases/sqlite/migrations/1621707690587-AddWaitColumn.ts @@ -8,7 +8,7 @@ export class AddWaitColumn1621707690587 implements MigrationInterface { async up(queryRunner: QueryRunner): Promise { logMigrationStart(this.name); - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`DROP TABLE IF EXISTS "${tablePrefix}temporary_execution_entity"`); await queryRunner.query( @@ -34,7 +34,7 @@ export class AddWaitColumn1621707690587 implements MigrationInterface { } async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( `CREATE TABLE IF NOT EXISTS "${tablePrefix}temporary_execution_entity" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "data" text NOT NULL, "finished" boolean NOT NULL, "mode" varchar NOT NULL, "retryOf" varchar, "retrySuccessId" varchar, "startedAt" datetime NOT NULL, "stoppedAt" datetime, "workflowData" text NOT NULL, "workflowId" varchar)`, diff --git a/packages/cli/src/databases/sqlite/migrations/1630330987096-UpdateWorkflowCredentials.ts b/packages/cli/src/databases/sqlite/migrations/1630330987096-UpdateWorkflowCredentials.ts index 9c9452f695..4b60c12f7f 100644 --- a/packages/cli/src/databases/sqlite/migrations/1630330987096-UpdateWorkflowCredentials.ts +++ b/packages/cli/src/databases/sqlite/migrations/1630330987096-UpdateWorkflowCredentials.ts @@ -1,5 +1,5 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; -import config = require('../../../../config'); +import * as config from '../../../../config'; import { MigrationHelpers } from '../../MigrationHelpers'; import { logMigrationEnd, logMigrationStart } from '../../utils/migrationHelpers'; @@ -12,7 +12,7 @@ export class UpdateWorkflowCredentials1630330987096 implements MigrationInterfac public async up(queryRunner: QueryRunner): Promise { logMigrationStart(this.name); - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); const helpers = new MigrationHelpers(queryRunner); const credentialsEntities = await queryRunner.query(` @@ -152,7 +152,7 @@ export class UpdateWorkflowCredentials1630330987096 implements MigrationInterfac } public async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); const helpers = new MigrationHelpers(queryRunner); const credentialsEntities = await queryRunner.query(` diff --git a/packages/cli/src/databases/sqlite/migrations/1644421939510-AddExecutionEntityIndexes.ts b/packages/cli/src/databases/sqlite/migrations/1644421939510-AddExecutionEntityIndexes.ts index 74f6822a93..8d6192a9ae 100644 --- a/packages/cli/src/databases/sqlite/migrations/1644421939510-AddExecutionEntityIndexes.ts +++ b/packages/cli/src/databases/sqlite/migrations/1644421939510-AddExecutionEntityIndexes.ts @@ -7,32 +7,32 @@ export class AddExecutionEntityIndexes1644421939510 implements MigrationInterfac public async up(queryRunner: QueryRunner): Promise { logMigrationStart(this.name); - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`DROP INDEX IF EXISTS 'IDX_${tablePrefix}c4d999a5e90784e8caccf5589d'`); - await queryRunner.query(`DROP INDEX 'IDX_${tablePrefix}ca4a71b47f28ac6ea88293a8e2'`); + await queryRunner.query(`DROP INDEX IF EXISTS 'IDX_${tablePrefix}ca4a71b47f28ac6ea88293a8e2'`); await queryRunner.query( - `CREATE INDEX 'IDX_${tablePrefix}06da892aaf92a48e7d3e400003' ON '${tablePrefix}execution_entity' ('workflowId', 'waitTill', 'id') `, + `CREATE INDEX IF NOT EXISTS 'IDX_${tablePrefix}06da892aaf92a48e7d3e400003' ON '${tablePrefix}execution_entity' ('workflowId', 'waitTill', 'id') `, ); await queryRunner.query( - `CREATE INDEX 'IDX_${tablePrefix}78d62b89dc1433192b86dce18a' ON '${tablePrefix}execution_entity' ('workflowId', 'finished', 'id') `, + `CREATE INDEX IF NOT EXISTS 'IDX_${tablePrefix}78d62b89dc1433192b86dce18a' ON '${tablePrefix}execution_entity' ('workflowId', 'finished', 'id') `, ); await queryRunner.query( - `CREATE INDEX 'IDX_${tablePrefix}1688846335d274033e15c846a4' ON '${tablePrefix}execution_entity' ('finished', 'id') `, + `CREATE INDEX IF NOT EXISTS 'IDX_${tablePrefix}1688846335d274033e15c846a4' ON '${tablePrefix}execution_entity' ('finished', 'id') `, ); await queryRunner.query( - `CREATE INDEX 'IDX_${tablePrefix}b94b45ce2c73ce46c54f20b5f9' ON '${tablePrefix}execution_entity' ('waitTill', 'id') `, + `CREATE INDEX IF NOT EXISTS 'IDX_${tablePrefix}b94b45ce2c73ce46c54f20b5f9' ON '${tablePrefix}execution_entity' ('waitTill', 'id') `, ); await queryRunner.query( - `CREATE INDEX 'IDX_${tablePrefix}81fc04c8a17de15835713505e4' ON '${tablePrefix}execution_entity' ('workflowId', 'id') `, + `CREATE INDEX IF NOT EXISTS 'IDX_${tablePrefix}81fc04c8a17de15835713505e4' ON '${tablePrefix}execution_entity' ('workflowId', 'id') `, ); logMigrationEnd(this.name); } public async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query(`DROP INDEX 'IDX_${tablePrefix}81fc04c8a17de15835713505e4'`); await queryRunner.query(`DROP INDEX 'IDX_${tablePrefix}b94b45ce2c73ce46c54f20b5f9'`); @@ -43,7 +43,7 @@ export class AddExecutionEntityIndexes1644421939510 implements MigrationInterfac `CREATE INDEX 'IDX_${tablePrefix}ca4a71b47f28ac6ea88293a8e2' ON '${tablePrefix}execution_entity' ('waitTill') `, ); await queryRunner.query( - `CREATE INDEX IF NOT EXISTS 'IDX_${tablePrefix}c4d999a5e90784e8caccf5589d' ON '${tablePrefix}execution_entity' ('workflowId') `, + `CREATE INDEX 'IDX_${tablePrefix}c4d999a5e90784e8caccf5589d' ON '${tablePrefix}execution_entity' ('workflowId') `, ); } } diff --git a/packages/cli/src/databases/sqlite/migrations/1646992772331-CreateUserManagement.ts b/packages/cli/src/databases/sqlite/migrations/1646992772331-CreateUserManagement.ts index d087335331..014753d813 100644 --- a/packages/cli/src/databases/sqlite/migrations/1646992772331-CreateUserManagement.ts +++ b/packages/cli/src/databases/sqlite/migrations/1646992772331-CreateUserManagement.ts @@ -1,6 +1,6 @@ import { MigrationInterface, QueryRunner } from 'typeorm'; import { v4 as uuid } from 'uuid'; -import config = require('../../../../config'); +import * as config from '../../../../config'; import { loadSurveyFromDisk, logMigrationEnd, @@ -13,7 +13,7 @@ export class CreateUserManagement1646992772331 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { logMigrationStart(this.name); - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( `CREATE TABLE "${tablePrefix}role" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(32) NOT NULL, "scope" varchar NOT NULL, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), CONSTRAINT "UQ_${tablePrefix}5b49d0f504f7ef31045a1fb2eb8" UNIQUE ("scope", "name"))`, @@ -104,7 +104,7 @@ export class CreateUserManagement1646992772331 implements MigrationInterface { } public async down(queryRunner: QueryRunner): Promise { - const tablePrefix = config.get('database.tablePrefix'); + const tablePrefix = config.getEnv('database.tablePrefix'); await queryRunner.query( `CREATE UNIQUE INDEX "IDX_${tablePrefix}943d8f922be094eb507cb9a7f9" ON "${tablePrefix}workflow_entity" ("name") `, ); diff --git a/packages/cli/src/databases/sqlite/migrations/index.ts b/packages/cli/src/databases/sqlite/migrations/index.ts index fe2a71b682..2f938fe0d1 100644 --- a/packages/cli/src/databases/sqlite/migrations/index.ts +++ b/packages/cli/src/databases/sqlite/migrations/index.ts @@ -1,4 +1,4 @@ -import config = require('../../../../config'); +import config from '../../../../config'; import { InitialMigration1588102412422 } from './1588102412422-InitialMigration'; import { WebhookModel1592445003908 } from './1592445003908-WebhookModel'; diff --git a/packages/cli/src/requests.d.ts b/packages/cli/src/requests.d.ts index 72e1ffe0e2..3ab1d7a301 100644 --- a/packages/cli/src/requests.d.ts +++ b/packages/cli/src/requests.d.ts @@ -1,5 +1,5 @@ /* eslint-disable import/no-cycle */ -import express = require('express'); +import express from 'express'; import { IConnections, ICredentialDataDecryptedObject, diff --git a/packages/cli/src/telemetry/index.ts b/packages/cli/src/telemetry/index.ts index 69a4bad456..fe648e6972 100644 --- a/packages/cli/src/telemetry/index.ts +++ b/packages/cli/src/telemetry/index.ts @@ -1,9 +1,9 @@ /* eslint-disable import/no-cycle */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import TelemetryClient = require('@rudderstack/rudder-sdk-node'); +import TelemetryClient from '@rudderstack/rudder-sdk-node'; import { IDataObject, LoggerProxy } from 'n8n-workflow'; -import config = require('../../config'); +import * as config from '../../config'; import { getLogger } from '../Logger'; type CountBufferItemKey = @@ -58,10 +58,10 @@ export class Telemetry { this.instanceId = instanceId; this.versionCli = versionCli; - const enabled = config.get('diagnostics.enabled') as boolean; - const logLevel = config.get('logs.level') as boolean; + const enabled = config.getEnv('diagnostics.enabled'); + const logLevel = config.getEnv('logs.level'); if (enabled) { - const conf = config.get('diagnostics.config.backend') as string; + const conf = config.getEnv('diagnostics.config.backend'); const [key, url] = conf.split(';'); if (!key || !url) { diff --git a/packages/cli/test/integration/auth.api.test.ts b/packages/cli/test/integration/auth.api.test.ts new file mode 100644 index 0000000000..ed49c63edb --- /dev/null +++ b/packages/cli/test/integration/auth.api.test.ts @@ -0,0 +1,283 @@ +import express = require('express'); +import validator from 'validator'; + +import config = require('../../config'); +import * as utils from './shared/utils'; +import { LOGGED_OUT_RESPONSE_BODY } from './shared/constants'; +import { Db } from '../../src'; +import type { Role } from '../../src/databases/entities/Role'; +import { randomValidPassword } from './shared/random'; +import * as testDb from './shared/testDb'; +import { AUTH_COOKIE_NAME } from '../../src/constants'; + +jest.mock('../../src/telemetry'); + +let app: express.Application; +let testDbName = ''; +let globalOwnerRole: Role; +let globalMemberRole: Role; + +beforeAll(async () => { + app = utils.initTestServer({ endpointGroups: ['auth'], applyAuth: true }); + const initResult = await testDb.init(); + testDbName = initResult.testDbName; + + globalOwnerRole = await testDb.getGlobalOwnerRole(); + globalMemberRole = await testDb.getGlobalMemberRole(); + utils.initTestLogger(); + utils.initTestTelemetry(); +}); + +beforeEach(async () => { + await testDb.truncate(['User'], testDbName); + + config.set('userManagement.isInstanceOwnerSetUp', true); + + await Db.collections.Settings!.update( + { key: 'userManagement.isInstanceOwnerSetUp' }, + { value: JSON.stringify(true) }, + ); +}); + +afterAll(async () => { + await testDb.terminate(testDbName); +}); + +test('POST /login should log user in', async () => { + const ownerPassword = randomValidPassword(); + const owner = await testDb.createUser({ + password: ownerPassword, + globalRole: globalOwnerRole, + }); + + const authlessAgent = utils.createAgent(app); + + const response = await authlessAgent.post('/login').send({ + email: owner.email, + password: ownerPassword, + }); + + expect(response.statusCode).toBe(200); + + const { + id, + email, + firstName, + lastName, + password, + personalizationAnswers, + globalRole, + resetPasswordToken, + } = response.body.data; + + expect(validator.isUUID(id)).toBe(true); + expect(email).toBe(owner.email); + expect(firstName).toBe(owner.firstName); + expect(lastName).toBe(owner.lastName); + expect(password).toBeUndefined(); + expect(personalizationAnswers).toBeNull(); + expect(password).toBeUndefined(); + expect(resetPasswordToken).toBeUndefined(); + expect(globalRole).toBeDefined(); + expect(globalRole.name).toBe('owner'); + expect(globalRole.scope).toBe('global'); + + const authToken = utils.getAuthToken(response); + expect(authToken).toBeDefined(); +}); + +test('GET /login should return 401 Unauthorized if no cookie', async () => { + const authlessAgent = utils.createAgent(app); + + const response = await authlessAgent.get('/login'); + + expect(response.statusCode).toBe(401); + + const authToken = utils.getAuthToken(response); + expect(authToken).toBeUndefined(); +}); + +test('GET /login should return cookie if UM is disabled', async () => { + const ownerShell = await testDb.createUserShell(globalOwnerRole); + + config.set('userManagement.isInstanceOwnerSetUp', false); + + await Db.collections.Settings!.update( + { key: 'userManagement.isInstanceOwnerSetUp' }, + { value: JSON.stringify(false) }, + ); + + const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + + const response = await authOwnerShellAgent.get('/login'); + + expect(response.statusCode).toBe(200); + + const authToken = utils.getAuthToken(response); + expect(authToken).toBeDefined(); +}); + +test('GET /login should return 401 Unauthorized if invalid cookie', async () => { + const invalidAuthAgent = utils.createAgent(app); + invalidAuthAgent.jar.setCookie(`${AUTH_COOKIE_NAME}=invalid`); + + const response = await invalidAuthAgent.get('/login'); + + expect(response.statusCode).toBe(401); + + const authToken = utils.getAuthToken(response); + expect(authToken).toBeUndefined(); +}); + +test('GET /login should return logged-in owner shell', async () => { + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authMemberAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + + const response = await authMemberAgent.get('/login'); + + expect(response.statusCode).toBe(200); + + const { + id, + email, + firstName, + lastName, + password, + personalizationAnswers, + globalRole, + resetPasswordToken, + } = response.body.data; + + expect(validator.isUUID(id)).toBe(true); + expect(email).toBeDefined(); + expect(firstName).toBeNull(); + expect(lastName).toBeNull(); + expect(password).toBeUndefined(); + expect(personalizationAnswers).toBeNull(); + expect(password).toBeUndefined(); + expect(resetPasswordToken).toBeUndefined(); + expect(globalRole).toBeDefined(); + expect(globalRole.name).toBe('owner'); + expect(globalRole.scope).toBe('global'); + + const authToken = utils.getAuthToken(response); + expect(authToken).toBeUndefined(); +}); + +test('GET /login should return logged-in member shell', async () => { + const memberShell = await testDb.createUserShell(globalMemberRole); + const authMemberAgent = utils.createAgent(app, { auth: true, user: memberShell }); + + const response = await authMemberAgent.get('/login'); + + expect(response.statusCode).toBe(200); + + const { + id, + email, + firstName, + lastName, + password, + personalizationAnswers, + globalRole, + resetPasswordToken, + } = response.body.data; + + expect(validator.isUUID(id)).toBe(true); + expect(email).toBeDefined(); + expect(firstName).toBeNull(); + expect(lastName).toBeNull(); + expect(password).toBeUndefined(); + expect(personalizationAnswers).toBeNull(); + expect(password).toBeUndefined(); + expect(resetPasswordToken).toBeUndefined(); + expect(globalRole).toBeDefined(); + expect(globalRole.name).toBe('member'); + expect(globalRole.scope).toBe('global'); + + const authToken = utils.getAuthToken(response); + expect(authToken).toBeUndefined(); +}); + +test('GET /login should return logged-in owner', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + + const response = await authOwnerAgent.get('/login'); + + expect(response.statusCode).toBe(200); + + const { + id, + email, + firstName, + lastName, + password, + personalizationAnswers, + globalRole, + resetPasswordToken, + } = response.body.data; + + expect(validator.isUUID(id)).toBe(true); + expect(email).toBe(owner.email); + expect(firstName).toBe(owner.firstName); + expect(lastName).toBe(owner.lastName); + expect(password).toBeUndefined(); + expect(personalizationAnswers).toBeNull(); + expect(password).toBeUndefined(); + expect(resetPasswordToken).toBeUndefined(); + expect(globalRole).toBeDefined(); + expect(globalRole.name).toBe('owner'); + expect(globalRole.scope).toBe('global'); + + const authToken = utils.getAuthToken(response); + expect(authToken).toBeUndefined(); +}); + +test('GET /login should return logged-in member', async () => { + const member = await testDb.createUser({ globalRole: globalMemberRole }); + const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); + + const response = await authMemberAgent.get('/login'); + + expect(response.statusCode).toBe(200); + + const { + id, + email, + firstName, + lastName, + password, + personalizationAnswers, + globalRole, + resetPasswordToken, + } = response.body.data; + + expect(validator.isUUID(id)).toBe(true); + expect(email).toBe(member.email); + expect(firstName).toBe(member.firstName); + expect(lastName).toBe(member.lastName); + expect(password).toBeUndefined(); + expect(personalizationAnswers).toBeNull(); + expect(password).toBeUndefined(); + expect(resetPasswordToken).toBeUndefined(); + expect(globalRole).toBeDefined(); + expect(globalRole.name).toBe('member'); + expect(globalRole.scope).toBe('global'); + + const authToken = utils.getAuthToken(response); + expect(authToken).toBeUndefined(); +}); + +test('POST /logout should log user out', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + + const response = await authOwnerAgent.post('/logout'); + + expect(response.statusCode).toBe(200); + expect(response.body).toEqual(LOGGED_OUT_RESPONSE_BODY); + + const authToken = utils.getAuthToken(response); + expect(authToken).toBeUndefined(); +}); diff --git a/packages/cli/test/integration/auth.endpoints.test.ts b/packages/cli/test/integration/auth.endpoints.test.ts index 23ef7e3e3d..fd24d49c0e 100644 --- a/packages/cli/test/integration/auth.endpoints.test.ts +++ b/packages/cli/test/integration/auth.endpoints.test.ts @@ -1,9 +1,9 @@ import { hashSync, genSaltSync } from 'bcryptjs'; -import express = require('express'); +import express from 'express'; import validator from 'validator'; import { v4 as uuid } from 'uuid'; -import config = require('../../config'); +import * as config from '../../config'; import * as utils from './shared/utils'; import { LOGGED_OUT_RESPONSE_BODY } from './shared/constants'; import { Db } from '../../src'; @@ -12,6 +12,8 @@ import { randomEmail, randomValidPassword, randomName } from './shared/random'; import { getGlobalOwnerRole } from './shared/testDb'; import * as testDb from './shared/testDb'; +jest.mock('../../src/telemetry'); + let globalOwnerRole: Role; let app: express.Application; @@ -35,7 +37,7 @@ beforeEach(async () => { email: TEST_USER.email, firstName: TEST_USER.firstName, lastName: TEST_USER.lastName, - password: hashSync(TEST_USER.password, genSaltSync(10)), + password: TEST_USER.password, globalRole: globalOwnerRole, }); diff --git a/packages/cli/test/integration/auth.middleware.test.ts b/packages/cli/test/integration/auth.mw.test.ts similarity index 82% rename from packages/cli/test/integration/auth.middleware.test.ts rename to packages/cli/test/integration/auth.mw.test.ts index d686496aab..872ae0c589 100644 --- a/packages/cli/test/integration/auth.middleware.test.ts +++ b/packages/cli/test/integration/auth.mw.test.ts @@ -1,16 +1,20 @@ -import express = require('express'); -import * as request from 'supertest'; +import express from 'express'; + +import request from 'supertest'; import { REST_PATH_SEGMENT, ROUTES_REQUIRING_AUTHORIZATION, ROUTES_REQUIRING_AUTHENTICATION, } from './shared/constants'; - import * as utils from './shared/utils'; import * as testDb from './shared/testDb'; +import type { Role } from '../../src/databases/entities/Role'; + +jest.mock('../../src/telemetry'); let app: express.Application; let testDbName = ''; +let globalMemberRole: Role; beforeAll(async () => { app = utils.initTestServer({ @@ -19,6 +23,9 @@ beforeAll(async () => { }); const initResult = await testDb.init(); testDbName = initResult.testDbName; + + globalMemberRole = await testDb.getGlobalMemberRole(); + utils.initTestLogger(); utils.initTestTelemetry(); }); @@ -41,12 +48,9 @@ ROUTES_REQUIRING_AUTHORIZATION.forEach(async (route) => { const [method, endpoint] = getMethodAndEndpoint(route); test(`${route} should return 403 Forbidden for member`, async () => { - const member = await testDb.createUser(); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const response = await authMemberAgent[method](endpoint); - if (response.statusCode === 500) { - console.log(response); - } expect(response.statusCode).toBe(403); }); diff --git a/packages/cli/test/integration/credentials.api.test.ts b/packages/cli/test/integration/credentials.api.test.ts index b05276c202..f5fa438cd0 100644 --- a/packages/cli/test/integration/credentials.api.test.ts +++ b/packages/cli/test/integration/credentials.api.test.ts @@ -1,15 +1,20 @@ -import express = require('express'); +import express from 'express'; import { UserSettings } from 'n8n-core'; import { Db } from '../../src'; import { randomName, randomString } from './shared/random'; import * as utils from './shared/utils'; import type { CredentialPayload, SaveCredentialFunction } from './shared/types'; -import { Role } from '../../src/databases/entities/Role'; -import { User } from '../../src/databases/entities/User'; +import type { Role } from '../../src/databases/entities/Role'; +import type { User } from '../../src/databases/entities/User'; import * as testDb from './shared/testDb'; +import { CredentialsEntity } from '../../src/databases/entities/CredentialsEntity'; + +jest.mock('../../src/telemetry'); let app: express.Application; let testDbName = ''; +let globalOwnerRole: Role; +let globalMemberRole: Role; let saveCredential: SaveCredentialFunction; beforeAll(async () => { @@ -22,19 +27,17 @@ beforeAll(async () => { utils.initConfigFile(); + globalOwnerRole = await testDb.getGlobalOwnerRole(); + globalMemberRole = await testDb.getGlobalMemberRole(); const credentialOwnerRole = await testDb.getCredentialOwnerRole(); saveCredential = affixRoleToSaveCredential(credentialOwnerRole); + + utils.initTestLogger(); utils.initTestTelemetry(); }); beforeEach(async () => { - await testDb.createOwnerShell(); -}); - -afterEach(async () => { - // do not combine calls - shared table must be cleared first and separately - await testDb.truncate(['SharedCredentials'], testDbName); - await testDb.truncate(['User', 'Credentials'], testDbName); + await testDb.truncate(['User', 'SharedCredentials', 'Credentials'], testDbName); }); afterAll(async () => { @@ -42,8 +45,9 @@ afterAll(async () => { }); test('POST /credentials should create cred', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const payload = credentialPayload(); const response = await authOwnerAgent.post('/credentials').send(payload); @@ -69,26 +73,28 @@ test('POST /credentials should create cred', async () => { where: { credentials: credential }, }); - expect(sharedCredential.user.id).toBe(owner.id); + expect(sharedCredential.user.id).toBe(ownerShell.id); expect(sharedCredential.credentials.name).toBe(payload.name); }); test('POST /credentials should fail with invalid inputs', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - for (const invalidPayload of INVALID_PAYLOADS) { - const response = await authOwnerAgent.post('/credentials').send(invalidPayload); - expect(response.statusCode).toBe(400); - } + await Promise.all( + INVALID_PAYLOADS.map(async (invalidPayload) => { + const response = await authOwnerAgent.post('/credentials').send(invalidPayload); + expect(response.statusCode).toBe(400); + }), + ); }); test('POST /credentials should fail with missing encryption key', async () => { const mock = jest.spyOn(UserSettings, 'getEncryptionKey'); mock.mockResolvedValue(undefined); - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const response = await authOwnerAgent.post('/credentials').send(credentialPayload()); @@ -98,8 +104,8 @@ test('POST /credentials should fail with missing encryption key', async () => { }); test('POST /credentials should ignore ID in payload', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const firstResponse = await authOwnerAgent .post('/credentials') @@ -115,9 +121,9 @@ test('POST /credentials should ignore ID in payload', async () => { }); test('DELETE /credentials/:id should delete owned cred for owner', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const savedCredential = await saveCredential(credentialPayload(), { user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const savedCredential = await saveCredential(credentialPayload(), { user: ownerShell }); const response = await authOwnerAgent.delete(`/credentials/${savedCredential.id}`); @@ -134,9 +140,9 @@ test('DELETE /credentials/:id should delete owned cred for owner', async () => { }); test('DELETE /credentials/:id should delete non-owned cred for owner', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const member = await testDb.createUser(); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const savedCredential = await saveCredential(credentialPayload(), { user: member }); const response = await authOwnerAgent.delete(`/credentials/${savedCredential.id}`); @@ -154,7 +160,7 @@ test('DELETE /credentials/:id should delete non-owned cred for owner', async () }); test('DELETE /credentials/:id should delete owned cred for member', async () => { - const member = await testDb.createUser(); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const savedCredential = await saveCredential(credentialPayload(), { user: member }); @@ -173,10 +179,10 @@ test('DELETE /credentials/:id should delete owned cred for member', async () => }); test('DELETE /credentials/:id should not delete non-owned cred for member', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const member = await testDb.createUser(); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); - const savedCredential = await saveCredential(credentialPayload(), { user: owner }); + const savedCredential = await saveCredential(credentialPayload(), { user: ownerShell }); const response = await authMemberAgent.delete(`/credentials/${savedCredential.id}`); @@ -192,8 +198,8 @@ test('DELETE /credentials/:id should not delete non-owned cred for member', asyn }); test('DELETE /credentials/:id should fail if cred not found', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const response = await authOwnerAgent.delete('/credentials/123'); @@ -201,9 +207,9 @@ test('DELETE /credentials/:id should fail if cred not found', async () => { }); test('PATCH /credentials/:id should update owned cred for owner', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const savedCredential = await saveCredential(credentialPayload(), { user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const savedCredential = await saveCredential(credentialPayload(), { user: ownerShell }); const patchPayload = credentialPayload(); const response = await authOwnerAgent @@ -235,9 +241,9 @@ test('PATCH /credentials/:id should update owned cred for owner', async () => { }); test('PATCH /credentials/:id should update non-owned cred for owner', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const member = await testDb.createUser(); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const savedCredential = await saveCredential(credentialPayload(), { user: member }); const patchPayload = credentialPayload(); @@ -270,7 +276,7 @@ test('PATCH /credentials/:id should update non-owned cred for owner', async () = }); test('PATCH /credentials/:id should update owned cred for member', async () => { - const member = await testDb.createUser(); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const savedCredential = await saveCredential(credentialPayload(), { user: member }); const patchPayload = credentialPayload(); @@ -304,10 +310,10 @@ test('PATCH /credentials/:id should update owned cred for member', async () => { }); test('PATCH /credentials/:id should not update non-owned cred for member', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const member = await testDb.createUser(); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); - const savedCredential = await saveCredential(credentialPayload(), { user: owner }); + const savedCredential = await saveCredential(credentialPayload(), { user: ownerShell }); const patchPayload = credentialPayload(); const response = await authMemberAgent @@ -322,22 +328,24 @@ test('PATCH /credentials/:id should not update non-owned cred for member', async }); test('PATCH /credentials/:id should fail with invalid inputs', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const savedCredential = await saveCredential(credentialPayload(), { user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const savedCredential = await saveCredential(credentialPayload(), { user: ownerShell }); - for (const invalidPayload of INVALID_PAYLOADS) { - const response = await authOwnerAgent - .patch(`/credentials/${savedCredential.id}`) - .send(invalidPayload); + await Promise.all( + INVALID_PAYLOADS.map(async (invalidPayload) => { + const response = await authOwnerAgent + .patch(`/credentials/${savedCredential.id}`) + .send(invalidPayload); - expect(response.statusCode).toBe(400); - } + expect(response.statusCode).toBe(400); + }), + ); }); test('PATCH /credentials/:id should fail if cred not found', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const response = await authOwnerAgent.patch('/credentials/123').send(credentialPayload()); @@ -348,8 +356,8 @@ test('PATCH /credentials/:id should fail with missing encryption key', async () const mock = jest.spyOn(UserSettings, 'getEncryptionKey'); mock.mockResolvedValue(undefined); - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const response = await authOwnerAgent.post('/credentials').send(credentialPayload()); @@ -359,14 +367,14 @@ test('PATCH /credentials/:id should fail with missing encryption key', async () }); test('GET /credentials should retrieve all creds for owner', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); for (let i = 0; i < 3; i++) { - await saveCredential(credentialPayload(), { user: owner }); + await saveCredential(credentialPayload(), { user: ownerShell }); } - const member = await testDb.createUser(); + const member = await testDb.createUser({ globalRole: globalMemberRole }); await saveCredential(credentialPayload(), { user: member }); @@ -375,18 +383,20 @@ test('GET /credentials should retrieve all creds for owner', async () => { expect(response.statusCode).toBe(200); expect(response.body.data.length).toBe(4); // 3 owner + 1 member - for (const credential of response.body.data) { - const { name, type, nodesAccess, data: encryptedData } = credential; + await Promise.all( + response.body.data.map(async (credential: CredentialsEntity) => { + const { name, type, nodesAccess, data: encryptedData } = credential; - expect(typeof name).toBe('string'); - expect(typeof type).toBe('string'); - expect(typeof nodesAccess[0].nodeType).toBe('string'); - expect(encryptedData).toBeUndefined(); - } + expect(typeof name).toBe('string'); + expect(typeof type).toBe('string'); + expect(typeof nodesAccess[0].nodeType).toBe('string'); + expect(encryptedData).toBeUndefined(); + }), + ); }); test('GET /credentials should retrieve owned creds for member', async () => { - const member = await testDb.createUser(); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); for (let i = 0; i < 3; i++) { @@ -398,23 +408,25 @@ test('GET /credentials should retrieve owned creds for member', async () => { expect(response.statusCode).toBe(200); expect(response.body.data.length).toBe(3); - for (const credential of response.body.data) { - const { name, type, nodesAccess, data: encryptedData } = credential; + await Promise.all( + response.body.data.map(async (credential: CredentialsEntity) => { + const { name, type, nodesAccess, data: encryptedData } = credential; - expect(typeof name).toBe('string'); - expect(typeof type).toBe('string'); - expect(typeof nodesAccess[0].nodeType).toBe('string'); - expect(encryptedData).toBeUndefined(); - } + expect(typeof name).toBe('string'); + expect(typeof type).toBe('string'); + expect(typeof nodesAccess[0].nodeType).toBe('string'); + expect(encryptedData).toBeUndefined(); + }), + ); }); test('GET /credentials should not retrieve non-owned creds for member', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const member = await testDb.createUser(); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); for (let i = 0; i < 3; i++) { - await saveCredential(credentialPayload(), { user: owner }); + await saveCredential(credentialPayload(), { user: ownerShell }); } const response = await authMemberAgent.get('/credentials'); @@ -424,9 +436,9 @@ test('GET /credentials should not retrieve non-owned creds for member', async () }); test('GET /credentials/:id should retrieve owned cred for owner', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const savedCredential = await saveCredential(credentialPayload(), { user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const savedCredential = await saveCredential(credentialPayload(), { user: ownerShell }); const firstResponse = await authOwnerAgent.get(`/credentials/${savedCredential.id}`); @@ -449,7 +461,7 @@ test('GET /credentials/:id should retrieve owned cred for owner', async () => { }); test('GET /credentials/:id should retrieve owned cred for member', async () => { - const member = await testDb.createUser(); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const savedCredential = await saveCredential(credentialPayload(), { user: member }); @@ -475,10 +487,10 @@ test('GET /credentials/:id should retrieve owned cred for member', async () => { }); test('GET /credentials/:id should not retrieve non-owned cred for member', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const member = await testDb.createUser(); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); - const savedCredential = await saveCredential(credentialPayload(), { user: owner }); + const savedCredential = await saveCredential(credentialPayload(), { user: ownerShell }); const response = await authMemberAgent.get(`/credentials/${savedCredential.id}`); @@ -487,9 +499,9 @@ test('GET /credentials/:id should not retrieve non-owned cred for member', async }); test('GET /credentials/:id should fail with missing encryption key', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const savedCredential = await saveCredential(credentialPayload(), { user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); + const savedCredential = await saveCredential(credentialPayload(), { user: ownerShell }); const mock = jest.spyOn(UserSettings, 'getEncryptionKey'); mock.mockResolvedValue(undefined); @@ -504,8 +516,8 @@ test('GET /credentials/:id should fail with missing encryption key', async () => }); test('GET /credentials/:id should return 404 if cred not found', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authMemberAgent = utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authMemberAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const response = await authMemberAgent.get('/credentials/789'); diff --git a/packages/cli/test/integration/me.endpoints.test.ts b/packages/cli/test/integration/me.api.test.ts similarity index 88% rename from packages/cli/test/integration/me.endpoints.test.ts rename to packages/cli/test/integration/me.api.test.ts index d8bbd66592..85c435a5b8 100644 --- a/packages/cli/test/integration/me.endpoints.test.ts +++ b/packages/cli/test/integration/me.api.test.ts @@ -1,18 +1,21 @@ -import { hashSync, genSaltSync } from 'bcryptjs'; -import express = require('express'); +import express from 'express'; import validator from 'validator'; +import { IsNull } from 'typeorm'; -import config = require('../../config'); +import config from '../../config'; import * as utils from './shared/utils'; import { SUCCESS_RESPONSE_BODY } from './shared/constants'; import { Db } from '../../src'; -import { Role } from '../../src/databases/entities/Role'; +import type { Role } from '../../src/databases/entities/Role'; import { randomValidPassword, randomEmail, randomName, randomString } from './shared/random'; import * as testDb from './shared/testDb'; +jest.mock('../../src/telemetry'); + let app: express.Application; let testDbName = ''; let globalOwnerRole: Role; +let globalMemberRole: Role; beforeAll(async () => { app = utils.initTestServer({ endpointGroups: ['me'], applyAuth: true }); @@ -20,6 +23,7 @@ beforeAll(async () => { testDbName = initResult.testDbName; globalOwnerRole = await testDb.getGlobalOwnerRole(); + globalMemberRole = await testDb.getGlobalMemberRole(); utils.initTestLogger(); utils.initTestTelemetry(); }); @@ -30,15 +34,11 @@ afterAll(async () => { describe('Owner shell', () => { beforeEach(async () => { - await testDb.createOwnerShell(); - }); - - afterEach(async () => { await testDb.truncate(['User'], testDbName); }); test('GET /me should return sanitized owner shell', async () => { - const ownerShell = await Db.collections.User!.findOneOrFail(); + const ownerShell = await testDb.createUserShell(globalOwnerRole); const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const response = await authOwnerShellAgent.get('/me'); @@ -70,7 +70,7 @@ describe('Owner shell', () => { }); test('PATCH /me should succeed with valid inputs', async () => { - const ownerShell = await Db.collections.User!.findOneOrFail(); + const ownerShell = await testDb.createUserShell(globalOwnerRole); const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); for (const validPayload of VALID_PATCH_ME_PAYLOADS) { @@ -110,7 +110,7 @@ describe('Owner shell', () => { }); test('PATCH /me should fail with invalid inputs', async () => { - const ownerShell = await Db.collections.User!.findOneOrFail(); + const ownerShell = await testDb.createUserShell(globalOwnerRole); const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); for (const invalidPayload of INVALID_PATCH_ME_PAYLOADS) { @@ -125,7 +125,7 @@ describe('Owner shell', () => { }); test('PATCH /me/password should fail for shell', async () => { - const ownerShell = await Db.collections.User!.findOneOrFail(); + const ownerShell = await testDb.createUserShell(globalOwnerRole); const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const validPasswordPayload = { @@ -133,40 +133,46 @@ describe('Owner shell', () => { newPassword: randomValidPassword(), }; - const payloads = [validPasswordPayload, ...INVALID_PASSWORD_PAYLOADS]; + const validPayloads = [validPasswordPayload, ...INVALID_PASSWORD_PAYLOADS]; - for (const payload of payloads) { - const response = await authOwnerShellAgent.patch('/me/password').send(payload); - expect([400, 500].includes(response.statusCode)).toBe(true); + await Promise.all( + validPayloads.map(async (payload) => { + const response = await authOwnerShellAgent.patch('/me/password').send(payload); + expect([400, 500].includes(response.statusCode)).toBe(true); - const storedMember = await Db.collections.User!.findOneOrFail(); + const storedMember = await Db.collections.User!.findOneOrFail(); - if (payload.newPassword) { - expect(storedMember.password).not.toBe(payload.newPassword); - } - if (payload.currentPassword) { - expect(storedMember.password).not.toBe(payload.currentPassword); - } - } + if (payload.newPassword) { + expect(storedMember.password).not.toBe(payload.newPassword); + } + + if (payload.currentPassword) { + expect(storedMember.password).not.toBe(payload.currentPassword); + } + }), + ); const storedOwnerShell = await Db.collections.User!.findOneOrFail(); expect(storedOwnerShell.password).toBeNull(); }); test('POST /me/survey should succeed with valid inputs', async () => { - const ownerShell = await Db.collections.User!.findOneOrFail(); + const ownerShell = await testDb.createUserShell(globalOwnerRole); const authOwnerShellAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const validPayloads = [SURVEY, {}]; for (const validPayload of validPayloads) { const response = await authOwnerShellAgent.post('/me/survey').send(validPayload); + expect(response.statusCode).toBe(200); expect(response.body).toEqual(SUCCESS_RESPONSE_BODY); - const { personalizationAnswers: storedAnswers } = await Db.collections.User!.findOneOrFail(); + const storedShellOwner = await Db.collections.User!.findOneOrFail({ + where: { email: IsNull() }, + }); - expect(storedAnswers).toEqual(validPayload); + expect(storedShellOwner.personalizationAnswers).toEqual(validPayload); } }); }); @@ -186,7 +192,7 @@ describe('Member', () => { }); test('GET /me should return sanitized member', async () => { - const member = await testDb.createUser(); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const response = await authMemberAgent.get('/me'); @@ -218,7 +224,7 @@ describe('Member', () => { }); test('PATCH /me should succeed with valid inputs', async () => { - const member = await testDb.createUser(); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); for (const validPayload of VALID_PATCH_ME_PAYLOADS) { @@ -258,7 +264,7 @@ describe('Member', () => { }); test('PATCH /me should fail with invalid inputs', async () => { - const member = await testDb.createUser(); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); for (const invalidPayload of INVALID_PATCH_ME_PAYLOADS) { @@ -275,7 +281,8 @@ describe('Member', () => { test('PATCH /me/password should succeed with valid inputs', async () => { const memberPassword = randomValidPassword(); const member = await testDb.createUser({ - password: hashSync(memberPassword, genSaltSync(10)), + password: memberPassword, + globalRole: globalMemberRole, }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); @@ -294,7 +301,7 @@ describe('Member', () => { }); test('PATCH /me/password should fail with invalid inputs', async () => { - const member = await testDb.createUser(); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); for (const payload of INVALID_PASSWORD_PAYLOADS) { @@ -313,7 +320,7 @@ describe('Member', () => { }); test('POST /me/survey should succeed with valid inputs', async () => { - const member = await testDb.createUser(); + const member = await testDb.createUser({ globalRole: globalMemberRole }); const authMemberAgent = utils.createAgent(app, { auth: true, user: member }); const validPayloads = [SURVEY, {}]; diff --git a/packages/cli/test/integration/owner.endpoints.test.ts b/packages/cli/test/integration/owner.api.test.ts similarity index 63% rename from packages/cli/test/integration/owner.endpoints.test.ts rename to packages/cli/test/integration/owner.api.test.ts index 74e6ba3777..3f97f298b3 100644 --- a/packages/cli/test/integration/owner.endpoints.test.ts +++ b/packages/cli/test/integration/owner.api.test.ts @@ -1,34 +1,35 @@ -import express = require('express'); +import express from 'express'; import validator from 'validator'; import * as utils from './shared/utils'; import * as testDb from './shared/testDb'; import { Db } from '../../src'; -import config = require('../../config'); +import config from '../../config'; import { randomEmail, randomName, randomValidPassword, randomInvalidPassword, } from './shared/random'; +import type { Role } from '../../src/databases/entities/Role'; + +jest.mock('../../src/telemetry'); let app: express.Application; let testDbName = ''; +let globalOwnerRole: Role; beforeAll(async () => { app = utils.initTestServer({ endpointGroups: ['owner'], applyAuth: true }); const initResult = await testDb.init(); testDbName = initResult.testDbName; + globalOwnerRole = await testDb.getGlobalOwnerRole(); utils.initTestLogger(); utils.initTestTelemetry(); }); beforeEach(async () => { - await testDb.createOwnerShell(); -}); - -afterEach(async () => { await testDb.truncate(['User'], testDbName); }); @@ -37,10 +38,17 @@ afterAll(async () => { }); test('POST /owner should create owner and enable isInstanceOwnerSetUp', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - const response = await authOwnerAgent.post('/owner').send(TEST_USER); + const newOwnerData = { + email: randomEmail(), + firstName: randomName(), + lastName: randomName(), + password: randomValidPassword(), + }; + + const response = await authOwnerAgent.post('/owner').send(newOwnerData); expect(response.statusCode).toBe(200); @@ -57,9 +65,9 @@ test('POST /owner should create owner and enable isInstanceOwnerSetUp', async () } = response.body.data; expect(validator.isUUID(id)).toBe(true); - expect(email).toBe(TEST_USER.email); - expect(firstName).toBe(TEST_USER.firstName); - expect(lastName).toBe(TEST_USER.lastName); + expect(email).toBe(newOwnerData.email); + expect(firstName).toBe(newOwnerData.firstName); + expect(lastName).toBe(newOwnerData.lastName); expect(personalizationAnswers).toBeNull(); expect(password).toBeUndefined(); expect(isPending).toBe(false); @@ -68,12 +76,12 @@ test('POST /owner should create owner and enable isInstanceOwnerSetUp', async () expect(globalRole.scope).toBe('global'); const storedOwner = await Db.collections.User!.findOneOrFail(id); - expect(storedOwner.password).not.toBe(TEST_USER.password); - expect(storedOwner.email).toBe(TEST_USER.email); - expect(storedOwner.firstName).toBe(TEST_USER.firstName); - expect(storedOwner.lastName).toBe(TEST_USER.lastName); + expect(storedOwner.password).not.toBe(newOwnerData.password); + expect(storedOwner.email).toBe(newOwnerData.email); + expect(storedOwner.firstName).toBe(newOwnerData.firstName); + expect(storedOwner.lastName).toBe(newOwnerData.lastName); - const isInstanceOwnerSetUpConfig = config.get('userManagement.isInstanceOwnerSetUp'); + const isInstanceOwnerSetUpConfig = config.getEnv('userManagement.isInstanceOwnerSetUp'); expect(isInstanceOwnerSetUpConfig).toBe(true); const isInstanceOwnerSetUpSetting = await utils.isInstanceOwnerSetUp(); @@ -81,24 +89,26 @@ test('POST /owner should create owner and enable isInstanceOwnerSetUp', async () }); test('POST /owner should fail with invalid inputs', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = await utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); - for (const invalidPayload of INVALID_POST_OWNER_PAYLOADS) { - const response = await authOwnerAgent.post('/owner').send(invalidPayload); - expect(response.statusCode).toBe(400); - } + await Promise.all( + INVALID_POST_OWNER_PAYLOADS.map(async (invalidPayload) => { + const response = await authOwnerAgent.post('/owner').send(invalidPayload); + expect(response.statusCode).toBe(400); + }), + ); }); test('POST /owner/skip-setup should persist skipping setup to the DB', async () => { - const owner = await Db.collections.User!.findOneOrFail(); - const authOwnerAgent = await utils.createAgent(app, { auth: true, user: owner }); + const ownerShell = await testDb.createUserShell(globalOwnerRole); + const authOwnerAgent = utils.createAgent(app, { auth: true, user: ownerShell }); const response = await authOwnerAgent.post('/owner/skip-setup').send(); expect(response.statusCode).toBe(200); - const skipConfig = config.get('userManagement.skipInstanceOwnerSetup'); + const skipConfig = config.getEnv('userManagement.skipInstanceOwnerSetup'); expect(skipConfig).toBe(true); const { value } = await Db.collections.Settings!.findOneOrFail({ @@ -107,13 +117,6 @@ test('POST /owner/skip-setup should persist skipping setup to the DB', async () expect(value).toBe('true'); }); -const TEST_USER = { - email: randomEmail(), - firstName: randomName(), - lastName: randomName(), - password: randomValidPassword(), -}; - const INVALID_POST_OWNER_PAYLOADS = [ { email: '', diff --git a/packages/cli/test/integration/passwordReset.endpoints.test.ts b/packages/cli/test/integration/passwordReset.api.test.ts similarity index 59% rename from packages/cli/test/integration/passwordReset.endpoints.test.ts rename to packages/cli/test/integration/passwordReset.api.test.ts index 36dd7d8261..8b41428862 100644 --- a/packages/cli/test/integration/passwordReset.endpoints.test.ts +++ b/packages/cli/test/integration/passwordReset.api.test.ts @@ -1,9 +1,9 @@ -import express = require('express'); +import express from 'express'; import { v4 as uuid } from 'uuid'; import * as utils from './shared/utils'; import { Db } from '../../src'; -import config = require('../../config'); +import config from '../../config'; import { compare } from 'bcryptjs'; import { randomEmail, @@ -11,49 +11,35 @@ import { randomName, randomValidPassword, } from './shared/random'; -import { Role } from '../../src/databases/entities/Role'; import * as testDb from './shared/testDb'; +import type { Role } from '../../src/databases/entities/Role'; + +jest.mock('../../src/telemetry'); let app: express.Application; -let globalOwnerRole: Role; let testDbName = ''; +let globalOwnerRole: Role; beforeAll(async () => { app = utils.initTestServer({ endpointGroups: ['passwordReset'], applyAuth: true }); const initResult = await testDb.init(); testDbName = initResult.testDbName; - await testDb.truncate(['User'], testDbName); - - globalOwnerRole = await Db.collections.Role!.findOneOrFail({ - name: 'owner', - scope: 'global', - }); + globalOwnerRole = await testDb.getGlobalOwnerRole(); utils.initTestTelemetry(); utils.initTestLogger(); }); beforeEach(async () => { - jest.isolateModules(() => { - jest.mock('../../config'); - }); + await testDb.truncate(['User'], testDbName); + + jest.mock('../../config'); config.set('userManagement.isInstanceOwnerSetUp', true); config.set('userManagement.emails.mode', ''); - await testDb.createUser({ - id: INITIAL_TEST_USER.id, - email: INITIAL_TEST_USER.email, - password: INITIAL_TEST_USER.password, - firstName: INITIAL_TEST_USER.firstName, - lastName: INITIAL_TEST_USER.lastName, - globalRole: globalOwnerRole, - }); -}); - -afterEach(async () => { - await testDb.truncate(['User'], testDbName); + jest.setTimeout(30000); // fake SMTP service might be slow }); afterAll(async () => { @@ -61,47 +47,38 @@ afterAll(async () => { }); test('POST /forgot-password should send password reset email', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authlessAgent = utils.createAgent(app); - const { - user, - pass, - smtp: { host, port, secure }, - } = await utils.getSmtpTestAccount(); + await utils.configureSmtp(); - config.set('userManagement.emails.mode', 'smtp'); - config.set('userManagement.emails.smtp.host', host); - config.set('userManagement.emails.smtp.port', port); - config.set('userManagement.emails.smtp.secure', secure); - config.set('userManagement.emails.smtp.auth.user', user); - config.set('userManagement.emails.smtp.auth.pass', pass); - - const response = await authlessAgent - .post('/forgot-password') - .send({ email: INITIAL_TEST_USER.email }); + const response = await authlessAgent.post('/forgot-password').send({ email: owner.email }); expect(response.statusCode).toBe(200); expect(response.body).toEqual({}); - const owner = await Db.collections.User!.findOneOrFail({ email: INITIAL_TEST_USER.email }); - expect(owner.resetPasswordToken).toBeDefined(); - expect(owner.resetPasswordTokenExpiration).toBeGreaterThan(Math.ceil(Date.now() / 1000)); + const storedOwner = await Db.collections.User!.findOneOrFail({ email: owner.email }); + expect(storedOwner.resetPasswordToken).toBeDefined(); + expect(storedOwner.resetPasswordTokenExpiration).toBeGreaterThan(Math.ceil(Date.now() / 1000)); }); test('POST /forgot-password should fail if emailing is not set up', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authlessAgent = utils.createAgent(app); - const response = await authlessAgent - .post('/forgot-password') - .send({ email: INITIAL_TEST_USER.email }); + const response = await authlessAgent.post('/forgot-password').send({ email: owner.email }); expect(response.statusCode).toBe(500); - const owner = await Db.collections.User!.findOneOrFail({ email: INITIAL_TEST_USER.email }); - expect(owner.resetPasswordToken).toBeNull(); + const storedOwner = await Db.collections.User!.findOneOrFail({ email: owner.email }); + expect(storedOwner.resetPasswordToken).toBeNull(); }); test('POST /forgot-password should fail with invalid inputs', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authlessAgent = utils.createAgent(app); config.set('userManagement.emails.mode', 'smtp'); @@ -114,13 +91,15 @@ test('POST /forgot-password should fail with invalid inputs', async () => { [{ email: randomName() }], ]; - for (const invalidPayload of invalidPayloads) { - const response = await authlessAgent.post('/forgot-password').send(invalidPayload); - expect(response.statusCode).toBe(400); + await Promise.all( + invalidPayloads.map(async (invalidPayload) => { + const response = await authlessAgent.post('/forgot-password').send(invalidPayload); + expect(response.statusCode).toBe(400); - const owner = await Db.collections.User!.findOneOrFail({ email: INITIAL_TEST_USER.email }); - expect(owner.resetPasswordToken).toBeNull(); - } + const storedOwner = await Db.collections.User!.findOneOrFail({ email: owner.email }); + expect(storedOwner.resetPasswordToken).toBeNull(); + }), + ); }); test('POST /forgot-password should fail if user is not found', async () => { @@ -130,38 +109,39 @@ test('POST /forgot-password should fail if user is not found', async () => { const response = await authlessAgent.post('/forgot-password').send({ email: randomEmail() }); - // response should have 200 to not provide any information to the requester - expect(response.statusCode).toBe(200); + expect(response.statusCode).toBe(200); // expect 200 to remain vague }); test('GET /resolve-password-token should succeed with valid inputs', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authlessAgent = utils.createAgent(app); const resetPasswordToken = uuid(); const resetPasswordTokenExpiration = Math.floor(Date.now() / 1000) + 100; - await Db.collections.User!.update(INITIAL_TEST_USER.id, { + await Db.collections.User!.update(owner.id, { resetPasswordToken, resetPasswordTokenExpiration, }); const response = await authlessAgent .get('/resolve-password-token') - .query({ userId: INITIAL_TEST_USER.id, token: resetPasswordToken }); + .query({ userId: owner.id, token: resetPasswordToken }); expect(response.statusCode).toBe(200); }); test('GET /resolve-password-token should fail with invalid inputs', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authlessAgent = utils.createAgent(app); config.set('userManagement.emails.mode', 'smtp'); const first = await authlessAgent.get('/resolve-password-token').query({ token: uuid() }); - const second = await authlessAgent - .get('/resolve-password-token') - .query({ userId: INITIAL_TEST_USER.id }); + const second = await authlessAgent.get('/resolve-password-token').query({ userId: owner.id }); for (const response of [first, second]) { expect(response.statusCode).toBe(400); @@ -169,24 +149,28 @@ test('GET /resolve-password-token should fail with invalid inputs', async () => }); test('GET /resolve-password-token should fail if user is not found', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authlessAgent = utils.createAgent(app); config.set('userManagement.emails.mode', 'smtp'); const response = await authlessAgent .get('/resolve-password-token') - .query({ userId: INITIAL_TEST_USER.id, token: uuid() }); + .query({ userId: owner.id, token: uuid() }); expect(response.statusCode).toBe(404); }); test('GET /resolve-password-token should fail if token is expired', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authlessAgent = utils.createAgent(app); const resetPasswordToken = uuid(); const resetPasswordTokenExpiration = Math.floor(Date.now() / 1000) - 1; - await Db.collections.User!.update(INITIAL_TEST_USER.id, { + await Db.collections.User!.update(owner.id, { resetPasswordToken, resetPasswordTokenExpiration, }); @@ -195,18 +179,20 @@ test('GET /resolve-password-token should fail if token is expired', async () => const response = await authlessAgent .get('/resolve-password-token') - .query({ userId: INITIAL_TEST_USER.id, token: resetPasswordToken }); + .query({ userId: owner.id, token: resetPasswordToken }); expect(response.statusCode).toBe(404); }); test('POST /change-password should succeed with valid inputs', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authlessAgent = utils.createAgent(app); const resetPasswordToken = uuid(); const resetPasswordTokenExpiration = Math.floor(Date.now() / 1000) + 100; - await Db.collections.User!.update(INITIAL_TEST_USER.id, { + await Db.collections.User!.update(owner.id, { resetPasswordToken, resetPasswordTokenExpiration, }); @@ -215,7 +201,7 @@ test('POST /change-password should succeed with valid inputs', async () => { const response = await authlessAgent.post('/change-password').send({ token: resetPasswordToken, - userId: INITIAL_TEST_USER.id, + userId: owner.id, password: passwordToStore, }); @@ -224,63 +210,65 @@ test('POST /change-password should succeed with valid inputs', async () => { const authToken = utils.getAuthToken(response); expect(authToken).toBeDefined(); - const { password: storedPassword } = await Db.collections.User!.findOneOrFail( - INITIAL_TEST_USER.id, - ); + const { password: storedPassword } = await Db.collections.User!.findOneOrFail(owner.id); - const comparisonResult = await compare(passwordToStore, storedPassword!); + const comparisonResult = await compare(passwordToStore, storedPassword); expect(comparisonResult).toBe(true); expect(storedPassword).not.toBe(passwordToStore); }); test('POST /change-password should fail with invalid inputs', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authlessAgent = utils.createAgent(app); const resetPasswordToken = uuid(); const resetPasswordTokenExpiration = Math.floor(Date.now() / 1000) + 100; - await Db.collections.User!.update(INITIAL_TEST_USER.id, { + await Db.collections.User!.update(owner.id, { resetPasswordToken, resetPasswordTokenExpiration, }); const invalidPayloads = [ { token: uuid() }, - { id: INITIAL_TEST_USER.id }, + { id: owner.id }, { password: randomValidPassword() }, - { token: uuid(), id: INITIAL_TEST_USER.id }, + { token: uuid(), id: owner.id }, { token: uuid(), password: randomValidPassword() }, - { id: INITIAL_TEST_USER.id, password: randomValidPassword() }, + { id: owner.id, password: randomValidPassword() }, { - id: INITIAL_TEST_USER.id, + id: owner.id, password: randomInvalidPassword(), token: resetPasswordToken, }, { - id: INITIAL_TEST_USER.id, + id: owner.id, password: randomValidPassword(), token: uuid(), }, ]; - const { password: originalHashedPassword } = await Db.collections.User!.findOneOrFail(); + await Promise.all( + invalidPayloads.map(async (invalidPayload) => { + const response = await authlessAgent.post('/change-password').query(invalidPayload); + expect(response.statusCode).toBe(400); - for (const invalidPayload of invalidPayloads) { - const response = await authlessAgent.post('/change-password').query(invalidPayload); - expect(response.statusCode).toBe(400); - - const { password: fetchedHashedPassword } = await Db.collections.User!.findOneOrFail(); - expect(originalHashedPassword).toBe(fetchedHashedPassword); - } + const { password: storedPassword } = await Db.collections.User!.findOneOrFail(); + expect(owner.password).toBe(storedPassword); + }), + ); }); test('POST /change-password should fail when token has expired', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authlessAgent = utils.createAgent(app); const resetPasswordToken = uuid(); const resetPasswordTokenExpiration = Math.floor(Date.now() / 1000) - 1; - await Db.collections.User!.update(INITIAL_TEST_USER.id, { + await Db.collections.User!.update(owner.id, { resetPasswordToken, resetPasswordTokenExpiration, }); @@ -289,17 +277,9 @@ test('POST /change-password should fail when token has expired', async () => { const response = await authlessAgent.post('/change-password').send({ token: resetPasswordToken, - userId: INITIAL_TEST_USER.id, + userId: owner.id, password: passwordToStore, }); expect(response.statusCode).toBe(404); }); - -const INITIAL_TEST_USER = { - id: uuid(), - email: randomEmail(), - firstName: randomName(), - lastName: randomName(), - password: randomValidPassword(), -}; diff --git a/packages/cli/test/integration/shared/constants.ts b/packages/cli/test/integration/shared/constants.ts index 99c624efb4..03865412d0 100644 --- a/packages/cli/test/integration/shared/constants.ts +++ b/packages/cli/test/integration/shared/constants.ts @@ -1,13 +1,13 @@ -import config = require('../../../config'); +import config from '../../../config'; -export const REST_PATH_SEGMENT = config.get('endpoints.rest') as Readonly; +export const REST_PATH_SEGMENT = config.getEnv('endpoints.rest') as Readonly; export const AUTHLESS_ENDPOINTS: Readonly = [ 'healthz', 'metrics', - config.get('endpoints.webhook') as string, - config.get('endpoints.webhookWaiting') as string, - config.get('endpoints.webhookTest') as string, + config.getEnv('endpoints.webhook'), + config.getEnv('endpoints.webhookWaiting'), + config.getEnv('endpoints.webhookTest'), ]; export const SUCCESS_RESPONSE_BODY = { diff --git a/packages/cli/test/integration/shared/random.ts b/packages/cli/test/integration/shared/random.ts index 4a531aba3b..68ea41cce7 100644 --- a/packages/cli/test/integration/shared/random.ts +++ b/packages/cli/test/integration/shared/random.ts @@ -17,7 +17,7 @@ const randomDigit = () => Math.floor(Math.random() * 10); const randomUppercaseLetter = () => chooseRandomly('ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')); export const randomValidPassword = () => - randomString(MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH) + randomUppercaseLetter() + randomDigit(); + randomString(MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH - 2) + randomUppercaseLetter() + randomDigit(); export const randomInvalidPassword = () => chooseRandomly([ diff --git a/packages/cli/test/integration/shared/testDb.ts b/packages/cli/test/integration/shared/testDb.ts index 7c64dcfd90..3ad2dcfc56 100644 --- a/packages/cli/test/integration/shared/testDb.ts +++ b/packages/cli/test/integration/shared/testDb.ts @@ -1,27 +1,28 @@ -import { createConnection, getConnection, ConnectionOptions } from 'typeorm'; +import { createConnection, getConnection, ConnectionOptions, Connection } from 'typeorm'; import { Credentials, UserSettings } from 'n8n-core'; -import config = require('../../../config'); +import config from '../../../config'; import { BOOTSTRAP_MYSQL_CONNECTION_NAME, BOOTSTRAP_POSTGRES_CONNECTION_NAME } from './constants'; import { DatabaseType, Db, ICredentialsDb, IDatabaseCollections } from '../../../src'; import { randomEmail, randomName, randomString, randomValidPassword } from './random'; import { CredentialsEntity } from '../../../src/databases/entities/CredentialsEntity'; - +import { hashPassword } from '../../../src/UserManagement/UserManagementHelper'; import { RESPONSE_ERROR_MESSAGES } from '../../../src/constants'; import { entities } from '../../../src/databases/entities'; import { mysqlMigrations } from '../../../src/databases/mysqldb/migrations'; import { postgresMigrations } from '../../../src/databases/postgresdb/migrations'; import { sqliteMigrations } from '../../../src/databases/sqlite/migrations'; +import { categorize } from './utils'; import type { Role } from '../../../src/databases/entities/Role'; import type { User } from '../../../src/databases/entities/User'; -import type { CredentialPayload } from './types'; +import type { CollectionName, CredentialPayload } from './types'; /** * Initialize one test DB per suite run, with bootstrap connection if needed. */ export async function init() { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); if (dbType === 'sqlite') { // no bootstrap connection required @@ -72,7 +73,7 @@ export async function init() { * Drop test DB, closing bootstrap connection if existing. */ export async function terminate(testDbName: string) { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); if (dbType === 'sqlite') { await getConnection(testDbName).close(); @@ -96,22 +97,49 @@ export async function terminate(testDbName: string) { } /** - * Truncate DB tables for specified entities. + * Truncate DB tables for collections. * - * @param entities Array of entity names whose tables to truncate. + * @param collections Array of entity names whose tables to truncate. * @param testDbName Name of the test DB to truncate tables in. */ -export async function truncate(entities: Array, testDbName: string) { - const dbType = config.get('database.type'); +export async function truncate(collections: CollectionName[], testDbName: string) { + const dbType = config.getEnv('database.type'); + + const testDb = getConnection(testDbName); if (dbType === 'sqlite') { - const testDb = getConnection(testDbName); await testDb.query('PRAGMA foreign_keys=OFF'); - await Promise.all(entities.map((entity) => Db.collections[entity]!.clear())); + await Promise.all(collections.map((collection) => Db.collections[collection]!.clear())); return testDb.query('PRAGMA foreign_keys=ON'); } - const map: { [K in keyof IDatabaseCollections]: string } = { + if (dbType === 'postgresdb') { + return Promise.all( + collections.map((collection) => { + const tableName = toTableName(collection); + testDb.query(`TRUNCATE TABLE "${tableName}" RESTART IDENTITY CASCADE;`); + }), + ); + } + + /** + * MySQL `TRUNCATE` requires enabling and disabling the global variable `foreign_key_checks`, + * which cannot be safely manipulated by parallel tests, so use `DELETE` and `AUTO_INCREMENT`. + * Clear shared tables first to avoid deadlock: https://stackoverflow.com/a/41174997 + */ + if (dbType === 'mysqldb') { + const { pass: isShared, fail: isNotShared } = categorize( + collections, + (collectionName: CollectionName) => collectionName.toLowerCase().startsWith('shared'), + ); + + await truncateMySql(testDb, isShared); + await truncateMySql(testDb, isNotShared); + } +} + +function toTableName(collectionName: CollectionName) { + return { Credentials: 'credentials_entity', Workflow: 'workflow_entity', Execution: 'execution_entity', @@ -122,27 +150,17 @@ export async function truncate(entities: Array, test SharedCredentials: 'shared_credentials', SharedWorkflow: 'shared_workflow', Settings: 'settings', - }; + }[collectionName]; +} - if (dbType === 'postgresdb') { - return Promise.all( - entities.map((entity) => - getConnection(testDbName).query( - `TRUNCATE TABLE "${map[entity]}" RESTART IDENTITY CASCADE;`, - ), - ), - ); - } - - // MySQL truncation requires globals, which cannot be safely manipulated by parallel tests - if (dbType === 'mysqldb') { - await Promise.all( - entities.map(async (entity) => { - await Db.collections[entity]!.delete({}); - await getConnection(testDbName).query(`ALTER TABLE ${map[entity]} AUTO_INCREMENT = 1;`); - }), - ); - } +function truncateMySql(connection: Connection, collections: Array) { + return Promise.all( + collections.map(async (collection) => { + const tableName = toTableName(collection); + await connection.query(`DELETE FROM ${tableName};`); + await connection.query(`ALTER TABLE ${tableName} AUTO_INCREMENT = 1;`); + }), + ); } // ---------------------------------- @@ -178,63 +196,65 @@ export async function saveCredential( } // ---------------------------------- -// user creation +// user creation // ---------------------------------- -/** - * Store a user in the DB, defaulting to a `member`. - */ -export async function createUser(attributes: Partial = {}): Promise { +export async function createUser(attributes: Partial & { globalRole: Role }): Promise { const { email, password, firstName, lastName, globalRole, ...rest } = attributes; + const user = { email: email ?? randomEmail(), - password: password ?? randomValidPassword(), + password: await hashPassword(password ?? randomValidPassword()), firstName: firstName ?? randomName(), lastName: lastName ?? randomName(), - globalRole: globalRole ?? (await getGlobalMemberRole()), + globalRole, ...rest, }; return Db.collections.User!.save(user); } -export async function createOwnerShell() { - const globalRole = await getGlobalOwnerRole(); - return Db.collections.User!.save({ globalRole }); -} +export function createUserShell(globalRole: Role): Promise { + if (globalRole.scope !== 'global') { + throw new Error(`Invalid role received: ${JSON.stringify(globalRole)}`); + } -export async function createMemberShell() { - const globalRole = await getGlobalMemberRole(); - return Db.collections.User!.save({ globalRole }); + const shell: Partial = { globalRole }; + + if (globalRole.name !== 'owner') { + shell.email = randomEmail(); + } + + return Db.collections.User!.save(shell); } // ---------------------------------- // role fetchers // ---------------------------------- -export async function getGlobalOwnerRole() { - return await Db.collections.Role!.findOneOrFail({ +export function getGlobalOwnerRole() { + return Db.collections.Role!.findOneOrFail({ name: 'owner', scope: 'global', }); } -export async function getGlobalMemberRole() { - return await Db.collections.Role!.findOneOrFail({ +export function getGlobalMemberRole() { + return Db.collections.Role!.findOneOrFail({ name: 'member', scope: 'global', }); } -export async function getWorkflowOwnerRole() { - return await Db.collections.Role!.findOneOrFail({ +export function getWorkflowOwnerRole() { + return Db.collections.Role!.findOneOrFail({ name: 'owner', scope: 'workflow', }); } -export async function getCredentialOwnerRole() { - return await Db.collections.Role!.findOneOrFail({ +export function getCredentialOwnerRole() { + return Db.collections.Role!.findOneOrFail({ name: 'owner', scope: 'credential', }); @@ -275,11 +295,11 @@ export const getSqliteOptions = ({ name }: { name: string }): ConnectionOptions * to create and drop test Postgres databases. */ export const getBootstrapPostgresOptions = () => { - const username = config.get('database.postgresdb.user'); - const password = config.get('database.postgresdb.password'); - const host = config.get('database.postgresdb.host'); - const port = config.get('database.postgresdb.port'); - const schema = config.get('database.postgresdb.schema'); + const username = config.getEnv('database.postgresdb.user'); + const password = config.getEnv('database.postgresdb.password'); + const host = config.getEnv('database.postgresdb.host'); + const port = config.getEnv('database.postgresdb.port'); + const schema = config.getEnv('database.postgresdb.schema'); return { name: BOOTSTRAP_POSTGRES_CONNECTION_NAME, @@ -294,11 +314,11 @@ export const getBootstrapPostgresOptions = () => { }; export const getPostgresOptions = ({ name }: { name: string }): ConnectionOptions => { - const username = config.get('database.postgresdb.user'); - const password = config.get('database.postgresdb.password'); - const host = config.get('database.postgresdb.host'); - const port = config.get('database.postgresdb.port'); - const schema = config.get('database.postgresdb.schema'); + const username = config.getEnv('database.postgresdb.user'); + const password = config.getEnv('database.postgresdb.password'); + const host = config.getEnv('database.postgresdb.host'); + const port = config.getEnv('database.postgresdb.port'); + const schema = config.getEnv('database.postgresdb.schema'); return { name, @@ -325,10 +345,10 @@ export const getPostgresOptions = ({ name }: { name: string }): ConnectionOption * to create and drop test MySQL databases. */ export const getBootstrapMySqlOptions = (): ConnectionOptions => { - const username = config.get('database.mysqldb.user'); - const password = config.get('database.mysqldb.password'); - const host = config.get('database.mysqldb.host'); - const port = config.get('database.mysqldb.port'); + const username = config.getEnv('database.mysqldb.user'); + const password = config.getEnv('database.mysqldb.password'); + const host = config.getEnv('database.mysqldb.host'); + const port = config.getEnv('database.mysqldb.port'); return { name: BOOTSTRAP_MYSQL_CONNECTION_NAME, @@ -346,10 +366,10 @@ export const getBootstrapMySqlOptions = (): ConnectionOptions => { * one per test suite run. */ export const getMySqlOptions = ({ name }: { name: string }): ConnectionOptions => { - const username = config.get('database.mysqldb.user'); - const password = config.get('database.mysqldb.password'); - const host = config.get('database.mysqldb.host'); - const port = config.get('database.mysqldb.port'); + const username = config.getEnv('database.mysqldb.user'); + const password = config.getEnv('database.mysqldb.password'); + const host = config.getEnv('database.mysqldb.host'); + const port = config.getEnv('database.mysqldb.port'); return { name, diff --git a/packages/cli/test/integration/shared/types.d.ts b/packages/cli/test/integration/shared/types.d.ts index b160faea01..bca1c86fbc 100644 --- a/packages/cli/test/integration/shared/types.d.ts +++ b/packages/cli/test/integration/shared/types.d.ts @@ -1,8 +1,10 @@ import type { ICredentialDataDecryptedObject, ICredentialNodeAccess } from 'n8n-workflow'; -import type { ICredentialsDb } from '../../../src'; +import type { ICredentialsDb, IDatabaseCollections } from '../../../src'; import type { CredentialsEntity } from '../../../src/databases/entities/CredentialsEntity'; import type { User } from '../../../src/databases/entities/User'; +export type CollectionName = keyof IDatabaseCollections; + export type SmtpTestAccount = { user: string; pass: string; diff --git a/packages/cli/test/integration/shared/utils.ts b/packages/cli/test/integration/shared/utils.ts index 45f97cfabf..4127eb98db 100644 --- a/packages/cli/test/integration/shared/utils.ts +++ b/packages/cli/test/integration/shared/utils.ts @@ -1,16 +1,16 @@ import { randomBytes } from 'crypto'; import { existsSync } from 'fs'; -import express = require('express'); -import * as superagent from 'superagent'; -import * as request from 'supertest'; +import express from 'express'; +import superagent from 'superagent'; +import request from 'supertest'; import { URL } from 'url'; -import bodyParser = require('body-parser'); -import * as util from 'util'; +import bodyParser from 'body-parser'; +import util from 'util'; import { createTestAccount } from 'nodemailer'; import { INodeTypes, LoggerProxy } from 'n8n-workflow'; import { UserSettings } from 'n8n-core'; -import config = require('../../../config'); +import config from '../../../config'; import { AUTHLESS_ENDPOINTS, REST_PATH_SEGMENT } from './constants'; import { AUTH_COOKIE_NAME } from '../../../src/constants'; import { addRoutes as authMiddleware } from '../../../src/UserManagement/routes'; @@ -23,9 +23,7 @@ import { passwordResetNamespace as passwordResetEndpoints } from '../../../src/U import { issueJWT } from '../../../src/UserManagement/auth/jwt'; import { getLogger } from '../../../src/Logger'; import { credentialsController } from '../../../src/api/credentials.api'; - import type { User } from '../../../src/databases/entities/User'; -import { Telemetry } from '../../../src/telemetry'; import type { EndpointGroup, SmtpTestAccount } from './types'; import type { N8nApp } from '../../../src/UserManagement/Interfaces'; @@ -89,12 +87,13 @@ export function initTestServer({ return testServer.app; } +/** + * Pre-requisite: Mock the telemetry module before calling. + */ export function initTestTelemetry() { const mockNodeTypes = { nodeTypes: {} } as INodeTypes; void InternalHooksManager.init('test-instance-id', 'test-version', mockNodeTypes); - - jest.spyOn(Telemetry.prototype, 'track').mockResolvedValue(); } /** @@ -117,10 +116,9 @@ const classifyEndpointGroups = (endpointGroups: string[]) => { // ---------------------------------- /** - * Initialize a silent logger for test runs. + * Initialize a logger for test runs. */ export function initTestLogger() { - config.set('logs.output', 'file'); // declutter console output LoggerProxy.init(getLogger()); } @@ -182,9 +180,7 @@ export function prefix(pathSegment: string) { export function getAuthToken(response: request.Response, authCookieName = AUTH_COOKIE_NAME) { const cookies: string[] = response.headers['set-cookie']; - if (!cookies) { - throw new Error("No 'set-cookie' header found in response"); - } + if (!cookies) return undefined; const authCookie = cookies.find((c) => c.startsWith(`${authCookieName}=`)); @@ -216,5 +212,37 @@ export async function isInstanceOwnerSetUp() { /** * Get an SMTP test account from https://ethereal.email to test sending emails. */ -export const getSmtpTestAccount = util.promisify(createTestAccount); +const getSmtpTestAccount = util.promisify(createTestAccount); +export async function configureSmtp() { + const { + user, + pass, + smtp: { host, port, secure }, + } = await getSmtpTestAccount(); + + config.set('userManagement.emails.mode', 'smtp'); + config.set('userManagement.emails.smtp.host', host); + config.set('userManagement.emails.smtp.port', port); + config.set('userManagement.emails.smtp.secure', secure); + config.set('userManagement.emails.smtp.auth.user', user); + config.set('userManagement.emails.smtp.auth.pass', pass); +} + +// ---------------------------------- +// misc +// ---------------------------------- + +/** + * Categorize array items into two groups based on whether they pass a test. + */ +export const categorize = (arr: T[], test: (str: T) => boolean) => { + return arr.reduce<{ pass: T[]; fail: T[] }>( + (acc, cur) => { + test(cur) ? acc.pass.push(cur) : acc.fail.push(cur); + + return acc; + }, + { pass: [], fail: [] }, + ); +}; diff --git a/packages/cli/test/integration/users.endpoints.test.ts b/packages/cli/test/integration/users.api.test.ts similarity index 59% rename from packages/cli/test/integration/users.endpoints.test.ts rename to packages/cli/test/integration/users.api.test.ts index 7760e57363..eaee6d4db8 100644 --- a/packages/cli/test/integration/users.endpoints.test.ts +++ b/packages/cli/test/integration/users.api.test.ts @@ -1,12 +1,10 @@ -import express = require('express'); +import express from 'express'; import validator from 'validator'; import { v4 as uuid } from 'uuid'; -import { compare } from 'bcryptjs'; import { Db } from '../../src'; -import config = require('../../config'); +import config from '../../config'; import { SUCCESS_RESPONSE_BODY } from './shared/constants'; -import { Role } from '../../src/databases/entities/Role'; import { randomEmail, randomValidPassword, @@ -15,13 +13,18 @@ import { } from './shared/random'; import { CredentialsEntity } from '../../src/databases/entities/CredentialsEntity'; import { WorkflowEntity } from '../../src/databases/entities/WorkflowEntity'; +import type { Role } from '../../src/databases/entities/Role'; +import type { User } from '../../src/databases/entities/User'; import * as utils from './shared/utils'; import * as testDb from './shared/testDb'; +import { compareHash } from '../../src/UserManagement/UserManagementHelper'; + +jest.mock('../../src/telemetry'); let app: express.Application; let testDbName = ''; -let globalOwnerRole: Role; let globalMemberRole: Role; +let globalOwnerRole: Role; let workflowOwnerRole: Role; let credentialOwnerRole: Role; @@ -44,25 +47,17 @@ beforeAll(async () => { utils.initTestTelemetry(); utils.initTestLogger(); + + jest.setTimeout(30000); // fake SMTP service might be slow }); beforeEach(async () => { - // do not combine calls - shared tables must be cleared first and separately - await testDb.truncate(['SharedCredentials', 'SharedWorkflow'], testDbName); - await testDb.truncate(['User', 'Workflow', 'Credentials'], testDbName); + await testDb.truncate( + ['User', 'SharedCredentials', 'SharedWorkflow', 'Workflow', 'Credentials'], + testDbName, + ); - jest.isolateModules(() => { - jest.mock('../../config'); - }); - - await testDb.createUser({ - id: INITIAL_TEST_USER.id, - email: INITIAL_TEST_USER.email, - password: INITIAL_TEST_USER.password, - firstName: INITIAL_TEST_USER.firstName, - lastName: INITIAL_TEST_USER.lastName, - globalRole: globalOwnerRole, - }); + jest.mock('../../config'); config.set('userManagement.disabled', false); config.set('userManagement.isInstanceOwnerSetUp', true); @@ -74,46 +69,48 @@ afterAll(async () => { }); test('GET /users should return all users', async () => { - const owner = await Db.collections.User!.findOneOrFail(); + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - await testDb.createUser(); + await testDb.createUser({ globalRole: globalMemberRole }); const response = await authOwnerAgent.get('/users'); expect(response.statusCode).toBe(200); expect(response.body.data.length).toBe(2); - for (const user of response.body.data) { - const { - id, - email, - firstName, - lastName, - personalizationAnswers, - globalRole, - password, - resetPasswordToken, - isPending, - } = user; + await Promise.all( + response.body.data.map(async (user: User) => { + const { + id, + email, + firstName, + lastName, + personalizationAnswers, + globalRole, + password, + resetPasswordToken, + isPending, + } = user; - expect(validator.isUUID(id)).toBe(true); - expect(email).toBeDefined(); - expect(firstName).toBeDefined(); - expect(lastName).toBeDefined(); - expect(personalizationAnswers).toBeUndefined(); - expect(password).toBeUndefined(); - expect(resetPasswordToken).toBeUndefined(); - expect(isPending).toBe(false); - expect(globalRole).toBeDefined(); - } + expect(validator.isUUID(id)).toBe(true); + expect(email).toBeDefined(); + expect(firstName).toBeDefined(); + expect(lastName).toBeDefined(); + expect(personalizationAnswers).toBeUndefined(); + expect(password).toBeUndefined(); + expect(resetPasswordToken).toBeUndefined(); + expect(isPending).toBe(false); + expect(globalRole).toBeDefined(); + }), + ); }); test('DELETE /users/:id should delete the user', async () => { - const owner = await Db.collections.User!.findOneOrFail(); + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const userToDelete = await testDb.createUser(); + const userToDelete = await testDb.createUser({ globalRole: globalMemberRole }); const newWorkflow = new WorkflowEntity(); @@ -179,7 +176,7 @@ test('DELETE /users/:id should delete the user', async () => { }); test('DELETE /users/:id should fail to delete self', async () => { - const owner = await Db.collections.User!.findOneOrFail(); + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); const response = await authOwnerAgent.delete(`/users/${owner.id}`); @@ -191,10 +188,10 @@ test('DELETE /users/:id should fail to delete self', async () => { }); test('DELETE /users/:id should fail if user to delete is transferee', async () => { - const owner = await Db.collections.User!.findOneOrFail(); + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const { id: idToDelete } = await testDb.createUser(); + const { id: idToDelete } = await testDb.createUser({ globalRole: globalMemberRole }); const response = await authOwnerAgent.delete(`/users/${idToDelete}`).query({ transferId: idToDelete, @@ -207,7 +204,7 @@ test('DELETE /users/:id should fail if user to delete is transferee', async () = }); test('DELETE /users/:id with transferId should perform transfer', async () => { - const owner = await Db.collections.User!.findOneOrFail(); + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); const userToDelete = await Db.collections.User!.save({ @@ -279,36 +276,34 @@ test('DELETE /users/:id with transferId should perform transfer', async () => { }); test('GET /resolve-signup-token should validate invite token', async () => { - const owner = await Db.collections.User!.findOneOrFail(); + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const { id: inviteeId } = await testDb.createMemberShell(); + const memberShell = await testDb.createUserShell(globalMemberRole); const response = await authOwnerAgent .get('/resolve-signup-token') - .query({ inviterId: INITIAL_TEST_USER.id }) - .query({ inviteeId }); + .query({ inviterId: owner.id }) + .query({ inviteeId: memberShell.id }); expect(response.statusCode).toBe(200); expect(response.body).toEqual({ data: { inviter: { - firstName: INITIAL_TEST_USER.firstName, - lastName: INITIAL_TEST_USER.lastName, + firstName: owner.firstName, + lastName: owner.lastName, }, }, }); }); test('GET /resolve-signup-token should fail with invalid inputs', async () => { - const owner = await Db.collections.User!.findOneOrFail(); + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const { id: inviteeId } = await testDb.createUser(); + const { id: inviteeId } = await testDb.createUser({ globalRole: globalMemberRole }); - const first = await authOwnerAgent - .get('/resolve-signup-token') - .query({ inviterId: INITIAL_TEST_USER.id }); + const first = await authOwnerAgent.get('/resolve-signup-token').query({ inviterId: owner.id }); const second = await authOwnerAgent.get('/resolve-signup-token').query({ inviteeId }); @@ -320,14 +315,14 @@ test('GET /resolve-signup-token should fail with invalid inputs', async () => { // user is already set up, so call should error const fourth = await authOwnerAgent .get('/resolve-signup-token') - .query({ inviterId: INITIAL_TEST_USER.id }) + .query({ inviterId: owner.id }) .query({ inviteeId }); // cause inconsistent DB state await Db.collections.User!.update(owner.id, { email: '' }); const fifth = await authOwnerAgent .get('/resolve-signup-token') - .query({ inviterId: INITIAL_TEST_USER.id }) + .query({ inviterId: owner.id }) .query({ inviteeId }); for (const response of [first, second, third, fourth, fifth]) { @@ -336,21 +331,20 @@ test('GET /resolve-signup-token should fail with invalid inputs', async () => { }); test('POST /users/:id should fill out a user shell', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + + const memberShell = await testDb.createUserShell(globalMemberRole); + + const memberData = { + inviterId: owner.id, + firstName: randomName(), + lastName: randomName(), + password: randomValidPassword(), + }; + const authlessAgent = utils.createAgent(app); - const userToFillOut = await Db.collections.User!.save({ - email: randomEmail(), - globalRole: globalMemberRole, - }); - - const newPassword = randomValidPassword(); - - const response = await authlessAgent.post(`/users/${userToFillOut.id}`).send({ - inviterId: INITIAL_TEST_USER.id, - firstName: INITIAL_TEST_USER.firstName, - lastName: INITIAL_TEST_USER.lastName, - password: newPassword, - }); + const response = await authlessAgent.post(`/users/${memberShell.id}`).send(memberData); const { id, @@ -366,8 +360,8 @@ test('POST /users/:id should fill out a user shell', async () => { expect(validator.isUUID(id)).toBe(true); expect(email).toBeDefined(); - expect(firstName).toBe(INITIAL_TEST_USER.firstName); - expect(lastName).toBe(INITIAL_TEST_USER.lastName); + expect(firstName).toBe(memberData.firstName); + expect(lastName).toBe(memberData.lastName); expect(personalizationAnswers).toBeNull(); expect(password).toBeUndefined(); expect(resetPasswordToken).toBeUndefined(); @@ -377,69 +371,98 @@ test('POST /users/:id should fill out a user shell', async () => { const authToken = utils.getAuthToken(response); expect(authToken).toBeDefined(); - const filledOutUser = await Db.collections.User!.findOneOrFail(userToFillOut.id); - expect(filledOutUser.firstName).toBe(INITIAL_TEST_USER.firstName); - expect(filledOutUser.lastName).toBe(INITIAL_TEST_USER.lastName); - expect(filledOutUser.password).not.toBe(newPassword); + const member = await Db.collections.User!.findOneOrFail(memberShell.id); + expect(member.firstName).toBe(memberData.firstName); + expect(member.lastName).toBe(memberData.lastName); + expect(member.password).not.toBe(memberData.password); }); test('POST /users/:id should fail with invalid inputs', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const authlessAgent = utils.createAgent(app); - const emailToStore = randomEmail(); + const memberShellEmail = randomEmail(); - const userToFillOut = await Db.collections.User!.save({ - email: emailToStore, + const memberShell = await Db.collections.User!.save({ + email: memberShellEmail, globalRole: globalMemberRole, }); - for (const invalidPayload of INVALID_FILL_OUT_USER_PAYLOADS) { - const response = await authlessAgent.post(`/users/${userToFillOut.id}`).send(invalidPayload); - expect(response.statusCode).toBe(400); + const invalidPayloads = [ + { + firstName: randomName(), + lastName: randomName(), + password: randomValidPassword(), + }, + { + inviterId: owner.id, + firstName: randomName(), + password: randomValidPassword(), + }, + { + inviterId: owner.id, + firstName: randomName(), + password: randomValidPassword(), + }, + { + inviterId: owner.id, + firstName: randomName(), + lastName: randomName(), + }, + { + inviterId: owner.id, + firstName: randomName(), + lastName: randomName(), + password: randomInvalidPassword(), + }, + ]; - const user = await Db.collections.User!.findOneOrFail({ where: { email: emailToStore } }); - expect(user.firstName).toBeNull(); - expect(user.lastName).toBeNull(); - expect(user.password).toBeNull(); - } + await Promise.all( + invalidPayloads.map(async (invalidPayload) => { + const response = await authlessAgent.post(`/users/${memberShell.id}`).send(invalidPayload); + expect(response.statusCode).toBe(400); + + const storedUser = await Db.collections.User!.findOneOrFail({ + where: { email: memberShellEmail }, + }); + expect(storedUser.firstName).toBeNull(); + expect(storedUser.lastName).toBeNull(); + expect(storedUser.password).toBeNull(); + }), + ); }); -test.skip('POST /users/:id should fail with already accepted invite', async () => { - const authlessAgent = utils.createAgent(app); +test('POST /users/:id should fail with already accepted invite', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); + const member = await testDb.createUser({ globalRole: globalMemberRole }); - const globalMemberRole = await Db.collections.Role!.findOneOrFail({ - name: 'member', - scope: 'global', - }); - - const shell = await Db.collections.User!.save({ - email: randomEmail(), - password: randomValidPassword(), // simulate accepted invite - globalRole: globalMemberRole, - }); - - const newPassword = randomValidPassword(); - - const response = await authlessAgent.post(`/users/${shell.id}`).send({ - inviterId: INITIAL_TEST_USER.id, + const newMemberData = { + inviterId: owner.id, firstName: randomName(), lastName: randomName(), - password: newPassword, - }); + password: randomValidPassword(), + }; + + const authlessAgent = utils.createAgent(app); + + const response = await authlessAgent.post(`/users/${member.id}`).send(newMemberData); expect(response.statusCode).toBe(400); - const fetchedShell = await Db.collections.User!.findOneOrFail({ where: { email: shell.email } }); - expect(fetchedShell.firstName).toBeNull(); - expect(fetchedShell.lastName).toBeNull(); + const storedMember = await Db.collections.User!.findOneOrFail({ + where: { email: member.email }, + }); + expect(storedMember.firstName).not.toBe(newMemberData.firstName); + expect(storedMember.lastName).not.toBe(newMemberData.lastName); - const comparisonResult = await compare(shell.password, newPassword); + const comparisonResult = await compareHash(member.password, storedMember.password); expect(comparisonResult).toBe(false); - expect(newPassword).not.toBe(fetchedShell.password); + expect(storedMember.password).not.toBe(newMemberData.password); }); test('POST /users should fail if emailing is not set up', async () => { - const owner = await Db.collections.User!.findOneOrFail(); + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); const response = await authOwnerAgent.post('/users').send([{ email: randomEmail() }]); @@ -448,7 +471,7 @@ test('POST /users should fail if emailing is not set up', async () => { }); test('POST /users should fail if user management is disabled', async () => { - const owner = await Db.collections.User!.findOneOrFail(); + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); config.set('userManagement.disabled', true); @@ -458,55 +481,48 @@ test('POST /users should fail if user management is disabled', async () => { expect(response.statusCode).toBe(500); }); -test.skip('POST /users should email invites and create user shells', async () => { - const owner = await Db.collections.User!.findOneOrFail(); +test('POST /users should email invites and create user shells', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - const { - user, - pass, - smtp: { host, port, secure }, - } = await utils.getSmtpTestAccount(); + await utils.configureSmtp(); - config.set('userManagement.emails.mode', 'smtp'); - config.set('userManagement.emails.smtp.host', host); - config.set('userManagement.emails.smtp.port', port); - config.set('userManagement.emails.smtp.secure', secure); - config.set('userManagement.emails.smtp.auth.user', user); - config.set('userManagement.emails.smtp.auth.pass', pass); + const testEmails = [randomEmail(), randomEmail(), randomEmail()]; - const payload = TEST_EMAILS_TO_CREATE_USER_SHELLS.map((e) => ({ email: e })); + const payload = testEmails.map((e) => ({ email: e })); const response = await authOwnerAgent.post('/users').send(payload); expect(response.statusCode).toBe(200); - for (const { - user: { id, email: receivedEmail }, - error, - } of response.body.data) { - expect(validator.isUUID(id)).toBe(true); - expect(TEST_EMAILS_TO_CREATE_USER_SHELLS.some((e) => e === receivedEmail)).toBe(true); - if (error) { - expect(error).toBe('Email could not be sent'); - } + await Promise.all( + response.body.data.map(async ({ user, error }: { user: User; error: Error }) => { + const { id, email: receivedEmail } = user; - const user = await Db.collections.User!.findOneOrFail(id); - const { firstName, lastName, personalizationAnswers, password, resetPasswordToken } = user; + expect(validator.isUUID(id)).toBe(true); + expect(testEmails.some((e) => e === receivedEmail)).toBe(true); + if (error) { + expect(error).toBe('Email could not be sent'); + } - expect(firstName).toBeNull(); - expect(lastName).toBeNull(); - expect(personalizationAnswers).toBeNull(); - expect(password).toBeNull(); - expect(resetPasswordToken).toBeNull(); - } + const storedUser = await Db.collections.User!.findOneOrFail(id); + const { firstName, lastName, personalizationAnswers, password, resetPasswordToken } = + storedUser; + + expect(firstName).toBeNull(); + expect(lastName).toBeNull(); + expect(personalizationAnswers).toBeNull(); + expect(password).toBeNull(); + expect(resetPasswordToken).toBeNull(); + }), + ); }); -test.skip('POST /users should fail with invalid inputs', async () => { - const owner = await Db.collections.User!.findOneOrFail(); +test('POST /users should fail with invalid inputs', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - config.set('userManagement.emails.mode', 'smtp'); + await utils.configureSmtp(); const invalidPayloads = [ randomEmail(), @@ -516,20 +532,22 @@ test.skip('POST /users should fail with invalid inputs', async () => { [{ email: randomName() }], ]; - for (const invalidPayload of invalidPayloads) { - const response = await authOwnerAgent.post('/users').send(invalidPayload); - expect(response.statusCode).toBe(400); + await Promise.all( + invalidPayloads.map(async (invalidPayload) => { + const response = await authOwnerAgent.post('/users').send(invalidPayload); + expect(response.statusCode).toBe(400); - const users = await Db.collections.User!.find(); - expect(users.length).toBe(1); // DB unaffected - } + const users = await Db.collections.User!.find(); + expect(users.length).toBe(1); // DB unaffected + }), + ); }); -test.skip('POST /users should ignore an empty payload', async () => { - const owner = await Db.collections.User!.findOneOrFail(); +test('POST /users should ignore an empty payload', async () => { + const owner = await testDb.createUser({ globalRole: globalOwnerRole }); const authOwnerAgent = utils.createAgent(app, { auth: true, user: owner }); - config.set('userManagement.emails.mode', 'smtp'); + await utils.configureSmtp(); const response = await authOwnerAgent.post('/users').send([]); @@ -559,42 +577,3 @@ test.skip('POST /users should ignore an empty payload', async () => { // expect(response.statusCode).toBe(500); // }); - -const INITIAL_TEST_USER = { - id: uuid(), - email: randomEmail(), - firstName: randomName(), - lastName: randomName(), - password: randomValidPassword(), -}; - -const INVALID_FILL_OUT_USER_PAYLOADS = [ - { - firstName: randomName(), - lastName: randomName(), - password: randomValidPassword(), - }, - { - inviterId: INITIAL_TEST_USER.id, - firstName: randomName(), - password: randomValidPassword(), - }, - { - inviterId: INITIAL_TEST_USER.id, - firstName: randomName(), - password: randomValidPassword(), - }, - { - inviterId: INITIAL_TEST_USER.id, - firstName: randomName(), - lastName: randomName(), - }, - { - inviterId: INITIAL_TEST_USER.id, - firstName: randomName(), - lastName: randomName(), - password: randomInvalidPassword(), - }, -]; - -const TEST_EMAILS_TO_CREATE_USER_SHELLS = [randomEmail(), randomEmail(), randomEmail()]; diff --git a/packages/cli/test/setup.ts b/packages/cli/test/setup.ts index fa881e3fd3..1180a082c5 100644 --- a/packages/cli/test/setup.ts +++ b/packages/cli/test/setup.ts @@ -1,18 +1,17 @@ import { exec as callbackExec } from 'child_process'; import { promisify } from 'util'; -import config = require('../config'); +import config from '../config'; import { BOOTSTRAP_MYSQL_CONNECTION_NAME } from './integration/shared/constants'; -import { DatabaseType } from '../src'; const exec = promisify(callbackExec); -const dbType = config.get('database.type') as DatabaseType; +const dbType = config.getEnv('database.type'); if (dbType === 'mysqldb') { - const username = config.get('database.mysqldb.user'); - const password = config.get('database.mysqldb.password'); - const host = config.get('database.mysqldb.host'); + const username = config.getEnv('database.mysqldb.user'); + const password = config.getEnv('database.mysqldb.password'); + const host = config.getEnv('database.mysqldb.host'); const passwordSegment = password ? `-p${password}` : ''; diff --git a/packages/cli/test/teardown.ts b/packages/cli/test/teardown.ts index 95fb810e39..790b4702cb 100644 --- a/packages/cli/test/teardown.ts +++ b/packages/cli/test/teardown.ts @@ -1,12 +1,11 @@ import { createConnection } from 'typeorm'; -import config = require('../config'); +import config from '../config'; import { exec } from 'child_process'; -import { DatabaseType } from '../src'; import { getBootstrapMySqlOptions, getBootstrapPostgresOptions } from './integration/shared/testDb'; import { BOOTSTRAP_MYSQL_CONNECTION_NAME } from './integration/shared/constants'; export default async () => { - const dbType = config.get('database.type') as DatabaseType; + const dbType = config.getEnv('database.type'); if (dbType === 'postgresdb') { const bootstrapPostgres = await createConnection(getBootstrapPostgresOptions()); @@ -25,9 +24,9 @@ export default async () => { } if (dbType === 'mysqldb') { - const user = config.get('database.mysqldb.user'); - const password = config.get('database.mysqldb.password'); - const host = config.get('database.mysqldb.host'); + const user = config.getEnv('database.mysqldb.user'); + const password = config.getEnv('database.mysqldb.password'); + const host = config.getEnv('database.mysqldb.host'); const bootstrapMySql = await createConnection(getBootstrapMySqlOptions()); diff --git a/packages/cli/test/unit/CredentialsHelper.test.ts b/packages/cli/test/unit/CredentialsHelper.test.ts index 7617630588..b8de4e0529 100644 --- a/packages/cli/test/unit/CredentialsHelper.test.ts +++ b/packages/cli/test/unit/CredentialsHelper.test.ts @@ -277,6 +277,8 @@ describe('CredentialsHelper', () => { nodeTypes, }); + const timezone = 'America/New_York'; + for (const testData of tests) { test(testData.description, async () => { const credentialTypes: ICredentialTypeData = { @@ -296,6 +298,7 @@ describe('CredentialsHelper', () => { JSON.parse(JSON.stringify(incomingRequestOptions)), workflow, node, + timezone, ); expect(result).toEqual(testData.output); diff --git a/packages/cli/tsconfig.json b/packages/cli/tsconfig.json index aa44bc610f..47213b3d47 100644 --- a/packages/cli/tsconfig.json +++ b/packages/cli/tsconfig.json @@ -20,7 +20,8 @@ "target": "es2017", "sourceMap": true, "emitDecoratorMetadata": true, - "experimentalDecorators": true + "experimentalDecorators": true, + "esModuleInterop": true }, "include": [ "**/*.d.ts", diff --git a/packages/cli/tslint.json b/packages/cli/tslint.json deleted file mode 100644 index 9b5a55973b..0000000000 --- a/packages/cli/tslint.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "linterOptions": { - "exclude": [ - "node_modules/**/*" - ] - }, - "defaultSeverity": "error", - "jsRules": {}, - "rules": { - "array-type": [ - true, - "array-simple" - ], - "arrow-return-shorthand": true, - "ban": [ - true, - { - "name": "Array", - "message": "tsstyle#array-constructor" - } - ], - "ban-types": [ - true, - [ - "Object", - "Use {} instead." - ], - [ - "String", - "Use 'string' instead." - ], - [ - "Number", - "Use 'number' instead." - ], - [ - "Boolean", - "Use 'boolean' instead." - ] - ], - "class-name": true, - "curly": [ - true, - "ignore-same-line" - ], - "forin": true, - "jsdoc-format": true, - "label-position": true, - "indent": [ - true, - "tabs", - 2 - ], - "member-access": [ - true, - "no-public" - ], - "new-parens": true, - "no-angle-bracket-type-assertion": true, - "no-any": true, - "no-arg": true, - "no-conditional-assignment": true, - "no-construct": true, - "no-debugger": true, - "no-default-export": true, - "no-duplicate-variable": true, - "no-inferrable-types": true, - "ordered-imports": [ - true, - { - "import-sources-order": "any", - "named-imports-order": "case-insensitive" - } - ], - "no-namespace": [ - true, - "allow-declarations" - ], - "no-reference": true, - "no-string-throw": true, - "no-unused-expression": true, - "no-var-keyword": true, - "object-literal-shorthand": true, - "only-arrow-functions": [ - true, - "allow-declarations", - "allow-named-functions" - ], - "prefer-const": true, - "radix": true, - "semicolon": [ - true, - "always", - "ignore-bound-class-methods" - ], - "switch-default": true, - "trailing-comma": [ - true, - { - "multiline": { - "objects": "always", - "arrays": "always", - "functions": "never", - "typeLiterals": "ignore" - }, - "esSpecCompliant": true - } - ], - "triple-equals": [ - true, - "allow-null-check" - ], - "use-isnan": true, - "quotes": [ - "error", - "single" - ], - "variable-name": [ - true, - "check-format", - "ban-keywords", - "allow-leading-underscore", - "allow-trailing-underscore" - ] - }, - "rulesDirectory": [] -} diff --git a/packages/core/package.json b/packages/core/package.json index df99a99392..d44ae74fd0 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "n8n-core", - "version": "0.111.0", + "version": "0.112.0", "description": "Core functionality of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", @@ -40,7 +40,7 @@ "source-map-support": "^0.5.9", "ts-jest": "^27.1.3", "tslint": "^6.1.2", - "typescript": "~4.3.5" + "typescript": "~4.6.0" }, "dependencies": { "axios": "^0.21.1", @@ -52,7 +52,7 @@ "form-data": "^4.0.0", "lodash.get": "^4.4.2", "mime-types": "^2.1.27", - "n8n-workflow": "~0.93.0", + "n8n-workflow": "~0.94.0", "oauth-1.0a": "^2.2.6", "p-cancelable": "^2.0.0", "qs": "^6.10.1", diff --git a/packages/core/src/BinaryDataManager/FileSystem.ts b/packages/core/src/BinaryDataManager/FileSystem.ts index 07586cb05d..d9a8e4d2a2 100644 --- a/packages/core/src/BinaryDataManager/FileSystem.ts +++ b/packages/core/src/BinaryDataManager/FileSystem.ts @@ -1,5 +1,5 @@ import { promises as fs } from 'fs'; -import * as path from 'path'; +import path from 'path'; import { v4 as uuid } from 'uuid'; import { IBinaryDataConfig, IBinaryDataManager } from '../Interfaces'; diff --git a/packages/core/src/Interfaces.ts b/packages/core/src/Interfaces.ts index b71e6356fc..70f6c7063e 100644 --- a/packages/core/src/Interfaces.ts +++ b/packages/core/src/Interfaces.ts @@ -23,7 +23,7 @@ import { } from 'n8n-workflow'; import { OptionsWithUri, OptionsWithUrl } from 'request'; -import * as requestPromise from 'request-promise-native'; +import requestPromise from 'request-promise-native'; interface Constructable { new (): T; diff --git a/packages/core/src/NodeExecuteFunctions.ts b/packages/core/src/NodeExecuteFunctions.ts index 1d54de9a11..c742cd08e4 100644 --- a/packages/core/src/NodeExecuteFunctions.ts +++ b/packages/core/src/NodeExecuteFunctions.ts @@ -60,20 +60,17 @@ import { import { Agent } from 'https'; import { stringify } from 'qs'; -import * as clientOAuth1 from 'oauth-1.0a'; -import { Token } from 'oauth-1.0a'; -import * as clientOAuth2 from 'client-oauth2'; -import * as crypto from 'crypto'; -import * as url from 'url'; +import clientOAuth1, { Token } from 'oauth-1.0a'; +import clientOAuth2 from 'client-oauth2'; +import crypto, { createHmac } from 'crypto'; // eslint-disable-next-line import/no-extraneous-dependencies import { get } from 'lodash'; // eslint-disable-next-line import/no-extraneous-dependencies -import * as express from 'express'; -import * as FormData from 'form-data'; -import * as path from 'path'; +import express from 'express'; +import FormData from 'form-data'; +import path from 'path'; import { OptionsWithUri, OptionsWithUrl } from 'request'; -import * as requestPromise from 'request-promise-native'; -import { createHmac } from 'crypto'; +import requestPromise from 'request-promise-native'; import { fromBuffer } from 'file-type'; import { lookup } from 'mime-types'; @@ -84,7 +81,7 @@ import axios, { AxiosResponse, Method, } from 'axios'; -import { URL, URLSearchParams } from 'url'; +import url, { URL, URLSearchParams } from 'url'; import { BinaryDataManager } from './BinaryDataManager'; // eslint-disable-next-line import/no-cycle import { @@ -1103,6 +1100,7 @@ export async function httpRequestWithAuthentication( requestOptions, workflow, node, + additionalData.timezone, ); return await httpRequest(requestOptions); @@ -1225,6 +1223,7 @@ export async function requestWithAuthentication( requestOptions as IHttpRequestOptions, workflow, node, + additionalData.timezone, ); return await proxyRequestToAxios(requestOptions as IDataObject); @@ -1375,6 +1374,7 @@ export async function getCredentials( nodeCredentials, type, mode, + additionalData.timezone, false, expressionResolveValues, ); @@ -1416,6 +1416,7 @@ export function getNodeParameter( parameterName: string, itemIndex: number, mode: WorkflowExecuteMode, + timezone: string, additionalKeys: IWorkflowDataProxyAdditionalKeys, fallbackValue?: any, ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object { @@ -1440,6 +1441,7 @@ export function getNodeParameter( node.name, connectionInputData, mode, + timezone, additionalKeys, ); } catch (e) { @@ -1478,6 +1480,7 @@ export function getNodeWebhookUrl( node: INode, additionalData: IWorkflowExecuteAdditionalData, mode: WorkflowExecuteMode, + timezone: string, additionalKeys: IWorkflowDataProxyAdditionalKeys, isTest?: boolean, ): string | undefined { @@ -1496,6 +1499,7 @@ export function getNodeWebhookUrl( node, webhookDescription.path, mode, + timezone, additionalKeys, ); if (path === undefined) { @@ -1506,6 +1510,7 @@ export function getNodeWebhookUrl( node, webhookDescription.isFullPath, mode, + timezone, additionalKeys, false, ) as boolean; @@ -1635,6 +1640,7 @@ export function getExecutePollFunctions( parameterName, itemIndex, mode, + additionalData.timezone, getAdditionalKeys(additionalData), fallbackValue, ); @@ -1750,6 +1756,9 @@ export function getExecuteTriggerFunctions( emit: (data: INodeExecutionData[][]): void => { throw new Error('Overwrite NodeExecuteFunctions.getExecuteTriggerFunctions.emit function!'); }, + emitError: (error: Error): void => { + throw new Error('Overwrite NodeExecuteFunctions.getExecuteTriggerFunctions.emit function!'); + }, async getCredentials(type: string): Promise { return getCredentials(workflow, node, type, additionalData, mode); }, @@ -1785,6 +1794,7 @@ export function getExecuteTriggerFunctions( parameterName, itemIndex, mode, + additionalData.timezone, getAdditionalKeys(additionalData), fallbackValue, ); @@ -1916,6 +1926,7 @@ export function getExecuteFunctions( node.name, connectionInputData, mode, + additionalData.timezone, getAdditionalKeys(additionalData), ); }, @@ -1991,6 +2002,7 @@ export function getExecuteFunctions( parameterName, itemIndex, mode, + additionalData.timezone, getAdditionalKeys(additionalData), fallbackValue, ); @@ -2020,6 +2032,7 @@ export function getExecuteFunctions( connectionInputData, {}, mode, + additionalData.timezone, getAdditionalKeys(additionalData), ); return dataProxy.getDataProxy(); @@ -2173,6 +2186,7 @@ export function getExecuteSingleFunctions( node.name, connectionInputData, mode, + additionalData.timezone, getAdditionalKeys(additionalData), ); }, @@ -2249,6 +2263,7 @@ export function getExecuteSingleFunctions( parameterName, itemIndex, mode, + additionalData.timezone, getAdditionalKeys(additionalData), fallbackValue, ); @@ -2266,6 +2281,7 @@ export function getExecuteSingleFunctions( connectionInputData, {}, mode, + additionalData.timezone, getAdditionalKeys(additionalData), ); return dataProxy.getDataProxy(); @@ -2422,6 +2438,7 @@ export function getLoadOptionsFunctions( parameterName, itemIndex, 'internal' as WorkflowExecuteMode, + additionalData.timezone, getAdditionalKeys(additionalData), fallbackValue, ); @@ -2551,6 +2568,7 @@ export function getExecuteHookFunctions( parameterName, itemIndex, mode, + additionalData.timezone, getAdditionalKeys(additionalData), fallbackValue, ); @@ -2562,6 +2580,7 @@ export function getExecuteHookFunctions( node, additionalData, mode, + additionalData.timezone, getAdditionalKeys(additionalData), isTest, ); @@ -2711,6 +2730,7 @@ export function getExecuteWebhookFunctions( parameterName, itemIndex, mode, + additionalData.timezone, getAdditionalKeys(additionalData), fallbackValue, ); @@ -2746,6 +2766,7 @@ export function getExecuteWebhookFunctions( node, additionalData, mode, + additionalData.timezone, getAdditionalKeys(additionalData), ); }, diff --git a/packages/core/src/UserSettings.ts b/packages/core/src/UserSettings.ts index e6620ccc4d..ca6406b66e 100644 --- a/packages/core/src/UserSettings.ts +++ b/packages/core/src/UserSettings.ts @@ -2,8 +2,8 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ -import * as fs from 'fs'; -import * as path from 'path'; +import fs from 'fs'; +import path from 'path'; import { createHash, randomBytes } from 'crypto'; // eslint-disable-next-line import/no-cycle import { diff --git a/packages/core/src/WorkflowExecute.ts b/packages/core/src/WorkflowExecute.ts index 4593f90664..1c799ac53f 100644 --- a/packages/core/src/WorkflowExecute.ts +++ b/packages/core/src/WorkflowExecute.ts @@ -9,7 +9,7 @@ /* eslint-disable no-restricted-syntax */ /* eslint-disable no-param-reassign */ /* eslint-disable @typescript-eslint/prefer-nullish-coalescing */ -import * as PCancelable from 'p-cancelable'; +import PCancelable from 'p-cancelable'; import { ExecutionError, diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 4fba454377..70e7a5777b 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -17,7 +17,9 @@ "declaration": true, "outDir": "./dist/", "target": "es2019", - "sourceMap": true + "sourceMap": true, + "esModuleInterop": true, + "useUnknownInCatchVariables": false, }, "include": [ "**/*.d.ts", diff --git a/packages/core/tslint.json b/packages/core/tslint.json deleted file mode 100644 index f03bbfee37..0000000000 --- a/packages/core/tslint.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "linterOptions": { - "exclude": [ - "node_modules/**/*" - ] - }, - "defaultSeverity": "error", - "jsRules": {}, - "rules": { - "array-type": [ - true, - "array-simple" - ], - "arrow-return-shorthand": true, - "ban": [ - true, - { - "name": "Array", - "message": "tsstyle#array-constructor" - } - ], - "ban-types": [ - true, - [ - "Object", - "Use {} instead." - ], - [ - "String", - "Use 'string' instead." - ], - [ - "Number", - "Use 'number' instead." - ], - [ - "Boolean", - "Use 'boolean' instead." - ] - ], - "class-name": true, - "curly": [ - true, - "ignore-same-line" - ], - "forin": true, - "jsdoc-format": true, - "label-position": true, - "indent": [ - true, - "tabs", - 2 - ], - "member-access": [ - true, - "no-public" - ], - "new-parens": true, - "no-angle-bracket-type-assertion": true, - "no-any": true, - "no-arg": true, - "no-conditional-assignment": true, - "no-construct": true, - "no-debugger": true, - "no-default-export": true, - "no-duplicate-variable": true, - "no-inferrable-types": true, - "ordered-imports": [ - true, - { - "import-sources-order": "any", - "named-imports-order": "case-insensitive" - } - ], - "no-namespace": [ - true, - "allow-declarations" - ], - "no-reference": true, - "no-string-throw": true, - "no-unused-expression": true, - "no-var-keyword": true, - "object-literal-shorthand": true, - "only-arrow-functions": [ - true, - "allow-declarations", - "allow-named-functions" - ], - "prefer-const": true, - "radix": true, - "semicolon": [ - true, - "always", - "ignore-bound-class-methods" - ], - "switch-default": true, - "trailing-comma": [ - true, - { - "multiline": { - "objects": "always", - "arrays": "always", - "functions": "always", - "typeLiterals": "ignore" - }, - "esSpecCompliant": true - } - ], - "triple-equals": [ - true, - "allow-null-check" - ], - "use-isnan": true, - "quotes": [ - "error", - "single" - ], - "variable-name": [ - true, - "check-format", - "ban-keywords", - "allow-leading-underscore", - "allow-trailing-underscore" - ] - }, - "rulesDirectory": [] -} diff --git a/packages/design-system/package.json b/packages/design-system/package.json index 2de93f09e9..66a6007464 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -73,7 +73,7 @@ "storybook-addon-designs": "^6.0.1", "storybook-addon-themes": "^6.1.0", "trim": ">=0.0.3", - "typescript": "~4.3.5", + "typescript": "~4.6.0", "vue": "^2.6.11", "vue-class-component": "^7.2.3", "vue-loader": "^15.9.7", diff --git a/packages/editor-ui/package.json b/packages/editor-ui/package.json index e95a509040..897000cb91 100644 --- a/packages/editor-ui/package.json +++ b/packages/editor-ui/package.json @@ -1,6 +1,6 @@ { "name": "n8n-editor-ui", - "version": "0.137.0", + "version": "0.138.0", "description": "Workflow Editor UI for n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", @@ -77,7 +77,7 @@ "lodash.debounce": "^4.0.8", "lodash.get": "^4.4.2", "lodash.set": "^4.3.2", - "n8n-workflow": "~0.93.0", + "n8n-workflow": "~0.94.0", "monaco-editor-webpack-plugin": "^5.0.0", "normalize-wheel": "^1.0.1", "prismjs": "^1.17.1", @@ -88,7 +88,7 @@ "string-template-parser": "^1.2.6", "ts-jest": "^27.1.3", "tslint": "^6.1.2", - "typescript": "~4.3.5", + "typescript": "~4.6.0", "uuid": "^8.3.2", "vue": "^2.6.11", "vue-agile": "^2.0.0", diff --git a/packages/editor-ui/src/components/CodeEdit.vue b/packages/editor-ui/src/components/CodeEdit.vue index 59461a3c78..04a5808d48 100644 --- a/packages/editor-ui/src/components/CodeEdit.vue +++ b/packages/editor-ui/src/components/CodeEdit.vue @@ -171,7 +171,7 @@ export default mixins( $resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, }; - const dataProxy = new WorkflowDataProxy(workflow, runExecutionData, runIndex, itemIndex, activeNode!.name, connectionInputData || [], {}, mode, additionalProxyKeys); + const dataProxy = new WorkflowDataProxy(workflow, runExecutionData, runIndex, itemIndex, activeNode!.name, connectionInputData || [], {}, mode, this.$store.getters.timezone, additionalProxyKeys); const proxy = dataProxy.getDataProxy(); const autoCompleteItems = [ diff --git a/packages/editor-ui/src/components/VariableSelector.vue b/packages/editor-ui/src/components/VariableSelector.vue index bbee96a932..03d6621364 100644 --- a/packages/editor-ui/src/components/VariableSelector.vue +++ b/packages/editor-ui/src/components/VariableSelector.vue @@ -386,7 +386,7 @@ export default mixins( $resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, }; - const dataProxy = new WorkflowDataProxy(workflow, runExecutionData, runIndex, itemIndex, nodeName, connectionInputData, {}, 'manual', additionalKeys); + const dataProxy = new WorkflowDataProxy(workflow, runExecutionData, runIndex, itemIndex, nodeName, connectionInputData, {}, 'manual', this.$store.getters.timezone, additionalKeys); const proxy = dataProxy.getDataProxy(); // @ts-ignore diff --git a/packages/editor-ui/src/components/mixins/deviceSupportHelpers.ts b/packages/editor-ui/src/components/mixins/deviceSupportHelpers.ts index 85ccd9c6a0..f47b9e208d 100644 --- a/packages/editor-ui/src/components/mixins/deviceSupportHelpers.ts +++ b/packages/editor-ui/src/components/mixins/deviceSupportHelpers.ts @@ -3,8 +3,8 @@ import Vue from 'vue'; export const deviceSupportHelpers = Vue.extend({ data() { return { - isTouchDevice: 'ontouchstart' in window || navigator.msMaxTouchPoints, - isMacOs: /(ipad|iphone|ipod|mac)/i.test(navigator.platform), + isTouchDevice: 'ontouchstart' in window || navigator.maxTouchPoints, + isMacOs: /(ipad|iphone|ipod|mac)/i.test(navigator.platform), // TODO: `platform` deprecated }; }, computed: { diff --git a/packages/editor-ui/src/components/mixins/workflowHelpers.ts b/packages/editor-ui/src/components/mixins/workflowHelpers.ts index 3c8965c2dc..d7a34ae81f 100644 --- a/packages/editor-ui/src/components/mixins/workflowHelpers.ts +++ b/packages/editor-ui/src/components/mixins/workflowHelpers.ts @@ -249,9 +249,9 @@ export const workflowHelpers = mixins( const workflowName = this.$store.getters.workflowName; if (copyData === true) { - return new Workflow({ id: workflowId, name: workflowName, nodes: JSON.parse(JSON.stringify(nodes)), connections: JSON.parse(JSON.stringify(connections)), active: false, nodeTypes}); + return new Workflow({ id: workflowId, name: workflowName, nodes: JSON.parse(JSON.stringify(nodes)), connections: JSON.parse(JSON.stringify(connections)), active: false, nodeTypes, settings: this.$store.getters.workflowSettings}); } else { - return new Workflow({ id: workflowId, name: workflowName, nodes, connections, active: false, nodeTypes}); + return new Workflow({ id: workflowId, name: workflowName, nodes, connections, active: false, nodeTypes, settings: this.$store.getters.workflowSettings}); } }, @@ -408,7 +408,7 @@ export const workflowHelpers = mixins( $resumeWebhookUrl: PLACEHOLDER_FILLED_AT_EXECUTION_TIME, }; - return workflow.expression.getParameterValue(parameter, runExecutionData, runIndex, itemIndex, activeNode.name, connectionInputData, 'manual', additionalKeys, false) as IDataObject; + return workflow.expression.getParameterValue(parameter, runExecutionData, runIndex, itemIndex, activeNode.name, connectionInputData, 'manual', this.$store.getters.timezone, additionalKeys, false) as IDataObject; }, resolveExpression(expression: string, siblingParameters: INodeParameters = {}) { diff --git a/packages/editor-ui/tsconfig.json b/packages/editor-ui/tsconfig.json index dc9f79a4e3..8e6dc8f622 100644 --- a/packages/editor-ui/tsconfig.json +++ b/packages/editor-ui/tsconfig.json @@ -12,6 +12,7 @@ "moduleResolution": "node", "esModuleInterop": true, "allowSyntheticDefaultImports": true, + "useUnknownInCatchVariables": false, "sourceMap": true, "baseUrl": ".", "types": [ diff --git a/packages/node-dev/package.json b/packages/node-dev/package.json index e640c00f36..d9248e3894 100644 --- a/packages/node-dev/package.json +++ b/packages/node-dev/package.json @@ -1,6 +1,6 @@ { "name": "n8n-node-dev", - "version": "0.50.0", + "version": "0.51.0", "description": "CLI to simplify n8n credentials/node development", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", @@ -61,12 +61,12 @@ "change-case": "^4.1.1", "copyfiles": "^2.1.1", "inquirer": "^7.0.1", - "n8n-core": "~0.111.0", - "n8n-workflow": "~0.93.0", + "n8n-core": "~0.112.0", + "n8n-workflow": "~0.94.0", "oauth-1.0a": "^2.2.6", "replace-in-file": "^6.0.0", "request": "^2.88.2", "tmp-promise": "^3.0.2", - "typescript": "~4.3.5" + "typescript": "~4.6.0" } } diff --git a/packages/node-dev/tslint.json b/packages/node-dev/tslint.json deleted file mode 100644 index f03bbfee37..0000000000 --- a/packages/node-dev/tslint.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "linterOptions": { - "exclude": [ - "node_modules/**/*" - ] - }, - "defaultSeverity": "error", - "jsRules": {}, - "rules": { - "array-type": [ - true, - "array-simple" - ], - "arrow-return-shorthand": true, - "ban": [ - true, - { - "name": "Array", - "message": "tsstyle#array-constructor" - } - ], - "ban-types": [ - true, - [ - "Object", - "Use {} instead." - ], - [ - "String", - "Use 'string' instead." - ], - [ - "Number", - "Use 'number' instead." - ], - [ - "Boolean", - "Use 'boolean' instead." - ] - ], - "class-name": true, - "curly": [ - true, - "ignore-same-line" - ], - "forin": true, - "jsdoc-format": true, - "label-position": true, - "indent": [ - true, - "tabs", - 2 - ], - "member-access": [ - true, - "no-public" - ], - "new-parens": true, - "no-angle-bracket-type-assertion": true, - "no-any": true, - "no-arg": true, - "no-conditional-assignment": true, - "no-construct": true, - "no-debugger": true, - "no-default-export": true, - "no-duplicate-variable": true, - "no-inferrable-types": true, - "ordered-imports": [ - true, - { - "import-sources-order": "any", - "named-imports-order": "case-insensitive" - } - ], - "no-namespace": [ - true, - "allow-declarations" - ], - "no-reference": true, - "no-string-throw": true, - "no-unused-expression": true, - "no-var-keyword": true, - "object-literal-shorthand": true, - "only-arrow-functions": [ - true, - "allow-declarations", - "allow-named-functions" - ], - "prefer-const": true, - "radix": true, - "semicolon": [ - true, - "always", - "ignore-bound-class-methods" - ], - "switch-default": true, - "trailing-comma": [ - true, - { - "multiline": { - "objects": "always", - "arrays": "always", - "functions": "always", - "typeLiterals": "ignore" - }, - "esSpecCompliant": true - } - ], - "triple-equals": [ - true, - "allow-null-check" - ], - "use-isnan": true, - "quotes": [ - "error", - "single" - ], - "variable-name": [ - true, - "check-format", - "ban-keywords", - "allow-leading-underscore", - "allow-trailing-underscore" - ] - }, - "rulesDirectory": [] -} diff --git a/packages/nodes-base/credentials/ActionNetworkApi.credentials.ts b/packages/nodes-base/credentials/ActionNetworkApi.credentials.ts index 95e889f419..394f343771 100644 --- a/packages/nodes-base/credentials/ActionNetworkApi.credentials.ts +++ b/packages/nodes-base/credentials/ActionNetworkApi.credentials.ts @@ -1,5 +1,8 @@ import { + ICredentialDataDecryptedObject, + ICredentialTestRequest, ICredentialType, + IHttpRequestOptions, INodeProperties, } from 'n8n-workflow'; @@ -15,4 +18,14 @@ export class ActionNetworkApi implements ICredentialType { default: '', }, ]; + test: ICredentialTestRequest = { + request: { + baseURL: 'https://actionnetwork.org/api/v2', + url: '/events?per_page=1', + }, + }; + async authenticate(credentials: ICredentialDataDecryptedObject, requestOptions: IHttpRequestOptions): Promise { + requestOptions.headers = { 'OSDI-API-Token': credentials.apiKey }; + return requestOptions; + } } diff --git a/packages/nodes-base/credentials/Magento2Api.credentials.ts b/packages/nodes-base/credentials/Magento2Api.credentials.ts index 487f68abf6..0bd4f0d728 100644 --- a/packages/nodes-base/credentials/Magento2Api.credentials.ts +++ b/packages/nodes-base/credentials/Magento2Api.credentials.ts @@ -1,4 +1,6 @@ import { + IAuthenticateBearer, + ICredentialTestRequest, ICredentialType, INodeProperties, } from 'n8n-workflow'; @@ -21,4 +23,15 @@ export class Magento2Api implements ICredentialType { default: '', }, ]; + test: ICredentialTestRequest = { + request: { + baseURL: '={{$credentials.host}}', + url: '/rest/default/V1/modules', + }, + }; + + authenticate = { + type: 'bearer', + properties: {}, + } as IAuthenticateBearer; } diff --git a/packages/nodes-base/credentials/MauticOAuth2Api.credentials.ts b/packages/nodes-base/credentials/MauticOAuth2Api.credentials.ts index 104ac82036..ea5e131ded 100644 --- a/packages/nodes-base/credentials/MauticOAuth2Api.credentials.ts +++ b/packages/nodes-base/credentials/MauticOAuth2Api.credentials.ts @@ -22,14 +22,14 @@ export class MauticOAuth2Api implements ICredentialType { displayName: 'Authorization URL', name: 'authUrl', type: 'hidden', - default: '={{$self["url"]}}/oauth/v2/authorize', + default: '={{$self["url"].endsWith("/") ? $self["url"].slice(0, -1) : $self["url"]}}/oauth/v2/authorize', required: true, }, { displayName: 'Access Token URL', name: 'accessTokenUrl', type: 'hidden', - default: '={{$self["url"]}}/oauth/v2/token', + default: '={{$self["url"].endsWith("/") ? $self["url"].slice(0, -1) : $self["url"]}}/oauth/v2/token', required: true, }, { diff --git a/packages/nodes-base/credentials/MicrosoftTeamsOAuth2Api.credentials.ts b/packages/nodes-base/credentials/MicrosoftTeamsOAuth2Api.credentials.ts index f0b35d78f5..dc852beea1 100644 --- a/packages/nodes-base/credentials/MicrosoftTeamsOAuth2Api.credentials.ts +++ b/packages/nodes-base/credentials/MicrosoftTeamsOAuth2Api.credentials.ts @@ -16,7 +16,7 @@ export class MicrosoftTeamsOAuth2Api implements ICredentialType { displayName: 'Scope', name: 'scope', type: 'hidden', - default: 'openid offline_access User.ReadWrite.All Group.ReadWrite.All', + default: 'openid offline_access User.ReadWrite.All Group.ReadWrite.All Chat.ReadWrite', }, ]; } diff --git a/packages/nodes-base/credentials/PayPalApi.credentials.ts b/packages/nodes-base/credentials/PayPalApi.credentials.ts index 897a66b627..9b2514efff 100644 --- a/packages/nodes-base/credentials/PayPalApi.credentials.ts +++ b/packages/nodes-base/credentials/PayPalApi.credentials.ts @@ -28,7 +28,7 @@ export class PayPalApi implements ICredentialType { default: 'live', options: [ { - name: 'Sanbox', + name: 'Sandbox', value: 'sanbox', }, { diff --git a/packages/nodes-base/credentials/SeaTableApi.credentials.ts b/packages/nodes-base/credentials/SeaTableApi.credentials.ts index 01805c19ad..7b0221161c 100644 --- a/packages/nodes-base/credentials/SeaTableApi.credentials.ts +++ b/packages/nodes-base/credentials/SeaTableApi.credentials.ts @@ -4,7 +4,7 @@ import { INodePropertyOptions, } from 'n8n-workflow'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; // Get options for timezones const timezones: INodePropertyOptions[] = moment.tz.countries().reduce( (timezones: INodePropertyOptions[], country: string) => { diff --git a/packages/nodes-base/credentials/ServiceNowBasicApi.credentials.ts b/packages/nodes-base/credentials/ServiceNowBasicApi.credentials.ts new file mode 100644 index 0000000000..f5cdd04d5b --- /dev/null +++ b/packages/nodes-base/credentials/ServiceNowBasicApi.credentials.ts @@ -0,0 +1,35 @@ +import { + IAuthenticateBasicAuth, + ICredentialTestRequest, + ICredentialType, + INodeProperties, +} from 'n8n-workflow'; + +export class ServiceNowBasicApi implements ICredentialType { + name = 'serviceNowBasicApi'; + extends = [ + 'httpBasicAuth', + ]; + displayName = 'ServiceNow Basic Auth API'; + documentationUrl = 'serviceNow'; + properties: INodeProperties[] = [ + { + displayName: 'Subdomain', + name: 'subdomain', + type: 'string', + default: '', + hint: 'The subdomain can be extracted from the URL. If the URL is: https://dev99890.service-now.com the subdomain is dev99890', + required: true, + }, + ]; + authenticate: IAuthenticateBasicAuth = { + type: 'basicAuth', + properties: {}, + }; + test: ICredentialTestRequest = { + request: { + baseURL: '=https://{{$credentials?.subdomain}}.service-now.com', + url: '/api/now/table/sys_user_role', + }, + }; +} diff --git a/packages/nodes-base/credentials/ServiceNowOAuth2Api.credentials.ts b/packages/nodes-base/credentials/ServiceNowOAuth2Api.credentials.ts index 9539cb1fe1..4bd0bc2e19 100644 --- a/packages/nodes-base/credentials/ServiceNowOAuth2Api.credentials.ts +++ b/packages/nodes-base/credentials/ServiceNowOAuth2Api.credentials.ts @@ -16,8 +16,7 @@ export class ServiceNowOAuth2Api implements ICredentialType { name: 'subdomain', type: 'string', default: '', - placeholder: 'n8n', - description: 'The subdomain of your ServiceNow environment', + hint: 'The subdomain can be extracted from the URL. If the URL is: https://dev99890.service-now.com the subdomain is dev99890', required: true, }, { diff --git a/packages/nodes-base/nodes/ActionNetwork/GenericFunctions.ts b/packages/nodes-base/nodes/ActionNetwork/GenericFunctions.ts index da67bd3b76..72cf055931 100644 --- a/packages/nodes-base/nodes/ActionNetwork/GenericFunctions.ts +++ b/packages/nodes-base/nodes/ActionNetwork/GenericFunctions.ts @@ -6,7 +6,6 @@ import { IDataObject, ILoadOptionsFunctions, NodeApiError, - NodeOperationError, } from 'n8n-workflow'; import { @@ -35,16 +34,7 @@ export async function actionNetworkApiRequest( body: IDataObject = {}, qs: IDataObject = {}, ) { - const credentials = await this.getCredentials('actionNetworkApi') as { apiKey: string } | undefined; - - if (credentials === undefined) { - throw new NodeOperationError(this.getNode(), 'No credentials got returned!'); - } - const options: OptionsWithUri = { - headers: { - 'OSDI-API-Token': credentials.apiKey, - }, method, body, qs, @@ -61,7 +51,7 @@ export async function actionNetworkApiRequest( } try { - return await this.helpers.request!(options); + return await this.helpers.requestWithAuthentication.call(this, 'actionNetworkApi', options); } catch (error) { throw new NodeApiError(this.getNode(), error); } @@ -95,13 +85,15 @@ export async function handleListing( return returnData.slice(0, limit); } - qs.page = responseData.page as number; - } while (responseData.total_pages && qs.page < responseData.total_pages); + if (responseData._links && responseData._links.next && responseData._links.next.href) { + const queryString = new URLSearchParams(responseData._links.next.href.split('?')[1]); + qs.page = queryString.get('page') as string; + } + } while (responseData._links && responseData._links.next); return returnData; } - // ---------------------------------------- // helpers // ---------------------------------------- diff --git a/packages/nodes-base/nodes/ActionNetwork/descriptions/PersonDescription.ts b/packages/nodes-base/nodes/ActionNetwork/descriptions/PersonDescription.ts index f8ce9dd9fe..30b90f1077 100644 --- a/packages/nodes-base/nodes/ActionNetwork/descriptions/PersonDescription.ts +++ b/packages/nodes-base/nodes/ActionNetwork/descriptions/PersonDescription.ts @@ -186,10 +186,11 @@ export const personFields: INodeProperties[] = [ displayName: 'Limit', name: 'limit', type: 'number', - default: 50, + default: 25, description: 'The number of results to return.', typeOptions: { minValue: 1, + maxValue: 25, }, displayOptions: { show: { diff --git a/packages/nodes-base/nodes/Airtable/AirtableTrigger.node.ts b/packages/nodes-base/nodes/Airtable/AirtableTrigger.node.ts index 6809c9755a..30953d3a20 100644 --- a/packages/nodes-base/nodes/Airtable/AirtableTrigger.node.ts +++ b/packages/nodes-base/nodes/Airtable/AirtableTrigger.node.ts @@ -15,7 +15,7 @@ import { downloadRecordAttachments, } from './GenericFunctions'; -import * as moment from 'moment'; +import moment from 'moment'; export class AirtableTrigger implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Asana/Asana.node.ts b/packages/nodes-base/nodes/Asana/Asana.node.ts index fe03bfbed5..2c4cf27da4 100644 --- a/packages/nodes-base/nodes/Asana/Asana.node.ts +++ b/packages/nodes-base/nodes/Asana/Asana.node.ts @@ -20,7 +20,7 @@ import { getWorkspaces, } from './GenericFunctions'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; import { snakeCase } from 'change-case'; diff --git a/packages/nodes-base/nodes/BambooHr/v1/actions/employee/create/execute.ts b/packages/nodes-base/nodes/BambooHr/v1/actions/employee/create/execute.ts index 60c74533d5..fb990bcd32 100644 --- a/packages/nodes-base/nodes/BambooHr/v1/actions/employee/create/execute.ts +++ b/packages/nodes-base/nodes/BambooHr/v1/actions/employee/create/execute.ts @@ -11,9 +11,9 @@ import { apiRequest, } from '../../../transport'; -import * as moment from 'moment'; +import moment from 'moment'; -import { +import { capitalCase } from 'change-case'; @@ -96,4 +96,4 @@ export async function create(this: IExecuteFunctions, index: number): Promise { // tslint:disable-line:no-any diff --git a/packages/nodes-base/nodes/CrateDb/CrateDb.node.ts b/packages/nodes-base/nodes/CrateDb/CrateDb.node.ts index 8c080f6050..26b29a3ca2 100644 --- a/packages/nodes-base/nodes/CrateDb/CrateDb.node.ts +++ b/packages/nodes-base/nodes/CrateDb/CrateDb.node.ts @@ -16,7 +16,7 @@ import { pgUpdate, } from '../Postgres/Postgres.node.functions'; -import * as pgPromise from 'pg-promise'; +import pgPromise from 'pg-promise'; export class CrateDb implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/DateTime/DateTime.node.ts b/packages/nodes-base/nodes/DateTime/DateTime.node.ts index 89e9def2c4..03e9823f83 100644 --- a/packages/nodes-base/nodes/DateTime/DateTime.node.ts +++ b/packages/nodes-base/nodes/DateTime/DateTime.node.ts @@ -17,7 +17,7 @@ import { set, } from 'lodash'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class DateTime implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Discourse/Discourse.node.ts b/packages/nodes-base/nodes/Discourse/Discourse.node.ts index 950b8aa9d2..5bc4d350af 100644 --- a/packages/nodes-base/nodes/Discourse/Discourse.node.ts +++ b/packages/nodes-base/nodes/Discourse/Discourse.node.ts @@ -45,7 +45,7 @@ import { userGroupOperations, } from './UserGroupDescription'; -//import * as moment from 'moment'; +//import moment from 'moment'; export class Discourse implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/EditImage/EditImage.node.ts b/packages/nodes-base/nodes/EditImage/EditImage.node.ts index b4a36928b1..935c1ba64d 100644 --- a/packages/nodes-base/nodes/EditImage/EditImage.node.ts +++ b/packages/nodes-base/nodes/EditImage/EditImage.node.ts @@ -12,7 +12,7 @@ import { INodeTypeDescription, NodeOperationError, } from 'n8n-workflow'; -import * as gm from 'gm'; +import gm from 'gm'; import { file } from 'tmp-promise'; import { parse as pathParse, diff --git a/packages/nodes-base/nodes/Egoi/Egoi.node.ts b/packages/nodes-base/nodes/Egoi/Egoi.node.ts index d798850fb4..c4ac073776 100644 --- a/packages/nodes-base/nodes/Egoi/Egoi.node.ts +++ b/packages/nodes-base/nodes/Egoi/Egoi.node.ts @@ -22,7 +22,7 @@ import { ICreateMemberBody, } from './Interfaces'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class Egoi implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/EmailReadImap/EmailReadImap.node.ts b/packages/nodes-base/nodes/EmailReadImap/EmailReadImap.node.ts index 3cd39dfb9b..c6f63fe64c 100644 --- a/packages/nodes-base/nodes/EmailReadImap/EmailReadImap.node.ts +++ b/packages/nodes-base/nodes/EmailReadImap/EmailReadImap.node.ts @@ -1,13 +1,15 @@ import { ITriggerFunctions } from 'n8n-core'; import { + createDeferredPromise, IBinaryData, IBinaryKeyData, IDataObject, + IDeferredPromise, INodeExecutionData, INodeType, INodeTypeDescription, ITriggerResponse, - LoggerProxy, + LoggerProxy as Logger, NodeOperationError, } from 'n8n-workflow'; @@ -23,11 +25,7 @@ import { Source as ParserSource, } from 'mailparser'; -import * as lodash from 'lodash'; - -import { - LoggerProxy as Logger -} from 'n8n-workflow'; +import _ from 'lodash'; export class EmailReadImap implements INodeType { description: INodeTypeDescription = { @@ -288,7 +286,7 @@ export class EmailReadImap implements INodeType { if (staticData.lastMessageUid === undefined || staticData.lastMessageUid as number < message.attributes.uid) { staticData.lastMessageUid = message.attributes.uid; } - const part = lodash.find(message.parts, { which: '' }); + const part = _.find(message.parts, { which: '' }); if (part === undefined) { throw new NodeOperationError(this.getNode(), 'Email part could not be parsed.'); @@ -358,7 +356,7 @@ export class EmailReadImap implements INodeType { if (staticData.lastMessageUid === undefined || staticData.lastMessageUid as number < message.attributes.uid) { staticData.lastMessageUid = message.attributes.uid; } - const part = lodash.find(message.parts, { which: 'TEXT' }); + const part = _.find(message.parts, { which: 'TEXT' }); if (part === undefined) { throw new NodeOperationError(this.getNode(), 'Email part could not be parsed.'); @@ -377,6 +375,8 @@ export class EmailReadImap implements INodeType { return newEmails; }; + const returnedPromise: IDeferredPromise | undefined = await createDeferredPromise(); + const establishConnection = (): Promise => { let searchCriteria = [ @@ -425,7 +425,11 @@ export class EmailReadImap implements INodeType { } } catch (error) { Logger.error('Email Read Imap node encountered an error fetching new emails', { error }); - throw error; + // Wait with resolving till the returnedPromise got resolved, else n8n will be unhappy + // if it receives an error before the workflow got activated + returnedPromise.promise().then(() => { + this.emitError(error as Error); + }); } } }, @@ -475,10 +479,12 @@ export class EmailReadImap implements INodeType { await connection.end(); } + // Resolve returned-promise so that waiting errors can be emitted + returnedPromise.resolve(); + return { closeFunction, }; - } } diff --git a/packages/nodes-base/nodes/EmailSend/EmailSend.node.ts b/packages/nodes-base/nodes/EmailSend/EmailSend.node.ts index a6abae2159..5d459b44ee 100644 --- a/packages/nodes-base/nodes/EmailSend/EmailSend.node.ts +++ b/packages/nodes-base/nodes/EmailSend/EmailSend.node.ts @@ -8,7 +8,7 @@ import { } from 'n8n-workflow'; import { createTransport } from 'nodemailer'; -import SMTPTransport = require('nodemailer/lib/smtp-transport'); +import SMTPTransport from 'nodemailer/lib/smtp-transport'; export class EmailSend implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Emelia/CampaignDescription.ts b/packages/nodes-base/nodes/Emelia/CampaignDescription.ts index 2fc0826e12..df2b46f77b 100644 --- a/packages/nodes-base/nodes/Emelia/CampaignDescription.ts +++ b/packages/nodes-base/nodes/Emelia/CampaignDescription.ts @@ -9,6 +9,7 @@ export const campaignOperations: INodeProperties[] = [ type: 'options', default: 'get', description: 'Operation to perform', + noDataExpression: true, options: [ { name: 'Add Contact', @@ -18,6 +19,10 @@ export const campaignOperations: INodeProperties[] = [ name: 'Create', value: 'create', }, + { + name: 'Duplicate', + value: 'duplicate', + }, { name: 'Get', value: 'get', @@ -58,7 +63,7 @@ export const campaignFields: INodeProperties[] = [ }, default: [], required: true, - description: 'The ID of the campaign to add the contact to.', + description: 'The ID of the campaign to add the contact to', displayOptions: { show: { resource: [ @@ -76,7 +81,7 @@ export const campaignFields: INodeProperties[] = [ type: 'string', required: true, default: '', - description: 'The email of the contact to add to the campaign.', + description: 'The email of the contact to add to the campaign', displayOptions: { show: { resource: [ @@ -113,7 +118,7 @@ export const campaignFields: INodeProperties[] = [ typeOptions: { multipleValues: true, }, - description: 'Filter by custom fields ', + description: 'Filter by custom fields', default: {}, options: [ { @@ -125,14 +130,14 @@ export const campaignFields: INodeProperties[] = [ name: 'fieldName', type: 'string', default: '', - description: 'The name of the field to add custom field to.', + description: 'The name of the field to add custom field to', }, { displayName: 'Value', name: 'value', type: 'string', default: '', - description: 'The value to set on custom field.', + description: 'The value to set on custom field', }, ], }, @@ -143,49 +148,49 @@ export const campaignFields: INodeProperties[] = [ name: 'firstName', type: 'string', default: '', - description: 'First name of the contact to add.', + description: 'First name of the contact to add', + }, + { + displayName: 'Last Contacted', + name: 'lastContacted', + type: 'dateTime', + default: '', + description: 'Last contacted date of the contact to add', }, { displayName: 'Last Name', name: 'lastName', type: 'string', default: '', - description: 'Last name of the contact to add.', - }, - { - displayName: 'Last Contacted', - name: 'lastContacted', - type: 'string', - default: '', - description: 'Last contacted date of the contact to add.', + description: 'Last name of the contact to add', }, { displayName: 'Last Open', name: 'lastOpen', - type: 'string', + type: 'dateTime', default: '', - description: 'Last opened date of the contact to add.', + description: 'Last opened date of the contact to add', }, { displayName: 'Last Replied', name: 'lastReplied', - type: 'string', + type: 'dateTime', default: '', - description: 'Last replied date of the contact to add.', + description: 'Last replied date of the contact to add', }, { displayName: 'Mails Sent', name: 'mailsSent', type: 'number', default: 0, - description: 'Number of emails sent to the contact to add.', + description: 'Number of emails sent to the contact to add', }, { displayName: 'Phone Number', name: 'phoneNumber', type: 'string', default: '', - description: 'Phone number of the contact to add.', + description: 'Phone number of the contact to add', }, ], }, @@ -199,7 +204,7 @@ export const campaignFields: INodeProperties[] = [ type: 'string', required: true, default: '', - description: 'The name of the campaign to create.', + description: 'The name of the campaign to create', displayOptions: { show: { resource: [ @@ -221,7 +226,7 @@ export const campaignFields: INodeProperties[] = [ type: 'string', default: '', required: true, - description: 'The ID of the campaign to retrieve.', + description: 'The ID of the campaign to retrieve', displayOptions: { show: { resource: [ @@ -242,7 +247,7 @@ export const campaignFields: INodeProperties[] = [ name: 'returnAll', type: 'boolean', default: false, - description: 'Return all results.', + description: 'Whether to return all results or only up to a given limit', displayOptions: { show: { resource: [ @@ -259,7 +264,7 @@ export const campaignFields: INodeProperties[] = [ name: 'limit', type: 'number', default: 100, - description: 'The number of results to return.', + description: 'Max number of results to return', typeOptions: { minValue: 1, maxValue: 100, @@ -323,4 +328,93 @@ export const campaignFields: INodeProperties[] = [ }, }, + // ---------------------------------- + // campaign: duplicate + // ---------------------------------- + { + displayName: 'Campaign ID', + name: 'campaignId', + type: 'options', + default: '', + required: true, + description: 'The ID of the campaign to duplicate', + typeOptions: { + loadOptionsMethod: 'getCampaigns', + }, + displayOptions: { + show: { + resource: [ + 'campaign', + ], + operation: [ + 'duplicate', + ], + }, + }, + }, + { + displayName: 'New Campaign Name', + name: 'campaignName', + type: 'string', + required: true, + default: '', + description: 'The name of the new campaign to create', + displayOptions: { + show: { + resource: [ + 'campaign', + ], + operation: [ + 'duplicate', + ], + }, + }, + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + default: {}, + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'duplicate', + ], + resource: [ + 'campaign', + ], + }, + }, + options: [ + { + displayName: 'Copy Contacts', + name: 'copyContacts', + type: 'boolean', + default: false, + description: 'Whether to copy all the contacts from the original campaign', + }, + { + displayName: 'Copy Email Provider', + name: 'copyProvider', + type: 'boolean', + default: true, + description: 'Whether to set the same email provider than the original campaign', + }, + { + displayName: 'Copy Email Sequence', + name: 'copyMails', + type: 'boolean', + default: true, + description: 'Whether to copy all the steps of the email sequence from the original campaign', + }, + { + displayName: 'Copy Global Settings', + name: 'copySettings', + type: 'boolean', + default: true, + description: 'Whether to copy all the general settings from the original campaign', + }, + ], + }, ]; diff --git a/packages/nodes-base/nodes/Emelia/ContactListDescription.ts b/packages/nodes-base/nodes/Emelia/ContactListDescription.ts index a303f39937..f48d9c7c49 100644 --- a/packages/nodes-base/nodes/Emelia/ContactListDescription.ts +++ b/packages/nodes-base/nodes/Emelia/ContactListDescription.ts @@ -7,8 +7,9 @@ export const contactListOperations: INodeProperties[] = [ displayName: 'Operation', name: 'operation', type: 'options', - default: 'get', + default: 'getAll', description: 'Operation to perform', + noDataExpression: true, options: [ { name: 'Add', @@ -42,7 +43,7 @@ export const contactListFields: INodeProperties[] = [ }, default: [], required: true, - description: 'The ID of the contact list to add the contact to.', + description: 'The ID of the contact list to add the contact to', displayOptions: { show: { resource: [ @@ -60,7 +61,7 @@ export const contactListFields: INodeProperties[] = [ type: 'string', required: true, default: '', - description: 'The email of the contact to add to the contact list.', + description: 'The email of the contact to add to the contact list', displayOptions: { show: { resource: [ @@ -97,7 +98,7 @@ export const contactListFields: INodeProperties[] = [ typeOptions: { multipleValues: true, }, - description: 'Filter by custom fields ', + description: 'Filter by custom fields', default: {}, options: [ { @@ -109,14 +110,14 @@ export const contactListFields: INodeProperties[] = [ name: 'fieldName', type: 'string', default: '', - description: 'The name of the field to add custom field to.', + description: 'The name of the field to add custom field to', }, { displayName: 'Value', name: 'value', type: 'string', default: '', - description: 'The value to set on custom field.', + description: 'The value to set on custom field', }, ], }, @@ -127,49 +128,49 @@ export const contactListFields: INodeProperties[] = [ name: 'firstName', type: 'string', default: '', - description: 'First name of the contact to add.', - }, - { - displayName: 'Last Name', - name: 'lastName', - type: 'string', - default: '', - description: 'Last name of the contact to add.', + description: 'First name of the contact to add', }, { displayName: 'Last Contacted', name: 'lastContacted', type: 'dateTime', default: '', - description: 'Last contacted date of the contact to add.', + description: 'Last contacted date of the contact to add', + }, + { + displayName: 'Last Name', + name: 'lastName', + type: 'string', + default: '', + description: 'Last name of the contact to add', }, { displayName: 'Last Open', name: 'lastOpen', type: 'dateTime', default: '', - description: 'Last opened date of the contact to add.', + description: 'Last opened date of the contact to add', }, { displayName: 'Last Replied', name: 'lastReplied', type: 'dateTime', default: '', - description: 'Last replied date of the contact to add.', + description: 'Last replied date of the contact to add', }, { displayName: 'Mails Sent', name: 'mailsSent', type: 'number', default: 0, - description: 'Number of emails sent to the contact to add.', + description: 'Number of emails sent to the contact to add', }, { displayName: 'Phone Number', name: 'phoneNumber', type: 'string', default: '', - description: 'Phone number of the contact to add.', + description: 'Phone number of the contact to add', }, ], }, @@ -182,7 +183,7 @@ export const contactListFields: INodeProperties[] = [ name: 'returnAll', type: 'boolean', default: false, - description: 'Return all results.', + description: 'Whether to return all results or only up to a given limit', displayOptions: { show: { resource: [ @@ -199,7 +200,7 @@ export const contactListFields: INodeProperties[] = [ name: 'limit', type: 'number', default: 100, - description: 'The number of results to return.', + description: 'Max number of results to return', typeOptions: { minValue: 1, maxValue: 100, diff --git a/packages/nodes-base/nodes/Emelia/Emelia.node.ts b/packages/nodes-base/nodes/Emelia/Emelia.node.ts index 53c0c4d603..d2d54e4dd1 100644 --- a/packages/nodes-base/nodes/Emelia/Emelia.node.ts +++ b/packages/nodes-base/nodes/Emelia/Emelia.node.ts @@ -7,10 +7,12 @@ import { ILoadOptionsFunctions, INodeExecutionData, INodeType, - INodeTypeDescription + INodeTypeDescription, + JsonObject } from 'n8n-workflow'; import { + emeliaApiTest, emeliaGraphqlRequest, loadResource, } from './GenericFunctions'; @@ -36,7 +38,7 @@ export class Emelia implements INodeType { icon: 'file:emelia.svg', group: ['input'], version: 1, - subtitle: '={{$parameter["resource"] + ": " + $parameter["operation"]}}', + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', description: 'Consume the Emelia API', defaults: { name: 'Emelia', @@ -47,6 +49,7 @@ export class Emelia implements INodeType { { name: 'emeliaApi', required: true, + testedBy: 'emeliaApiTest', }, ], properties: [ @@ -54,6 +57,7 @@ export class Emelia implements INodeType { displayName: 'Resource', name: 'resource', type: 'options', + noDataExpression: true, options: [ { name: 'Campaign', @@ -66,7 +70,7 @@ export class Emelia implements INodeType { ], default: 'campaign', required: true, - description: 'The resource to operate on.', + description: 'The resource to operate on', }, ...campaignOperations, ...campaignFields, @@ -76,6 +80,10 @@ export class Emelia implements INodeType { }; methods = { + credentialTest: { + emeliaApiTest, + }, + loadOptions: { async getCampaigns(this: ILoadOptionsFunctions) { return loadResource.call(this, 'campaign'); @@ -290,6 +298,46 @@ export class Emelia implements INodeType { returnData.push({ success: true }); + } else if (operation === 'duplicate') { + + // ---------------------------------- + // campaign: duplicate + // ---------------------------------- + + const options = this.getNodeParameter('options', i) as IDataObject; + const variables = { + fromId: this.getNodeParameter('campaignId', i), + name: this.getNodeParameter('campaignName', i), + copySettings: true, + copyMails: true, + copyContacts: false, + copyProvider: true, + ...options, + }; + const { data: { duplicateCampaign } } = await emeliaGraphqlRequest.call(this, { + query: ` + mutation duplicateCampaign( + $fromId: ID! + $name: String! + $copySettings: Boolean! + $copyMails: Boolean! + $copyContacts: Boolean! + $copyProvider: Boolean! + ) { + duplicateCampaign( + fromId: $fromId + name: $name + copySettings: $copySettings + copyMails: $copyMails + copyContacts: $copyContacts + copyProvider: $copyProvider + ) + }`, + operationName: 'duplicateCampaign', + variables, + }); + + returnData.push({ _id: duplicateCampaign }); } } else if (resource === 'contactList') { @@ -373,7 +421,7 @@ export class Emelia implements INodeType { } catch (error) { if (this.continueOnFail()) { - returnData.push({ error: error.message }); + returnData.push({ error: (error as JsonObject).message }); continue; } diff --git a/packages/nodes-base/nodes/Emelia/EmeliaTrigger.node.ts b/packages/nodes-base/nodes/Emelia/EmeliaTrigger.node.ts index e9023b5107..c418248f96 100644 --- a/packages/nodes-base/nodes/Emelia/EmeliaTrigger.node.ts +++ b/packages/nodes-base/nodes/Emelia/EmeliaTrigger.node.ts @@ -10,6 +10,7 @@ import { import { emeliaApiRequest, + emeliaApiTest, emeliaGraphqlRequest, } from './GenericFunctions'; @@ -23,6 +24,7 @@ export class EmeliaTrigger implements INodeType { displayName: 'Emelia Trigger', name: 'emeliaTrigger', icon: 'file:emelia.svg', + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', group: ['trigger'], version: 1, description: 'Handle Emelia campaign activity events via webhooks', @@ -35,6 +37,7 @@ export class EmeliaTrigger implements INodeType { { name: 'emeliaApi', required: true, + testedBy: 'emeliaApiTest', }, ], webhooks: [ @@ -93,6 +96,10 @@ export class EmeliaTrigger implements INodeType { }; methods = { + credentialTest: { + emeliaApiTest, + }, + loadOptions: { async getCampaigns(this: ILoadOptionsFunctions): Promise { const responseData = await emeliaGraphqlRequest.call(this, { diff --git a/packages/nodes-base/nodes/Emelia/GenericFunctions.ts b/packages/nodes-base/nodes/Emelia/GenericFunctions.ts index 745dcd5228..a1feb5efa1 100644 --- a/packages/nodes-base/nodes/Emelia/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Emelia/GenericFunctions.ts @@ -4,8 +4,12 @@ import { } from 'n8n-core'; import { + ICredentialsDecrypted, + ICredentialTestFunctions, IHookFunctions, + INodeCredentialTestResult, INodePropertyOptions, + JsonObject, NodeApiError, } from 'n8n-workflow'; @@ -51,7 +55,7 @@ export async function emeliaApiRequest( try { return await this.helpers.request!.call(this, options); } catch (error) { - throw new NodeApiError(this.getNode(), error); + throw new NodeApiError(this.getNode(), (error as JsonObject)); } } @@ -91,5 +95,47 @@ export async function loadResource( name: campaign.name, value: campaign._id, })); - +} + +export async function emeliaApiTest(this: ICredentialTestFunctions, credential: ICredentialsDecrypted): Promise { + const credentials = credential.data; + + const body = { + query: ` + query all_campaigns { + all_campaigns { + _id + name + status + createdAt + stats { + mailsSent + } + } + }`, + operationName: 'all_campaigns', + }; + + const options = { + headers: { + Authorization: credentials?.apiKey, + }, + method: 'POST', + body, + uri: `https://graphql.emelia.io/graphql`, + json: true, + }; + + try { + await this.helpers.request!(options); + } catch (error) { + return { + status: 'Error', + message: `Connection details not valid: ${(error as JsonObject).message}`, + }; + } + return { + status: 'OK', + message: 'Authentication successful!', + }; } diff --git a/packages/nodes-base/nodes/Ftp/Ftp.node.ts b/packages/nodes-base/nodes/Ftp/Ftp.node.ts index c373bb17bf..9925581d13 100644 --- a/packages/nodes-base/nodes/Ftp/Ftp.node.ts +++ b/packages/nodes-base/nodes/Ftp/Ftp.node.ts @@ -13,8 +13,8 @@ import { dirname, } from 'path'; -import * as ftpClient from 'promise-ftp'; -import * as sftpClient from 'ssh2-sftp-client'; +import ftpClient from 'promise-ftp'; +import sftpClient from 'ssh2-sftp-client'; interface ReturnFtpItem { type: string; @@ -51,6 +51,7 @@ export class Ftp implements INodeType { outputs: ['main'], credentials: [ { + // nodelinter-ignore-next-line name: 'ftp', required: true, displayOptions: { @@ -62,6 +63,7 @@ export class Ftp implements INodeType { }, }, { + // nodelinter-ignore-next-line name: 'sftp', required: true, displayOptions: { @@ -124,6 +126,7 @@ export class Ftp implements INodeType { ], default: 'download', description: 'Operation to perform.', + noDataExpression: true, }, // ---------------------------------- @@ -253,6 +256,29 @@ export class Ftp implements INodeType { description: 'The new path', required: true, }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + operation: [ + 'rename', + ], + }, + }, + options: [ + { + displayName: 'Create Directories', + name: 'createDirectories', + type: 'boolean', + default: false, + description: `Recursively create destination directory when renaming an existing file or folder`, + }, + ], + }, // ---------------------------------- // upload @@ -381,8 +407,8 @@ export class Ftp implements INodeType { throw new NodeOperationError(this.getNode(), 'Failed to get credentials!'); } - let ftp : ftpClient; - let sftp : sftpClient; + let ftp: ftpClient; + let sftp: sftpClient; if (protocol === 'sftp') { sftp = new sftpClient(); @@ -452,9 +478,13 @@ export class Ftp implements INodeType { if (operation === 'rename') { const oldPath = this.getNodeParameter('oldPath', i) as string; - + const { createDirectories = false } = this.getNodeParameter('options', i) as { createDirectories: boolean }; const newPath = this.getNodeParameter('newPath', i) as string; + if (createDirectories) { + await recursivelyCreateSftpDirs(sftp!, newPath); + } + responseData = await sftp!.rename(oldPath, newPath); returnItems.push({ json: { success: true } }); @@ -475,16 +505,7 @@ export class Ftp implements INodeType { if (operation === 'upload') { const remotePath = this.getNodeParameter('path', i) as string; - - // Check if dir path exists - const dirPath = dirname(remotePath); - const dirExists = await sftp!.exists(dirPath); - - // If dir does not exist, create all recursively in path - if (!dirExists) { - // Create directory - await sftp!.mkdir(dirPath, true); - } + await recursivelyCreateSftpDirs(sftp!, remotePath); if (this.getNodeParameter('binaryData', i) === true) { // Is binary file to upload @@ -635,7 +656,7 @@ export class Ftp implements INodeType { } catch (error) { if (this.continueOnFail()) { - return this.prepareOutputData([{json:{ error: error.message }}]); + return this.prepareOutputData([{ json: { error: error.message } }]); } throw error; @@ -661,17 +682,17 @@ function normalizeSFtpItem(input: sftpClient.FileInfo, path: string, recursive = } async function callRecursiveList(path: string, client: sftpClient | ftpClient, normalizeFunction: (input: ftpClient.ListingElement & sftpClient.FileInfo, path: string, recursive?: boolean) => void) { - const pathArray : string[] = [path]; + const pathArray: string[] = [path]; let currentPath = path; - const directoryItems : sftpClient.FileInfo[] = []; + const directoryItems: sftpClient.FileInfo[] = []; let index = 0; do { // tslint:disable-next-line: array-type - const returnData : sftpClient.FileInfo[] | (string | ftpClient.ListingElement)[] = await client.list(pathArray[index]); + const returnData: sftpClient.FileInfo[] | (string | ftpClient.ListingElement)[] = await client.list(pathArray[index]); // @ts-ignore - returnData.map((item : sftpClient.FileInfo) => { + returnData.map((item: sftpClient.FileInfo) => { if ((pathArray[index] as string).endsWith('/')) { currentPath = `${pathArray[index]}${item.name}`; } else { @@ -693,3 +714,12 @@ async function callRecursiveList(path: string, client: sftpClient | ftpClient, n return directoryItems; } + +async function recursivelyCreateSftpDirs(sftp: sftpClient, path: string) { + const dirPath = dirname(path); + const dirExists = await sftp!.exists(dirPath); + + if (!dirExists) { + await sftp!.mkdir(dirPath, true); + } +} diff --git a/packages/nodes-base/nodes/GetResponse/GetResponse.node.ts b/packages/nodes-base/nodes/GetResponse/GetResponse.node.ts index 0458a74626..5f4d054c33 100644 --- a/packages/nodes-base/nodes/GetResponse/GetResponse.node.ts +++ b/packages/nodes-base/nodes/GetResponse/GetResponse.node.ts @@ -21,7 +21,7 @@ import { contactOperations, } from './ContactDescription'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class GetResponse implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Ghost/GenericFunctions.ts b/packages/nodes-base/nodes/Ghost/GenericFunctions.ts index 15b93bac21..7560d8276f 100644 --- a/packages/nodes-base/nodes/Ghost/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Ghost/GenericFunctions.ts @@ -13,7 +13,7 @@ import { IDataObject, NodeApiError, } from 'n8n-workflow'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; export async function ghostApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: any = {}, query: IDataObject = {}, uri?: string): Promise { // tslint:disable-line:no-any diff --git a/packages/nodes-base/nodes/Ghost/Ghost.node.ts b/packages/nodes-base/nodes/Ghost/Ghost.node.ts index d9d94174e6..2cb0658660 100644 --- a/packages/nodes-base/nodes/Ghost/Ghost.node.ts +++ b/packages/nodes-base/nodes/Ghost/Ghost.node.ts @@ -23,7 +23,7 @@ import { postOperations, } from './PostDescription'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class Ghost implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/GoToWebinar/GenericFunctions.ts b/packages/nodes-base/nodes/GoToWebinar/GenericFunctions.ts index 82bdf928b3..8ad4380537 100644 --- a/packages/nodes-base/nodes/GoToWebinar/GenericFunctions.ts +++ b/packages/nodes-base/nodes/GoToWebinar/GenericFunctions.ts @@ -14,7 +14,7 @@ import { OptionsWithUri, } from 'request'; -import * as moment from 'moment'; +import moment from 'moment'; import * as losslessJSON from 'lossless-json'; diff --git a/packages/nodes-base/nodes/GoToWebinar/GoToWebinar.node.ts b/packages/nodes-base/nodes/GoToWebinar/GoToWebinar.node.ts index 00d44ae852..8de6664ae7 100644 --- a/packages/nodes-base/nodes/GoToWebinar/GoToWebinar.node.ts +++ b/packages/nodes-base/nodes/GoToWebinar/GoToWebinar.node.ts @@ -43,7 +43,7 @@ import { omit, } from 'lodash'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class GoToWebinar implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Google/Analytics/GoogleAnalytics.node.ts b/packages/nodes-base/nodes/Google/Analytics/GoogleAnalytics.node.ts index 0050abe1ca..0c5f39fd8a 100644 --- a/packages/nodes-base/nodes/Google/Analytics/GoogleAnalytics.node.ts +++ b/packages/nodes-base/nodes/Google/Analytics/GoogleAnalytics.node.ts @@ -28,7 +28,7 @@ import { simplify, } from './GenericFunctions'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; import { IData, diff --git a/packages/nodes-base/nodes/Google/Books/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Books/GenericFunctions.ts index a387aa71c3..12ccbcd9d7 100644 --- a/packages/nodes-base/nodes/Google/Books/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Books/GenericFunctions.ts @@ -12,9 +12,9 @@ import { IDataObject, NodeApiError, NodeOperationError, } from 'n8n-workflow'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; interface IGoogleAuthCredentials { delegatedEmail?: string; diff --git a/packages/nodes-base/nodes/Google/Calendar/GoogleCalendar.node.ts b/packages/nodes-base/nodes/Google/Calendar/GoogleCalendar.node.ts index 6fb5e949a0..dbd031de54 100644 --- a/packages/nodes-base/nodes/Google/Calendar/GoogleCalendar.node.ts +++ b/packages/nodes-base/nodes/Google/Calendar/GoogleCalendar.node.ts @@ -33,7 +33,7 @@ import { IEvent, } from './EventInterface'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; import { v4 as uuid } from 'uuid'; import { moveMessagePortToContext } from 'worker_threads'; diff --git a/packages/nodes-base/nodes/Google/Calendar/GoogleCalendarTrigger.node.ts b/packages/nodes-base/nodes/Google/Calendar/GoogleCalendarTrigger.node.ts index 8aac097caa..1cf9103b13 100644 --- a/packages/nodes-base/nodes/Google/Calendar/GoogleCalendarTrigger.node.ts +++ b/packages/nodes-base/nodes/Google/Calendar/GoogleCalendarTrigger.node.ts @@ -16,7 +16,7 @@ import { googleApiRequestAllItems, } from './GenericFunctions'; -import * as moment from 'moment'; +import moment from 'moment'; export class GoogleCalendarTrigger implements INodeType { description: INodeTypeDescription = { @@ -211,4 +211,4 @@ export class GoogleCalendarTrigger implements INodeType { return null; } -} \ No newline at end of file +} diff --git a/packages/nodes-base/nodes/Google/Chat/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Chat/GenericFunctions.ts index f0ac35ac25..e78e93c3d5 100644 --- a/packages/nodes-base/nodes/Google/Chat/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Chat/GenericFunctions.ts @@ -17,9 +17,9 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; interface IGoogleAuthCredentials { delegatedEmail?: string; diff --git a/packages/nodes-base/nodes/Google/Chat/GoogleChat.node.ts b/packages/nodes-base/nodes/Google/Chat/GoogleChat.node.ts index 3958199048..ffe7f6161b 100644 --- a/packages/nodes-base/nodes/Google/Chat/GoogleChat.node.ts +++ b/packages/nodes-base/nodes/Google/Chat/GoogleChat.node.ts @@ -45,9 +45,9 @@ import { validateJSON, } from './GenericFunctions'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; export class GoogleChat implements INodeType { description: INodeTypeDescription = { displayName: 'Google Chat', diff --git a/packages/nodes-base/nodes/Google/Contacts/GoogleContacts.node.ts b/packages/nodes-base/nodes/Google/Contacts/GoogleContacts.node.ts index fe965815b4..052db75133 100644 --- a/packages/nodes-base/nodes/Google/Contacts/GoogleContacts.node.ts +++ b/packages/nodes-base/nodes/Google/Contacts/GoogleContacts.node.ts @@ -23,7 +23,7 @@ import { contactOperations, } from './ContactDescription'; -import * as moment from 'moment'; +import moment from 'moment'; import { IData } from '../Analytics/Interfaces'; export class GoogleContacts implements INodeType { diff --git a/packages/nodes-base/nodes/Google/Docs/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Docs/GenericFunctions.ts index 0a49079e92..1a193c091c 100644 --- a/packages/nodes-base/nodes/Google/Docs/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Docs/GenericFunctions.ts @@ -13,9 +13,9 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; interface IGoogleAuthCredentials { delegatedEmail?: string; diff --git a/packages/nodes-base/nodes/Google/Drive/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Drive/GenericFunctions.ts index 73a86434d8..48ef48a8c6 100644 --- a/packages/nodes-base/nodes/Google/Drive/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Drive/GenericFunctions.ts @@ -15,9 +15,9 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; interface IGoogleAuthCredentials { delegatedEmail?: string; diff --git a/packages/nodes-base/nodes/Google/Drive/GoogleDriveTrigger.node.ts b/packages/nodes-base/nodes/Google/Drive/GoogleDriveTrigger.node.ts index 6d27fae8b2..939e8d0e03 100644 --- a/packages/nodes-base/nodes/Google/Drive/GoogleDriveTrigger.node.ts +++ b/packages/nodes-base/nodes/Google/Drive/GoogleDriveTrigger.node.ts @@ -18,7 +18,7 @@ import { googleApiRequestAllItems, } from './GenericFunctions'; -import * as moment from 'moment'; +import moment from 'moment'; export class GoogleDriveTrigger implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GenericFunctions.ts index 4c5501dbaf..1af2cb7fa6 100644 --- a/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Firebase/CloudFirestore/GenericFunctions.ts @@ -12,7 +12,7 @@ import { IDataObject, NodeApiError, } from 'n8n-workflow'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export async function googleApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri: string | null = null): Promise { // tslint:disable-line:no-any diff --git a/packages/nodes-base/nodes/Google/Gmail/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Gmail/GenericFunctions.ts index 72d7eb5b84..5ea259adb2 100644 --- a/packages/nodes-base/nodes/Google/Gmail/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Gmail/GenericFunctions.ts @@ -24,9 +24,9 @@ import { IEmail, } from './Gmail.node'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; interface IGoogleAuthCredentials { delegatedEmail?: string; diff --git a/packages/nodes-base/nodes/Google/Sheet/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Sheet/GenericFunctions.ts index 81aa75a506..5e34987d76 100644 --- a/packages/nodes-base/nodes/Google/Sheet/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Sheet/GenericFunctions.ts @@ -13,9 +13,9 @@ import { IDataObject, NodeApiError, NodeOperationError, } from 'n8n-workflow'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; export interface IGoogleAuthCredentials { delegatedEmail?: string; diff --git a/packages/nodes-base/nodes/Google/Slides/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Slides/GenericFunctions.ts index 629d8c8c12..66d7a57fa4 100644 --- a/packages/nodes-base/nodes/Google/Slides/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Slides/GenericFunctions.ts @@ -14,9 +14,9 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; interface IGoogleAuthCredentials { delegatedEmail?: string; diff --git a/packages/nodes-base/nodes/Google/Task/GoogleTasks.node.ts b/packages/nodes-base/nodes/Google/Task/GoogleTasks.node.ts index b7aff3e732..98f256f224 100644 --- a/packages/nodes-base/nodes/Google/Task/GoogleTasks.node.ts +++ b/packages/nodes-base/nodes/Google/Task/GoogleTasks.node.ts @@ -171,7 +171,7 @@ export class GoogleTasks implements INodeType { //https://developers.google.com/tasks/v1/reference/tasks/list const returnAll = this.getNodeParameter('returnAll', i) as boolean; const taskListId = this.getNodeParameter('task', i) as string; - const options = this.getNodeParameter( + const { showCompleted = true, showDeleted = false, showHidden = false, ...options } = this.getNodeParameter( 'additionalFields', i, ) as IDataObject; @@ -187,15 +187,11 @@ export class GoogleTasks implements INodeType { if (options.dueMax) { qs.dueMax = options.dueMax as string; } - if (options.showCompleted) { - qs.showCompleted = options.showCompleted as boolean; - } - if (options.showDeleted) { - qs.showDeleted = options.showDeleted as boolean; - } - if (options.showHidden) { - qs.showHidden = options.showHidden as boolean; - } + + qs.showCompleted = showCompleted; + qs.showDeleted = showDeleted; + qs.showHidden = showHidden; + if (options.updatedMin) { qs.updatedMin = options.updatedMin as string; } diff --git a/packages/nodes-base/nodes/Google/Task/TaskDescription.ts b/packages/nodes-base/nodes/Google/Task/TaskDescription.ts index c757365df7..87fd42e828 100644 --- a/packages/nodes-base/nodes/Google/Task/TaskDescription.ts +++ b/packages/nodes-base/nodes/Google/Task/TaskDescription.ts @@ -76,6 +76,16 @@ export const taskFields: INodeProperties[] = [ type: 'string', default: '', description: 'Title of the task.', + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'task', + ], + }, + }, }, { displayName: 'Additional Fields', @@ -350,21 +360,21 @@ export const taskFields: INodeProperties[] = [ name: 'showCompleted', type: 'boolean', default: true, - description: 'Flag indicating whether completed tasks are returned in the result', + description: 'Flag indicating whether completed tasks are returned in the result. Show Hidden must also be True to show tasks completed in first party clients such as the web UI or Google\'s mobile apps.', }, { displayName: 'Show Deleted', name: 'showDeleted', type: 'boolean', default: false, - description: 'Flag indicating whether deleted tasks are returned in the result', + description: 'Flag indicating whether deleted tasks are returned in the result.', }, { displayName: 'Show Hidden', name: 'showHidden', type: 'boolean', default: false, - description: 'Flag indicating whether hidden tasks are returned in the result', + description: 'Flag indicating whether hidden tasks are returned in the result.', }, { displayName: 'Updated Min', diff --git a/packages/nodes-base/nodes/Google/Translate/GenericFunctions.ts b/packages/nodes-base/nodes/Google/Translate/GenericFunctions.ts index 50ab4c153c..940e36c18b 100644 --- a/packages/nodes-base/nodes/Google/Translate/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Google/Translate/GenericFunctions.ts @@ -12,9 +12,9 @@ import { IDataObject, NodeApiError, NodeOperationError, } from 'n8n-workflow'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; interface IGoogleAuthCredentials { delegatedEmail?: string; diff --git a/packages/nodes-base/nodes/GraphQL/GraphQL.node.ts b/packages/nodes-base/nodes/GraphQL/GraphQL.node.ts index 92df9d1814..7048d9461f 100644 --- a/packages/nodes-base/nodes/GraphQL/GraphQL.node.ts +++ b/packages/nodes-base/nodes/GraphQL/GraphQL.node.ts @@ -4,6 +4,7 @@ import { INodeExecutionData, INodeType, INodeTypeDescription, + JsonObject, NodeApiError, NodeOperationError, } from 'n8n-workflow'; @@ -412,17 +413,22 @@ export class GraphQL implements INodeType { } else { if (typeof response === 'string') { try { - returnItems.push({ json: JSON.parse(response) }); + response = JSON.parse(response); } catch (error) { throw new NodeOperationError(this.getNode(), 'Response body is not valid JSON. Change "Response Format" to "String"'); } - } else { - returnItems.push({ json: response }); } + + if (response.errors) { + const message = response.errors?.map((error: IDataObject) => error.message).join(', ') || 'Unexpected error'; + throw new NodeApiError(this.getNode(), response.errors, { message }); + } + + returnItems.push({ json: response }); } } catch (error) { if (this.continueOnFail()) { - returnItems.push({ json: { error: error.message } }); + returnItems.push({ json: { error: (error as JsonObject).message } }); continue; } throw error; diff --git a/packages/nodes-base/nodes/HtmlExtract/HtmlExtract.node.ts b/packages/nodes-base/nodes/HtmlExtract/HtmlExtract.node.ts index d3d2f1900c..3a9e92348f 100644 --- a/packages/nodes-base/nodes/HtmlExtract/HtmlExtract.node.ts +++ b/packages/nodes-base/nodes/HtmlExtract/HtmlExtract.node.ts @@ -1,4 +1,4 @@ -import * as cheerio from 'cheerio'; +import cheerio from 'cheerio'; import { IExecuteFunctions } from 'n8n-core'; import { IDataObject, diff --git a/packages/nodes-base/nodes/Hubspot/GenericFunctions.ts b/packages/nodes-base/nodes/Hubspot/GenericFunctions.ts index 64c75a1633..c37d7a19fe 100644 --- a/packages/nodes-base/nodes/Hubspot/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Hubspot/GenericFunctions.ts @@ -17,7 +17,7 @@ import { NodeApiError, } from 'n8n-workflow'; -import * as moment from 'moment'; +import moment from 'moment'; export async function hubspotApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: any = {}, query: IDataObject = {}, uri?: string): Promise { // tslint:disable-line:no-any diff --git a/packages/nodes-base/nodes/ICalendar/ICalendar.node.ts b/packages/nodes-base/nodes/ICalendar/ICalendar.node.ts index c6ec87c60e..15c9012436 100644 --- a/packages/nodes-base/nodes/ICalendar/ICalendar.node.ts +++ b/packages/nodes-base/nodes/ICalendar/ICalendar.node.ts @@ -13,7 +13,7 @@ import { promisify, } from 'util'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; import * as ics from 'ics'; diff --git a/packages/nodes-base/nodes/If/If.node.ts b/packages/nodes-base/nodes/If/If.node.ts index 9187597487..b623027e7c 100644 --- a/packages/nodes-base/nodes/If/If.node.ts +++ b/packages/nodes-base/nodes/If/If.node.ts @@ -1,4 +1,4 @@ -import moment = require('moment'); +import moment from 'moment'; import { IExecuteFunctions } from 'n8n-core'; import { INodeExecutionData, @@ -133,7 +133,7 @@ export class If implements INodeType { value: 'smaller', }, { - name: 'Smaller Equal', + name: 'Smaller or Equal', value: 'smallerEqual', }, { @@ -149,7 +149,7 @@ export class If implements INodeType { value: 'larger', }, { - name: 'Larger Equal', + name: 'Larger or Equal', value: 'largerEqual', }, { diff --git a/packages/nodes-base/nodes/Iterable/Iterable.node.ts b/packages/nodes-base/nodes/Iterable/Iterable.node.ts index 5ef0c067da..051c010112 100644 --- a/packages/nodes-base/nodes/Iterable/Iterable.node.ts +++ b/packages/nodes-base/nodes/Iterable/Iterable.node.ts @@ -32,7 +32,7 @@ import { userListOperations, } from './UserListDescription'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class Iterable implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Keap/Keap.node.ts b/packages/nodes-base/nodes/Keap/Keap.node.ts index 99102466a8..8b314f2540 100644 --- a/packages/nodes-base/nodes/Keap/Keap.node.ts +++ b/packages/nodes-base/nodes/Keap/Keap.node.ts @@ -100,7 +100,7 @@ import { pascalCase, } from 'change-case'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class Keap implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/KoBoToolbox/GenericFunctions.ts b/packages/nodes-base/nodes/KoBoToolbox/GenericFunctions.ts index db5fe25363..0fbf61e697 100644 --- a/packages/nodes-base/nodes/KoBoToolbox/GenericFunctions.ts +++ b/packages/nodes-base/nodes/KoBoToolbox/GenericFunctions.ts @@ -12,7 +12,7 @@ import { IWebhookFunctions, } from 'n8n-workflow'; -import * as _ from 'lodash'; +import _ from 'lodash'; export async function koBoToolboxApiRequest(this: IExecuteFunctions | IWebhookFunctions | IHookFunctions | ILoadOptionsFunctions, option: IDataObject = {}): Promise { // tslint:disable-line:no-any const credentials = await this.getCredentials('koBoToolboxApi') as IDataObject; diff --git a/packages/nodes-base/nodes/Linear/GenericFunctions.ts b/packages/nodes-base/nodes/Linear/GenericFunctions.ts index 7aa1619bed..666299260f 100644 --- a/packages/nodes-base/nodes/Linear/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Linear/GenericFunctions.ts @@ -17,9 +17,9 @@ import { NodeApiError, } from 'n8n-workflow'; -import get = require('lodash.get'); +import get from 'lodash.get'; -import { +import { query, } from './Queries'; diff --git a/packages/nodes-base/nodes/MQTT/Mqtt.node.ts b/packages/nodes-base/nodes/MQTT/Mqtt.node.ts index 41d7a815a5..a090532cd0 100644 --- a/packages/nodes-base/nodes/MQTT/Mqtt.node.ts +++ b/packages/nodes-base/nodes/MQTT/Mqtt.node.ts @@ -9,7 +9,7 @@ import { INodeTypeDescription, } from 'n8n-workflow'; -import * as mqtt from 'mqtt'; +import mqtt from 'mqtt'; import { IClientOptions, diff --git a/packages/nodes-base/nodes/MQTT/MqttTrigger.node.ts b/packages/nodes-base/nodes/MQTT/MqttTrigger.node.ts index 0225c8ce70..104f82437e 100644 --- a/packages/nodes-base/nodes/MQTT/MqttTrigger.node.ts +++ b/packages/nodes-base/nodes/MQTT/MqttTrigger.node.ts @@ -10,7 +10,7 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as mqtt from 'mqtt'; +import mqtt from 'mqtt'; import { IClientOptions, ISubscriptionMap, diff --git a/packages/nodes-base/nodes/Magento/GenericFunctions.ts b/packages/nodes-base/nodes/Magento/GenericFunctions.ts index cf09bba885..4a7353a507 100644 --- a/packages/nodes-base/nodes/Magento/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Magento/GenericFunctions.ts @@ -28,10 +28,6 @@ export async function magentoApiRequest(this: IWebhookFunctions | IHookFunctions const credentials = await this.getCredentials('magento2Api') as IDataObject; let options: OptionsWithUri = { - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${credentials.accessToken}`, - }, method, body, qs, @@ -45,7 +41,7 @@ export async function magentoApiRequest(this: IWebhookFunctions | IHookFunctions delete options.body; } //@ts-ignore - return await this.helpers.request.call(this, options); + return await this.helpers.requestWithAuthentication.call(this, 'magento2Api', options); } catch (error) { throw new NodeApiError(this.getNode(), error); } diff --git a/packages/nodes-base/nodes/Magento/Magento2.node.ts b/packages/nodes-base/nodes/Magento/Magento2.node.ts index 5b0440127e..b1ac7c9410 100644 --- a/packages/nodes-base/nodes/Magento/Magento2.node.ts +++ b/packages/nodes-base/nodes/Magento/Magento2.node.ts @@ -1,10 +1,18 @@ +import { + OptionsWithUri, +} from 'request'; + + import { IExecuteFunctions, } from 'n8n-core'; import { + ICredentialsDecrypted, + ICredentialTestFunctions, IDataObject, ILoadOptionsFunctions, + INodeCredentialTestResult, INodeExecutionData, INodePropertyOptions, INodeType, diff --git a/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts b/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts index 966479ee16..fdca21ebee 100644 --- a/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts +++ b/packages/nodes-base/nodes/Mailchimp/Mailchimp.node.ts @@ -19,7 +19,7 @@ import { validateJSON, } from './GenericFunctions'; -import * as moment from 'moment'; +import moment from 'moment'; enum Status { subscribe = 'subscribe', diff --git a/packages/nodes-base/nodes/Mandrill/GenericFunctions.ts b/packages/nodes-base/nodes/Mandrill/GenericFunctions.ts index e4730f64c8..fe7899e517 100644 --- a/packages/nodes-base/nodes/Mandrill/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Mandrill/GenericFunctions.ts @@ -8,7 +8,7 @@ import { ILoadOptionsFunctions, } from 'n8n-core'; -import * as _ from 'lodash'; +import _ from 'lodash'; import { NodeApiError, NodeOperationError, } from 'n8n-workflow'; export async function mandrillApiRequest(this: IExecuteFunctions | IHookFunctions | ILoadOptionsFunctions, resource: string, method: string, action: string, body: any = {}, headers?: object): Promise { // tslint:disable-line:no-any diff --git a/packages/nodes-base/nodes/Mandrill/Mandrill.node.ts b/packages/nodes-base/nodes/Mandrill/Mandrill.node.ts index 1afe56babe..97cc9b1529 100644 --- a/packages/nodes-base/nodes/Mandrill/Mandrill.node.ts +++ b/packages/nodes-base/nodes/Mandrill/Mandrill.node.ts @@ -21,9 +21,9 @@ import { validateJSON } from './GenericFunctions'; -import * as moment from 'moment'; +import moment from 'moment'; -import * as _ from 'lodash'; +import _ from 'lodash'; interface Attachments { type: string; diff --git a/packages/nodes-base/nodes/Matrix/GenericFunctions.ts b/packages/nodes-base/nodes/Matrix/GenericFunctions.ts index 3293aff87d..25a0d22a88 100644 --- a/packages/nodes-base/nodes/Matrix/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Matrix/GenericFunctions.ts @@ -10,7 +10,7 @@ import { ILoadOptionsFunctions, } from 'n8n-core'; -import * as _ from 'lodash'; +import _ from 'lodash'; import { v4 as uuid } from 'uuid'; diff --git a/packages/nodes-base/nodes/Mautic/GenericFunctions.ts b/packages/nodes-base/nodes/Mautic/GenericFunctions.ts index c0ff315d9e..6b68c00ff9 100644 --- a/packages/nodes-base/nodes/Mautic/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Mautic/GenericFunctions.ts @@ -10,7 +10,11 @@ import { } from 'n8n-core'; import { - IDataObject, JsonObject, NodeApiError, + ICredentialDataDecryptedObject, + ICredentialTestFunctions, + IDataObject, + JsonObject, + NodeApiError, } from 'n8n-workflow'; export async function mauticApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: any = {}, query?: IDataObject, uri?: string): Promise { // tslint:disable-line:no-any @@ -31,19 +35,21 @@ export async function mauticApiRequest(this: IHookFunctions | IExecuteFunctions if (authenticationMethod === 'credentials') { const credentials = await this.getCredentials('mauticApi') as IDataObject; + const baseUrl = credentials!.url as string; const base64Key = Buffer.from(`${credentials.username}:${credentials.password}`).toString('base64'); options.headers!.Authorization = `Basic ${base64Key}`; - options.uri = `${credentials.url}${options.uri}`; + options.uri = `${baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl}${options.uri}`; //@ts-ignore returnData = await this.helpers.request(options); } else { const credentials = await this.getCredentials('mauticOAuth2Api') as IDataObject; + const baseUrl = credentials!.url as string; - options.uri = `${credentials.url}${options.uri}`; + options.uri = `${baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl}${options.uri}`; //@ts-ignore returnData = await this.helpers.requestOAuth2.call(this, 'mauticOAuth2Api', options, { includeCredentialsOnRefreshOnBody: true }); } @@ -96,3 +102,30 @@ export function validateJSON(json: string | undefined): any { // tslint:disable- } return result; } + +export async function validateCredentials(this: ICredentialTestFunctions, decryptedCredentials: ICredentialDataDecryptedObject): Promise { // tslint:disable-line:no-any + const credentials = decryptedCredentials; + + const { + url, + username, + password, + } = credentials as { + url: string, + username: string, + password: string, + }; + + const base64Key = Buffer.from(`${username}:${password}`).toString('base64'); + + const options: OptionsWithUri = { + method: 'GET', + headers: { + Authorization: `Basic ${base64Key}`, + }, + uri: url.endsWith('/') ? `${url}api/users/self` : `${url}/api/users/self`, + json: true, + }; + + return await this.helpers.request(options); +} diff --git a/packages/nodes-base/nodes/Mautic/Mautic.node.ts b/packages/nodes-base/nodes/Mautic/Mautic.node.ts index d84dbdde09..a1ee45190e 100644 --- a/packages/nodes-base/nodes/Mautic/Mautic.node.ts +++ b/packages/nodes-base/nodes/Mautic/Mautic.node.ts @@ -3,8 +3,12 @@ import { } from 'n8n-core'; import { + ICredentialDataDecryptedObject, + ICredentialsDecrypted, + ICredentialTestFunctions, IDataObject, ILoadOptionsFunctions, + INodeCredentialTestResult, INodeExecutionData, INodePropertyOptions, INodeType, @@ -17,6 +21,7 @@ import { import { mauticApiRequest, mauticApiRequestAllItems, + validateCredentials, validateJSON, } from './GenericFunctions'; @@ -80,6 +85,7 @@ export class Mautic implements INodeType { ], }, }, + testedBy: 'mauticCredentialTest', }, { name: 'mauticOAuth2Api', @@ -166,6 +172,29 @@ export class Mautic implements INodeType { }; methods = { + credentialTest: { + async mauticCredentialTest(this: ICredentialTestFunctions, credential: ICredentialsDecrypted): Promise { + try { + let responseData; + responseData = await validateCredentials.call(this, credential.data as ICredentialDataDecryptedObject); + if (responseData.id) { + return { + status: 'OK', + message: 'Authentication successful!', + }; + } + } catch (error) { + return { + status: 'Error', + message: 'Invalid credentials', + }; + } + return { + status: 'Error', + message: 'Invalid credentials', + }; + }, + }, loadOptions: { // Get all the available companies to display them to user so that he can // select them easily diff --git a/packages/nodes-base/nodes/Microsoft/Sql/MicrosoftSql.node.ts b/packages/nodes-base/nodes/Microsoft/Sql/MicrosoftSql.node.ts index 55d9038c52..738e24bc16 100644 --- a/packages/nodes-base/nodes/Microsoft/Sql/MicrosoftSql.node.ts +++ b/packages/nodes-base/nodes/Microsoft/Sql/MicrosoftSql.node.ts @@ -15,7 +15,7 @@ import { flatten, } from '../../utils/utilities'; -import * as mssql from 'mssql'; +import mssql from 'mssql'; import { ITables, diff --git a/packages/nodes-base/nodes/Microsoft/Teams/ChatMessageDescription.ts b/packages/nodes-base/nodes/Microsoft/Teams/ChatMessageDescription.ts new file mode 100644 index 0000000000..7ad4030845 --- /dev/null +++ b/packages/nodes-base/nodes/Microsoft/Teams/ChatMessageDescription.ts @@ -0,0 +1,201 @@ +import { + INodeProperties, +} from 'n8n-workflow'; + +export const chatMessageOperations: INodeProperties[] = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'chatMessage', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a message', + }, + { + name: 'Get', + value: 'get', + description: 'Get a message', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get all messages', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, +]; + +export const chatMessageFields: INodeProperties[] = [ + + /* -------------------------------------------------------------------------- */ + /* chatMessage:create */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Chat ID', + name: 'chatId', + required: true, + type: 'options', + typeOptions: { + loadOptionsMethod: 'getChats', + }, + displayOptions: { + show: { + operation: [ + 'create', + 'get', + ], + resource: [ + 'chatMessage', + ], + }, + }, + default: '', + description: 'Chat ID', + }, + { + displayName: 'Message Type', + name: 'messageType', + required: true, + type: 'options', + options: [ + { + name: 'Text', + value: 'text', + }, + { + name: 'HTML', + value: 'html', + }, + ], + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'chatMessage', + ], + }, + }, + default: '', + description: 'The type of the content', + }, + { + displayName: 'Message', + name: 'message', + required: true, + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + displayOptions: { + show: { + operation: [ + 'create', + ], + resource: [ + 'chatMessage', + ], + }, + }, + default: '', + description: 'The content of the item.', + }, + + /* -------------------------------------------------------------------------- */ + /* chatMessage:get */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Message ID', + name: 'messageId', + required: true, + type: 'string', + displayOptions: { + show: { + operation: [ + 'get', + ], + resource: [ + 'chatMessage', + ], + }, + }, + default: '', + }, + /* -------------------------------------------------------------------------- */ + /* chatMessage:getAll */ + /* -------------------------------------------------------------------------- */ + { + displayName: 'Chat ID', + name: 'chatId', + required: true, + type: 'options', + typeOptions: { + loadOptionsMethod: 'getChats', + }, + displayOptions: { + show: { + operation: [ + 'getAll', + ], + resource: [ + 'chatMessage', + ], + }, + }, + default: '', + description: 'Chat ID', + }, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + operation: [ + 'getAll', + ], + resource: [ + 'chatMessage', + ], + }, + }, + default: false, + description: 'If all results should be returned or only up to a given limit.', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + operation: [ + 'getAll', + ], + resource: [ + 'chatMessage', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 500, + }, + default: 100, + description: 'How many results to return.', + }, +]; diff --git a/packages/nodes-base/nodes/Microsoft/Teams/MicrosoftTeams.node.ts b/packages/nodes-base/nodes/Microsoft/Teams/MicrosoftTeams.node.ts index 0a28318500..e042dacb59 100644 --- a/packages/nodes-base/nodes/Microsoft/Teams/MicrosoftTeams.node.ts +++ b/packages/nodes-base/nodes/Microsoft/Teams/MicrosoftTeams.node.ts @@ -26,6 +26,11 @@ import { channelMessageOperations, } from './ChannelMessageDescription'; +import { + chatMessageFields, + chatMessageOperations, +} from './ChatMessageDescription'; + import { taskFields, taskOperations, @@ -65,6 +70,10 @@ export class MicrosoftTeams implements INodeType { name: 'Channel Message (Beta)', value: 'channelMessage', }, + { + name: 'Chat Message', + value: 'chatMessage', + }, { name: 'Task', value: 'task', @@ -79,6 +88,8 @@ export class MicrosoftTeams implements INodeType { /// MESSAGE ...channelMessageOperations, ...channelMessageFields, + ...chatMessageOperations, + ...chatMessageFields, ///TASK ...taskOperations, ...taskFields, @@ -189,6 +200,29 @@ export class MicrosoftTeams implements INodeType { } return returnData; }, + // Get all the chats to display them to user so that they can + // select them easily + async getChats(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + const qs: IDataObject = { + $expand: 'members', + }; + const { value } = await microsoftApiRequest.call(this, 'GET', '/v1.0/chats', {}, qs); + for (const chat of value) { + if (!chat.topic) { + chat.topic = chat.members + .filter((member: IDataObject) => member.displayName) + .map((member: IDataObject) => member.displayName).join(', '); + } + const chatName = `${chat.topic || '(no title) - ' + chat.id} (${chat.chatType})`; + const chatId = chat.id; + returnData.push({ + name: chatName, + value: chatId, + }); + } + return returnData; + }, }, }; @@ -298,6 +332,39 @@ export class MicrosoftTeams implements INodeType { } } } + if (resource === 'chatMessage') { + // https://docs.microsoft.com/en-us/graph/api/channel-post-messages?view=graph-rest-1.0&tabs=http + if (operation === 'create') { + const chatId = this.getNodeParameter('chatId', i) as string; + const messageType = this.getNodeParameter('messageType', i) as string; + const message = this.getNodeParameter('message', i) as string; + const body: IDataObject = { + body: { + contentType: messageType, + content: message, + }, + }; + responseData = await microsoftApiRequest.call(this, 'POST', `/v1.0/chats/${chatId}/messages`, body); + } + // https://docs.microsoft.com/en-us/graph/api/chat-list-messages?view=graph-rest-1.0&tabs=http + if (operation === 'get') { + const chatId = this.getNodeParameter('chatId', i) as string; + const messageId = this.getNodeParameter('messageId', i) as string; + responseData = await microsoftApiRequest.call(this, 'GET', `/v1.0/chats/${chatId}/messages/${messageId}`); + } + // https://docs.microsoft.com/en-us/graph/api/chat-list-messages?view=graph-rest-1.0&tabs=http + if (operation === 'getAll') { + const chatId = this.getNodeParameter('chatId', i) as string; + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + if (returnAll) { + responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/v1.0/chats/${chatId}/messages`); + } else { + qs.limit = this.getNodeParameter('limit', i) as number; + responseData = await microsoftApiRequestAllItems.call(this, 'value', 'GET', `/v1.0/chats/${chatId}/messages`, {}); + responseData = responseData.splice(0, qs.limit); + } + } + } if (resource === 'task') { //https://docs.microsoft.com/en-us/graph/api/planner-post-tasks?view=graph-rest-1.0&tabs=http if (operation === 'create') { diff --git a/packages/nodes-base/nodes/Microsoft/ToDo/MicrosoftToDo.node.ts b/packages/nodes-base/nodes/Microsoft/ToDo/MicrosoftToDo.node.ts index c842d07aa7..5f3b870325 100644 --- a/packages/nodes-base/nodes/Microsoft/ToDo/MicrosoftToDo.node.ts +++ b/packages/nodes-base/nodes/Microsoft/ToDo/MicrosoftToDo.node.ts @@ -32,7 +32,7 @@ import { listOperations, } from './ListDescription'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class MicrosoftToDo implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Mocean/GenericFunctions.ts b/packages/nodes-base/nodes/Mocean/GenericFunctions.ts index 3951df2dee..52849300ae 100644 --- a/packages/nodes-base/nodes/Mocean/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Mocean/GenericFunctions.ts @@ -4,7 +4,7 @@ import { } from 'n8n-core'; import { - IDataObject, NodeApiError, NodeOperationError, + IDataObject, JsonObject, NodeApiError, NodeOperationError, } from 'n8n-workflow'; /** @@ -47,6 +47,6 @@ export async function moceanApiRequest(this: IHookFunctions | IExecuteFunctions, try { return await this.helpers.request(options); } catch (error) { - throw new NodeApiError(this.getNode(), error); + throw new NodeApiError(this.getNode(), (error as JsonObject)); } } diff --git a/packages/nodes-base/nodes/Mocean/Mocean.node.ts b/packages/nodes-base/nodes/Mocean/Mocean.node.ts index 959610c9eb..06009320e5 100644 --- a/packages/nodes-base/nodes/Mocean/Mocean.node.ts +++ b/packages/nodes-base/nodes/Mocean/Mocean.node.ts @@ -1,20 +1,29 @@ -import { IExecuteFunctions } from 'n8n-core'; import { + IExecuteFunctions, +} from 'n8n-core'; + +import { + ICredentialsDecrypted, + ICredentialTestFunctions, IDataObject, + INodeCredentialTestResult, INodeExecutionData, INodeType, INodeTypeDescription, + JsonObject, NodeOperationError, } from 'n8n-workflow'; -import {moceanApiRequest} from './GenericFunctions'; - +import { + moceanApiRequest, +} from './GenericFunctions'; export class Mocean implements INodeType { description: INodeTypeDescription = { displayName: 'Mocean', name: 'mocean', - icon: 'file:mocean.png', + subtitle: `={{$parameter["operation"] + ": " + $parameter["resource"]}}`, + icon: 'file:mocean.svg', group: ['transform'], version: 1, description: 'Send SMS and voice messages via Mocean', @@ -27,6 +36,7 @@ export class Mocean implements INodeType { { name: 'moceanApi', required: true, + testedBy: 'moceanApiTest', }, ], properties: [ @@ -36,7 +46,8 @@ export class Mocean implements INodeType { displayName: 'Resource', name: 'resource', type: 'options', - options:[ + noDataExpression: true, + options: [ { name: 'SMS', value: 'sms', @@ -52,6 +63,7 @@ export class Mocean implements INodeType { displayName: 'Operation', name: 'operation', type: 'options', + noDataExpression: true, displayOptions: { show: { resource: [ @@ -68,7 +80,7 @@ export class Mocean implements INodeType { }, ], default: 'send', - description: 'The operation to perform.', + description: 'Operation to perform', }, { displayName: 'From', @@ -88,7 +100,7 @@ export class Mocean implements INodeType { ], }, }, - description: 'The number to which to send the message', + description: 'Number to which to send the message', }, { @@ -109,14 +121,14 @@ export class Mocean implements INodeType { ], }, }, - description: 'The number from which to send the message', + description: 'Number from which to send the message', }, { displayName: 'Language', name: 'language', type: 'options', - options:[ + options: [ { name: 'Chinese Mandarin (China)', value: 'cmn-CN', @@ -169,10 +181,66 @@ export class Mocean implements INodeType { ], }, }, - description: 'The message to send', + description: 'Message to send', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Field', + displayOptions: { + show: { + operation: [ + 'send', + ], + resource: [ + 'sms', + ], + }, + }, + default: {}, + options: [ + { + displayName: 'Delivery Report URL', + name: 'dlrUrl', + type: 'string', + default: '', + placeholder: '', + description: 'Delivery report URL', + }, + ], }, ], + }; + methods = { + credentialTest: { + async moceanApiTest(this: ICredentialTestFunctions, credential: ICredentialsDecrypted): Promise { + const credentials = credential.data; + const query: IDataObject = {}; + query['mocean-api-key'] = credentials!['mocean-api-key']; + query['mocean-api-secret'] = credentials!['mocean-api-secret']; + + const options = { + method: 'GET', + qs: query, + uri: `https://rest.moceanapi.com/rest/2/account/balance`, + json: true, + }; + try { + await this.helpers.request!(options); + } catch (error) { + return { + status: 'Error', + message: `Connection details not valid: ${(error as JsonObject).message}`, + }; + } + return { + status: 'OK', + message: 'Authentication successful!', + }; + }, + }, }; @@ -185,6 +253,7 @@ export class Mocean implements INodeType { let requesetMethod: string; let resource: string; let text: string; + let dlrUrl: string; let dataKey: string; // For Post let body: IDataObject; @@ -196,7 +265,7 @@ export class Mocean implements INodeType { qs = {}; try { resource = this.getNodeParameter('resource', itemIndex, '') as string; - operation = this.getNodeParameter('operation',itemIndex,'') as string; + operation = this.getNodeParameter('operation', itemIndex, '') as string; text = this.getNodeParameter('message', itemIndex, '') as string; requesetMethod = 'POST'; body['mocean-from'] = this.getNodeParameter('from', itemIndex, '') as string; @@ -215,16 +284,21 @@ export class Mocean implements INodeType { dataKey = 'voice'; body['mocean-command'] = JSON.stringify(command); endpoint = '/rest/2/voice/dial'; - } else if(resource === 'sms') { + } else if (resource === 'sms') { + dlrUrl = this.getNodeParameter('options.dlrUrl', itemIndex, '') as string; dataKey = 'messages'; body['mocean-text'] = text; + if (dlrUrl !== '') { + body['mocean-dlr-url'] = dlrUrl; + body['mocean-dlr-mask'] = '1'; + } endpoint = '/rest/2/sms'; } else { throw new NodeOperationError(this.getNode(), `Unknown resource ${resource}`); } if (operation === 'send') { - const responseData = await moceanApiRequest.call(this,requesetMethod,endpoint,body,qs); + const responseData = await moceanApiRequest.call(this, requesetMethod, endpoint, body, qs); for (const item of responseData[dataKey] as IDataObject[]) { item.type = resource; @@ -236,7 +310,7 @@ export class Mocean implements INodeType { } } catch (error) { if (this.continueOnFail()) { - returnData.push({ error: error.message }); + returnData.push({ error: (error as JsonObject).message }); continue; } throw error; diff --git a/packages/nodes-base/nodes/Mocean/mocean.png b/packages/nodes-base/nodes/Mocean/mocean.png deleted file mode 100644 index f660c71e0a..0000000000 Binary files a/packages/nodes-base/nodes/Mocean/mocean.png and /dev/null differ diff --git a/packages/nodes-base/nodes/Mocean/mocean.svg b/packages/nodes-base/nodes/Mocean/mocean.svg new file mode 100644 index 0000000000..ed5d0de24e --- /dev/null +++ b/packages/nodes-base/nodes/Mocean/mocean.svg @@ -0,0 +1,24 @@ + + + + +Created by potrace 1.16, written by Peter Selinger 2001-2019 + + + + + diff --git a/packages/nodes-base/nodes/MoveBinaryData/MoveBinaryData.node.ts b/packages/nodes-base/nodes/MoveBinaryData/MoveBinaryData.node.ts index c2cec884aa..7343ba86b5 100644 --- a/packages/nodes-base/nodes/MoveBinaryData/MoveBinaryData.node.ts +++ b/packages/nodes-base/nodes/MoveBinaryData/MoveBinaryData.node.ts @@ -19,7 +19,7 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as iconv from 'iconv-lite'; +import iconv from 'iconv-lite'; iconv.encodingExists('utf8'); // Create options for bomAware and encoding diff --git a/packages/nodes-base/nodes/MySql/MySql.node.ts b/packages/nodes-base/nodes/MySql/MySql.node.ts index aaab6fb49c..37abc7f63a 100644 --- a/packages/nodes-base/nodes/MySql/MySql.node.ts +++ b/packages/nodes-base/nodes/MySql/MySql.node.ts @@ -7,7 +7,7 @@ import { NodeOperationError, } from 'n8n-workflow'; // @ts-ignore -import * as mysql2 from 'mysql2/promise'; +import mysql2 from 'mysql2/promise'; import { copyInputItems } from './GenericFunctions'; diff --git a/packages/nodes-base/nodes/Nasa/Nasa.node.ts b/packages/nodes-base/nodes/Nasa/Nasa.node.ts index c1a61db867..eb53135e50 100644 --- a/packages/nodes-base/nodes/Nasa/Nasa.node.ts +++ b/packages/nodes-base/nodes/Nasa/Nasa.node.ts @@ -15,7 +15,7 @@ import { nasaApiRequestAllItems, } from './GenericFunctions'; -import * as moment from 'moment'; +import moment from 'moment'; export class Nasa implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/NocoDB/GenericFunctions.ts b/packages/nodes-base/nodes/NocoDB/GenericFunctions.ts index b4c6720640..f1215e2fdd 100644 --- a/packages/nodes-base/nodes/NocoDB/GenericFunctions.ts +++ b/packages/nodes-base/nodes/NocoDB/GenericFunctions.ts @@ -96,13 +96,12 @@ export async function apiRequestAllItems(this: IHookFunctions | IExecuteFunction do { responseData = await apiRequest.call(this, method, endpoint, body, query); - returnData.push(...responseData); query.offset += query.limit; } while ( - responseData.length === 0 + responseData.length !== 0 ); return returnData; diff --git a/packages/nodes-base/nodes/Notion/GenericFunctions.ts b/packages/nodes-base/nodes/Notion/GenericFunctions.ts index 14bd0e2080..d6a1f568f9 100644 --- a/packages/nodes-base/nodes/Notion/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Notion/GenericFunctions.ts @@ -30,7 +30,7 @@ import { filters, } from './Filters'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; import { validate as uuidValidate } from 'uuid'; @@ -397,7 +397,7 @@ export function mapFilters(filters: IDataObject[], timezone: string) { } else if (key === 'phone_number') { key = 'phone'; } else if (key === 'date' && !['is_empty', 'is_not_empty'].includes(value.condition as string)) { - valuePropertyName = (value.date === '') ? {} : moment.tz(value.date, timezone).utc().format(); + valuePropertyName = (value.date === '') ? {} : moment.tz(value.date, timezone).utc().format(); } else if (key === 'boolean') { key = 'checkbox'; } @@ -945,4 +945,4 @@ export function validateJSON(json: string | undefined): any { // tslint:disable- result = undefined; } return result; -} \ No newline at end of file +} diff --git a/packages/nodes-base/nodes/Notion/NotionTrigger.node.ts b/packages/nodes-base/nodes/Notion/NotionTrigger.node.ts index ecaa6e3de7..3642d3e0dc 100644 --- a/packages/nodes-base/nodes/Notion/NotionTrigger.node.ts +++ b/packages/nodes-base/nodes/Notion/NotionTrigger.node.ts @@ -16,7 +16,7 @@ import { simplifyObjects, } from './GenericFunctions'; -import * as moment from 'moment'; +import moment from 'moment'; export class NotionTrigger implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Notion/v1/NotionV1.node.ts b/packages/nodes-base/nodes/Notion/v1/NotionV1.node.ts index a5356e8a1b..8cccf7b3fc 100644 --- a/packages/nodes-base/nodes/Notion/v1/NotionV1.node.ts +++ b/packages/nodes-base/nodes/Notion/v1/NotionV1.node.ts @@ -26,7 +26,7 @@ import { simplifyObjects, } from '../GenericFunctions'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; import { versionDescription diff --git a/packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts b/packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts index 3f9b0432c8..e4a7c8e52e 100644 --- a/packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts +++ b/packages/nodes-base/nodes/Notion/v2/NotionV2.node.ts @@ -34,7 +34,7 @@ import { validateJSON, } from '../GenericFunctions'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; import { versionDescription diff --git a/packages/nodes-base/nodes/Onfleet/GenericFunctions.ts b/packages/nodes-base/nodes/Onfleet/GenericFunctions.ts index 0c3020388d..de4ec2fde0 100644 --- a/packages/nodes-base/nodes/Onfleet/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Onfleet/GenericFunctions.ts @@ -14,7 +14,7 @@ import { OptionsWithUri, } from 'request'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export async function onfleetApiRequest( this: IWebhookFunctions | IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, diff --git a/packages/nodes-base/nodes/Onfleet/Onfleet.ts b/packages/nodes-base/nodes/Onfleet/Onfleet.ts index 70d4818fe6..30bf7c48aa 100644 --- a/packages/nodes-base/nodes/Onfleet/Onfleet.ts +++ b/packages/nodes-base/nodes/Onfleet/Onfleet.ts @@ -35,7 +35,7 @@ import { onfleetApiRequestAllItems, } from './GenericFunctions'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; const formatAddress = ( unparsed: boolean, @@ -1340,4 +1340,4 @@ export class Onfleet { return responseData; } -} \ No newline at end of file +} diff --git a/packages/nodes-base/nodes/Orbit/Orbit.node.ts b/packages/nodes-base/nodes/Orbit/Orbit.node.ts index 6c2db49df0..b55526f6ac 100644 --- a/packages/nodes-base/nodes/Orbit/Orbit.node.ts +++ b/packages/nodes-base/nodes/Orbit/Orbit.node.ts @@ -37,7 +37,7 @@ import { postOperations, } from './PostDescription'; -import * as moment from 'moment'; +import moment from 'moment'; export class Orbit implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Oura/Oura.node.ts b/packages/nodes-base/nodes/Oura/Oura.node.ts index 8a141a5ecc..cb8a58767e 100644 --- a/packages/nodes-base/nodes/Oura/Oura.node.ts +++ b/packages/nodes-base/nodes/Oura/Oura.node.ts @@ -22,7 +22,7 @@ import { summaryOperations, } from './SummaryDescription'; -import * as moment from 'moment'; +import moment from 'moment'; export class Oura implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Paddle/Paddle.node.ts b/packages/nodes-base/nodes/Paddle/Paddle.node.ts index 1e78e322d9..2f8f272ad2 100644 --- a/packages/nodes-base/nodes/Paddle/Paddle.node.ts +++ b/packages/nodes-base/nodes/Paddle/Paddle.node.ts @@ -49,7 +49,7 @@ import { // orderFields, // } from './OrderDescription'; -import * as moment from 'moment'; +import moment from 'moment'; export class Paddle implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/PagerDuty/PagerDuty.node.ts b/packages/nodes-base/nodes/PagerDuty/PagerDuty.node.ts index 1f13440250..164b1b01f5 100644 --- a/packages/nodes-base/nodes/PagerDuty/PagerDuty.node.ts +++ b/packages/nodes-base/nodes/PagerDuty/PagerDuty.node.ts @@ -45,7 +45,7 @@ import { snakeCase, } from 'change-case'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class PagerDuty implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/PayPal/GenericFunctions.ts b/packages/nodes-base/nodes/PayPal/GenericFunctions.ts index a7859b335c..1e8b84b4eb 100644 --- a/packages/nodes-base/nodes/PayPal/GenericFunctions.ts +++ b/packages/nodes-base/nodes/PayPal/GenericFunctions.ts @@ -38,8 +38,8 @@ export async function payPalApiRequest(this: IHookFunctions | IExecuteFunctions function getEnvironment(env: string): string { // @ts-ignore return { - 'sanbox': 'https://api.sandbox.paypal.com', - 'live': 'https://api.paypal.com', + 'sanbox': 'https://api-m.sandbox.paypal.com', + 'live': 'https://api-m.paypal.com', }[env]; } diff --git a/packages/nodes-base/nodes/PayPal/PayPal.node.ts b/packages/nodes-base/nodes/PayPal/PayPal.node.ts index f72cffde66..36e4d6ee34 100644 --- a/packages/nodes-base/nodes/PayPal/PayPal.node.ts +++ b/packages/nodes-base/nodes/PayPal/PayPal.node.ts @@ -1,8 +1,14 @@ +import { + OptionsWithUri +} from 'request'; import { IExecuteFunctions, } from 'n8n-core'; import { + ICredentialsDecrypted, + ICredentialTestFunctions, IDataObject, + INodeCredentialTestResult, INodeExecutionData, INodeType, INodeTypeDescription, @@ -46,6 +52,7 @@ export class PayPal implements INodeType { { name: 'payPalApi', required: true, + testedBy: 'payPalApiTest', }, ], properties: [ @@ -75,6 +82,58 @@ export class PayPal implements INodeType { ], }; + methods = { + credentialTest: { + async payPalApiTest(this: ICredentialTestFunctions, credential: ICredentialsDecrypted): Promise { + const credentials = credential.data; + const clientId = credentials!.clientId; + const clientSecret = credentials!.secret; + const environment = credentials!.env; + + if (!clientId || !clientSecret || !environment) { + return { + status: 'Error', + message: `Connection details not valid: missing credentials`, + }; + } + + let baseUrl = ''; + if (environment !== 'live') { + baseUrl = 'https://api-m.sandbox.paypal.com'; + } else { + baseUrl = 'https://api-m.paypal.com'; + } + + const base64Key = Buffer.from(`${clientId}:${clientSecret}`).toString('base64'); + + const options: OptionsWithUri = { + headers: { + 'Authorization': `Basic ${base64Key}`, + }, + method: 'POST', + uri: `${baseUrl}/v1/oauth2/token`, + form: { + grant_type: 'client_credentials', + }, + }; + + try { + await this.helpers.request!(options); + return { + status: 'OK', + message: 'Authentication successful!', + }; + } + catch (error) { + return { + status: 'Error', + message: `Connection details not valid: ${error.message}`, + }; + } + }, + }, + }; + async execute(this: IExecuteFunctions): Promise { const items = this.getInputData(); const returnData: IDataObject[] = []; @@ -168,5 +227,6 @@ export class PayPal implements INodeType { } } return [this.helpers.returnJsonArray(returnData)]; + } } diff --git a/packages/nodes-base/nodes/Pipedrive/PipedriveTrigger.node.ts b/packages/nodes-base/nodes/Pipedrive/PipedriveTrigger.node.ts index 62d7c3f4e5..7a2eb0bad7 100644 --- a/packages/nodes-base/nodes/Pipedrive/PipedriveTrigger.node.ts +++ b/packages/nodes-base/nodes/Pipedrive/PipedriveTrigger.node.ts @@ -13,7 +13,7 @@ import { pipedriveApiRequest, } from './GenericFunctions'; -import * as basicAuth from 'basic-auth'; +import basicAuth from 'basic-auth'; import { Response, diff --git a/packages/nodes-base/nodes/PostHog/PostHog.node.ts b/packages/nodes-base/nodes/PostHog/PostHog.node.ts index 8bd846eb29..7981aaa3c5 100644 --- a/packages/nodes-base/nodes/PostHog/PostHog.node.ts +++ b/packages/nodes-base/nodes/PostHog/PostHog.node.ts @@ -37,7 +37,7 @@ import { identityOperations, } from './IdentityDescription'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class PostHog implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Postgres/Postgres.node.functions.ts b/packages/nodes-base/nodes/Postgres/Postgres.node.functions.ts index 1ba9440de3..f409c33d8e 100644 --- a/packages/nodes-base/nodes/Postgres/Postgres.node.functions.ts +++ b/packages/nodes-base/nodes/Postgres/Postgres.node.functions.ts @@ -1,6 +1,6 @@ import { IDataObject, INodeExecutionData } from 'n8n-workflow'; -import pgPromise = require('pg-promise'); -import pg = require('pg-promise/typescript/pg-subset'); +import pgPromise from 'pg-promise'; +import pg from 'pg-promise/typescript/pg-subset'; /** * Returns of a shallow copy of the items which only contains the json data and diff --git a/packages/nodes-base/nodes/Postgres/Postgres.node.ts b/packages/nodes-base/nodes/Postgres/Postgres.node.ts index b5f71367b2..e10d354382 100644 --- a/packages/nodes-base/nodes/Postgres/Postgres.node.ts +++ b/packages/nodes-base/nodes/Postgres/Postgres.node.ts @@ -7,7 +7,7 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as pgPromise from 'pg-promise'; +import pgPromise from 'pg-promise'; import { pgInsert, pgQuery, pgUpdate } from './Postgres.node.functions'; diff --git a/packages/nodes-base/nodes/Pushbullet/Pushbullet.node.ts b/packages/nodes-base/nodes/Pushbullet/Pushbullet.node.ts index 2bb77d891c..38306bdf39 100644 --- a/packages/nodes-base/nodes/Pushbullet/Pushbullet.node.ts +++ b/packages/nodes-base/nodes/Pushbullet/Pushbullet.node.ts @@ -18,7 +18,7 @@ import { pushbulletApiRequestAllItems, } from './GenericFunctions'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class Pushbullet implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts b/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts index 88d7869ab2..e625d2e9a0 100644 --- a/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts +++ b/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts @@ -7,7 +7,7 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as pgPromise from 'pg-promise'; +import pgPromise from 'pg-promise'; import { pgInsert, diff --git a/packages/nodes-base/nodes/ReadBinaryFiles/ReadBinaryFiles.node.ts b/packages/nodes-base/nodes/ReadBinaryFiles/ReadBinaryFiles.node.ts index 8025c177a4..61099e77e2 100644 --- a/packages/nodes-base/nodes/ReadBinaryFiles/ReadBinaryFiles.node.ts +++ b/packages/nodes-base/nodes/ReadBinaryFiles/ReadBinaryFiles.node.ts @@ -4,8 +4,8 @@ import { INodeType, INodeTypeDescription, } from 'n8n-workflow'; -import * as glob from 'fast-glob'; -import * as path from 'path'; +import glob from 'fast-glob'; +import path from 'path'; import { readFile as fsReadFile, diff --git a/packages/nodes-base/nodes/Redis/Redis.node.ts b/packages/nodes-base/nodes/Redis/Redis.node.ts index 5bc1830405..4978f90b96 100644 --- a/packages/nodes-base/nodes/Redis/Redis.node.ts +++ b/packages/nodes-base/nodes/Redis/Redis.node.ts @@ -9,9 +9,9 @@ import { } from 'n8n-workflow'; import { set } from 'lodash'; -import * as redis from 'redis'; +import redis from 'redis'; -import * as util from 'util'; +import util from 'util'; export class Redis implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Redis/RedisTrigger.node.ts b/packages/nodes-base/nodes/Redis/RedisTrigger.node.ts index 592db25cb9..c6105b3b8f 100644 --- a/packages/nodes-base/nodes/Redis/RedisTrigger.node.ts +++ b/packages/nodes-base/nodes/Redis/RedisTrigger.node.ts @@ -10,7 +10,7 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as redis from 'redis'; +import redis from 'redis'; export class RedisTrigger implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/RssFeedRead/RssFeedRead.node.ts b/packages/nodes-base/nodes/RssFeedRead/RssFeedRead.node.ts index be78360244..9211a4c7f7 100644 --- a/packages/nodes-base/nodes/RssFeedRead/RssFeedRead.node.ts +++ b/packages/nodes-base/nodes/RssFeedRead/RssFeedRead.node.ts @@ -7,7 +7,7 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as Parser from 'rss-parser'; +import Parser from 'rss-parser'; import { URL } from 'url'; export class RssFeedRead implements INodeType { diff --git a/packages/nodes-base/nodes/Salesforce/GenericFunctions.ts b/packages/nodes-base/nodes/Salesforce/GenericFunctions.ts index 94e0ee37c1..911fb377a5 100644 --- a/packages/nodes-base/nodes/Salesforce/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Salesforce/GenericFunctions.ts @@ -14,9 +14,9 @@ import { NodeApiError, } from 'n8n-workflow'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; -import * as jwt from 'jsonwebtoken'; +import jwt from 'jsonwebtoken'; import { LoggerProxy as Logger diff --git a/packages/nodes-base/nodes/Salesforce/Salesforce.node.ts b/packages/nodes-base/nodes/Salesforce/Salesforce.node.ts index 5d839a1fe8..483d4a8805 100644 --- a/packages/nodes-base/nodes/Salesforce/Salesforce.node.ts +++ b/packages/nodes-base/nodes/Salesforce/Salesforce.node.ts @@ -2184,6 +2184,9 @@ export class Salesforce implements INodeType { if (additionalFields.reason !== undefined) { body.Reason = additionalFields.reason as string; } + if (additionalFields.status !== undefined) { + body.Status = additionalFields.status as string; + } if (additionalFields.owner !== undefined) { body.OwnerId = additionalFields.owner as string; } @@ -2248,6 +2251,9 @@ export class Salesforce implements INodeType { if (updateFields.reason !== undefined) { body.Reason = updateFields.reason as string; } + if (updateFields.status !== undefined) { + body.Status = updateFields.status as string; + } if (updateFields.owner !== undefined) { body.OwnerId = updateFields.owner as string; } diff --git a/packages/nodes-base/nodes/SeaTable/GenericFunctions.ts b/packages/nodes-base/nodes/SeaTable/GenericFunctions.ts index 70e139b983..528c5a5d0a 100644 --- a/packages/nodes-base/nodes/SeaTable/GenericFunctions.ts +++ b/packages/nodes-base/nodes/SeaTable/GenericFunctions.ts @@ -34,7 +34,7 @@ import { IRowObject, } from './Interfaces'; -import * as _ from 'lodash'; +import _ from 'lodash'; export async function seaTableApiRequest(this: IExecuteFunctions | ILoadOptionsFunctions | IPollFunctions, ctx: ICtx, method: string, endpoint: string, body: any = {}, qs: IDataObject = {}, url: string | undefined = undefined, option: IDataObject = {}): Promise { // tslint:disable-line:no-any diff --git a/packages/nodes-base/nodes/SeaTable/SeaTableTrigger.node.ts b/packages/nodes-base/nodes/SeaTable/SeaTableTrigger.node.ts index 34a6cfb6a1..1b8d7c8491 100644 --- a/packages/nodes-base/nodes/SeaTable/SeaTableTrigger.node.ts +++ b/packages/nodes-base/nodes/SeaTable/SeaTableTrigger.node.ts @@ -24,7 +24,7 @@ import { IRowResponse, } from './Interfaces'; -import * as moment from 'moment'; +import moment from 'moment'; export class SeaTableTrigger implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/SecurityScorecard/SecurityScorecard.node.ts b/packages/nodes-base/nodes/SecurityScorecard/SecurityScorecard.node.ts index ebb28479a0..f21f902e49 100644 --- a/packages/nodes-base/nodes/SecurityScorecard/SecurityScorecard.node.ts +++ b/packages/nodes-base/nodes/SecurityScorecard/SecurityScorecard.node.ts @@ -44,7 +44,7 @@ import { simplify, } from './GenericFunctions'; -import * as moment from 'moment'; +import moment from 'moment'; export class SecurityScorecard implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/SendGrid/SendGrid.node.ts b/packages/nodes-base/nodes/SendGrid/SendGrid.node.ts index 1d843a5f15..5dc37dab49 100644 --- a/packages/nodes-base/nodes/SendGrid/SendGrid.node.ts +++ b/packages/nodes-base/nodes/SendGrid/SendGrid.node.ts @@ -31,7 +31,7 @@ import { sendGridApiRequestAllItems, } from './GenericFunctions'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class SendGrid implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/ServiceNow/BusinessServiceDescription.ts b/packages/nodes-base/nodes/ServiceNow/BusinessServiceDescription.ts index c5fd6dd0fe..fddf24e3f9 100644 --- a/packages/nodes-base/nodes/ServiceNow/BusinessServiceDescription.ts +++ b/packages/nodes-base/nodes/ServiceNow/BusinessServiceDescription.ts @@ -7,6 +7,7 @@ export const businessServiceOperations: INodeProperties[] = [ displayName: 'Operation', name: 'operation', type: 'options', + noDataExpression: true, displayOptions: { show: { resource: [ @@ -44,7 +45,7 @@ export const businessServiceFields: INodeProperties[] = [ }, }, default: false, - description: 'If all results should be returned or only up to a given limit', + description: 'Whether to return all results or only up to a given limit', }, { displayName: 'Limit', @@ -99,17 +100,19 @@ export const businessServiceFields: INodeProperties[] = [ name: 'sysparm_fields', type: 'multiOptions', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getColumns', }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Filter', name: 'sysparm_query', type: 'string', default: '', - description: 'An encoded query string used to filter the results. More info', + description: 'An encoded query string used to filter the results. More info.', }, { displayName: 'Return Values', diff --git a/packages/nodes-base/nodes/ServiceNow/ConfigurationItemsDescription.ts b/packages/nodes-base/nodes/ServiceNow/ConfigurationItemsDescription.ts index 1d3f738f08..33804b9601 100644 --- a/packages/nodes-base/nodes/ServiceNow/ConfigurationItemsDescription.ts +++ b/packages/nodes-base/nodes/ServiceNow/ConfigurationItemsDescription.ts @@ -7,6 +7,7 @@ export const configurationItemsOperations: INodeProperties[] = [ displayName: 'Operation', name: 'operation', type: 'options', + noDataExpression: true, displayOptions: { show: { resource: [ @@ -44,7 +45,7 @@ export const configurationItemsFields: INodeProperties[] = [ }, }, default: false, - description: 'If all results should be returned or only up to a given limit', + description: 'Whether to return all results or only up to a given limit', }, { displayName: 'Limit', @@ -68,7 +69,7 @@ export const configurationItemsFields: INodeProperties[] = [ maxValue: 500, }, default: 50, - description: 'The max number of results to return', + description: 'Max number of results to return', }, { displayName: 'Options', @@ -99,17 +100,19 @@ export const configurationItemsFields: INodeProperties[] = [ name: 'sysparm_fields', type: 'multiOptions', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getColumns', }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Filter', name: 'sysparm_query', type: 'string', default: '', - description: 'An encoded query string used to filter the results. More info', + description: 'An encoded query string used to filter the results. More info.', }, { displayName: 'Return Values', diff --git a/packages/nodes-base/nodes/ServiceNow/DepartmentDescription.ts b/packages/nodes-base/nodes/ServiceNow/DepartmentDescription.ts index 28c3d93090..dcc6f950fb 100644 --- a/packages/nodes-base/nodes/ServiceNow/DepartmentDescription.ts +++ b/packages/nodes-base/nodes/ServiceNow/DepartmentDescription.ts @@ -7,6 +7,7 @@ export const departmentOperations: INodeProperties[] = [ displayName: 'Operation', name: 'operation', type: 'options', + noDataExpression: true, displayOptions: { show: { resource: [ @@ -44,7 +45,7 @@ export const departmentFields: INodeProperties[] = [ }, }, default: false, - description: 'If all results should be returned or only up to a given limit', + description: 'Whether to return all results or only up to a given limit', }, { displayName: 'Limit', @@ -99,17 +100,19 @@ export const departmentFields: INodeProperties[] = [ name: 'sysparm_fields', type: 'multiOptions', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getColumns', }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Filter', name: 'sysparm_query', type: 'string', default: '', - description: 'An encoded query string used to filter the results. More info', + description: 'An encoded query string used to filter the results. More info.', }, { displayName: 'Return Values', diff --git a/packages/nodes-base/nodes/ServiceNow/DictionaryDescription.ts b/packages/nodes-base/nodes/ServiceNow/DictionaryDescription.ts index ba1152b31c..718a24cbf9 100644 --- a/packages/nodes-base/nodes/ServiceNow/DictionaryDescription.ts +++ b/packages/nodes-base/nodes/ServiceNow/DictionaryDescription.ts @@ -7,6 +7,7 @@ export const dictionaryOperations: INodeProperties[] = [ displayName: 'Operation', name: 'operation', type: 'options', + noDataExpression: true, displayOptions: { show: { resource: [ @@ -44,7 +45,7 @@ export const dictionaryFields: INodeProperties[] = [ }, }, default: false, - description: 'If all results should be returned or only up to a given limit', + description: 'Whether to return all results or only up to a given limit', }, { displayName: 'Limit', @@ -99,17 +100,19 @@ export const dictionaryFields: INodeProperties[] = [ name: 'sysparm_fields', type: 'multiOptions', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getColumns', }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Filter', name: 'sysparm_query', type: 'string', default: '', - description: 'An encoded query string used to filter the results. More info', + description: 'An encoded query string used to filter the results. More info.', }, { displayName: 'Return Values', diff --git a/packages/nodes-base/nodes/ServiceNow/GenericFunctions.ts b/packages/nodes-base/nodes/ServiceNow/GenericFunctions.ts index 2924cdf53d..5d121933f0 100644 --- a/packages/nodes-base/nodes/ServiceNow/GenericFunctions.ts +++ b/packages/nodes-base/nodes/ServiceNow/GenericFunctions.ts @@ -10,15 +10,25 @@ import { import { IDataObject, INodePropertyOptions, + JsonObject, NodeApiError, } from 'n8n-workflow'; export async function serviceNowApiRequest(this: IExecuteFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any - const credentials = await this.getCredentials('serviceNowOAuth2Api'); + const headers = {} as IDataObject; + const authenticationMethod = this.getNodeParameter('authentication', 0, 'oAuth2') as string; + + let credentials; + + if (authenticationMethod === 'basicAuth') { + credentials = await this.getCredentials('serviceNowBasicApi'); + } else { + credentials = await this.getCredentials('serviceNowOAuth2Api'); + } const options: OptionsWithUri = { - headers: {}, + headers, method, qs, body, @@ -38,11 +48,11 @@ export async function serviceNowApiRequest(this: IExecuteFunctions | ILoadOption } try { - - return await this.helpers.requestOAuth2!.call(this, 'serviceNowOAuth2Api', options); + const credentialType = authenticationMethod === 'oAuth2' ? 'serviceNowOAuth2Api' : 'serviceNowBasicApi'; + return await this.helpers.requestWithAuthentication.call(this, credentialType, options); } catch (error) { - throw new NodeApiError(this.getNode(), error); + throw new NodeApiError(this.getNode(), (error as JsonObject)); } } diff --git a/packages/nodes-base/nodes/ServiceNow/IncidentDescription.ts b/packages/nodes-base/nodes/ServiceNow/IncidentDescription.ts index ba06f0d45e..744ee35472 100644 --- a/packages/nodes-base/nodes/ServiceNow/IncidentDescription.ts +++ b/packages/nodes-base/nodes/ServiceNow/IncidentDescription.ts @@ -7,6 +7,7 @@ export const incidentOperations: INodeProperties[] = [ displayName: 'Operation', name: 'operation', type: 'options', + noDataExpression: true, displayOptions: { show: { resource: [ @@ -85,19 +86,21 @@ export const incidentFields: INodeProperties[] = [ name: 'assigned_to', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getUsers', loadOptionsDependsOn: [ 'additionalFields.assignment_group', ], }, default: '', - description: 'Which user is the incident assigned to. Requires the selection of an assignment group', + description: 'Which user is the incident assigned to. Requires the selection of an assignment group.', }, { displayName: 'Assignment Group', name: 'assignment_group', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getAssignmentGroups', }, default: '', @@ -108,6 +111,7 @@ export const incidentFields: INodeProperties[] = [ name: 'business_service', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getBusinessServices', }, default: '', @@ -125,6 +129,7 @@ export const incidentFields: INodeProperties[] = [ name: 'category', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getIncidentCategories', }, default: '', @@ -142,9 +147,10 @@ export const incidentFields: INodeProperties[] = [ name: 'cmdb_ci', type: 'multiOptions', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getConfigurationItems', }, - default: '', + default: [], description: 'Configuration Items, \'cmdb_ci\' in metadata', }, { @@ -197,7 +203,7 @@ export const incidentFields: INodeProperties[] = [ value: 1, }, ], - default: '', + default: 1, description: 'The impact of the incident', }, { @@ -205,16 +211,18 @@ export const incidentFields: INodeProperties[] = [ name: 'close_code', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getIncidentResolutionCodes', }, default: '', - description: 'The resolution code of the incident. \'close_code\' in metadata', + description: 'The resolution code of the incident, \'close_code\' in metadata', }, { displayName: 'State', name: 'state', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getIncidentStates', }, default: '', @@ -225,6 +233,7 @@ export const incidentFields: INodeProperties[] = [ name: 'subcategory', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getIncidentSubcategories', loadOptionsDependsOn: [ 'additionalFields.category', @@ -251,7 +260,7 @@ export const incidentFields: INodeProperties[] = [ value: 1, }, ], - default: '', + default: 1, description: 'The urgency of the incident', }, ], @@ -275,7 +284,7 @@ export const incidentFields: INodeProperties[] = [ }, }, default: false, - description: 'If all results should be returned or only up to a given limit', + description: 'Whether to return all results or only up to a given limit', }, { displayName: 'Limit', @@ -330,17 +339,19 @@ export const incidentFields: INodeProperties[] = [ name: 'sysparm_fields', type: 'multiOptions', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getColumns', }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Filter', name: 'sysparm_query', type: 'string', default: '', - description: 'An encoded query string used to filter the results. More info', + description: 'An encoded query string used to filter the results. More info.', }, { displayName: 'Return Values', @@ -417,10 +428,12 @@ export const incidentFields: INodeProperties[] = [ name: 'sysparm_fields', type: 'multiOptions', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getColumns', }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Return Values', @@ -489,19 +502,21 @@ export const incidentFields: INodeProperties[] = [ name: 'assigned_to', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getUsers', loadOptionsDependsOn: [ 'additionalFields.assignment_group', ], }, default: '', - description: 'Which user is the incident assigned to. Requires the selection of an assignment group', + description: 'Which user is the incident assigned to. Requires the selection of an assignment group.', }, { displayName: 'Assignment Group', name: 'assignment_group', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getAssignmentGroups', }, default: '', @@ -512,6 +527,7 @@ export const incidentFields: INodeProperties[] = [ name: 'business_service', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getBusinessServices', }, default: '', @@ -529,6 +545,7 @@ export const incidentFields: INodeProperties[] = [ name: 'category', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getIncidentCategories', }, default: '', @@ -546,9 +563,10 @@ export const incidentFields: INodeProperties[] = [ name: 'cmdb_ci', type: 'multiOptions', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getConfigurationItems', }, - default: '', + default: [], description: 'Configuration Items, \'cmdb_ci\' in metadata', }, { @@ -601,7 +619,7 @@ export const incidentFields: INodeProperties[] = [ value: 1, }, ], - default: '', + default: 1, description: 'The impact of the incident', }, { @@ -609,9 +627,11 @@ export const incidentFields: INodeProperties[] = [ name: 'close_code', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getIncidentResolutionCodes', }, default: '', + // nodelinter-ignore-next-line description: 'The resolution code of the incident. \'close_code\' in metadata', }, { @@ -619,6 +639,7 @@ export const incidentFields: INodeProperties[] = [ name: 'hold_reason', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getIncidentHoldReasons', }, default: '', @@ -629,6 +650,7 @@ export const incidentFields: INodeProperties[] = [ name: 'state', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getIncidentStates', }, default: '', @@ -639,6 +661,7 @@ export const incidentFields: INodeProperties[] = [ name: 'subcategory', type: 'options', typeOptions: { + // nodelinter-ignore-next-line loadOptionsMethod: 'getIncidentSubcategories', loadOptionsDependsOn: [ 'additionalFields.category', @@ -665,7 +688,7 @@ export const incidentFields: INodeProperties[] = [ value: 1, }, ], - default: '', + default: 1, description: 'The urgency of the incident', }, ], diff --git a/packages/nodes-base/nodes/ServiceNow/ServiceNow.node.ts b/packages/nodes-base/nodes/ServiceNow/ServiceNow.node.ts index 98ad4bf4b4..d68afb18a3 100644 --- a/packages/nodes-base/nodes/ServiceNow/ServiceNow.node.ts +++ b/packages/nodes-base/nodes/ServiceNow/ServiceNow.node.ts @@ -9,6 +9,7 @@ import { INodePropertyOptions, INodeType, INodeTypeDescription, + JsonObject, NodeOperationError, } from 'n8n-workflow'; @@ -82,13 +83,49 @@ export class ServiceNow implements INodeType { { name: 'serviceNowOAuth2Api', required: true, + displayOptions: { + show: { + authentication: [ + 'oAuth2', + ], + }, + }, + }, + { + name: 'serviceNowBasicApi', + required: true, + displayOptions: { + show: { + authentication: [ + 'basicAuth', + ], + }, + }, }, ], properties: [ + { + displayName: 'Authentication', + name: 'authentication', + type: 'options', + options: [ + { + name: 'Basic Auth', + value: 'basicAuth', + }, + { + name: 'OAuth2', + value: 'oAuth2', + }, + ], + default: 'oAuth2', + description: 'Authentication method to use', + }, { displayName: 'Resource', name: 'resource', type: 'options', + noDataExpression: true, options: [ { name: 'Business Service', @@ -427,7 +464,7 @@ export class ServiceNow implements INodeType { const returnAll = this.getNodeParameter('returnAll', i) as boolean; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -448,7 +485,7 @@ export class ServiceNow implements INodeType { const returnAll = this.getNodeParameter('returnAll', i) as boolean; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -469,7 +506,7 @@ export class ServiceNow implements INodeType { const returnAll = this.getNodeParameter('returnAll', i) as boolean; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -490,7 +527,7 @@ export class ServiceNow implements INodeType { const returnAll = this.getNodeParameter('returnAll', i) as boolean; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -529,7 +566,7 @@ export class ServiceNow implements INodeType { const id = this.getNodeParameter('id', i) as string; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -541,7 +578,7 @@ export class ServiceNow implements INodeType { const returnAll = this.getNodeParameter('returnAll', i) as boolean; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -604,7 +641,7 @@ export class ServiceNow implements INodeType { const id = this.getNodeParameter('id', i) as string; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -617,7 +654,7 @@ export class ServiceNow implements INodeType { const returnAll = this.getNodeParameter('returnAll', i) as boolean; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -679,7 +716,7 @@ export class ServiceNow implements INodeType { const getOption = this.getNodeParameter('getOption', i) as string; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -700,7 +737,7 @@ export class ServiceNow implements INodeType { const returnAll = this.getNodeParameter('returnAll', i) as boolean; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -730,7 +767,7 @@ export class ServiceNow implements INodeType { const returnAll = this.getNodeParameter('returnAll', i) as boolean; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -751,7 +788,7 @@ export class ServiceNow implements INodeType { const returnAll = this.getNodeParameter('returnAll', i) as boolean; qs = this.getNodeParameter('options', i) as IDataObject; - if (qs.sysparm_fields) { + if (qs.sysparm_fields && typeof qs.sysparm_fields !== 'string') { qs.sysparm_fields = (qs.sysparm_fields as string[]).join(','); } @@ -771,7 +808,7 @@ export class ServiceNow implements INodeType { } } catch (error) { if (this.continueOnFail()) { - returnData.push({ error: error.message }); + returnData.push({ error: (error as JsonObject).message }); continue; } diff --git a/packages/nodes-base/nodes/ServiceNow/TableRecordDescription.ts b/packages/nodes-base/nodes/ServiceNow/TableRecordDescription.ts index 9c60fbc511..a48cb47259 100644 --- a/packages/nodes-base/nodes/ServiceNow/TableRecordDescription.ts +++ b/packages/nodes-base/nodes/ServiceNow/TableRecordDescription.ts @@ -7,6 +7,7 @@ export const tableRecordOperations: INodeProperties[] = [ displayName: 'Operation', name: 'operation', type: 'options', + noDataExpression: true, displayOptions: { show: { resource: [ @@ -71,7 +72,7 @@ export const tableRecordFields: INodeProperties[] = [ type: 'options', options: [ { - name: 'Auto-map Input Data to Columns', + name: 'Auto-Map Input Data to Columns', value: 'mapInput', description: 'Use when node input names match destination field names', }, @@ -117,7 +118,7 @@ export const tableRecordFields: INodeProperties[] = [ }, default: '', required: false, - description: 'List of input properties to avoid sending, separated by commas. Leave empty to send all inputs', + description: 'List of input properties to avoid sending, separated by commas. Leave empty to send all inputs.', }, { displayName: 'Fields to Send', @@ -208,7 +209,7 @@ export const tableRecordFields: INodeProperties[] = [ }, }, default: false, - description: 'If all results should be returned or only up to a given limit', + description: 'Whether to return all results or only up to a given limit', }, { displayName: 'Limit', @@ -268,15 +269,16 @@ export const tableRecordFields: INodeProperties[] = [ 'tableName', ], }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Filter', name: 'sysparm_query', type: 'string', default: '', - description: 'An encoded query string used to filter the results. More info', + description: 'An encoded query string used to filter the results. More info.', }, { displayName: 'Return Values', @@ -380,8 +382,9 @@ export const tableRecordFields: INodeProperties[] = [ 'tableName', ], }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Return Values', @@ -455,7 +458,7 @@ export const tableRecordFields: INodeProperties[] = [ type: 'options', options: [ { - name: 'Auto-map Input Data to Columns', + name: 'Auto-Map Input Data to Columns', value: 'mapInput', description: 'Use when node input names match destination field names', }, @@ -501,7 +504,7 @@ export const tableRecordFields: INodeProperties[] = [ }, default: '', required: false, - description: 'List of input properties to avoid sending, separated by commas. Leave empty to send all inputs', + description: 'List of input properties to avoid sending, separated by commas. Leave empty to send all inputs.', }, { displayName: 'Fields to Send', diff --git a/packages/nodes-base/nodes/ServiceNow/UserDescription.ts b/packages/nodes-base/nodes/ServiceNow/UserDescription.ts index ca76b3c4b4..7a26f845b3 100644 --- a/packages/nodes-base/nodes/ServiceNow/UserDescription.ts +++ b/packages/nodes-base/nodes/ServiceNow/UserDescription.ts @@ -7,6 +7,7 @@ export const userOperations: INodeProperties[] = [ displayName: 'Operation', name: 'operation', type: 'options', + noDataExpression: true, displayOptions: { show: { resource: [ @@ -84,7 +85,7 @@ export const userFields: INodeProperties[] = [ displayName: 'Active', name: 'active', type: 'boolean', - default: '', + default: false, description: 'Whether to activate the user', }, { @@ -196,7 +197,7 @@ export const userFields: INodeProperties[] = [ displayName: 'Password Needs Reset', name: 'password_needs_reset', type: 'boolean', - default: '', + default: false, description: 'Whether to require a password reset when the user logs in', }, { @@ -213,7 +214,7 @@ export const userFields: INodeProperties[] = [ typeOptions: { loadOptionsMethod: 'getUserRoles', }, - default: '', + default: [], description: 'Roles of the user', }, { @@ -242,6 +243,7 @@ export const userFields: INodeProperties[] = [ name: 'user_name', type: 'string', default: '', + // nodelinter-ignore-next-line description: 'A username associated with the user (e.g. user_name.123)', }, { @@ -272,7 +274,7 @@ export const userFields: INodeProperties[] = [ }, }, default: false, - description: 'If all results should be returned or only up to a given limit', + description: 'Whether to return all results or only up to a given limit', }, { displayName: 'Limit', @@ -332,15 +334,16 @@ export const userFields: INodeProperties[] = [ 'operation', ], }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Filter', name: 'sysparm_query', type: 'string', default: '', - description: 'An encoded query string used to filter the results. More info', + description: 'An encoded query string used to filter the results. More info.', }, { displayName: 'Return Values', @@ -491,8 +494,9 @@ export const userFields: INodeProperties[] = [ 'operation', ], }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Return Values', @@ -560,7 +564,7 @@ export const userFields: INodeProperties[] = [ displayName: 'Active', name: 'active', type: 'boolean', - default: '', + default: false, description: 'Whether to activate the user', }, { @@ -672,7 +676,7 @@ export const userFields: INodeProperties[] = [ displayName: 'Password Needs Reset', name: 'password_needs_reset', type: 'boolean', - default: '', + default: false, description: 'Whether to require a password reset when the user logs in', }, { @@ -689,7 +693,7 @@ export const userFields: INodeProperties[] = [ typeOptions: { loadOptionsMethod: 'getUserRoles', }, - default: '', + default: [], description: 'Roles of the user', }, { @@ -718,6 +722,7 @@ export const userFields: INodeProperties[] = [ name: 'user_name', type: 'string', default: '', + // nodelinter-ignore-next-line description: 'A username associated with the user (e.g. user_name.123)', }, { diff --git a/packages/nodes-base/nodes/ServiceNow/UserGroupDescription.ts b/packages/nodes-base/nodes/ServiceNow/UserGroupDescription.ts index 271e7ea76d..a631c49905 100644 --- a/packages/nodes-base/nodes/ServiceNow/UserGroupDescription.ts +++ b/packages/nodes-base/nodes/ServiceNow/UserGroupDescription.ts @@ -7,6 +7,7 @@ export const userGroupOperations: INodeProperties[] = [ displayName: 'Operation', name: 'operation', type: 'options', + noDataExpression: true, displayOptions: { show: { resource: [ @@ -44,7 +45,7 @@ export const userGroupFields: INodeProperties[] = [ }, }, default: false, - description: 'If all results should be returned or only up to a given limit', + description: 'Whether to return all results or only up to a given limit', }, { displayName: 'Limit', @@ -101,15 +102,16 @@ export const userGroupFields: INodeProperties[] = [ typeOptions: { loadOptionsMethod: 'getColumns', }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Filter', name: 'sysparm_query', type: 'string', default: '', - description: 'An encoded query string used to filter the results. More info', + description: 'An encoded query string used to filter the results. More info.', }, { displayName: 'Return Values', diff --git a/packages/nodes-base/nodes/ServiceNow/UserRoleDescription.ts b/packages/nodes-base/nodes/ServiceNow/UserRoleDescription.ts index 59bb84f4fa..ba43b0d4af 100644 --- a/packages/nodes-base/nodes/ServiceNow/UserRoleDescription.ts +++ b/packages/nodes-base/nodes/ServiceNow/UserRoleDescription.ts @@ -7,6 +7,7 @@ export const userRoleOperations: INodeProperties[] = [ displayName: 'Operation', name: 'operation', type: 'options', + noDataExpression: true, displayOptions: { show: { resource: [ @@ -44,7 +45,7 @@ export const userRoleFields: INodeProperties[] = [ }, }, default: false, - description: 'If all results should be returned or only up to a given limit', + description: 'Whether to return all results or only up to a given limit', }, { displayName: 'Limit', @@ -101,15 +102,16 @@ export const userRoleFields: INodeProperties[] = [ typeOptions: { loadOptionsMethod: 'getColumns', }, - default: '', + default: [], description: 'A list of fields to return', + hint: 'String of comma separated values or an array of strings can be set in an expression', }, { displayName: 'Filter', name: 'sysparm_query', type: 'string', default: '', - description: 'An encoded query string used to filter the results. More info', + description: 'An encoded query string used to filter the results. More info.', }, { displayName: 'Return Values', diff --git a/packages/nodes-base/nodes/Slack/GenericFunctions.ts b/packages/nodes-base/nodes/Slack/GenericFunctions.ts index e9ee771177..c8b9e0f5c6 100644 --- a/packages/nodes-base/nodes/Slack/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Slack/GenericFunctions.ts @@ -15,7 +15,7 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as _ from 'lodash'; +import _ from 'lodash'; export async function slackApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: object = {}, query: object = {}, headers: {} | undefined = undefined, option: {} = {}): Promise { // tslint:disable-line:no-any const authenticationMethod = this.getNodeParameter('authentication', 0, 'accessToken') as string; diff --git a/packages/nodes-base/nodes/Slack/Slack.node.ts b/packages/nodes-base/nodes/Slack/Slack.node.ts index fd6cb8c861..6115717cb6 100644 --- a/packages/nodes-base/nodes/Slack/Slack.node.ts +++ b/packages/nodes-base/nodes/Slack/Slack.node.ts @@ -63,7 +63,7 @@ import { IAttachment, } from './MessageInterface'; -import moment = require('moment'); +import moment from 'moment'; interface Attachment { fields: { diff --git a/packages/nodes-base/nodes/Snowflake/GenericFunctions.ts b/packages/nodes-base/nodes/Snowflake/GenericFunctions.ts index d0217b9955..f970090060 100644 --- a/packages/nodes-base/nodes/Snowflake/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Snowflake/GenericFunctions.ts @@ -3,7 +3,7 @@ import { INodeExecutionData, } from 'n8n-workflow'; -import * as snowflake from 'snowflake-sdk'; +import snowflake from 'snowflake-sdk'; export function connect(conn: snowflake.Connection) { return new Promise((resolve, reject) => { diff --git a/packages/nodes-base/nodes/Snowflake/Snowflake.node.ts b/packages/nodes-base/nodes/Snowflake/Snowflake.node.ts index 64db243e4c..0bace73093 100644 --- a/packages/nodes-base/nodes/Snowflake/Snowflake.node.ts +++ b/packages/nodes-base/nodes/Snowflake/Snowflake.node.ts @@ -16,7 +16,7 @@ import { execute, } from './GenericFunctions'; -import * as snowflake from 'snowflake-sdk'; +import snowflake from 'snowflake-sdk'; export class Snowflake implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Spontit/Spontit.node.ts b/packages/nodes-base/nodes/Spontit/Spontit.node.ts index 799daa3d2f..edf8fe24ea 100644 --- a/packages/nodes-base/nodes/Spontit/Spontit.node.ts +++ b/packages/nodes-base/nodes/Spontit/Spontit.node.ts @@ -17,7 +17,7 @@ import { pushOperations, } from './PushDescription'; -import * as moment from 'moment'; +import moment from 'moment'; export class Spontit implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/SseTrigger/SseTrigger.node.ts b/packages/nodes-base/nodes/SseTrigger/SseTrigger.node.ts index 979b480c09..6dc56e3ef8 100644 --- a/packages/nodes-base/nodes/SseTrigger/SseTrigger.node.ts +++ b/packages/nodes-base/nodes/SseTrigger/SseTrigger.node.ts @@ -1,4 +1,4 @@ -import * as EventSource from 'eventsource'; +import EventSource from 'eventsource'; import { ITriggerFunctions } from 'n8n-core'; import { INodeType, diff --git a/packages/nodes-base/nodes/Strava/ActivityDescription.ts b/packages/nodes-base/nodes/Strava/ActivityDescription.ts index a1e4875300..d4e34765b1 100644 --- a/packages/nodes-base/nodes/Strava/ActivityDescription.ts +++ b/packages/nodes-base/nodes/Strava/ActivityDescription.ts @@ -46,6 +46,11 @@ export const activityOperations: INodeProperties[] = [ value: 'getLaps', description: 'Get all activity laps', }, + { + name: 'Get Streams', + value: 'getStreams', + description: 'Get activity streams', + }, { name: 'Get Zones', value: 'getZones', @@ -316,6 +321,7 @@ export const activityFields: INodeProperties[] = [ 'getLaps', 'getKudos', 'getZones', + 'getStreams', ], }, }, @@ -369,7 +375,70 @@ export const activityFields: INodeProperties[] = [ default: 50, description: 'How many results to return.', }, - + { + displayName: 'Keys', + name: 'keys', + type: 'multiOptions', + options: [ + { + name: 'Altitude', + value: 'altitude', + }, + { + name: 'Cadence', + value: 'cadence', + }, + { + name: 'Distance', + value: 'distance', + }, + { + name: 'Gradient', + value: 'grade_smooth', + }, + { + name: 'Heartrate', + value: 'heartrate', + }, + { + name: 'Latitude / Longitude', + value: 'latlng', + }, + { + name: 'Moving', + value: 'moving', + }, + { + name: 'Temperature', + value: 'temp', + }, + { + name: 'Time', + value: 'time', + }, + { + name: 'Velocity', + value: 'velocity_smooth', + }, + { + name: 'Watts', + value: 'watts', + }, + ], + displayOptions: { + show: { + resource: [ + 'activity', + ], + operation: [ + 'getStreams', + ], + }, + }, + required: true, + default: [], + description: 'Desired stream types to return', + }, /* -------------------------------------------------------------------------- */ /* activity:getAll */ /* -------------------------------------------------------------------------- */ diff --git a/packages/nodes-base/nodes/Strava/Strava.node.ts b/packages/nodes-base/nodes/Strava/Strava.node.ts index cacf732193..7b76bd8f8a 100644 --- a/packages/nodes-base/nodes/Strava/Strava.node.ts +++ b/packages/nodes-base/nodes/Strava/Strava.node.ts @@ -19,7 +19,7 @@ import { activityOperations, } from './ActivityDescription'; -import * as moment from 'moment'; +import moment from 'moment'; export class Strava implements INodeType { description: INodeTypeDescription = { @@ -129,6 +129,15 @@ export class Strava implements INodeType { responseData = responseData.splice(0, limit); } } + //https://developers.strava.com/docs/reference/#api-Streams-getActivityStreams + if (operation === 'getStreams') { + const activityId = this.getNodeParameter('activityId', i) as string; + const keys = this.getNodeParameter('keys', i) as string[]; + qs.keys = keys.toString(); + qs.key_by_type = true; + + responseData = await stravaApiRequest.call(this, 'GET', `/activities/${activityId}/streams`, {}, qs); + } //https://developers.mailerlite.com/reference#subscribers if (operation === 'getAll') { const returnAll = this.getNodeParameter('returnAll', i) as boolean; diff --git a/packages/nodes-base/nodes/TheHive/GenericFunctions.ts b/packages/nodes-base/nodes/TheHive/GenericFunctions.ts index e53a6d8cd1..b9ed363f12 100644 --- a/packages/nodes-base/nodes/TheHive/GenericFunctions.ts +++ b/packages/nodes-base/nodes/TheHive/GenericFunctions.ts @@ -12,7 +12,7 @@ import { IDataObject, NodeApiError, NodeOperationError, } from 'n8n-workflow'; -import * as moment from 'moment'; +import moment from 'moment'; import { Eq } from './QueryFunctions'; export async function theHiveApiRequest(this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, query: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any diff --git a/packages/nodes-base/nodes/TimescaleDb/TimescaleDb.node.ts b/packages/nodes-base/nodes/TimescaleDb/TimescaleDb.node.ts index 6917a61263..4d9bec9739 100644 --- a/packages/nodes-base/nodes/TimescaleDb/TimescaleDb.node.ts +++ b/packages/nodes-base/nodes/TimescaleDb/TimescaleDb.node.ts @@ -16,7 +16,7 @@ import { pgUpdate, } from '../Postgres/Postgres.node.functions'; -import * as pgPromise from 'pg-promise'; +import pgPromise from 'pg-promise'; export class TimescaleDb implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Toggl/TogglTrigger.node.ts b/packages/nodes-base/nodes/Toggl/TogglTrigger.node.ts index 1d826f7bcf..caf033c663 100644 --- a/packages/nodes-base/nodes/Toggl/TogglTrigger.node.ts +++ b/packages/nodes-base/nodes/Toggl/TogglTrigger.node.ts @@ -8,7 +8,7 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as moment from 'moment'; +import moment from 'moment'; import { togglApiRequest } from './GenericFunctions'; export class TogglTrigger implements INodeType { diff --git a/packages/nodes-base/nodes/TravisCi/GenericFunctions.ts b/packages/nodes-base/nodes/TravisCi/GenericFunctions.ts index 2d167150e8..00c224bb37 100644 --- a/packages/nodes-base/nodes/TravisCi/GenericFunctions.ts +++ b/packages/nodes-base/nodes/TravisCi/GenericFunctions.ts @@ -17,7 +17,7 @@ import { get, } from 'lodash'; -import * as querystring from 'querystring'; +import querystring from 'querystring'; export async function travisciApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any const credentials = await this.getCredentials('travisCiApi'); diff --git a/packages/nodes-base/nodes/Twist/Twist.node.ts b/packages/nodes-base/nodes/Twist/Twist.node.ts index e1d094ac4c..ce94ac1a32 100644 --- a/packages/nodes-base/nodes/Twist/Twist.node.ts +++ b/packages/nodes-base/nodes/Twist/Twist.node.ts @@ -37,7 +37,7 @@ import { commentOperations } from './CommentDescription'; import { v4 as uuid } from 'uuid'; -import * as moment from 'moment'; +import moment from 'moment'; export class Twist implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/UnleashedSoftware/GenericFunctions.ts b/packages/nodes-base/nodes/UnleashedSoftware/GenericFunctions.ts index b5be8cede0..d33a386a64 100644 --- a/packages/nodes-base/nodes/UnleashedSoftware/GenericFunctions.ts +++ b/packages/nodes-base/nodes/UnleashedSoftware/GenericFunctions.ts @@ -18,7 +18,7 @@ import { createHmac, } from 'crypto'; -import * as qs from 'qs'; +import qs from 'qs'; export async function unleashedApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, path: string, body: any = {}, query: IDataObject = {}, pageNumber?: number, headers?: object): Promise { // tslint:disable-line:no-any diff --git a/packages/nodes-base/nodes/UnleashedSoftware/UnleashedSoftware.node.ts b/packages/nodes-base/nodes/UnleashedSoftware/UnleashedSoftware.node.ts index 2600ec8e2b..aeacb9681d 100644 --- a/packages/nodes-base/nodes/UnleashedSoftware/UnleashedSoftware.node.ts +++ b/packages/nodes-base/nodes/UnleashedSoftware/UnleashedSoftware.node.ts @@ -25,7 +25,7 @@ import { stockOnHandOperations, } from './StockOnHandDescription'; -import * as moment from 'moment'; +import moment from 'moment'; export class UnleashedSoftware implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/UptimeRobot/UptimeRobot.node.ts b/packages/nodes-base/nodes/UptimeRobot/UptimeRobot.node.ts index 18f5117475..c4ce555a6d 100644 --- a/packages/nodes-base/nodes/UptimeRobot/UptimeRobot.node.ts +++ b/packages/nodes-base/nodes/UptimeRobot/UptimeRobot.node.ts @@ -33,7 +33,7 @@ import { publicStatusPageOperations, } from './PublicStatusPageDescription'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; export class UptimeRobot implements INodeType { description: INodeTypeDescription = { diff --git a/packages/nodes-base/nodes/Wait/Wait.node.ts b/packages/nodes-base/nodes/Wait/Wait.node.ts index 5ca7a012e3..7f79064dfa 100644 --- a/packages/nodes-base/nodes/Wait/Wait.node.ts +++ b/packages/nodes-base/nodes/Wait/Wait.node.ts @@ -14,15 +14,15 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as basicAuth from 'basic-auth'; +import basicAuth from 'basic-auth'; import { Response } from 'express'; -import * as fs from 'fs'; +import fs from 'fs'; -import * as formidable from 'formidable'; +import formidable from 'formidable'; -import * as isbot from 'isbot'; +import isbot from 'isbot'; function authorizationError(resp: Response, realm: string, responseCode: number, message?: string) { if (message === undefined) { diff --git a/packages/nodes-base/nodes/Webhook/Webhook.node.ts b/packages/nodes-base/nodes/Webhook/Webhook.node.ts index 16256249bf..b2e96f7153 100644 --- a/packages/nodes-base/nodes/Webhook/Webhook.node.ts +++ b/packages/nodes-base/nodes/Webhook/Webhook.node.ts @@ -12,15 +12,15 @@ import { NodeOperationError, } from 'n8n-workflow'; -import * as basicAuth from 'basic-auth'; +import basicAuth from 'basic-auth'; import { Response } from 'express'; -import * as fs from 'fs'; +import fs from 'fs'; -import * as formidable from 'formidable'; +import formidable from 'formidable'; -import * as isbot from 'isbot'; +import isbot from 'isbot'; function authorizationError(resp: Response, realm: string, responseCode: number, message?: string) { if (message === undefined) { diff --git a/packages/nodes-base/nodes/Wise/Wise.node.ts b/packages/nodes-base/nodes/Wise/Wise.node.ts index 1063a33821..cf10a5d149 100644 --- a/packages/nodes-base/nodes/Wise/Wise.node.ts +++ b/packages/nodes-base/nodes/Wise/Wise.node.ts @@ -40,7 +40,7 @@ import { omit, } from 'lodash'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; import { v4 as uuid } from 'uuid'; diff --git a/packages/nodes-base/nodes/WooCommerce/GenericFunctions.ts b/packages/nodes-base/nodes/WooCommerce/GenericFunctions.ts index 0096f76aa7..74f59a9aa6 100644 --- a/packages/nodes-base/nodes/WooCommerce/GenericFunctions.ts +++ b/packages/nodes-base/nodes/WooCommerce/GenericFunctions.ts @@ -53,7 +53,6 @@ export async function woocommerceApiRequest(this: IHookFunctions | IExecuteFunct uri: uri || `${credentials.url}/wp-json/wc/v3${resource}`, json: true, }; - if (credentials.includeCredentialsInQuery === true) { delete options.auth; Object.assign(qs, { consumer_key: credentials.consumerKey, consumer_secret: credentials.consumerSecret }); @@ -79,7 +78,11 @@ export async function woocommerceApiRequestAllItems(this: IExecuteFunctions | IL query.per_page = 100; do { responseData = await woocommerceApiRequest.call(this, method, endpoint, body, query, uri, { resolveWithFullResponse: true }); - uri = responseData.headers['link'].split(';')[0].replace('<', '').replace('>', ''); + const links = responseData.headers.link.split(','); + const nextLink = links.find((link: string) => link.indexOf('rel="next"') !== -1); + if (nextLink) { + uri = nextLink.split(';')[0].replace(/<(.*)>/, '$1'); + } returnData.push.apply(returnData, responseData.body); } while ( responseData.headers['link'] !== undefined && @@ -156,7 +159,7 @@ export function setFields(fieldsToSet: IDataObject, body: IDataObject) { } else { body[snakeCase(fields.toString())] = fieldsToSet[fields]; } - + } } diff --git a/packages/nodes-base/nodes/Zoom/Zoom.node.ts b/packages/nodes-base/nodes/Zoom/Zoom.node.ts index a0b97918db..6397bcf063 100644 --- a/packages/nodes-base/nodes/Zoom/Zoom.node.ts +++ b/packages/nodes-base/nodes/Zoom/Zoom.node.ts @@ -31,7 +31,7 @@ import { // webinarFields, // } from './WebinarDescription'; -import * as moment from 'moment-timezone'; +import moment from 'moment-timezone'; interface Settings { host_video?: boolean; diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 43ab38c5fa..cad6ad0ac9 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -1,6 +1,6 @@ { "name": "n8n-nodes-base", - "version": "0.168.0", + "version": "0.169.1", "description": "Base nodes of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", @@ -258,6 +258,7 @@ "dist/credentials/SentryIoOAuth2Api.credentials.js", "dist/credentials/SentryIoServerApi.credentials.js", "dist/credentials/ServiceNowOAuth2Api.credentials.js", + "dist/credentials/ServiceNowBasicApi.credentials.js", "dist/credentials/Sftp.credentials.js", "dist/credentials/ShopifyApi.credentials.js", "dist/credentials/Signl4Api.credentials.js", @@ -712,11 +713,11 @@ "@types/xml2js": "^0.4.3", "gulp": "^4.0.0", "jest": "^27.4.7", - "n8n-workflow": "~0.93.0", + "n8n-workflow": "~0.94.0", "nodelinter": "^0.1.9", "ts-jest": "^27.1.3", "tslint": "^6.1.2", - "typescript": "~4.3.5" + "typescript": "~4.6.0" }, "dependencies": { "@kafkajs/confluent-schema-registry": "1.0.6", @@ -748,13 +749,13 @@ "lodash.unset": "^4.5.2", "lossless-json": "^1.0.4", "mailparser": "^3.2.0", - "moment": "2.29.1", + "moment": "~2.29.2", "moment-timezone": "^0.5.28", "mongodb": "^3.6.9", "mqtt": "4.2.6", "mssql": "^6.2.0", "mysql2": "~2.3.0", - "n8n-core": "~0.111.0", + "n8n-core": "~0.112.0", "node-ssh": "^12.0.0", "nodemailer": "^6.5.0", "pdf-parse": "^1.1.1", @@ -765,7 +766,7 @@ "request": "^2.88.2", "rhea": "^1.0.11", "rss-parser": "^3.7.0", - "simple-git": "^2.36.2", + "simple-git": "^3.5.0", "snowflake-sdk": "^1.5.3", "ssh2-sftp-client": "^7.0.0", "tmp-promise": "^3.0.2", diff --git a/packages/nodes-base/tsconfig.json b/packages/nodes-base/tsconfig.json index 791b66eb1d..2be084bcd7 100644 --- a/packages/nodes-base/tsconfig.json +++ b/packages/nodes-base/tsconfig.json @@ -16,7 +16,9 @@ "declaration": true, "outDir": "./dist/", "target": "es2019", - "sourceMap": true + "sourceMap": true, + "esModuleInterop": true, + "useUnknownInCatchVariables": false, }, "include": [ "credentials/**/*", diff --git a/packages/workflow/package.json b/packages/workflow/package.json index 9004a2130b..2f41e0c92f 100644 --- a/packages/workflow/package.json +++ b/packages/workflow/package.json @@ -1,6 +1,6 @@ { "name": "n8n-workflow", - "version": "0.93.0", + "version": "0.94.0", "description": "Workflow base code of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", @@ -47,7 +47,7 @@ "prettier": "^2.3.2", "ts-jest": "^27.1.3", "tslint": "^6.1.2", - "typescript": "~4.3.5" + "typescript": "~4.6.0" }, "dependencies": { "jmespath": "^0.16.0", diff --git a/packages/workflow/src/Expression.ts b/packages/workflow/src/Expression.ts index e14c9b960a..b89b9114cd 100644 --- a/packages/workflow/src/Expression.ts +++ b/packages/workflow/src/Expression.ts @@ -69,6 +69,7 @@ export class Expression { activeNodeName: string, connectionInputData: INodeExecutionData[], mode: WorkflowExecuteMode, + timezone: string, additionalKeys: IWorkflowDataProxyAdditionalKeys, returnObjectAsString = false, selfData = {}, @@ -95,6 +96,7 @@ export class Expression { connectionInputData, siblingParameters, mode, + timezone, additionalKeys, -1, selfData, @@ -157,6 +159,7 @@ export class Expression { node: INode, parameterValue: string | boolean | undefined, mode: WorkflowExecuteMode, + timezone: string, additionalKeys: IWorkflowDataProxyAdditionalKeys, defaultValue?: boolean | number | string, ): boolean | number | string | undefined { @@ -183,6 +186,7 @@ export class Expression { node.name, connectionInputData, mode, + timezone, additionalKeys, ) as boolean | number | string | undefined; } @@ -200,6 +204,7 @@ export class Expression { node: INode, parameterValue: NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[], mode: WorkflowExecuteMode, + timezone: string, additionalKeys: IWorkflowDataProxyAdditionalKeys, defaultValue: | NodeParameterValue @@ -233,6 +238,7 @@ export class Expression { node.name, connectionInputData, mode, + timezone, additionalKeys, false, selfData, @@ -247,6 +253,7 @@ export class Expression { node.name, connectionInputData, mode, + timezone, additionalKeys, false, selfData, @@ -276,6 +283,7 @@ export class Expression { activeNodeName: string, connectionInputData: INodeExecutionData[], mode: WorkflowExecuteMode, + timezone: string, additionalKeys: IWorkflowDataProxyAdditionalKeys, returnObjectAsString = false, selfData = {}, @@ -301,6 +309,7 @@ export class Expression { activeNodeName, connectionInputData, mode, + timezone, additionalKeys, returnObjectAsString, selfData, @@ -315,6 +324,7 @@ export class Expression { activeNodeName, connectionInputData, mode, + timezone, additionalKeys, returnObjectAsString, selfData, @@ -332,6 +342,7 @@ export class Expression { activeNodeName, connectionInputData, mode, + timezone, additionalKeys, returnObjectAsString, selfData, diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts index 058b471c43..240a912b71 100644 --- a/packages/workflow/src/Interfaces.ts +++ b/packages/workflow/src/Interfaces.ts @@ -160,6 +160,7 @@ export abstract class ICredentialsHelper { requestOptions: IHttpRequestOptions | IRequestOptionsSimplified, workflow: Workflow, node: INode, + defaultTimezone: string, ): Promise; abstract getCredentials( @@ -171,6 +172,7 @@ export abstract class ICredentialsHelper { nodeCredentials: INodeCredentialsDetails, type: string, mode: WorkflowExecuteMode, + defaultTimezone: string, raw?: boolean, expressionResolveValues?: ICredentialsExpressionResolveValues, ): Promise; @@ -683,6 +685,7 @@ export interface ITriggerFunctions { data: INodeExecutionData[][], responsePromise?: IDeferredPromise, ): void; + emitError(error: Error, responsePromise?: IDeferredPromise): void; getCredentials(type: string): Promise; getMode(): WorkflowExecuteMode; getActivationMode(): WorkflowActivateMode; diff --git a/packages/workflow/src/NodeHelpers.ts b/packages/workflow/src/NodeHelpers.ts index f56fc5d943..109905be0b 100644 --- a/packages/workflow/src/NodeHelpers.ts +++ b/packages/workflow/src/NodeHelpers.ts @@ -867,6 +867,7 @@ export function getNodeWebhooks( node, webhookDescription.path, mode, + additionalData.timezone, {}, ); if (nodeWebhookPath === undefined) { @@ -890,6 +891,7 @@ export function getNodeWebhooks( node, webhookDescription.isFullPath, 'internal', + additionalData.timezone, {}, false, ) as boolean; @@ -897,6 +899,7 @@ export function getNodeWebhooks( node, webhookDescription.restartWebhook, 'internal', + additionalData.timezone, {}, false, ) as boolean; @@ -906,6 +909,7 @@ export function getNodeWebhooks( node, webhookDescription.httpMethod, mode, + additionalData.timezone, {}, 'GET', ); @@ -937,86 +941,6 @@ export function getNodeWebhooks( return returnData; } -export function getNodeWebhooksBasic(workflow: Workflow, node: INode): IWebhookData[] { - if (node.disabled === true) { - // Node is disabled so webhooks will also not be enabled - return []; - } - - const nodeType = workflow.nodeTypes.getByNameAndVersion(node.type, node.typeVersion) as INodeType; - - if (nodeType.description.webhooks === undefined) { - // Node does not have any webhooks so return - return []; - } - - const workflowId = workflow.id || '__UNSAVED__'; - - const mode = 'internal'; - - const returnData: IWebhookData[] = []; - for (const webhookDescription of nodeType.description.webhooks) { - let nodeWebhookPath = workflow.expression.getSimpleParameterValue( - node, - webhookDescription.path, - mode, - {}, - ); - if (nodeWebhookPath === undefined) { - // TODO: Use a proper logger - console.error( - `No webhook path could be found for node "${node.name}" in workflow "${workflowId}".`, - ); - continue; - } - - nodeWebhookPath = nodeWebhookPath.toString(); - - if (nodeWebhookPath.startsWith('/')) { - nodeWebhookPath = nodeWebhookPath.slice(1); - } - if (nodeWebhookPath.endsWith('/')) { - nodeWebhookPath = nodeWebhookPath.slice(0, -1); - } - - const isFullPath: boolean = workflow.expression.getSimpleParameterValue( - node, - webhookDescription.isFullPath, - mode, - {}, - false, - ) as boolean; - - const path = getNodeWebhookPath(workflowId, node, nodeWebhookPath, isFullPath); - - const httpMethod = workflow.expression.getSimpleParameterValue( - node, - webhookDescription.httpMethod, - mode, - {}, - ); - - if (httpMethod === undefined) { - // TODO: Use a proper logger - console.error( - `The webhook "${path}" for node "${node.name}" in workflow "${workflowId}" could not be added because the httpMethod is not defined.`, - ); - continue; - } - - // @ts-ignore - returnData.push({ - httpMethod: httpMethod.toString() as WebhookHttpMethod, - node: node.name, - path, - webhookDescription, - workflowId, - }); - } - - return returnData; -} - /** * Returns the webhook path * diff --git a/packages/workflow/src/RoutingNode.ts b/packages/workflow/src/RoutingNode.ts index 6a6aab984d..d7779be174 100644 --- a/packages/workflow/src/RoutingNode.ts +++ b/packages/workflow/src/RoutingNode.ts @@ -558,6 +558,7 @@ export class RoutingNode { this.node.name, this.connectionInputData, this.mode, + this.additionalData.timezone, additionalKeys ?? {}, returnObjectAsString, ); diff --git a/packages/workflow/src/Workflow.ts b/packages/workflow/src/Workflow.ts index db696ab9fd..adcee421bc 100644 --- a/packages/workflow/src/Workflow.ts +++ b/packages/workflow/src/Workflow.ts @@ -949,7 +949,7 @@ export class Workflow { const triggerResponse = await nodeType.trigger.call(triggerFunctions); // Add the manual trigger response which resolves when the first time data got emitted - triggerResponse!.manualTriggerResponse = new Promise((resolve) => { + triggerResponse!.manualTriggerResponse = new Promise((resolve, reject) => { triggerFunctions.emit = ( (resolveEmit) => ( @@ -967,6 +967,20 @@ export class Workflow { resolveEmit(data); } )(resolve); + triggerFunctions.emitError = ( + (rejectEmit) => + (error: Error, responsePromise?: IDeferredPromise) => { + additionalData.hooks!.hookFunctions.sendResponse = [ + async (): Promise => { + if (responsePromise) { + responsePromise.reject(error); + } + }, + ]; + + rejectEmit(error); + } + )(reject); }); return triggerResponse; diff --git a/packages/workflow/src/WorkflowDataProxy.ts b/packages/workflow/src/WorkflowDataProxy.ts index 7e7416e694..4cfc185a37 100644 --- a/packages/workflow/src/WorkflowDataProxy.ts +++ b/packages/workflow/src/WorkflowDataProxy.ts @@ -7,7 +7,7 @@ /* eslint-disable no-prototype-builtins */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ -import { DateTime, Duration, Interval } from 'luxon'; +import { DateTime, Duration, Interval, Settings } from 'luxon'; import * as jmespath from 'jmespath'; // eslint-disable-next-line import/no-cycle @@ -47,6 +47,10 @@ export class WorkflowDataProxy { private additionalKeys: IWorkflowDataProxyAdditionalKeys; + private defaultTimezone: string; + + private timezone: string; + constructor( workflow: Workflow, runExecutionData: IRunExecutionData | null, @@ -56,6 +60,7 @@ export class WorkflowDataProxy { connectionInputData: INodeExecutionData[], siblingParameters: INodeParameters, mode: WorkflowExecuteMode, + defaultTimezone: string, additionalKeys: IWorkflowDataProxyAdditionalKeys, defaultReturnRunIndex = -1, selfData = {}, @@ -69,8 +74,12 @@ export class WorkflowDataProxy { this.connectionInputData = connectionInputData; this.siblingParameters = siblingParameters; this.mode = mode; + this.defaultTimezone = defaultTimezone; + this.timezone = (this.workflow.settings.timezone as string) || this.defaultTimezone; this.selfData = selfData; this.additionalKeys = additionalKeys; + + Settings.defaultZone = this.timezone; } /** @@ -191,6 +200,7 @@ export class WorkflowDataProxy { that.activeNodeName, that.connectionInputData, that.mode, + that.timezone, that.additionalKeys, ); } @@ -633,6 +643,7 @@ export class WorkflowDataProxy { that.activeNodeName, that.connectionInputData, that.mode, + that.timezone, that.additionalKeys, ); }, @@ -647,6 +658,7 @@ export class WorkflowDataProxy { this.connectionInputData, that.siblingParameters, that.mode, + that.defaultTimezone, that.additionalKeys, defaultReturnRunIndex, ); diff --git a/packages/workflow/test/Helpers.ts b/packages/workflow/test/Helpers.ts index 58df9f0933..8e66d737d1 100644 --- a/packages/workflow/test/Helpers.ts +++ b/packages/workflow/test/Helpers.ts @@ -144,6 +144,7 @@ export function getNodeParameter( parameterName: string, itemIndex: number, mode: WorkflowExecuteMode, + timezone: string, additionalKeys: IWorkflowDataProxyAdditionalKeys, fallbackValue?: any, ): NodeParameterValue | INodeParameters | NodeParameterValue[] | INodeParameters[] | object { @@ -168,6 +169,7 @@ export function getNodeParameter( node.name, connectionInputData, mode, + timezone, additionalKeys, ); } catch (e) { @@ -253,6 +255,7 @@ export function getExecuteFunctions( parameterName, itemIndex, mode, + additionalData.timezone, {}, fallbackValue, ); @@ -286,6 +289,7 @@ export function getExecuteFunctions( connectionInputData, {}, mode, + additionalData.timezone, {}, ); return dataProxy.getDataProxy(); @@ -445,6 +449,7 @@ export function getExecuteSingleFunctions( parameterName, itemIndex, mode, + additionalData.timezone, {}, fallbackValue, ); @@ -466,6 +471,7 @@ export function getExecuteSingleFunctions( connectionInputData, {}, mode, + additionalData.timezone, {}, ); return dataProxy.getDataProxy(); diff --git a/packages/workflow/test/Workflow.test.ts b/packages/workflow/test/Workflow.test.ts index effb496370..453bdcc2d8 100644 --- a/packages/workflow/test/Workflow.test.ts +++ b/packages/workflow/test/Workflow.test.ts @@ -998,6 +998,7 @@ describe('Workflow', () => { ]; const nodeTypes = Helpers.NodeTypes(); + const timezone = 'America/New_York'; for (const testData of tests) { test(testData.description, () => { @@ -1110,6 +1111,7 @@ describe('Workflow', () => { activeNodeName, connectionInputData, 'manual', + timezone, {}, ); // @ts-ignore @@ -1264,6 +1266,7 @@ describe('Workflow', () => { activeNodeName, connectionInputData, 'manual', + timezone, {}, ); diff --git a/packages/workflow/test/WorkflowDataProxy.test.ts b/packages/workflow/test/WorkflowDataProxy.test.ts index 3d795c414e..9509a36ddb 100644 --- a/packages/workflow/test/WorkflowDataProxy.test.ts +++ b/packages/workflow/test/WorkflowDataProxy.test.ts @@ -1,11 +1,6 @@ import { Workflow, WorkflowDataProxy } from '../src'; import * as Helpers from './Helpers'; -import { - IConnections, - INode, - INodeExecutionData, - IRunExecutionData, -} from '../src/Interfaces'; +import { IConnections, INode, INodeExecutionData, IRunExecutionData } from '../src/Interfaces'; describe('WorkflowDataProxy', () => { describe('test data proxy', () => { @@ -133,13 +128,13 @@ describe('WorkflowDataProxy', () => { }, }; - const renameNodeConnectionInputData: INodeExecutionData[] = [ - { json: { length: 105 } }, - { json: { length: 160 } }, - { json: { length: 121 } }, - { json: { length: 275 } }, - { json: { length: 950 } } - ] + const renameNodeConnectionInputData: INodeExecutionData[] = [ + { json: { length: 105 } }, + { json: { length: 160 } }, + { json: { length: 121 } }, + { json: { length: 275 } }, + { json: { length: 950 } }, + ]; const nodeTypes = Helpers.NodeTypes(); const workflow = new Workflow({ nodes, connections, active: false, nodeTypes }); @@ -153,6 +148,7 @@ describe('WorkflowDataProxy', () => { renameNodeConnectionInputData || [], {}, 'manual', + 'America/New_York', {}, ); const proxy = dataProxy.getDataProxy(); diff --git a/packages/workflow/tsconfig.json b/packages/workflow/tsconfig.json index 5e25408639..972096a036 100644 --- a/packages/workflow/tsconfig.json +++ b/packages/workflow/tsconfig.json @@ -19,7 +19,8 @@ "declaration": true, "outDir": "./dist/", "target": "es2019", - "sourceMap": true + "sourceMap": true, + "useUnknownInCatchVariables": false, }, "include": [ "**/*.d.ts", diff --git a/packages/workflow/tslint.json b/packages/workflow/tslint.json deleted file mode 100644 index f03bbfee37..0000000000 --- a/packages/workflow/tslint.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "linterOptions": { - "exclude": [ - "node_modules/**/*" - ] - }, - "defaultSeverity": "error", - "jsRules": {}, - "rules": { - "array-type": [ - true, - "array-simple" - ], - "arrow-return-shorthand": true, - "ban": [ - true, - { - "name": "Array", - "message": "tsstyle#array-constructor" - } - ], - "ban-types": [ - true, - [ - "Object", - "Use {} instead." - ], - [ - "String", - "Use 'string' instead." - ], - [ - "Number", - "Use 'number' instead." - ], - [ - "Boolean", - "Use 'boolean' instead." - ] - ], - "class-name": true, - "curly": [ - true, - "ignore-same-line" - ], - "forin": true, - "jsdoc-format": true, - "label-position": true, - "indent": [ - true, - "tabs", - 2 - ], - "member-access": [ - true, - "no-public" - ], - "new-parens": true, - "no-angle-bracket-type-assertion": true, - "no-any": true, - "no-arg": true, - "no-conditional-assignment": true, - "no-construct": true, - "no-debugger": true, - "no-default-export": true, - "no-duplicate-variable": true, - "no-inferrable-types": true, - "ordered-imports": [ - true, - { - "import-sources-order": "any", - "named-imports-order": "case-insensitive" - } - ], - "no-namespace": [ - true, - "allow-declarations" - ], - "no-reference": true, - "no-string-throw": true, - "no-unused-expression": true, - "no-var-keyword": true, - "object-literal-shorthand": true, - "only-arrow-functions": [ - true, - "allow-declarations", - "allow-named-functions" - ], - "prefer-const": true, - "radix": true, - "semicolon": [ - true, - "always", - "ignore-bound-class-methods" - ], - "switch-default": true, - "trailing-comma": [ - true, - { - "multiline": { - "objects": "always", - "arrays": "always", - "functions": "always", - "typeLiterals": "ignore" - }, - "esSpecCompliant": true - } - ], - "triple-equals": [ - true, - "allow-null-check" - ], - "use-isnan": true, - "quotes": [ - "error", - "single" - ], - "variable-name": [ - true, - "check-format", - "ban-keywords", - "allow-leading-underscore", - "allow-trailing-underscore" - ] - }, - "rulesDirectory": [] -}