From 324597b2a44209e5d860098e0f04a3026b843c71 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Sun, 10 Nov 2024 16:28:43 +0000 Subject: [PATCH 01/40] dependency upgrades for security scanners --- packages/backend-core/package.json | 8 +- packages/server/package.json | 12 +- packages/worker/package.json | 12 +- yarn.lock | 1023 +++++++++++----------------- 4 files changed, 432 insertions(+), 623 deletions(-) diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index b68cba5fd9..9c996b8b3b 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -31,11 +31,12 @@ "bcryptjs": "2.4.3", "bull": "4.10.1", "correlation-id": "4.0.0", - "dd-trace": "5.2.0", + "dd-trace": "5.23.0", "dotenv": "16.0.1", "ioredis": "5.3.2", "joi": "17.6.0", "jsonwebtoken": "9.0.2", + "knex": "2.4.2", "koa-passport": "^6.0.0", "koa-pino-logger": "4.0.0", "lodash": "4.17.21", @@ -47,14 +48,13 @@ "pino-http": "8.3.3", "posthog-node": "4.0.1", "pouchdb": "7.3.0", - "pouchdb-find": "7.2.2", + "pouchdb-find": "9.0.0", "redlock": "4.2.0", "rotating-file-stream": "3.1.0", "sanitize-s3-objectkey": "0.0.1", "semver": "^7.5.4", "tar-fs": "2.1.1", - "uuid": "^8.3.2", - "knex": "2.4.2" + "uuid": "^8.3.2" }, "devDependencies": { "@shopify/jest-koa-mocks": "5.1.1", diff --git a/packages/server/package.json b/packages/server/package.json index 76dd03b5a8..ff4a1ee0fd 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -60,7 +60,7 @@ "@bull-board/koa": "5.10.2", "@elastic/elasticsearch": "7.10.0", "@google-cloud/firestore": "7.8.0", - "@koa/router": "8.0.8", + "@koa/router": "^13.1.0", "@socket.io/redis-adapter": "^8.2.1", "@types/xml2js": "^0.4.14", "airtable": "0.12.2", @@ -75,8 +75,8 @@ "content-disposition": "^0.5.4", "cookies": "0.8.0", "csvtojson": "2.0.10", - "curlconverter": "3.21.0", - "dd-trace": "5.2.0", + "curlconverter": "4.11.0", + "dd-trace": "5.23.0", "dotenv": "8.2.0", "form-data": "4.0.0", "global-agent": "3.0.0", @@ -107,12 +107,12 @@ "pg": "8.10.0", "pouchdb": "7.3.0", "pouchdb-all-dbs": "1.1.1", - "pouchdb-find": "7.2.2", + "pouchdb-find": "9.0.0", "redis": "4", "serialize-error": "^7.0.1", "server-destroy": "1.0.1", "snowflake-promise": "^4.5.0", - "socket.io": "4.7.5", + "socket.io": "4.8.1", "tar": "6.2.1", "tmp": "0.2.3", "to-json-schema": "0.2.5", @@ -130,7 +130,7 @@ "@types/jest": "29.5.5", "@types/koa": "2.13.4", "@types/koa-send": "^4.1.6", - "@types/koa__router": "8.0.8", + "@types/koa__router": "^12.0.4", "@types/lodash": "4.14.200", "@types/mssql": "9.1.4", "@types/node-fetch": "2.6.4", diff --git a/packages/worker/package.json b/packages/worker/package.json index a65b5ed90f..786ca11c21 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -41,18 +41,19 @@ "@budibase/pro": "0.0.0", "@budibase/string-templates": "0.0.0", "@budibase/types": "0.0.0", - "@koa/router": "8.0.8", - "@techpass/passport-openidconnect": "0.3.3", + "@koa/router": "^13.1.0", + "@techpass/passport-openidconnect": "^1.0.0", "@types/global-agent": "2.1.1", "aws-sdk": "2.1030.0", "bcrypt": "5.1.0", "bcryptjs": "2.4.3", "bull": "4.10.1", - "dd-trace": "5.2.0", + "dd-trace": "5.23.0", "dotenv": "8.6.0", "global-agent": "3.0.0", "ical-generator": "4.1.0", "joi": "17.6.0", + "knex": "2.4.2", "koa": "2.13.4", "koa-body": "4.2.0", "koa-compress": "4.0.1", @@ -68,8 +69,7 @@ "passport-local": "1.0.0", "pouchdb": "7.3.0", "pouchdb-all-dbs": "1.1.1", - "server-destroy": "1.0.1", - "knex": "2.4.2" + "server-destroy": "1.0.1" }, "devDependencies": { "@swc/core": "1.3.71", @@ -77,7 +77,7 @@ "@types/jest": "29.5.5", "@types/jsonwebtoken": "9.0.3", "@types/koa": "2.13.4", - "@types/koa__router": "8.0.8", + "@types/koa__router": "^12.0.4", "@types/lodash": "4.14.200", "@types/node-fetch": "2.6.4", "@types/server-destroy": "1.0.1", diff --git a/yarn.lock b/yarn.lock index 8fabcddd00..d1526b08c8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -764,20 +764,20 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/identity@4.2.1", "@azure/identity@^3.4.1": - version "4.2.1" - resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" - integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== +"@azure/identity@^3.4.1": + version "3.4.2" + resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-3.4.2.tgz#6b01724c9caac7cadab6b63c76584345bda8e2de" + integrity sha512-0q5DL4uyR0EZ4RXQKD8MadGH6zTIcloUoS/RVbCpNpej4pwte0xpqYxk8K97Py2RiuUvI7F4GXpoT4046VfufA== dependencies: "@azure/abort-controller" "^1.0.0" "@azure/core-auth" "^1.5.0" "@azure/core-client" "^1.4.0" "@azure/core-rest-pipeline" "^1.1.0" "@azure/core-tracing" "^1.0.0" - "@azure/core-util" "^1.3.0" + "@azure/core-util" "^1.6.1" "@azure/logger" "^1.0.0" - "@azure/msal-browser" "^3.11.1" - "@azure/msal-node" "^2.9.2" + "@azure/msal-browser" "^3.5.0" + "@azure/msal-node" "^2.5.1" events "^3.0.0" jws "^4.0.0" open "^8.0.0" @@ -808,24 +808,24 @@ dependencies: tslib "^2.2.0" -"@azure/msal-browser@^3.11.1": - version "3.24.0" - resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.24.0.tgz#3208047672d0b0c943b0bef5f995d510d6582ae4" - integrity sha512-JGNV9hTYAa7lsum9IMIibn2kKczAojNihGo1hi7pG0kNrcKej530Fl6jxwM05A44/6I079CSn6WxYxbVhKUmWg== +"@azure/msal-browser@^3.5.0": + version "3.27.0" + resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.27.0.tgz#b6f02f73c8e102d3f115009b4677539fb173fe2b" + integrity sha512-+b4ZKSD8+vslCtVRVetkegEhOFMLP3rxDWJY212ct+2r6jVg6OSQKc1Qz3kCoXo0FgwaXkb+76TMZfpHp8QtgA== dependencies: - "@azure/msal-common" "14.15.0" + "@azure/msal-common" "14.16.0" -"@azure/msal-common@14.15.0": - version "14.15.0" - resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.15.0.tgz#0e27ac0bb88fe100f4f8d1605b64d5c268636a55" - integrity sha512-ImAQHxmpMneJ/4S8BRFhjt1MZ3bppmpRPYYNyzeQPeFN288YKbb8TmmISQEbtfkQ1BPASvYZU5doIZOPBAqENQ== +"@azure/msal-common@14.16.0": + version "14.16.0" + resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.16.0.tgz#f3470fcaec788dbe50859952cd499340bda23d7a" + integrity sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA== -"@azure/msal-node@^2.9.2": - version "2.14.0" - resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.14.0.tgz#7881895d41b03d8b9b38a29550ba3bbb15f73b3c" - integrity sha512-rrfzIpG3Q1rHjVYZmHAEDidWAZZ2cgkxlIcMQ8dHebRISaZ2KCV33Q8Vs+uaV6lxweROabNxKFlR2lIKagZqYg== +"@azure/msal-node@^2.5.1": + version "2.16.0" + resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.16.0.tgz#028ac69bc75738d6744dab3e3f20f8240f4f6e2c" + integrity sha512-oww0oJTOOvPKTVXqVyxfcFVjExQKYEkKR5KM0cTG3jnzt6u/MRMx8XaK49L/bxV35r9sCHQFjNlEShad9qGSYA== dependencies: - "@azure/msal-common" "14.15.0" + "@azure/msal-common" "14.16.0" jsonwebtoken "^9.0.0" uuid "^8.3.0" @@ -2051,44 +2051,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@2.33.2": - version "0.0.0" - dependencies: - "@budibase/nano" "10.1.5" - "@budibase/pouchdb-replication-stream" "1.2.11" - "@budibase/shared-core" "0.0.0" - "@budibase/types" "0.0.0" - aws-cloudfront-sign "3.0.2" - aws-sdk "2.1030.0" - bcrypt "5.1.0" - bcryptjs "2.4.3" - bull "4.10.1" - correlation-id "4.0.0" - dd-trace "5.2.0" - dotenv "16.0.1" - ioredis "5.3.2" - joi "17.6.0" - jsonwebtoken "9.0.2" - knex "2.4.2" - koa-passport "^6.0.0" - koa-pino-logger "4.0.0" - lodash "4.17.21" - node-fetch "2.6.7" - passport-google-oauth "2.0.0" - passport-local "1.0.0" - passport-oauth2-refresh "^2.1.0" - pino "8.11.0" - pino-http "8.3.3" - posthog-node "4.0.1" - pouchdb "7.3.0" - pouchdb-find "7.2.2" - redlock "4.2.0" - rotating-file-stream "3.1.0" - sanitize-s3-objectkey "0.0.1" - semver "^7.5.4" - tar-fs "2.1.1" - uuid "^8.3.2" - "@budibase/handlebars-helpers@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77" @@ -2131,47 +2093,6 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@npm:@budibase/pro@latest": - version "2.33.2" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.33.2.tgz#5c2012f7b2bf0fd871cda1ad37ad7a0442c84658" - integrity sha512-lBB6Wfp6OIOHRlGq82WS9KxvEXRs/P2QlwJT0Aj9PhmkQFsnXm2r8d18f0xTGvcflD+iR7XGP/k56JlCanmhQg== - dependencies: - "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "2.33.2" - "@budibase/shared-core" "2.33.2" - "@budibase/string-templates" "2.33.2" - "@budibase/types" "2.33.2" - "@koa/router" "8.0.8" - bull "4.10.1" - dd-trace "5.2.0" - joi "17.6.0" - jsonwebtoken "9.0.2" - lru-cache "^7.14.1" - memorystream "^0.3.1" - node-fetch "2.6.7" - openai "4.59.0" - scim-patch "^0.8.1" - scim2-parse-filter "^0.2.8" - -"@budibase/shared-core@2.33.2": - version "0.0.0" - dependencies: - "@budibase/types" "0.0.0" - cron-validate "1.4.5" - -"@budibase/string-templates@2.33.2": - version "0.0.0" - dependencies: - "@budibase/handlebars-helpers" "^0.13.2" - dayjs "^1.10.8" - handlebars "^4.7.8" - lodash.clonedeep "^4.5.0" - -"@budibase/types@2.33.2": - version "0.0.0" - dependencies: - scim-patch "^0.8.1" - "@bull-board/api@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3" @@ -2316,24 +2237,6 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@curlconverter/yargs-parser@^0.0.1": - version "0.0.1" - resolved "https://registry.yarnpkg.com/@curlconverter/yargs-parser/-/yargs-parser-0.0.1.tgz#62a360cea3d62b9b5805e61e8110cea98da8d140" - integrity sha512-DbEVRYqrorzwqc63MQ3RODflut1tNla8ZCKo1h83lF7+fbntgubZsDfRDBv5Lxj3vkKuvAolysNM2ekwJev8wA== - -"@curlconverter/yargs@^0.0.2": - version "0.0.2" - resolved "https://registry.yarnpkg.com/@curlconverter/yargs/-/yargs-0.0.2.tgz#a8ad4a2a2d0b0f897f8c117f664199165b59fd8a" - integrity sha512-Q1YEebpCY61kxme4wvU0/IN/uMBfG5pZOKCo9FU+w20ElPvN+eH2qEVbK1C12t3Tee3qeYLLEU6HkiUeO1gc4A== - dependencies: - "@curlconverter/yargs-parser" "^0.0.1" - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - "@dabh/diagnostics@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" @@ -2355,25 +2258,25 @@ resolved "https://registry.yarnpkg.com/@dagrejs/graphlib/-/graphlib-2.2.4.tgz#d77bfa9ff49e2307c0c6e6b8b26b5dd3c05816c4" integrity sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw== -"@datadog/native-appsec@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-7.0.0.tgz#a380174dd49aef2d9bb613a0ec8ead6dc7822095" - integrity sha512-bywstWFW2hWxzPuS0+mFMVHHL0geulx5yQFtsjfszaH2LTAgk2D+Rt40MKbAoZ8q3tRw2dy6aYQ7svO3ca8jpA== +"@datadog/native-appsec@8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.1.1.tgz#76aa34697e6ecbd3d9ef7e6938d3cdcfa689b1f3" + integrity sha512-mf+Ym/AzET4FeUTXOs8hz0uLOSsVIUnavZPUx8YoKWK5lKgR2L+CLfEzOpjBwgFpDgbV8I1/vyoGelgGpsMKHA== dependencies: node-gyp-build "^3.9.0" -"@datadog/native-iast-rewriter@2.2.2": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.2.2.tgz#3f7feaf6be1af4c83ad063065b8ed509bbaf11cb" - integrity sha512-13ZBhJpjZ/tiV6rYfyAf/ITye9cyd3x12M/2NKhD4Ivev4N4uKBREAjpArOtzKtPXZ5b6oXwVV4ofT1SHoYyzA== +"@datadog/native-iast-rewriter@2.4.1": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.4.1.tgz#e8211f78c818906513fb96a549374da0382c7623" + integrity sha512-j3auTmyyn63e2y+SL28CGNy/l+jXQyh+pxqoGTacWaY5FW/dvo5nGQepAismgJ3qJ8VhQfVWRdxBSiT7wu9clw== dependencies: lru-cache "^7.14.0" node-gyp-build "^4.5.0" -"@datadog/native-iast-taint-tracking@1.6.4": - version "1.6.4" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-1.6.4.tgz#16c21ad7c36a53420c0d3c5a3720731809cc7e98" - integrity sha512-Owxk7hQ4Dxwv4zJAoMjRga0IvE6lhvxnNc8pJCHsemCWBXchjr/9bqg05Zy5JnMbKUWn4XuZeJD6RFZpRa8bfw== +"@datadog/native-iast-taint-tracking@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.1.0.tgz#7b2ed7f8fad212d65e5ab03bcdea8b42a3051b2e" + integrity sha512-rw6qSjmxmu1yFHVvZLXFt/rVq2tUZXocNogPLB8n7MPpA0jijNGb109WokWw5ITImiW91GcGDuBW6elJDVKouQ== dependencies: node-gyp-build "^3.9.0" @@ -2385,15 +2288,15 @@ node-addon-api "^6.1.0" node-gyp-build "^3.9.0" -"@datadog/pprof@5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.0.0.tgz#0c0aaf06def6d2bc4b2d353ec7b264dadbfbefab" - integrity sha512-vhNan4SBuNWLpexunDJQ+hNbRAgWdk2qy5Iyh7Nn94uSSHXigAJMAvu4jwMKKQKFfchtobOkWT8GQUWW3tgpFg== +"@datadog/pprof@5.3.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.3.0.tgz#c2f58d328ecced7f99887f1a559d7fe3aecb9219" + integrity sha512-53z2Q3K92T6Pf4vz4Ezh8kfkVEvLzbnVqacZGgcbkP//q0joFzO8q00Etw1S6NdnCX0XmX08ULaF4rUI5r14mw== dependencies: delay "^5.0.0" node-gyp-build "<4.0" p-limit "^3.1.0" - pprof-format "^2.0.7" + pprof-format "^2.1.0" source-map "^0.7.4" "@datadog/sketches-js@^2.1.0": @@ -3460,6 +3363,16 @@ resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== +"@jsep-plugin/assignment@^1.2.1": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@jsep-plugin/assignment/-/assignment-1.3.0.tgz#fcfc5417a04933f7ceee786e8ab498aa3ce2b242" + integrity sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ== + +"@jsep-plugin/regex@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" + integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== + "@koa/cors@^5.0.0": version "5.0.0" resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-5.0.0.tgz#0029b5f057fa0d0ae0e37dd2c89ece315a0daffd" @@ -3467,17 +3380,14 @@ dependencies: vary "^1.1.2" -"@koa/router@8.0.8": - version "8.0.8" - resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.8.tgz#95f32d11373d03d89dcb63fabe9ac6f471095236" - integrity sha512-FnT93N4NUehnXr+juupDmG2yfi0JnWdCmNEuIXpCG4TtG+9xvtrLambBH3RclycopVUOEYAim2lydiNBI7IRVg== +"@koa/router@^13.1.0": + version "13.1.0" + resolved "https://registry.yarnpkg.com/@koa/router/-/router-13.1.0.tgz#43f4c554444ea4f4a148a5735a9525c6d16fd1b5" + integrity sha512-mNVu1nvkpSd8Q8gMebGbCkDWJ51ODetrFvLKYusej+V0ByD4btqHYnPIzTBLXnQMVUlm/oxVwqmWBY3zQfZilw== dependencies: - debug "^4.1.1" - http-errors "^1.7.3" + http-errors "^2.0.0" koa-compose "^4.1.0" - methods "^1.1.2" - path-to-regexp "1.x" - urijs "^1.19.2" + path-to-regexp "^6.3.0" "@lerna/child-process@7.4.2": version "7.4.2" @@ -3953,7 +3863,12 @@ dependencies: "@octokit/openapi-types" "^18.0.0" -"@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.0.1": +"@opentelemetry/api@>=1.0.0 <1.9.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" + integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== + +"@opentelemetry/api@^1.0.1": version "1.7.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.7.0.tgz#b139c81999c23e3c8d3c0a7234480e945920fc40" integrity sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw== @@ -5226,16 +5141,13 @@ dependencies: defer-to-connect "^2.0.0" -"@techpass/passport-openidconnect@0.3.3", "@techpass/passport-openidconnect@^0.3.0": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-0.3.3.tgz#6c01c78bd8da0ca8917378dfbe18024702620352" - integrity sha512-i2X/CofjnGBqpTmw6b+Ex3Co/NrR2xjnIHvnOJk62XIlJJHNSTwmhJ1PkXoA5RGKlxZWchADFGjLTJnebvRj7A== +"@techpass/passport-openidconnect@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-1.0.0.tgz#e79a70b2ccd54d04122b774a33469cb52858a6bd" + integrity sha512-jcTny/3ZUlp1wN9xrUPjPQpVOfMtZ9ehSF/1T6AXse/FvgiWXDIVZUPW/QcoDsXXqYeI6huWPMGM4AwxtMe8bA== dependencies: - base64url "^3.0.1" - oauth "^0.9.15" + oauth "~0.9.0" passport-strategy "^1.0.0" - request "^2.88.0" - webfinger "^0.4.2" "@techteamer/ocsp@1.0.0": version "1.0.0" @@ -5767,10 +5679,10 @@ dependencies: "@types/koa" "*" -"@types/koa__router@8.0.8": - version "8.0.8" - resolved "https://registry.yarnpkg.com/@types/koa__router/-/koa__router-8.0.8.tgz#b1e0e9a512498777d3366bbdf0e853df27ec831c" - integrity sha512-9pGCaDtzCsj4HJ8HmGuqzk8+s57sPj4njWd08GG5o92n5Xp9io2snc40CPpXFhoKcZ8OKhuu6ht4gNou9e1C2w== +"@types/koa__router@^12.0.4": + version "12.0.4" + resolved "https://registry.yarnpkg.com/@types/koa__router/-/koa__router-12.0.4.tgz#a1f9afec9dc7e7d9fa1252d1938c44b403e19a28" + integrity sha512-Y7YBbSmfXZpa/m5UGGzb7XadJIRBRnwNY9cdAojZGp65Cpe5MAP3mOZE7e3bImt8dfKS4UFcR16SLH8L/z7PBw== dependencies: "@types/koa" "*" @@ -6717,11 +6629,6 @@ JSONStream@^1.3.5: jsonparse "^1.2.0" through ">=2.2.7 <3" -a-sync-waterfall@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7" - integrity sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA== - abab@^2.0.3, abab@^2.0.5, abab@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" @@ -6804,10 +6711,10 @@ acorn-globals@^7.0.0: acorn "^8.1.0" acorn-walk "^8.0.2" -acorn-import-assertions@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== acorn-jsx-walk@^2.0.0: version "2.0.0" @@ -6905,7 +6812,7 @@ ajv-formats@^2.0.2: dependencies: ajv "^8.0.0" -ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -7264,7 +7171,7 @@ arrify@^2.0.0, arrify@^2.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== -asap@^2.0.0, asap@^2.0.3: +asap@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== @@ -7302,18 +7209,13 @@ asn1.js@^5.0.0, asn1.js@^5.4.1: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" -asn1@^0.2.6, asn1@~0.2.3: +asn1@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== dependencies: safer-buffer "~2.1.0" -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== - assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" @@ -7417,17 +7319,23 @@ aws-sdk@2.1030.0: uuid "3.3.2" xml2js "0.4.19" -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== +axios@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" + integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" -aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" -axios@1.1.3, axios@1.6.3, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.5.0, axios@^1.6.2: +axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.5.0, axios@^1.6.2: version "1.6.3" resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.3.tgz#7f50f23b3aa246eff43c54834272346c396613f4" integrity sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww== @@ -7618,12 +7526,12 @@ base64id@2.0.0, base64id@~2.0.0: resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== -base64url@3.x.x, base64url@^3.0.1: +base64url@3.x.x: version "3.0.1" resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== -bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2: +bcrypt-pbkdf@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== @@ -8234,11 +8142,6 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001449: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001460.tgz#31d2e26f0a2309860ed3eff154e03890d9d851a7" integrity sha512-Bud7abqjvEjipUkpLs4D7gR0l8hBYBHoa+tGtKJHvT2AYzLp1z7EmVkUT4ERpVUfca8S2HGIVs883D8pUH1ZzQ== -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== - chai@^4.3.7: version "4.5.0" resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8" @@ -8617,7 +8520,7 @@ columnify@1.6.0: strip-ansi "^6.0.1" wcwidth "^1.0.0" -combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -8654,11 +8557,6 @@ commander@^2.16.0, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, comm resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - commander@^7.1.0, commander@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" @@ -8923,10 +8821,10 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -cookie@^0.4.1, cookie@~0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== +cookie@~0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" + integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== cookiejar@^2.1.4: version "2.1.4" @@ -8961,11 +8859,6 @@ core-js-compat@^3.20.2, core-js-compat@^3.21.0, core-js-compat@^3.25.1, core-js- dependencies: browserslist "^4.21.5" -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== - core-util-is@^1.0.2, core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -9283,17 +9176,16 @@ csvtojson@2.0.10: lodash "^4.17.3" strip-bom "^2.0.0" -curlconverter@3.21.0: - version "3.21.0" - resolved "https://registry.yarnpkg.com/curlconverter/-/curlconverter-3.21.0.tgz#50b9568b8d24967ef55a0fcd872e7a18eea4cbc2" - integrity sha512-DXCnp1A/Xa69FujksUfdvWQFAnIn/C+4Wuv8t+UVdZkF/lY5bzj98GGKOGme7V/ckSHDLxE29Xp76sJ5Cpsp5A== +curlconverter@4.11.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/curlconverter/-/curlconverter-4.11.0.tgz#39a319675cf243278a488411c583c9ada5f74efe" + integrity sha512-jBSvfDN10L6rGWVlkAYgtkIG8lYprDvtBgos7mafxtv15keYeQWsxUgnzns3JmqEcGJMeaGlDNdRUszURPCUaw== dependencies: - "@curlconverter/yargs" "^0.0.2" - cookie "^0.4.1" jsesc "^3.0.2" - nunjucks "^3.2.3" - query-string "^7.0.1" - string.prototype.startswith "^1.0.0" + lossless-json "^4.0.2" + tree-sitter "^0.21.1" + tree-sitter-bash "^0.23.1" + web-tree-sitter "^0.24.3" yamljs "^0.3.0" "d3-color@1 - 3": @@ -9363,13 +9255,6 @@ dargs@^7.0.0: resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== - dependencies: - assert-plus "^1.0.0" - data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -9430,46 +9315,46 @@ dayjs@^1.10.8, dayjs@^1.8.15: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -dc-polyfill@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.3.tgz#fe9eefc86813439dd46d6f9ad9582ec079c39720" - integrity sha512-Wyk5n/5KUj3GfVKV2jtDbtChC/Ff9fjKsBcg4ZtYW1yQe3DXNHcGURvmoxhqQdfOQ9TwyMjnfyv1lyYcOkFkFA== +dc-polyfill@^0.1.4: + version "0.1.6" + resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" + integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== -dd-trace@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.2.0.tgz#6ca2d76ece95f08d98468d7782c22f24192afa53" - integrity sha512-Z5ql3ZKzVW3DPstHPkTPcIPvKljHNtzTYY/WuZRlgT4XK7rMaN0j5nA8LlUh7m+tOPWs05IiKngbYVZjsqhRgA== +dd-trace@5.23.0: + version "5.23.0" + resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.23.0.tgz#a0c11863406de440a6675648caf06e1d07d67ba8" + integrity sha512-nLvwSGpTMIk6S3sMSge6yFqqgqI573VgZc8MF31vl6K0ouJoE7OkVx9cmSVjS4CbSi525tcKq9z7tApsNLpVLQ== dependencies: - "@datadog/native-appsec" "7.0.0" - "@datadog/native-iast-rewriter" "2.2.2" - "@datadog/native-iast-taint-tracking" "1.6.4" + "@datadog/native-appsec" "8.1.1" + "@datadog/native-iast-rewriter" "2.4.1" + "@datadog/native-iast-taint-tracking" "3.1.0" "@datadog/native-metrics" "^2.0.0" - "@datadog/pprof" "5.0.0" + "@datadog/pprof" "5.3.0" "@datadog/sketches-js" "^2.1.0" - "@opentelemetry/api" "^1.0.0" + "@opentelemetry/api" ">=1.0.0 <1.9.0" "@opentelemetry/core" "^1.14.0" crypto-randomuuid "^1.0.0" - dc-polyfill "^0.1.2" + dc-polyfill "^0.1.4" ignore "^5.2.4" - import-in-the-middle "^1.7.3" + import-in-the-middle "1.11.2" int64-buffer "^0.1.9" - ipaddr.js "^2.1.0" istanbul-lib-coverage "3.2.0" jest-docblock "^29.7.0" + jsonpath-plus "^9.0.0" koalas "^1.0.2" limiter "1.1.5" lodash.sortby "^4.7.0" lru-cache "^7.14.0" - methods "^1.1.2" module-details-from-path "^1.0.3" msgpack-lite "^0.1.26" - node-abort-controller "^3.1.1" opentracing ">=0.12.1" - path-to-regexp "^0.1.2" - pprof-format "^2.0.7" + path-to-regexp "^0.1.10" + pprof-format "^2.1.0" protobufjs "^7.2.5" retry "^0.13.1" + rfdc "^1.3.1" semver "^7.5.4" + shell-quote "^1.8.1" tlhunter-sorted-set "^0.1.0" debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: @@ -9516,7 +9401,7 @@ decimal.js@^10.2.1, decimal.js@^10.4.3: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== -decode-uri-component@^0.2.0, decode-uri-component@^0.2.2: +decode-uri-component@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== @@ -10301,14 +10186,6 @@ easymde@^2.16.1: codemirror-spell-checker "1.1.2" marked "^4.1.0" -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" @@ -10433,17 +10310,17 @@ engine.io-parser@~5.2.1: resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.2.tgz#37b48e2d23116919a3453738c5720455e64e1c49" integrity sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw== -engine.io@~6.5.2: - version "6.5.5" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.5.5.tgz#430b80d8840caab91a50e9e23cb551455195fc93" - integrity sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA== +engine.io@~6.6.0: + version "6.6.2" + resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.6.2.tgz#32bd845b4db708f8c774a4edef4e5c8a98b3da72" + integrity sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw== dependencies: "@types/cookie" "^0.4.1" "@types/cors" "^2.8.12" "@types/node" ">=10.0.0" accepts "~1.3.4" base64id "2.0.0" - cookie "~0.4.1" + cookie "~0.7.2" cors "~2.8.5" debug "~4.3.1" engine.io-parser "~5.2.1" @@ -10513,7 +10390,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2: +es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2: version "1.23.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== @@ -11238,7 +11115,7 @@ extend-shallow@^2.0.1: dependencies: is-extendable "^0.1.0" -extend@^3.0.2, extend@~3.0.2: +extend@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -11252,16 +11129,6 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== - -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - fast-copy@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.1.tgz#9e89ef498b8c04c1cd76b33b8e14271658a732aa" @@ -11330,7 +11197,14 @@ fast-url-parser@^1.1.3: dependencies: punycode "^1.3.2" -fast-xml-parser@4.2.5, fast-xml-parser@4.4.1, fast-xml-parser@^4.1.3, fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: +fast-xml-parser@4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" + integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== + dependencies: + strnum "^1.0.5" + +fast-xml-parser@^4.1.3, fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: version "4.4.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== @@ -11377,13 +11251,6 @@ fengari@^0.1.4: sprintf-js "^1.1.1" tmp "^0.0.33" -fetch-cookie@0.10.1: - version "0.10.1" - resolved "https://registry.yarnpkg.com/fetch-cookie/-/fetch-cookie-0.10.1.tgz#5ea88f3d36950543c87997c27ae2aeafb4b5c4d4" - integrity sha512-beB+VEd4cNeVG1PY+ee74+PkuCQnik78pgLi5Ah/7qdUfov8IctU0vLUbBT8/10Ma5GMBeI4wtxhGrEfKNYs2g== - dependencies: - tough-cookie "^2.3.3 || ^3.0.1 || ^4.0.0" - fetch-cookie@0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/fetch-cookie/-/fetch-cookie-0.11.0.tgz#e046d2abadd0ded5804ce7e2cae06d4331c15407" @@ -11391,6 +11258,14 @@ fetch-cookie@0.11.0: dependencies: tough-cookie "^2.3.3 || ^3.0.1 || ^4.0.0" +fetch-cookie@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/fetch-cookie/-/fetch-cookie-2.2.0.tgz#01086b6b5b1c3e08f15ffd8647b02ca100377365" + integrity sha512-h9AgfjURuCgA2+2ISl8GbavpUdR+WGAM2McW/ovn4tVccegp8ZqCKWSBR8uRdM8dDNlx5WdKRWxBYUwteLDCNQ== + dependencies: + set-cookie-parser "^2.4.8" + tough-cookie "^4.0.0" + fflate@^0.4.8: version "0.4.8" resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae" @@ -11508,11 +11383,6 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -filter-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" - integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== - find-free-port@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/find-free-port/-/find-free-port-2.0.0.tgz#4b22e5f6579eb1a38c41ac6bcb3efed1b6da9b1b" @@ -11584,6 +11454,11 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== +follow-redirects@^1.14.0: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + follow-redirects@^1.15.0: version "1.15.6" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" @@ -11609,11 +11484,6 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== - form-data-encoder@1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040" @@ -11646,15 +11516,6 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - formdata-node@^4.3.2: version "4.4.1" resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2" @@ -12006,13 +11867,6 @@ getopts@2.3.0: resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.3.0.tgz#71e5593284807e03e2427449d4f6712a268666f4" integrity sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA== -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== - dependencies: - assert-plus "^1.0.0" - gifwrap@^0.10.1: version "0.10.1" resolved "https://registry.yarnpkg.com/gifwrap/-/gifwrap-0.10.1.tgz#9ed46a5d51913b482d4221ce9c727080260b681e" @@ -12425,19 +12279,6 @@ handlebars@^4.7.7, handlebars@^4.7.8: optionalDependencies: uglify-js "^3.1.4" -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - hard-rejection@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" @@ -12666,7 +12507,12 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -12678,7 +12524,7 @@ http-cookie-agent@^4.0.2: dependencies: agent-base "^6.0.2" -http-errors@2.0.0: +http-errors@2.0.0, http-errors@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== @@ -12728,15 +12574,6 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - http2-wrapper@^1.0.0-beta.5.2: version "1.0.3" resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" @@ -12914,13 +12751,13 @@ import-from@^3.0.0: dependencies: resolve-from "^5.0.0" -import-in-the-middle@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.7.3.tgz#ffa784cdd57a47d2b68d2e7dd33070ff06baee43" - integrity sha512-R2I11NRi0lI3jD2+qjqyVlVEahsejw7LDnYEbGb47QEFjczE3bZYsmWheCTQA+LFs2DzOQxR7Pms7naHW1V4bQ== +import-in-the-middle@1.11.2: + version "1.11.2" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz#dd848e72b63ca6cd7c34df8b8d97fc9baee6174f" + integrity sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA== dependencies: acorn "^8.8.2" - acorn-import-assertions "^1.9.0" + acorn-import-attributes "^1.9.5" cjs-module-lexer "^1.2.2" module-details-from-path "^1.0.3" @@ -13138,11 +12975,6 @@ ip@^2.0.0: resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== -ipaddr.js@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" - integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== - is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -13191,6 +13023,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-builtin-module@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" @@ -13558,7 +13395,7 @@ is-typed-array@^1.1.13: dependencies: which-typed-array "^1.1.14" -is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== @@ -13667,11 +13504,6 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isobject@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" - integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== - isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -14281,11 +14113,6 @@ jsbi@^4.3.0: resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-4.3.0.tgz#b54ee074fb6fcbc00619559305c8f7e912b04741" integrity sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g== -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== - jsdom@^16.0.1: version "16.7.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" @@ -14351,6 +14178,11 @@ jsdom@^21.1.1: ws "^8.13.0" xml-name-validator "^4.0.0" +jsep@^1.3.8: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsep/-/jsep-1.4.0.tgz#19feccbfa51d8a79f72480b4b8e40ce2e17152f0" + integrity sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw== + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -14413,11 +14245,6 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json-schema@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -14433,7 +14260,7 @@ json-stable-stringify@^1.0.1: jsonify "^0.0.1" object-keys "^1.1.1" -json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: +json-stringify-safe@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== @@ -14474,6 +14301,15 @@ jsonparse@^1.2.0, jsonparse@^1.3.1: resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg== +jsonpath-plus@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/jsonpath-plus/-/jsonpath-plus-9.0.0.tgz#bb8703ee481531142bca8dee9a42fe72b8358a7f" + integrity sha512-bqE77VIDStrOTV/czspZhTn+o27Xx9ZJRGVkdVShEtPoqsIx5yALv3lWVU6y+PqYvWPJNWE7ORCQheQkEe0DDA== + dependencies: + "@jsep-plugin/assignment" "^1.2.1" + "@jsep-plugin/regex" "^1.0.3" + jsep "^1.3.8" + jsonschema@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.4.0.tgz#1afa34c4bc22190d8e42271ec17ac8b3404f87b2" @@ -14495,16 +14331,6 @@ jsonwebtoken@9.0.2, jsonwebtoken@^9.0.0: ms "^2.1.1" semver "^7.5.4" -jsprim@^1.2.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" - integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - jstransform@~11.0.0: version "11.0.3" resolved "https://registry.yarnpkg.com/jstransform/-/jstransform-11.0.3.tgz#09a78993e0ae4d4ef4487f6155a91f6190cb4223" @@ -14591,7 +14417,14 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@^3.0.2, kind-of@^3.1.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -14677,14 +14510,14 @@ koa-mount@^4.0.0: debug "^4.0.1" koa-compose "^4.1.0" -koa-passport@4.1.4, koa-passport@^4.1.4: +koa-passport@4.1.4: version "4.1.4" resolved "https://registry.yarnpkg.com/koa-passport/-/koa-passport-4.1.4.tgz#5f1665c1c2a37ace79af9f970b770885ca30ccfa" integrity sha512-dJBCkl4X+zdYxbI2V2OtoGy0PUenpvp2ZLLWObc8UJhsId0iQpTFT8RVcuA0709AL2txGwRHnSPoT1bYNGa6Kg== dependencies: passport "^0.4.0" -koa-passport@^6.0.0: +koa-passport@6.0.0, koa-passport@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/koa-passport/-/koa-passport-6.0.0.tgz#c30d2b859eaff8349c553eb479f365244188df53" integrity sha512-bgcrQN7Ylfgi1PVr5l6hHYkr38RHUzx+ty3m7e/xoTte8MR0zbDt6+pvP3/nuF/yXL6Ba7IzX1rSqmCy6OrrIw== @@ -15468,6 +15301,11 @@ lossless-json@^4.0.1: resolved "https://registry.yarnpkg.com/lossless-json/-/lossless-json-4.0.1.tgz#d45229e3abb213a0235812780ca894ea8c5b2c6b" integrity sha512-l0L+ppmgPDnb+JGxNLndPtJZGNf6+ZmVaQzoxQm3u6TXmhdnsA+YtdVR8DjzZd/em58686CQhOFDPewfJ4l7MA== +lossless-json@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lossless-json/-/lossless-json-4.0.2.tgz#f00c52815805d1421930a87e2670e27350958a3f" + integrity sha512-+z0EaLi2UcWi8MZRxA5iTb6m4Ys4E80uftGY+yG5KNFJb5EceQXOhdW/pWJZ8m97s26u7yZZAYMcKWNztSZssA== + loupe@^2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" @@ -15881,7 +15719,7 @@ mime-kind@^3.0.0: file-type "^12.1.0" mime-types "^2.1.24" -mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.24, mime-types@^2.1.29, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.24, mime-types@^2.1.29, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -16254,7 +16092,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@1.10.1, msgpackr@^1.5.2: +msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -16463,18 +16301,37 @@ node-addon-api@^6.1.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-6.1.0.tgz#ac8470034e58e67d0c6f1204a18ae6995d9c0d76" integrity sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA== +node-addon-api@^8.0.0, node-addon-api@^8.2.1: + version "8.2.2" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-8.2.2.tgz#3658f78d04d260aa95931d3bbc45f22ce433b821" + integrity sha512-9emqXAKhVoNrQ792nLI/wpzPpJ/bj/YXxW0CvAau1+RdGBcCRF1Dmz7719zgVsQNrzHl9Tzn3ImZ4qWFarWL0A== + node-domexception@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.0, node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: +node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.9, node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1.2.1, node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -16495,6 +16352,11 @@ node-gyp-build@^4.3.0, node-gyp-build@^4.5.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== +node-gyp-build@^4.8.0, node-gyp-build@^4.8.2: + version "4.8.2" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.2.tgz#4f802b71c1ab2ca16af830e6c1ea7dd1ad9496fa" + integrity sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw== + node-gyp-build@~4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb" @@ -16829,15 +16691,6 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" -nunjucks@^3.2.3: - version "3.2.4" - resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-3.2.4.tgz#f0878eef528ce7b0aa35d67cc6898635fd74649e" - integrity "sha1-8IeO71KM57CqNdZ8xomGNf10ZJ4= sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==" - dependencies: - a-sync-waterfall "^1.0.0" - asap "^2.0.3" - commander "^5.1.0" - nwsapi@^2.2.0, nwsapi@^2.2.4: version "2.2.12" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.12.tgz#fb6af5c0ec35b27b4581eb3bbad34ec9e5c696f8" @@ -16912,12 +16765,7 @@ nx@16.10.0, "nx@>=16.5.1 < 17": "@nx/nx-win32-arm64-msvc" "16.10.0" "@nx/nx-win32-x64-msvc" "16.10.0" -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -oauth@0.9.x, oauth@^0.9.15: +oauth@0.9.x, oauth@~0.9.0: version "0.9.15" resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" integrity sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA== @@ -17631,7 +17479,15 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@0.6.0, passport@^0.4.0, passport@^0.6.0: +passport@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" + integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + +passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -17691,22 +17547,15 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@1.x: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" +path-to-regexp@^0.1.10: + version "0.1.11" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.11.tgz#a527e662c89efc4646dbfa8100bf3e847e495761" + integrity sha512-c0t+KCuUkO/YDLPG4WWzEwx3J5F/GHXsD1h/SNZfySqAIKe/BaP95x8fWtOfRJokpS5yYHRJjMtYlXD8jxnpbw== -path-to-regexp@^0.1.2: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -path-to-regexp@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5" - integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== +path-to-regexp@^6.1.0, path-to-regexp@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" + integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== path-type@^3.0.0: version "3.0.0" @@ -17761,11 +17610,6 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== - periscopic@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/periscopic/-/periscopic-3.1.0.tgz#7e9037bf51c5855bd33b48928828db4afa79d97a" @@ -18441,19 +18285,18 @@ pouch-stream@^0.4.0: inherits "^2.0.1" readable-stream "^1.0.27-1" -pouchdb-abstract-mapreduce@7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/pouchdb-abstract-mapreduce/-/pouchdb-abstract-mapreduce-7.2.2.tgz#dd1b10a83f8d24361dce9aaaab054614b39f766f" - integrity sha512-7HWN/2yV2JkwMnGnlp84lGvFtnm0Q55NiBUdbBcaT810+clCGKvhssBCrXnmwShD1SXTwT83aszsgiSfW+SnBA== +pouchdb-abstract-mapreduce@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/pouchdb-abstract-mapreduce/-/pouchdb-abstract-mapreduce-9.0.0.tgz#d5f189a6f8980931835c41ea1f0b692368ce4686" + integrity sha512-SnTtqwAEiAa3uxKbc1J7LfiBViwEkKe2xkK92zxyTXPqWBvMnh4UU3GXxx7GrXTM4L9llsQ3lSjpbH4CNqG1Mw== dependencies: - pouchdb-binary-utils "7.2.2" - pouchdb-collate "7.2.2" - pouchdb-collections "7.2.2" - pouchdb-errors "7.2.2" - pouchdb-fetch "7.2.2" - pouchdb-mapreduce-utils "7.2.2" - pouchdb-md5 "7.2.2" - pouchdb-utils "7.2.2" + pouchdb-binary-utils "9.0.0" + pouchdb-collate "9.0.0" + pouchdb-errors "9.0.0" + pouchdb-fetch "9.0.0" + pouchdb-mapreduce-utils "9.0.0" + pouchdb-md5 "9.0.0" + pouchdb-utils "9.0.0" pouchdb-adapter-leveldb-core@7.2.2: version "7.2.2" @@ -18514,10 +18357,15 @@ pouchdb-binary-utils@7.2.2: dependencies: buffer-from "1.1.1" -pouchdb-collate@7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/pouchdb-collate/-/pouchdb-collate-7.2.2.tgz#fc261f5ef837c437e3445fb0abc3f125d982c37c" - integrity sha512-/SMY9GGasslknivWlCVwXMRMnQ8myKHs4WryQ5535nq1Wj/ehpqWloMwxEQGvZE1Sda3LOm7/5HwLTcB8Our+w== +pouchdb-binary-utils@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/pouchdb-binary-utils/-/pouchdb-binary-utils-9.0.0.tgz#eafed32c21e92ef4b253456f9e53c4cf2cfd99fd" + integrity sha512-2OMtgDZi82vqs+zNDE0YiYjOaWkYCUcZJZKK3WkRr+XYRu+2B7umJrnygJFhUwoGedBbHSrlQBLhdNV3F1AX1A== + +pouchdb-collate@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/pouchdb-collate/-/pouchdb-collate-9.0.0.tgz#654f6766927ada60603ba25b6b2ae533564fa302" + integrity sha512-TrnEDNZEmIIl+W3xKUO8h+geqVLQ90oZe5ujPkl8myUzpREULWXWQBnV5EzPXVEKDBpJlb8T3I6oy/zdWGQpdA== pouchdb-collections@7.2.2: version "7.2.2" @@ -18531,27 +18379,31 @@ pouchdb-errors@7.2.2: dependencies: inherits "2.0.4" -pouchdb-fetch@7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/pouchdb-fetch/-/pouchdb-fetch-7.2.2.tgz#492791236d60c899d7e9973f9aca0d7b9cc02230" - integrity sha512-lUHmaG6U3zjdMkh8Vob9GvEiRGwJfXKE02aZfjiVQgew+9SLkuOxNw3y2q4d1B6mBd273y1k2Lm0IAziRNxQnA== - dependencies: - abort-controller "3.0.0" - fetch-cookie "0.10.1" - node-fetch "2.6.0" +pouchdb-errors@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/pouchdb-errors/-/pouchdb-errors-9.0.0.tgz#f84269ce3327abef9455c0a90a51c26d7dca20c6" + integrity sha512-961PSMLhW0UqqdJ566g+CdLZ5pkBJRd6l4WWpCDdD0USvE4xYfYGzv43w7nZZBw1k3Xdy092yqPge7yX/tfnyw== -pouchdb-find@7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/pouchdb-find/-/pouchdb-find-7.2.2.tgz#1227afdd761812d508fe0794b3e904518a721089" - integrity sha512-BmFeFVQ0kHmDehvJxNZl9OmIztCjPlZlVSdpijuFbk/Fi1EFPU1BAv3kLC+6DhZuOqU/BCoaUBY9sn66pPY2ag== +pouchdb-fetch@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/pouchdb-fetch/-/pouchdb-fetch-9.0.0.tgz#a2cf407c75c9fc68a1924b08c9b574d28e1be7dd" + integrity sha512-TbE3cUcAJQrwb9kr44tDP0X+NAbcqgjsTvcL30L4xzBNJeCPTIRjukYX80s154SHJUXBxcWRiPsMmNqpXsjfCA== dependencies: - pouchdb-abstract-mapreduce "7.2.2" - pouchdb-collate "7.2.2" - pouchdb-errors "7.2.2" - pouchdb-fetch "7.2.2" - pouchdb-md5 "7.2.2" - pouchdb-selector-core "7.2.2" - pouchdb-utils "7.2.2" + fetch-cookie "2.2.0" + node-fetch "2.6.9" + +pouchdb-find@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/pouchdb-find/-/pouchdb-find-9.0.0.tgz#3d1b80d2adc9f9fd86c2ad559cd0144e406cb539" + integrity sha512-vvVhq4eEOmSkwSRwf2NBYtdhURB7ryJ7sUI4WDN00GuLUj2g8jAXBJuZIryVgdYt/5S5cfn70iRL6Eow+LFhpA== + dependencies: + pouchdb-abstract-mapreduce "9.0.0" + pouchdb-collate "9.0.0" + pouchdb-errors "9.0.0" + pouchdb-fetch "9.0.0" + pouchdb-md5 "9.0.0" + pouchdb-selector-core "9.0.0" + pouchdb-utils "9.0.0" pouchdb-json@7.2.2: version "7.2.2" @@ -18560,15 +18412,12 @@ pouchdb-json@7.2.2: dependencies: vuvuzela "1.0.3" -pouchdb-mapreduce-utils@7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/pouchdb-mapreduce-utils/-/pouchdb-mapreduce-utils-7.2.2.tgz#13a46a3cc2a3f3b8e24861da26966904f2963146" - integrity sha512-rAllb73hIkU8rU2LJNbzlcj91KuulpwQu804/F6xF3fhZKC/4JQMClahk+N/+VATkpmLxp1zWmvmgdlwVU4HtQ== +pouchdb-mapreduce-utils@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/pouchdb-mapreduce-utils/-/pouchdb-mapreduce-utils-9.0.0.tgz#8a2edf30ca0fa24d095eabcfbe8ebb8f3f1160e3" + integrity sha512-Bjh8W6QXqp1j7MKmHhYYp5cYlcQsm5drD8Jd/F+ZlfNt18uiD2SQXWzGM5797+tiW/LszFGb8ttw0uHWjxufCQ== dependencies: - argsarray "0.0.1" - inherits "2.0.4" - pouchdb-collections "7.2.2" - pouchdb-utils "7.2.2" + pouchdb-utils "9.0.0" pouchdb-md5@7.2.2: version "7.2.2" @@ -18578,6 +18427,14 @@ pouchdb-md5@7.2.2: pouchdb-binary-utils "7.2.2" spark-md5 "3.0.1" +pouchdb-md5@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/pouchdb-md5/-/pouchdb-md5-9.0.0.tgz#f67a2ba627309e65f8d1ce4d4baf6a5f29164617" + integrity sha512-58xUYBvW3/s+aH0j4uOhhN8yCk0LQ254cxBzI/gbKA9PrfwHpe4zrr0L/ia5ml3A30oH1f8aTnuVMwWDkFcuww== + dependencies: + pouchdb-binary-utils "9.0.0" + spark-md5 "3.0.2" + pouchdb-merge@7.2.2: version "7.2.2" resolved "https://registry.yarnpkg.com/pouchdb-merge/-/pouchdb-merge-7.2.2.tgz#940d85a2b532d6a93a6cab4b250f5648511bcc16" @@ -18590,13 +18447,13 @@ pouchdb-promise@6.4.3, pouchdb-promise@^6.0.4: dependencies: lie "3.1.1" -pouchdb-selector-core@7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/pouchdb-selector-core/-/pouchdb-selector-core-7.2.2.tgz#264d7436a8c8ac3801f39960e79875ef7f3879a0" - integrity sha512-XYKCNv9oiNmSXV5+CgR9pkEkTFqxQGWplnVhO3W9P154H08lU0ZoNH02+uf+NjZ2kjse7Q1fxV4r401LEcGMMg== +pouchdb-selector-core@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/pouchdb-selector-core/-/pouchdb-selector-core-9.0.0.tgz#6fee1df82cd5ecdbd0a034b38e6c604557d2e22a" + integrity sha512-ZYHYsdoedwm8j5tYofz+3+uUSK8i+7tRCBb01T0OuqDQb17+w5mzjHF8Ppi160xdPUPaWCo1Un+nLWGJzkmA3g== dependencies: - pouchdb-collate "7.2.2" - pouchdb-utils "7.2.2" + pouchdb-collate "9.0.0" + pouchdb-utils "9.0.0" pouchdb-utils@7.2.2: version "7.2.2" @@ -18612,6 +18469,15 @@ pouchdb-utils@7.2.2: pouchdb-md5 "7.2.2" uuid "8.1.0" +pouchdb-utils@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/pouchdb-utils/-/pouchdb-utils-9.0.0.tgz#b68f3259add50163998201d1a6d16e6a35d5d57f" + integrity sha512-xWZE5c+nAslgmLC8JBZbky8AYgdz7pKtv7KTSi6CD2tuQD0WyNKib0YnhZndeE84dksTeZlqlg56RQHsHoB2LQ== + dependencies: + pouchdb-errors "9.0.0" + pouchdb-md5 "9.0.0" + uuid "8.3.2" + pouchdb@7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/pouchdb/-/pouchdb-7.3.0.tgz#440fbef12dfd8f9002320802528665e883a3b7f8" @@ -18638,10 +18504,10 @@ pouchdb@7.3.0: uuid "8.3.2" vuvuzela "1.0.3" -pprof-format@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.0.7.tgz#526e4361f8b37d16b2ec4bb0696b5292de5046a4" - integrity sha512-1qWaGAzwMpaXJP9opRa23nPnt2Egi7RMNoNBptEE/XwHbcn4fC2b/4U4bKc5arkGkIh2ZabpF2bEb+c5GNHEKA== +pprof-format@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.1.0.tgz#acc8d7773bcf4faf0a3d3df11bceefba7ac06664" + integrity sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw== preact@^10.19.3: version "10.20.1" @@ -19005,11 +18871,6 @@ qs@^6.10.3, qs@^6.11.0, qs@^6.4.0: dependencies: side-channel "^1.0.6" -qs@~6.5.2: - version "6.5.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" - integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== - query-string@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" @@ -19019,16 +18880,6 @@ query-string@^5.0.1: object-assign "^4.1.0" strict-uri-encode "^1.0.0" -query-string@^7.0.1: - version "7.1.3" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" - integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg== - dependencies: - decode-uri-component "^0.2.2" - filter-obj "^1.1.0" - split-on-first "^1.0.0" - strict-uri-encode "^2.0.0" - querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -19471,32 +19322,6 @@ remixicon@2.5.0: resolved "https://registry.yarnpkg.com/remixicon/-/remixicon-2.5.0.tgz#b5e245894a1550aa23793f95daceadbf96ad1a41" integrity sha512-q54ra2QutYDZpuSnFjmeagmEiN9IMo56/zz5dDNitzKD23oFRw77cWo4TsrAdmdkPiEn8mxlrTqxnkujDbEGww== -request@^2.88.0: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -19653,6 +19478,11 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== +rfdc@^1.3.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== + rimraf@3.0.2, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -19948,7 +19778,7 @@ safe-stable-stringify@^2.1.0, safe-stable-stringify@^2.3.1: resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -20054,13 +19884,33 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3, semver@~2.3.1: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +semver@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" + integrity sha512-abLdIKCosKfpnmhS52NCTjO4RiLspDfsn37prjzGrp9im5DPJOgh82Os92vtwGh6XdQryKI/7SREZnV+aqiXrA== + seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -20097,6 +19947,11 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== +set-cookie-parser@^2.4.8: + version "2.7.1" + resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943" + integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ== + set-function-length@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" @@ -20178,6 +20033,11 @@ shell-exec@1.0.2: resolved "https://registry.yarnpkg.com/shell-exec/-/shell-exec-1.0.2.tgz#2e9361b0fde1d73f476c4b6671fa17785f696756" integrity sha512-jyVd+kU2X+mWKMmGhx4fpWbPsjvD53k9ivqetutVW/BQ+WIZoDoP4d8vUMGezV6saZsiNoW2f9GIhg9Dondohg== +shell-quote@^1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" + integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== + shortid@2.2.15: version "2.2.15" resolved "https://registry.yarnpkg.com/shortid/-/shortid-2.2.15.tgz#2b902eaa93a69b11120373cd42a1f1fe4437c122" @@ -20362,16 +20222,16 @@ socket.io-parser@~4.2.4: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" -socket.io@4.7.5: - version "4.7.5" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.5.tgz#56eb2d976aef9d1445f373a62d781a41c7add8f8" - integrity sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA== +socket.io@4.8.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.8.1.tgz#fa0eaff965cc97fdf4245e8d4794618459f7558a" + integrity sha512-oZ7iUCxph8WYRHHcjBEc9unw3adt5CmSNlppj/5Q4k2RIrhl8Z5yY2Xr4j9zj0+wzVZ0bxmYoGSzKJnRl6A4yg== dependencies: accepts "~1.3.4" base64id "~2.0.0" cors "~2.8.5" debug "~4.3.2" - engine.io "~6.5.2" + engine.io "~6.6.0" socket.io-adapter "~2.5.2" socket.io-parser "~4.2.4" @@ -20532,11 +20392,6 @@ split-ca@^1.0.1: resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== -split-on-first@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" - integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== - split2@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" @@ -20597,21 +20452,6 @@ ssh2@^1.11.0, ssh2@^1.4.0: cpu-features "~0.0.9" nan "^2.18.0" -sshpk@^1.7.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5" - integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - ssri@^10.0.0, ssri@^10.0.1: version "10.0.3" resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.3.tgz#7f83da39058ca1d599d174e9eee4237659710bf4" @@ -20675,11 +20515,6 @@ std-env@^3.3.1, std-env@^3.7.0: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== -step@0.0.x: - version "0.0.6" - resolved "https://registry.yarnpkg.com/step/-/step-0.0.6.tgz#143e7849a5d7d3f4a088fe29af94915216eeede2" - integrity sha512-qSSeQinUJk2w38vUFobjFoE307GqsozMC8VisOCkJLpklvKPT0ptPHwWOrENoag8rgLudvTkfP3bancwP93/Jw== - stop-iteration-iterator@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" @@ -20726,11 +20561,6 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== -strict-uri-encode@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" - integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== - string-hash@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" @@ -20754,16 +20584,7 @@ string-similarity@^4.0.4: resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -20790,14 +20611,6 @@ string-width@^5.0.0, string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string.prototype.startswith@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/string.prototype.startswith/-/string.prototype.startswith-1.0.0.tgz#92a361fb1ac172033d53eb1db3d659b0cfab6280" - integrity sha512-VHhsDkuf8gsw4JNRK9cIZjYe6r7PsVUutVohaBhqYAoPaRADoQH+mMgUg7Cs/TgQeDGEvI+PzPEMOdvdsCMvpg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string.prototype.trim@^1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" @@ -20854,7 +20667,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -20868,13 +20681,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -21655,7 +21461,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2, tough-cookie@~2.5.0: +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -21684,6 +21490,22 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +tree-sitter-bash@^0.23.1: + version "0.23.2" + resolved "https://registry.yarnpkg.com/tree-sitter-bash/-/tree-sitter-bash-0.23.2.tgz#73286bca0ead777cd42b7d693ca7e1d3f8f7f411" + integrity sha512-pTe5u2c41joNINYWrp3ZmFJX9cqPF4og1k4JtKoG22377BA7SmD2THfwj1wF2n0tHAgYLOzHZ9m8nUjhEwX5Jw== + dependencies: + node-addon-api "^8.2.1" + node-gyp-build "^4.8.2" + +tree-sitter@^0.21.1: + version "0.21.1" + resolved "https://registry.yarnpkg.com/tree-sitter/-/tree-sitter-0.21.1.tgz#fbb34c09056700814af0e1e37688e06463ba04c4" + integrity sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ== + dependencies: + node-addon-api "^8.0.0" + node-gyp-build "^4.8.0" + trim-newlines@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" @@ -21855,7 +21677,7 @@ tunnel@^0.0.6: resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== -tweetnacl@^0.14.3, tweetnacl@~0.14.0: +tweetnacl@^0.14.3: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== @@ -22194,14 +22016,6 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unset-value@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" - integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== - dependencies: - has-value "^2.0.2" - isobject "^4.0.0" - untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -22252,11 +22066,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urijs@^1.19.2: - version "1.19.11" - resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" - integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== - url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -22405,15 +22214,6 @@ vary@^1, vary@^1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - vite-node@0.29.8: version "0.29.8" resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.29.8.tgz#6a1c9d4fb31e7b4e0f825d3a37abe3404e52bd8e" @@ -22603,19 +22403,16 @@ web-streams-polyfill@4.0.0-beta.3: resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38" integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug== +web-tree-sitter@^0.24.3: + version "0.24.4" + resolved "https://registry.yarnpkg.com/web-tree-sitter/-/web-tree-sitter-0.24.4.tgz#c223df93a1284efbe871aa36c2c9de097a116ec1" + integrity sha512-sETP1Sf9OTd4LusrKBNznNgTt3fWoWhJnAFaKPiGSeVKXJbZ72qoMpxddKMdVI5BgXv32OI7tkKQre5PmF9reA== + web-vitals@^4.0.1: version "4.2.3" resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.3.tgz#270c4baecfbc6ec6fc15da1989e465e5f9b94fb7" integrity sha512-/CFAm1mNxSmOj6i0Co+iGFJ58OS4NRGVP+AWS/l509uIK5a1bSoIVaHz/ZumpHTfHSZBpgrJ+wjfpAOrTHok5Q== -webfinger@^0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/webfinger/-/webfinger-0.4.2.tgz#3477a6d97799461896039fcffc650b73468ee76d" - integrity sha512-PvvQ/k74HkC3q5G7bGu4VYeKDt3ePZMzT5qFPtEnOL8eyIU1/06OtDn9X5vlkQ23BlegA3eN89rDLiYUife3xQ== - dependencies: - step "0.0.x" - xml2js "0.1.x" - webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -22831,7 +22628,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -22849,15 +22646,6 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -22985,10 +22773,26 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.1.x, xml2js@0.4.19, xml2js@0.5.0, xml2js@0.6.2, xml2js@^0.4.19, xml2js@^0.4.5: - version "0.6.2" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" - integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== +xml2js@0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" + integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== + dependencies: + sax ">=0.6.0" + xmlbuilder "~9.0.1" + +xml2js@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xml2js@^0.4.19, xml2js@^0.4.5: + version "0.4.23" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" + integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== dependencies: sax ">=0.6.0" xmlbuilder "~11.0.0" @@ -22998,6 +22802,11 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== +xmlbuilder@~9.0.1: + version "9.0.7" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" + integrity sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ== + xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" From bcfe0479b85ef4c61551ed794f56a642140ec32c Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 18 Nov 2024 15:45:09 +0000 Subject: [PATCH 02/40] bump pouch in backend core --- package.json | 6 +- packages/backend-core/package.json | 4 +- yarn.lock | 1854 ++++------------------------ 3 files changed, 275 insertions(+), 1589 deletions(-) diff --git a/package.json b/package.json index fc7e202e3d..6dce697a90 100644 --- a/package.json +++ b/package.json @@ -98,9 +98,7 @@ }, "workspaces": { "packages": [ - "packages/*", - "!packages/account-portal", - "packages/account-portal/packages/*" + "packages/*" ] }, "resolutions": { @@ -114,7 +112,7 @@ "semver": "7.5.3", "http-cache-semantics": "4.1.1", "msgpackr": "1.10.1", - "axios": "1.6.3", + "axios": "1.7.7", "xml2js": "0.6.2", "unset-value": "2.0.1", "passport": "0.6.0", diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 9c996b8b3b..096997b2a1 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -47,7 +47,7 @@ "pino": "8.11.0", "pino-http": "8.3.3", "posthog-node": "4.0.1", - "pouchdb": "7.3.0", + "pouchdb": "^9.0.0", "pouchdb-find": "9.0.0", "redlock": "4.2.0", "rotating-file-stream": "3.1.0", @@ -65,7 +65,7 @@ "@types/jest": "29.5.5", "@types/lodash": "4.14.200", "@types/node-fetch": "2.6.4", - "@types/pouchdb": "6.4.0", + "@types/pouchdb": "^6.4.2", "@types/redlock": "4.0.7", "@types/semver": "7.3.7", "@types/tar-fs": "2.0.1", diff --git a/yarn.lock b/yarn.lock index d1526b08c8..6a7af6c0ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,7 +17,7 @@ resolved "https://registry.yarnpkg.com/@adobe/spectrum-css-workflow-icons/-/spectrum-css-workflow-icons-1.2.1.tgz#7e2cb3fcfb5c8b12d7275afafbb6ec44913551b4" integrity sha512-uVgekyBXnOVkxp+CUssjN/gefARtudZC8duEn1vm0lBQFwGRZFlDEzU1QC+aIRWCrD1Z8OgRpmBYlSZ7QS003w== -"@ampproject/remapping@^2.2.0", "@ampproject/remapping@^2.2.1", "@ampproject/remapping@^2.3.0": +"@ampproject/remapping@^2.2.0", "@ampproject/remapping@^2.2.1": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== @@ -638,13 +638,6 @@ dependencies: tslib "^2.5.0" -"@aws/dynamodb-auto-marshaller@^0.7.1": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@aws/dynamodb-auto-marshaller/-/dynamodb-auto-marshaller-0.7.1.tgz#70676c056e4ecb798c08ec2e398a3d93e703858d" - integrity sha512-LeURlf6/avrfFo9+4Yht9J3CUTJ72yoBpm1FOUmlexuHNW4Ka61tG30w3ZDCXXXmCO2rG0k3ywAgNJEo3WPbyw== - dependencies: - tslib "^1.8.1" - "@azure/abort-controller@^1.0.0", "@azure/abort-controller@^1.0.4": version "1.1.0" resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" @@ -2000,7 +1993,7 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": +"@babel/runtime@^7.10.5", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": version "7.25.6" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.6.tgz#9afc3289f7184d8d7f98b099884c26317b9264d2" integrity sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ== @@ -2121,32 +2114,6 @@ dependencies: "@bull-board/api" "5.10.2" -"@camunda8/sdk@^8.5.3": - version "8.6.12" - resolved "https://registry.yarnpkg.com/@camunda8/sdk/-/sdk-8.6.12.tgz#8a210359cd9873b9e1750dcde45e62045409cc17" - integrity sha512-dQNw9rMCrL0hJezjAeCAJWMyhuV/ouizP21UzgG9Edqnj/od9ko9XQjEd/AuSj9VMEEQ+bt40mBMnZszbISONg== - dependencies: - "@grpc/grpc-js" "1.10.9" - "@grpc/proto-loader" "0.7.13" - chalk "^2.4.2" - console-stamp "^3.0.2" - dayjs "^1.8.15" - debug "^4.3.4" - fast-xml-parser "^4.1.3" - got "^11.8.6" - jwt-decode "^4.0.0" - lodash.mergewith "^4.6.2" - long "^4.0.0" - lossless-json "^4.0.1" - neon-env "^0.1.3" - promise-retry "^1.1.1" - reflect-metadata "^0.2.1" - stack-trace "0.0.10" - typed-duration "^1.0.12" - uuid "^7.0.3" - optionalDependencies: - win-ca "3.5.1" - "@codemirror/autocomplete@^6.0.0", "@codemirror/autocomplete@^6.7.1": version "6.7.1" resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.7.1.tgz#3364799b78dff70fb8f81615536c52ea53ce40b2" @@ -2258,6 +2225,13 @@ resolved "https://registry.yarnpkg.com/@dagrejs/graphlib/-/graphlib-2.2.4.tgz#d77bfa9ff49e2307c0c6e6b8b26b5dd3c05816c4" integrity sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw== +"@datadog/native-appsec@7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-7.0.0.tgz#a380174dd49aef2d9bb613a0ec8ead6dc7822095" + integrity sha512-bywstWFW2hWxzPuS0+mFMVHHL0geulx5yQFtsjfszaH2LTAgk2D+Rt40MKbAoZ8q3tRw2dy6aYQ7svO3ca8jpA== + dependencies: + node-gyp-build "^3.9.0" + "@datadog/native-appsec@8.1.1": version "8.1.1" resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.1.1.tgz#76aa34697e6ecbd3d9ef7e6938d3cdcfa689b1f3" @@ -2265,6 +2239,14 @@ dependencies: node-gyp-build "^3.9.0" +"@datadog/native-iast-rewriter@2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.2.2.tgz#3f7feaf6be1af4c83ad063065b8ed509bbaf11cb" + integrity sha512-13ZBhJpjZ/tiV6rYfyAf/ITye9cyd3x12M/2NKhD4Ivev4N4uKBREAjpArOtzKtPXZ5b6oXwVV4ofT1SHoYyzA== + dependencies: + lru-cache "^7.14.0" + node-gyp-build "^4.5.0" + "@datadog/native-iast-rewriter@2.4.1": version "2.4.1" resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.4.1.tgz#e8211f78c818906513fb96a549374da0382c7623" @@ -2273,6 +2255,13 @@ lru-cache "^7.14.0" node-gyp-build "^4.5.0" +"@datadog/native-iast-taint-tracking@1.6.4": + version "1.6.4" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-1.6.4.tgz#16c21ad7c36a53420c0d3c5a3720731809cc7e98" + integrity sha512-Owxk7hQ4Dxwv4zJAoMjRga0IvE6lhvxnNc8pJCHsemCWBXchjr/9bqg05Zy5JnMbKUWn4XuZeJD6RFZpRa8bfw== + dependencies: + node-gyp-build "^3.9.0" + "@datadog/native-iast-taint-tracking@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.1.0.tgz#7b2ed7f8fad212d65e5ab03bcdea8b42a3051b2e" @@ -2288,6 +2277,17 @@ node-addon-api "^6.1.0" node-gyp-build "^3.9.0" +"@datadog/pprof@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.0.0.tgz#0c0aaf06def6d2bc4b2d353ec7b264dadbfbefab" + integrity sha512-vhNan4SBuNWLpexunDJQ+hNbRAgWdk2qy5Iyh7Nn94uSSHXigAJMAvu4jwMKKQKFfchtobOkWT8GQUWW3tgpFg== + dependencies: + delay "^5.0.0" + node-gyp-build "<4.0" + p-limit "^3.1.0" + pprof-format "^2.0.7" + source-map "^0.7.4" + "@datadog/pprof@5.3.0": version "5.3.0" resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.3.0.tgz#c2f58d328ecced7f99887f1a559d7fe3aecb9219" @@ -2324,231 +2324,116 @@ find-up "^5.0.0" strip-json-comments "^3.1.1" -"@esbuild/aix-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" - integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== - "@esbuild/android-arm64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622" integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ== -"@esbuild/android-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" - integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== - "@esbuild/android-arm@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682" integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw== -"@esbuild/android-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" - integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== - "@esbuild/android-x64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2" integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg== -"@esbuild/android-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" - integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== - "@esbuild/darwin-arm64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1" integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA== -"@esbuild/darwin-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" - integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== - "@esbuild/darwin-x64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d" integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ== -"@esbuild/darwin-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" - integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== - "@esbuild/freebsd-arm64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54" integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw== -"@esbuild/freebsd-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" - integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== - "@esbuild/freebsd-x64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e" integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ== -"@esbuild/freebsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" - integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== - "@esbuild/linux-arm64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0" integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA== -"@esbuild/linux-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" - integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== - "@esbuild/linux-arm@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0" integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg== -"@esbuild/linux-arm@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" - integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== - "@esbuild/linux-ia32@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7" integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA== -"@esbuild/linux-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" - integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== - "@esbuild/linux-loong64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d" integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg== -"@esbuild/linux-loong64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" - integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== - "@esbuild/linux-mips64el@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231" integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ== -"@esbuild/linux-mips64el@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" - integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== - "@esbuild/linux-ppc64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb" integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA== -"@esbuild/linux-ppc64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" - integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== - "@esbuild/linux-riscv64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6" integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A== -"@esbuild/linux-riscv64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" - integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== - "@esbuild/linux-s390x@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071" integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ== -"@esbuild/linux-s390x@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" - integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== - "@esbuild/linux-x64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338" integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w== -"@esbuild/linux-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" - integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== - "@esbuild/netbsd-x64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1" integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A== -"@esbuild/netbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" - integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== - "@esbuild/openbsd-x64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae" integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg== -"@esbuild/openbsd-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" - integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== - "@esbuild/sunos-x64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d" integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ== -"@esbuild/sunos-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" - integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== - "@esbuild/win32-arm64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9" integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg== -"@esbuild/win32-arm64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" - integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== - "@esbuild/win32-ia32@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102" integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g== -"@esbuild/win32-ia32@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" - integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== - "@esbuild/win32-x64@0.18.20": version "0.18.20" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d" integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ== -"@esbuild/win32-x64@0.21.5": - version "0.21.5" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" - integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== - "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -2556,20 +2441,11 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.11.0", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": version "4.11.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== -"@eslint/config-array@^0.18.0": - version "0.18.0" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.18.0.tgz#37d8fe656e0d5e3dbaea7758ea56540867fd074d" - integrity sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw== - dependencies: - "@eslint/object-schema" "^2.1.4" - debug "^4.3.1" - minimatch "^3.1.2" - "@eslint/eslintrc@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" @@ -2585,36 +2461,11 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/eslintrc@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6" - integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ== - dependencies: - ajv "^6.12.4" - debug "^4.3.2" - espree "^10.0.1" - globals "^14.0.0" - ignore "^5.2.0" - import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" - strip-json-comments "^3.1.1" - "@eslint/js@8.57.0": version "8.57.0" resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== -"@eslint/js@9.9.1", "@eslint/js@^9.7.0": - version "9.9.1" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.9.1.tgz#4a97e85e982099d6c7ee8410aacb55adaa576f06" - integrity sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ== - -"@eslint/object-schema@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.4.tgz#9e69f8bb4031e11df79e03db09f9dbbae1740843" - integrity sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ== - "@fontsource/source-sans-pro@^5.0.3": version "5.0.3" resolved "https://registry.yarnpkg.com/@fontsource/source-sans-pro/-/source-sans-pro-5.0.3.tgz#7d6e84a8169ba12fa5e6ce70757aa2ca7e74d855" @@ -2646,7 +2497,7 @@ dependencies: "@fortawesome/fontawesome-common-types" "6.4.2" -"@gar/promisify@^1.0.1", "@gar/promisify@^1.1.3": +"@gar/promisify@^1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== @@ -2703,14 +2554,6 @@ teeny-request "^8.0.0" uuid "^8.0.0" -"@grpc/grpc-js@1.10.9": - version "1.10.9" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.10.9.tgz#468cc1549a3fe37b760a16745fb7685d91f4f10c" - integrity sha512-5tcgUctCG0qoNyfChZifz2tJqbRbXVO9J7X6duFcOjY3HUNCxg5D0ZCK7EP9vIcZ0zRpLU9bWkyCqVCLZ46IbQ== - dependencies: - "@grpc/proto-loader" "^0.7.13" - "@js-sdsl/ordered-map" "^4.4.2" - "@grpc/grpc-js@^1.10.9": version "1.10.10" resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.10.10.tgz#476d315feeb9dbb0f2d6560008c92688c30f13e0" @@ -2719,7 +2562,7 @@ "@grpc/proto-loader" "^0.7.13" "@js-sdsl/ordered-map" "^4.4.2" -"@grpc/proto-loader@0.7.13", "@grpc/proto-loader@^0.7.13": +"@grpc/proto-loader@^0.7.13": version "0.7.13" resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.13.tgz#f6a44b2b7c9f7b609f5748c6eac2d420e37670cf" integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw== @@ -2729,32 +2572,18 @@ protobufjs "^7.2.5" yargs "^17.7.2" -"@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": +"@hapi/hoek@^9.0.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== -"@hapi/topo@^5.0.0", "@hapi/topo@^5.1.0": +"@hapi/topo@^5.0.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012" integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg== dependencies: "@hapi/hoek" "^9.0.0" -"@hubspot/api-client@7.1.2": - version "7.1.2" - resolved "https://registry.yarnpkg.com/@hubspot/api-client/-/api-client-7.1.2.tgz#a405b0a18b8caa27f129fd510b2555e5a5cc2708" - integrity sha512-JVQqh0fdHf97ePk0Hg/7BJsiXNlS9HQRPiM/CLgvVWt5CIviSLQ/kHLZXREmZqTWu7BisjCgHxnSx/d7gRdr2g== - dependencies: - bluebird "^3.7.2" - bottleneck "^2.19.5" - btoa "^1.2.1" - es6-promise "^4.2.4" - form-data "^2.5.0" - lodash "^4.17.21" - node-fetch "^2.6.0" - url-parse "^1.4.3" - "@humanwhocodes/config-array@^0.11.14": version "0.11.14" resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" @@ -2774,11 +2603,6 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== -"@humanwhocodes/retry@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.3.0.tgz#6d86b8cb322660f03d3f0aa94b99bdd8e172d570" - integrity sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew== - "@hutson/parse-repository-url@^3.0.0": version "3.0.2" resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340" @@ -3373,12 +3197,17 @@ resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== -"@koa/cors@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@koa/cors/-/cors-5.0.0.tgz#0029b5f057fa0d0ae0e37dd2c89ece315a0daffd" - integrity sha512-x/iUDjcS90W69PryLDIMgFyV21YLTnG9zOpPXS7Bkt2b8AsY3zZsIpOLBkYr9fBcF3HbkKaER5hOBZLfpLgYNw== +"@koa/router@8.0.8": + version "8.0.8" + resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.8.tgz#95f32d11373d03d89dcb63fabe9ac6f471095236" + integrity sha512-FnT93N4NUehnXr+juupDmG2yfi0JnWdCmNEuIXpCG4TtG+9xvtrLambBH3RclycopVUOEYAim2lydiNBI7IRVg== dependencies: - vary "^1.1.2" + debug "^4.1.1" + http-errors "^1.7.3" + koa-compose "^4.1.0" + methods "^1.1.2" + path-to-regexp "1.x" + urijs "^1.19.2" "@koa/router@^13.1.0": version "13.1.0" @@ -3576,14 +3405,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@npmcli/fs@^1.0.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" - integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== - dependencies: - "@gar/promisify" "^1.0.1" - semver "^7.3.5" - "@npmcli/fs@^2.1.0": version "2.1.2" resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-2.1.2.tgz#a9e2541a4a2fec2e69c29b35e6060973da79b865" @@ -3621,14 +3442,6 @@ npm-bundled "^3.0.0" npm-normalize-package-bin "^3.0.0" -"@npmcli/move-file@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" - integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== - dependencies: - mkdirp "^1.0.4" - rimraf "^3.0.2" - "@npmcli/move-file@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-2.0.1.tgz#26f6bdc379d87f75e55739bab89db525b06100e4" @@ -3868,6 +3681,11 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== +"@opentelemetry/api@^1.0.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" + integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== + "@opentelemetry/api@^1.0.1": version "1.7.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.7.0.tgz#b139c81999c23e3c8d3c0a7234480e945920fc40" @@ -4078,14 +3896,6 @@ is-module "^1.0.0" resolve "^1.22.1" -"@rollup/plugin-replace@^2.4.2": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz#a2d539314fbc77c244858faa523012825068510a" - integrity sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg== - dependencies: - "@rollup/pluginutils" "^3.1.0" - magic-string "^0.25.7" - "@rollup/plugin-replace@^5.0.2", "@rollup/plugin-replace@^5.0.3": version "5.0.7" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-5.0.7.tgz#150c9ee9db8031d9e4580a61a0edeaaed3d37687" @@ -4217,23 +4027,6 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.2.tgz#e4291e3c1bc637083f87936c333cdbcad22af63b" integrity sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA== -"@roxi/routify@2.18.0": - version "2.18.0" - resolved "https://registry.yarnpkg.com/@roxi/routify/-/routify-2.18.0.tgz#8f88bedd936312d0dbe44cbc11ab179b1f938ec2" - integrity sha512-MVB50HN+VQWLzfjLplcBjsSBvwOiExKOmht2DuWR3WQ60JxQi9pSejkB06tFVkFKNXz2X5iYtKDqKBTdae/gRg== - dependencies: - "@roxi/ssr" "^0.2.1" - "@types/node" ">=4.2.0 < 13" - chalk "^4.0.0" - cheap-watch "^1.0.2" - commander "^7.1.0" - configent "^2.1.4" - esm "^3.2.25" - fs-extra "^9.0.1" - log-symbols "^3.0.0" - picomatch "^2.2.2" - rollup-pluginutils "^2.8.2" - "@roxi/routify@2.18.12": version "2.18.12" resolved "https://registry.yarnpkg.com/@roxi/routify/-/routify-2.18.12.tgz#901ca95b96f274ddddaefbf18424557ee1ae3fae" @@ -4269,22 +4062,14 @@ koa "^2.13.4" node-mocks-http "^1.11.0" -"@shopify/jest-koa-mocks@5.3.0": - version "5.3.0" - resolved "https://registry.yarnpkg.com/@shopify/jest-koa-mocks/-/jest-koa-mocks-5.3.0.tgz#0b9b6ce01a7ef945df7272aa08cda559c11b39f5" - integrity sha512-Yy9uS298/aWhT/bjfhUAcFRaq7pq7j0ybaI6U/vWQ5IcdWD3E73iqptkw+FNC+Z9cdV9QT8osFd0r0frFNb9Nw== - dependencies: - koa "^2.13.4" - node-mocks-http "^1.11.0" - -"@sideway/address@^4.1.3", "@sideway/address@^4.1.5": +"@sideway/address@^4.1.3": version "4.1.5" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" integrity sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q== dependencies: "@hapi/hoek" "^9.0.0" -"@sideway/formula@^3.0.0", "@sideway/formula@^3.0.1": +"@sideway/formula@^3.0.0": version "3.0.1" resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== @@ -4323,11 +4108,6 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.7.0.tgz#9a06f4f137ee84d7df0460c1fdb1135ffa6c50fd" integrity sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow== -"@sindresorhus/is@^4.0.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" - integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== - "@sinonjs/commons@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3" @@ -5134,13 +4914,6 @@ dependencies: defer-to-connect "^1.0.1" -"@szmarczak/http-timer@^4.0.5": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" - integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== - dependencies: - defer-to-connect "^2.0.0" - "@techpass/passport-openidconnect@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-1.0.0.tgz#e79a70b2ccd54d04122b774a33469cb52858a6bd" @@ -5305,13 +5078,6 @@ dependencies: "@babel/types" "^7.3.0" -"@types/bcrypt@^5.0.2": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@types/bcrypt/-/bcrypt-5.0.2.tgz#22fddc11945ea4fbc3655b3e8b8847cc9f811477" - integrity sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ== - dependencies: - "@types/node" "*" - "@types/bluebird@*": version "3.5.38" resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.38.tgz#7a671e66750ccd21c9fc9d264d0e1e5330bc9908" @@ -5325,16 +5091,6 @@ "@types/connect" "*" "@types/node" "*" -"@types/cacheable-request@^6.0.1": - version "6.0.3" - resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" - integrity sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw== - dependencies: - "@types/http-cache-semantics" "*" - "@types/keyv" "^3.1.4" - "@types/node" "*" - "@types/responselike" "^1.0.0" - "@types/caseless@*": version "0.12.2" resolved "https://registry.yarnpkg.com/@types/caseless/-/caseless-0.12.2.tgz#f65d3d6389e01eeb458bd54dc8f52b95a9463bc8" @@ -5465,21 +5221,6 @@ "@types/docker-modem" "*" "@types/node" "*" -"@types/eslint@*": - version "9.6.1" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.1.tgz#d5795ad732ce81715f27f75da913004a56751584" - integrity sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/eslint__js@^8.42.3": - version "8.42.3" - resolved "https://registry.yarnpkg.com/@types/eslint__js/-/eslint__js-8.42.3.tgz#d1fa13e5c1be63a10b4e3afe992779f81c1179a0" - integrity sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw== - dependencies: - "@types/eslint" "*" - "@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.0", "@types/estree@^1.0.1": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" @@ -5533,11 +5274,6 @@ resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.5.3.tgz#ef8e3d1a8d46c387f04ab0f2e8ab8cb0c5078661" integrity sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA== -"@types/http-cache-semantics@*": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4" - integrity sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA== - "@types/http-errors@*": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.1.tgz#20172f9578b225f6c7da63446f56d4ce108d5a65" @@ -5577,7 +5313,7 @@ expect "^29.0.0" pretty-format "^29.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9": +"@types/json-schema@^7.0.6", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -5599,13 +5335,6 @@ resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72" integrity sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw== -"@types/keyv@^3.1.4": - version "3.1.4" - resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6" - integrity sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg== - dependencies: - "@types/node" "*" - "@types/koa-compose@*": version "3.2.5" resolved "https://registry.yarnpkg.com/@types/koa-compose/-/koa-compose-3.2.5.tgz#85eb2e80ac50be95f37ccf8c407c09bbe3468e9d" @@ -5613,37 +5342,13 @@ dependencies: "@types/koa" "*" -"@types/koa-passport@^4.0.3": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@types/koa-passport/-/koa-passport-4.0.3.tgz#063ec6310edee76cf854aadaa717b97f04b104fb" - integrity sha512-tNMYd/bcv0Zw7fc0CzEBYM9uUzVtn4XWzdUYfkTgSkEljP6nap7eI4E5x43ukrUQvztgXSYFkz3Uk+ujFeUzTg== - dependencies: - "@types/koa" "*" - "@types/passport" "*" - -"@types/koa-send@*", "@types/koa-send@^4.1.6": +"@types/koa-send@^4.1.6": version "4.1.6" resolved "https://registry.yarnpkg.com/@types/koa-send/-/koa-send-4.1.6.tgz#15d90e95e3ccce669a15b6a3c56c3a650a167cea" integrity sha512-vgnNGoOJkx7FrF0Jl6rbK1f8bBecqAchKpXtKuXzqIEdXTDO6dsSTjr+eZ5m7ltSjH4K/E7auNJEQCAd0McUPA== dependencies: "@types/koa" "*" -"@types/koa-session@^6.4.5": - version "6.4.5" - resolved "https://registry.yarnpkg.com/@types/koa-session/-/koa-session-6.4.5.tgz#ac10bac507f4bb722fa6c55c33607b5c8769f779" - integrity sha512-Vc6+fslnPuMH2v9y80WYeo39UMo8mweuNNthKCwYU2ZE6l5vnRrzRU3BRvexKwsoI5sxsRl5CxDsBlLI8kY/XA== - dependencies: - "@types/cookies" "*" - "@types/koa" "*" - -"@types/koa-static@^4.0.2": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@types/koa-static/-/koa-static-4.0.4.tgz#ce6f2a5d14cc7ef19f9bf6ee8e4f3eadfcc77323" - integrity sha512-j1AUzzl7eJYEk9g01hNTlhmipFh8RFbOQmaMNLvLcNNAkPw0bdTs3XTa3V045XFlrWN0QYnblbDJv2RzawTn6A== - dependencies: - "@types/koa" "*" - "@types/koa-send" "*" - "@types/koa@*": version "2.13.5" resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.5.tgz#64b3ca4d54e08c0062e89ec666c9f45443b21a61" @@ -5672,10 +5377,10 @@ "@types/koa-compose" "*" "@types/node" "*" -"@types/koa__cors@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@types/koa__cors/-/koa__cors-5.0.0.tgz#74567a045b599266e2cd3940cef96cedecc2ef1f" - integrity sha512-LCk/n25Obq5qlernGOK/2LUwa/2YJb2lxHUkkvYFDOpLXlVI6tKcdfCHRBQnOY4LwH6el5WOLs6PD/a8Uzau6g== +"@types/koa__router@8.0.8": + version "8.0.8" + resolved "https://registry.yarnpkg.com/@types/koa__router/-/koa__router-8.0.8.tgz#b1e0e9a512498777d3366bbdf0e853df27ec831c" + integrity sha512-9pGCaDtzCsj4HJ8HmGuqzk8+s57sPj4njWd08GG5o92n5Xp9io2snc40CPpXFhoKcZ8OKhuu6ht4gNou9e1C2w== dependencies: "@types/koa" "*" @@ -5751,7 +5456,7 @@ "@types/node" "*" form-data "^4.0.0" -"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=13.13.4", "@types/node@>=13.7.0", "@types/node@>=8.1.0": +"@types/node@*", "@types/node@>=10.0.0", "@types/node@>=13.13.4", "@types/node@>=13.7.0": version "22.5.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.1.tgz#de01dce265f6b99ed32b295962045d10b5b99560" integrity sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw== @@ -5770,16 +5475,16 @@ dependencies: undici-types "~5.26.4" -"@types/node@>=4.2.0 < 13", "@types/node@^12.20.52": - version "12.20.55" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" - integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== - "@types/node@>=8.0.0 <15": version "14.18.37" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.37.tgz#0bfcd173e8e1e328337473a8317e37b3b14fd30d" integrity sha512-7GgtHCs/QZrBrDzgIJnQtuSvhFSwhyYSI2uafSwZoNt1iOGhEN5fwNrQMjtONyHm9+/LoA4453jH0CMYcr06Pg== +"@types/node@^12.20.52": + version "12.20.55" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" + integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== + "@types/node@^18.11.18": version "18.19.10" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.10.tgz#4de314ab66faf6bc8ba691021a091ddcdf13a158" @@ -5794,25 +5499,11 @@ dependencies: undici-types "~5.26.4" -"@types/nodemailer@^6.4.4": - version "6.4.15" - resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.15.tgz#494be695e11c438f7f5df738fb4ab740312a6ed2" - integrity sha512-0EBJxawVNjPkng1zm2vopRctuWVCxk34JcIlRuXSf54habUWdz1FB7wHDqOqvDa8Mtpt0Q3LTXQkAs2LNyK5jQ== - dependencies: - "@types/node" "*" - "@types/normalize-package-data@^2.4.0": version "2.4.1" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== -"@types/oauth@*": - version "0.9.5" - resolved "https://registry.yarnpkg.com/@types/oauth/-/oauth-0.9.5.tgz#acc4209bfa1c8d7d3aaf2c9ad0b32216a29616c1" - integrity sha512-+oQ3C2Zx6ambINOcdIARF5Z3Tu3x//HipE889/fqo3sgpQZbe9c6ExdQFtN6qlhpR7p83lTZfPJt0tCAW29dog== - dependencies: - "@types/node" "*" - "@types/oracledb@6.5.1": version "6.5.1" resolved "https://registry.yarnpkg.com/@types/oracledb/-/oracledb-6.5.1.tgz#17d021cabc9d216dfa6d3d65ae3ee585c33baab3" @@ -5820,37 +5511,6 @@ dependencies: "@types/node" "*" -"@types/passport-google-oauth@^1.0.42": - version "1.0.45" - resolved "https://registry.yarnpkg.com/@types/passport-google-oauth/-/passport-google-oauth-1.0.45.tgz#c986c787ec9706b4a596d2bae43342b50b54973d" - integrity sha512-O3Y3DDKnf9lR8+DSaUOCEGF6aFjVYdI8TLhQYtySZ3Sq75c5tGYJ0KJRDZw0GsyLD/Que0nqFkP/GnDVwZZL9w== - dependencies: - "@types/express" "*" - "@types/passport" "*" - -"@types/passport-microsoft@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/passport-microsoft/-/passport-microsoft-1.0.0.tgz#a2ddc2200843570d38c35c53f6388e33df915b58" - integrity sha512-vD9ajSUc9Sz/8gdCj0ODUbPYQDxcI/imIDdgMPh//c5yMK/PgV6SNUXFLBzJo89Y30LU6bYAfXKn40WJqtMBiA== - dependencies: - "@types/passport-oauth2" "*" - -"@types/passport-oauth2@*": - version "1.4.17" - resolved "https://registry.yarnpkg.com/@types/passport-oauth2/-/passport-oauth2-1.4.17.tgz#d5d54339d44f6883d03e69dc0cc0e2114067abb4" - integrity sha512-ODiAHvso6JcWJ6ZkHHroVp05EHGhqQN533PtFNBkg8Fy5mERDqsr030AX81M0D69ZcaMvhF92SRckEk2B0HYYg== - dependencies: - "@types/express" "*" - "@types/oauth" "*" - "@types/passport" "*" - -"@types/passport@*": - version "1.0.16" - resolved "https://registry.yarnpkg.com/@types/passport/-/passport-1.0.16.tgz#5a2918b180a16924c4d75c31254c31cdca5ce6cf" - integrity sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A== - dependencies: - "@types/express" "*" - "@types/pg@8.6.6": version "8.6.6" resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.6.6.tgz#21cdf873a3e345a6e78f394677e3b3b1b543cb80" @@ -5985,7 +5645,7 @@ "@types/pouchdb-core" "*" "@types/pouchdb-find" "*" -"@types/pouchdb@6.4.0", "@types/pouchdb@^6.4.0": +"@types/pouchdb@^6.4.0": version "6.4.0" resolved "https://registry.yarnpkg.com/@types/pouchdb/-/pouchdb-6.4.0.tgz#f9c41ca64b23029f9bf2eb4bf6956e6431cb79f8" integrity sha512-eGCpX+NXhd5VLJuJMzwe3L79fa9+IDTrAG3CPaf4s/31PD56hOrhDJTSmRELSXuiqXr6+OHzzP0PldSaWsFt7w== @@ -6006,6 +5666,27 @@ "@types/pouchdb-node" "*" "@types/pouchdb-replication" "*" +"@types/pouchdb@^6.4.2": + version "6.4.2" + resolved "https://registry.yarnpkg.com/@types/pouchdb/-/pouchdb-6.4.2.tgz#54777533d86f4abd1a3989b272e085323623bbe1" + integrity sha512-YsI47rASdtzR+3V3JE2UKY58snhm0AglHBpyckQBkRYoCbTvGagXHtV0x5n8nzN04jQmvTG+Sm85cIzKT3KXBA== + dependencies: + "@types/pouchdb-adapter-cordova-sqlite" "*" + "@types/pouchdb-adapter-fruitdown" "*" + "@types/pouchdb-adapter-http" "*" + "@types/pouchdb-adapter-idb" "*" + "@types/pouchdb-adapter-leveldb" "*" + "@types/pouchdb-adapter-localstorage" "*" + "@types/pouchdb-adapter-memory" "*" + "@types/pouchdb-adapter-node-websql" "*" + "@types/pouchdb-adapter-websql" "*" + "@types/pouchdb-browser" "*" + "@types/pouchdb-core" "*" + "@types/pouchdb-http" "*" + "@types/pouchdb-mapreduce" "*" + "@types/pouchdb-node" "*" + "@types/pouchdb-replication" "*" + "@types/proper-lockfile@^4.1.4": version "4.1.4" resolved "https://registry.yarnpkg.com/@types/proper-lockfile/-/proper-lockfile-4.1.4.tgz#cd9fab92bdb04730c1ada542c356f03620f84008" @@ -6083,13 +5764,6 @@ resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== -"@types/responselike@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.3.tgz#cc29706f0a397cfe6df89debfe4bf5cea159db50" - integrity sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw== - dependencies: - "@types/node" "*" - "@types/retry@*": version "0.12.5" resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.5.tgz#f090ff4bd8d2e5b940ff270ab39fd5ca1834a07e" @@ -6120,13 +5794,6 @@ dependencies: "@types/node" "*" -"@types/server-destroy@^1.0.1": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@types/server-destroy/-/server-destroy-1.0.4.tgz#bd94af933e73e04795042edf38af267ddebd4e98" - integrity sha512-+x8oAQ4Xp1wtDi2Hlmi7gUNXZNVhB5EoSQpi0qEmINdDN5Ab724WLGAalEdT1SudVY/NzMhbfZO7vU+klT0R+A== - dependencies: - "@types/node" "*" - "@types/ssh2-streams@*": version "0.1.12" resolved "https://registry.yarnpkg.com/@types/ssh2-streams/-/ssh2-streams-0.1.12.tgz#e68795ba2bf01c76b93f9c9809e1f42f0eaaec5f" @@ -6228,7 +5895,7 @@ dependencies: "@types/node" "*" -"@types/uuid@8.3.4", "@types/uuid@^8.3.4": +"@types/uuid@8.3.4": version "8.3.4" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== @@ -6278,7 +5945,7 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@7.18.0", "@typescript-eslint/eslint-plugin@^7.16.1": +"@typescript-eslint/eslint-plugin@7.18.0": version "7.18.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz#b16d3cf3ee76bf572fdf511e79c248bdec619ea3" integrity sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw== @@ -6304,7 +5971,7 @@ "@typescript-eslint/visitor-keys" "6.9.0" debug "^4.3.4" -"@typescript-eslint/parser@7.18.0", "@typescript-eslint/parser@^7.16.1": +"@typescript-eslint/parser@7.18.0": version "7.18.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.18.0.tgz#83928d0f1b7f4afa974098c64b5ce6f9051f96a0" integrity sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg== @@ -6339,7 +6006,7 @@ "@typescript-eslint/types" "7.18.0" "@typescript-eslint/visitor-keys" "7.18.0" -"@typescript-eslint/type-utils@7.18.0", "@typescript-eslint/type-utils@^7.2.0": +"@typescript-eslint/type-utils@7.18.0": version "7.18.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz#2165ffaee00b1fbbdd2d40aa85232dab6998f53b" integrity sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA== @@ -6422,7 +6089,7 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/utils@7.18.0", "@typescript-eslint/utils@^7.3.1": +"@typescript-eslint/utils@7.18.0": version "7.18.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.18.0.tgz#bca01cde77f95fc6a8d5b0dbcbfb3d6ca4be451f" integrity sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw== @@ -6492,23 +6159,6 @@ "@vitest/utils" "0.29.8" chai "^4.3.7" -"@vitest/expect@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.0.5.tgz#f3745a6a2c18acbea4d39f5935e913f40d26fa86" - integrity sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA== - dependencies: - "@vitest/spy" "2.0.5" - "@vitest/utils" "2.0.5" - chai "^5.1.1" - tinyrainbow "^1.2.0" - -"@vitest/pretty-format@2.0.5", "@vitest/pretty-format@^2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.0.5.tgz#91d2e6d3a7235c742e1a6cc50e7786e2f2979b1e" - integrity sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ== - dependencies: - tinyrainbow "^1.2.0" - "@vitest/runner@0.29.8": version "0.29.8" resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-0.29.8.tgz#ede8a7be8a074ea1180bc1d1595bd879ed15971c" @@ -6518,23 +6168,6 @@ p-limit "^4.0.0" pathe "^1.1.0" -"@vitest/runner@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.0.5.tgz#89197e712bb93513537d6876995a4843392b2a84" - integrity sha512-TfRfZa6Bkk9ky4tW0z20WKXFEwwvWhRY+84CnSEtq4+3ZvDlJyY32oNTJtM7AW9ihW90tX/1Q78cb6FjoAs+ig== - dependencies: - "@vitest/utils" "2.0.5" - pathe "^1.1.2" - -"@vitest/snapshot@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.0.5.tgz#a2346bc5013b73c44670c277c430e0334690a162" - integrity sha512-SgCPUeDFLaM0mIUHfaArq8fD2WbaXG/zVXjRupthYfYGzc8ztbFbu6dUNOblBG7XLMR1kEhS/DNnfCZ2IhdDew== - dependencies: - "@vitest/pretty-format" "2.0.5" - magic-string "^0.30.10" - pathe "^1.1.2" - "@vitest/spy@0.29.8": version "0.29.8" resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-0.29.8.tgz#2e0c3b30e04d317b2197e3356234448aa432e131" @@ -6542,13 +6175,6 @@ dependencies: tinyspy "^1.0.2" -"@vitest/spy@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.0.5.tgz#590fc07df84a78b8e9dd976ec2090920084a2b9f" - integrity sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA== - dependencies: - tinyspy "^3.0.0" - "@vitest/utils@0.29.8": version "0.29.8" resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-0.29.8.tgz#423da85fd0c6633f3ab496cf7d2fc0119b850df8" @@ -6559,16 +6185,6 @@ loupe "^2.3.6" pretty-format "^27.5.1" -"@vitest/utils@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.0.5.tgz#6f8307a4b6bc6ceb9270007f73c67c915944e926" - integrity sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ== - dependencies: - "@vitest/pretty-format" "2.0.5" - estree-walker "^3.0.3" - loupe "^3.1.1" - tinyrainbow "^1.2.0" - "@xyflow/svelte@^0.1.18": version "0.1.18" resolved "https://registry.yarnpkg.com/@xyflow/svelte/-/svelte-0.1.18.tgz#ba2f9f72adc64ff6f71a5ad03cf759af8d7c9748" @@ -6651,7 +6267,7 @@ abortcontroller-polyfill@^1.4.0: resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== -abstract-leveldown@^6.2.1, abstract-leveldown@^6.3.0: +abstract-leveldown@^6.2.1: version "6.3.0" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-6.3.0.tgz#d25221d1e6612f820c35963ba4bd739928f6026a" integrity sha512-TU5nlYgta8YrBMNpc9FwQzRbiXsj49gsALsXadbGHt9CROPzX5fB0rWDR5mtdpOOKa5XqRFpbj1QroPAoPzVjQ== @@ -6662,6 +6278,18 @@ abstract-leveldown@^6.2.1, abstract-leveldown@^6.3.0: level-supports "~1.0.0" xtend "~4.0.0" +abstract-leveldown@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-7.2.0.tgz#08d19d4e26fb5be426f7a57004851b39e1795a2e" + integrity sha512-DnhQwcFEaYsvYDnACLZhMmCWd3rkOeEvglpa4q5i/5Jlm3UIsWaxVzuXvDLFCSCWRO3yy2/+V/G7FusFgejnfQ== + dependencies: + buffer "^6.0.3" + catering "^2.0.0" + is-buffer "^2.0.5" + level-concat-iterator "^3.0.0" + level-supports "^2.0.1" + queue-microtask "^1.2.3" + abstract-leveldown@~0.12.0, abstract-leveldown@~0.12.1: version "0.12.4" resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-0.12.4.tgz#29e18e632e60e4e221d5810247852a63d7b2e410" @@ -6716,29 +6344,17 @@ acorn-import-attributes@^1.9.5: resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== -acorn-jsx-walk@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/acorn-jsx-walk/-/acorn-jsx-walk-2.0.0.tgz#a5ed648264e68282d7c2aead80216bfdf232573a" - integrity sha512-uuo6iJj4D4ygkdzd6jPtcxs8vZgDX9YFIkqczGImoypX2fQ4dVImmu3UzA4ynixCIMTrEOWW+95M2HuBaCEOVA== - acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn-loose@^8.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/acorn-loose/-/acorn-loose-8.4.0.tgz#26d3e219756d1e180d006f5bcc8d261a28530f55" - integrity sha512-M0EUka6rb+QC4l9Z3T0nJEzNOO7JcoJlYMrBlyBCiFSXRyxjLKayd4TbQs2FDRWQU1h9FR7QVNHt+PEaoNL5rQ== - dependencies: - acorn "^8.11.0" - acorn-walk@^7.1.1: version "7.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== -acorn-walk@^8.0.2, acorn-walk@^8.1.1, acorn-walk@^8.2.0, acorn-walk@^8.3.3: +acorn-walk@^8.0.2, acorn-walk@^8.1.1, acorn-walk@^8.2.0: version "8.3.3" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== @@ -6755,7 +6371,7 @@ acorn@^7.1.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.1.0, acorn@^8.10.0, acorn@^8.11.0, acorn@^8.11.3, acorn@^8.12.0, acorn@^8.12.1, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.1.0, acorn@^8.10.0, acorn@^8.11.0, acorn@^8.11.3, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: version "8.12.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== @@ -6779,7 +6395,7 @@ agent-base@^7.0.2: dependencies: debug "^4.3.4" -agentkeepalive@^4.1.3, agentkeepalive@^4.2.1: +agentkeepalive@^4.2.1: version "4.5.0" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923" integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew== @@ -6822,7 +6438,7 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.1.0, ajv@^8.17.1, ajv@^8.4.0: +ajv@^8.0.0, ajv@^8.1.0, ajv@^8.4.0: version "8.17.1" resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== @@ -7221,11 +6837,6 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -assertion-error@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" - integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== - ast-module-types@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-2.7.1.tgz#3f7989ef8dfa1fdb82dfe0ab02bdfc7c77a57dd3" @@ -7253,13 +6864,6 @@ async-retry@^1.3.3: dependencies: retry "0.13.1" -async@^2.6.3: - version "2.6.4" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" - integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== - dependencies: - lodash "^4.17.14" - async@^3.2.1, async@^3.2.3, async@^3.2.4: version "3.2.5" resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" @@ -7561,11 +7165,6 @@ big-integer@^1.6.43: resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - bignumber.js@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.4.0.tgz#838a992da9f9d737e0f4b2db0be62bb09dd0c5e8" @@ -7586,13 +7185,6 @@ binascii@0.0.2: resolved "https://registry.yarnpkg.com/binascii/-/binascii-0.0.2.tgz#a7f8a8801dbccf8b1756b743daa0fee9e2d9e0ee" integrity sha512-rA2CrUl1+6yKrn+XgLs8Hdy18OER1UW146nM+ixzhQXDY+Bd3ySkyIJGwF2a4I45JwbvF1mDL/nWkqBwpOcdBA== -bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - bl@^1.0.0: version "1.2.3" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" @@ -7657,11 +7249,6 @@ boolean@^3.0.1: resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b" integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw== -bottleneck@^2.19.5: - version "2.19.5" - resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" - integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== - bowser@^2.11.0: version "2.11.0" resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" @@ -7811,11 +7398,6 @@ bson@^6.7.0: resolved "https://registry.yarnpkg.com/bson/-/bson-6.8.0.tgz#5063c41ba2437c2b8ff851b50d9e36cb7aaa7525" integrity sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ== -btoa@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" - integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== - buffer-alloc-unsafe@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" @@ -7968,30 +7550,6 @@ cac@^6.7.14: resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== -cacache@^15.2.0: - version "15.3.0" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" - integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== - dependencies: - "@npmcli/fs" "^1.0.0" - "@npmcli/move-file" "^1.0.1" - chownr "^2.0.0" - fs-minipass "^2.0.0" - glob "^7.1.4" - infer-owner "^1.0.4" - lru-cache "^6.0.0" - minipass "^3.1.1" - minipass-collect "^1.0.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.2" - mkdirp "^1.0.3" - p-map "^4.0.0" - promise-inflight "^1.0.1" - rimraf "^3.0.2" - ssri "^8.0.1" - tar "^6.0.2" - unique-filename "^1.1.1" - cacache@^16.1.0: version "16.1.3" resolved "https://registry.yarnpkg.com/cacache/-/cacache-16.1.3.tgz#a02b9f34ecfaf9a78c9f4bc16fceb94d5d67a38e" @@ -8043,11 +7601,6 @@ cache-content-type@^1.0.0: mime-types "^2.1.18" ylru "^1.2.0" -cacheable-lookup@^5.0.3: - version "5.0.4" - resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz#5a6b865b2c44357be3d5ebc2a467b032719a7005" - integrity sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA== - cacheable-request@^2.1.1: version "2.1.4" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" @@ -8074,19 +7627,6 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" -cacheable-request@^7.0.2: - version "7.0.4" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.4.tgz#7a33ebf08613178b403635be7b899d3e69bbe817" - integrity sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^4.0.0" - lowercase-keys "^2.0.0" - normalize-url "^6.0.1" - responselike "^2.0.0" - call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" @@ -8142,6 +7682,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001449: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001460.tgz#31d2e26f0a2309860ed3eff154e03890d9d851a7" integrity sha512-Bud7abqjvEjipUkpLs4D7gR0l8hBYBHoa+tGtKJHvT2AYzLp1z7EmVkUT4ERpVUfca8S2HGIVs883D8pUH1ZzQ== +catering@^2.0.0, catering@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" + integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== + chai@^4.3.7: version "4.5.0" resolved "https://registry.yarnpkg.com/chai/-/chai-4.5.0.tgz#707e49923afdd9b13a8b0b47d33d732d13812fd8" @@ -8155,17 +7700,6 @@ chai@^4.3.7: pathval "^1.1.1" type-detect "^4.1.0" -chai@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.1.tgz#f035d9792a22b481ead1c65908d14bb62ec1c82c" - integrity sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA== - dependencies: - assertion-error "^2.0.1" - check-error "^2.1.1" - deep-eql "^5.0.1" - loupe "^3.1.0" - pathval "^2.0.0" - chalk@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" @@ -8214,7 +7748,7 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -cheap-watch@^1.0.2, cheap-watch@^1.0.4: +cheap-watch@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/cheap-watch/-/cheap-watch-1.0.4.tgz#0bcb4a3a8fbd9d5327936493f6b56baa668d8fef" integrity sha512-QR/9FrtRL5fjfUJBhAKCdi0lSRQ3rVRRum3GF9wDKp2TJbEIMGhUEr2yU8lORzm9Isdjx7/k9S0DFDx+z5VGtw== @@ -8226,11 +7760,6 @@ check-error@^1.0.3: dependencies: get-func-name "^2.0.2" -check-error@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" - integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== - chokidar@3.5.3, chokidar@^3.5.2, chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" @@ -8547,17 +8076,12 @@ commander@^11.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906" integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ== -commander@^12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" - integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== - commander@^2.16.0, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, commander@^2.5.0, commander@^2.7.1, commander@^2.8.1: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^7.1.0, commander@^7.2.0: +commander@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== @@ -8682,7 +8206,7 @@ config-chain@^1.1.13: ini "^1.3.4" proto-list "~1.2.1" -configent@^2.1.4, configent@^2.2.0: +configent@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/configent/-/configent-2.2.0.tgz#2de230fc43f22c47cfd99016aa6962d6f9546994" integrity sha512-yIN6zfOWk2nycNJ2JFNiWEai0oiqAhISIht8+pbEBP8bdcpwoQ74AhCZPbUv9aRVJwo7wh1MbCBDUV44UJa7Kw== @@ -8711,14 +8235,6 @@ console-control-strings@^1.0.0, console-control-strings@^1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== -console-stamp@^3.0.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/console-stamp/-/console-stamp-3.1.2.tgz#35dac393e16069a4d9d37b71ca6d5d13d7f3f8fd" - integrity sha512-ab66x3NxOTxPuq71dI6gXEiw2X6ql4Le5gZz0bm7FW3FSCB00eztra/oQUuCoCGlsyKOxtULnHwphzMrRtzMBg== - dependencies: - chalk "^4.1.2" - dateformat "^4.6.3" - consolidate@^0.16.0: version "0.16.0" resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.16.0.tgz#a11864768930f2f19431660a65906668f5fbdc16" @@ -9310,16 +8826,53 @@ dateformat@^4.6.3: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== -dayjs@^1.10.8, dayjs@^1.8.15: +dayjs@^1.10.8: version "1.11.13" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -dc-polyfill@^0.1.4: +dc-polyfill@^0.1.2, dc-polyfill@^0.1.4: version "0.1.6" resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== +dd-trace@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.2.0.tgz#6ca2d76ece95f08d98468d7782c22f24192afa53" + integrity sha512-Z5ql3ZKzVW3DPstHPkTPcIPvKljHNtzTYY/WuZRlgT4XK7rMaN0j5nA8LlUh7m+tOPWs05IiKngbYVZjsqhRgA== + dependencies: + "@datadog/native-appsec" "7.0.0" + "@datadog/native-iast-rewriter" "2.2.2" + "@datadog/native-iast-taint-tracking" "1.6.4" + "@datadog/native-metrics" "^2.0.0" + "@datadog/pprof" "5.0.0" + "@datadog/sketches-js" "^2.1.0" + "@opentelemetry/api" "^1.0.0" + "@opentelemetry/core" "^1.14.0" + crypto-randomuuid "^1.0.0" + dc-polyfill "^0.1.2" + ignore "^5.2.4" + import-in-the-middle "^1.7.3" + int64-buffer "^0.1.9" + ipaddr.js "^2.1.0" + istanbul-lib-coverage "3.2.0" + jest-docblock "^29.7.0" + koalas "^1.0.2" + limiter "1.1.5" + lodash.sortby "^4.7.0" + lru-cache "^7.14.0" + methods "^1.1.2" + module-details-from-path "^1.0.3" + msgpack-lite "^0.1.26" + node-abort-controller "^3.1.1" + opentracing ">=0.12.1" + path-to-regexp "^0.1.2" + pprof-format "^2.0.7" + protobufjs "^7.2.5" + retry "^0.13.1" + semver "^7.5.4" + tlhunter-sorted-set "^0.1.0" + dd-trace@5.23.0: version "5.23.0" resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.23.0.tgz#a0c11863406de440a6675648caf06e1d07d67ba8" @@ -9357,7 +8910,7 @@ dd-trace@5.23.0: shell-quote "^1.8.1" tlhunter-sorted-set "^0.1.0" -debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@^4.3.5, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: version "4.3.6" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== @@ -9490,11 +9043,6 @@ deep-eql@^4.1.3: dependencies: type-detect "^4.0.0" -deep-eql@^5.0.1: - version "5.0.2" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" - integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== - deep-equal@^2.0.5: version "2.2.3" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1" @@ -9534,11 +9082,6 @@ deep-is@^0.1.3, deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -deepmerge-ts@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/deepmerge-ts/-/deepmerge-ts-5.1.0.tgz#c55206cc4c7be2ded89b9c816cf3608884525d7a" - integrity sha512-eS8dRJOckyo9maw9Tu5O5RUi/4inFLrnoLkBe3cPfDMx3WZioXtmOew4TXQaxq7Rhl4xjDtR7c6x8nNTxOvbFw== - deepmerge@^4.2.2: version "4.3.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" @@ -9556,11 +9099,6 @@ defer-to-connect@^1.0.1: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== -defer-to-connect@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" - integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== - deferred-leveldown@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-0.2.0.tgz#2cef1f111e1c57870d8bbb8af2650e587cd2f5b4" @@ -9604,11 +9142,6 @@ defined@^1.0.0: resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf" integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q== -defined@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-0.0.0.tgz#f35eea7d705e933baf13b2f03b3f83d921403b3e" - integrity sha512-zpqiCT8bODLu3QSmLLic8xJnYWBFjOSu/fBCm189oAiTtPq/PSanNACKZDS7kgSyCJY7P+IcODzlIogBK/9RBg== - delay@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" @@ -9644,34 +9177,6 @@ depd@^1.1.0, depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== -dependency-cruiser@^16.3.7: - version "16.4.0" - resolved "https://registry.yarnpkg.com/dependency-cruiser/-/dependency-cruiser-16.4.0.tgz#a1b7d452acddf05045ae4f7942a2e9337aedad35" - integrity sha512-la/NnD23m6esCox8KMiZ/pcmtec6G/r7LgnJvkBepcErdzlGaxWnyaxtpoYB3fgODrU/7E2u81/nX5FNu5zfyw== - dependencies: - acorn "^8.12.1" - acorn-jsx "^5.3.2" - acorn-jsx-walk "^2.0.0" - acorn-loose "^8.4.0" - acorn-walk "^8.3.3" - ajv "^8.17.1" - commander "^12.1.0" - enhanced-resolve "^5.17.1" - ignore "^5.3.2" - interpret "^3.1.1" - is-installed-globally "^1.0.0" - json5 "^2.2.3" - memoize "^10.0.0" - picocolors "^1.0.1" - picomatch "^4.0.2" - prompts "^2.4.2" - rechoir "^0.8.0" - safe-regex "^2.1.1" - semver "^7.6.3" - teamcity-service-messages "^0.1.14" - tsconfig-paths-webpack-plugin "^4.1.0" - watskeburt "^4.1.0" - dependency-tree@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/dependency-tree/-/dependency-tree-9.0.0.tgz#9288dd6daf35f6510c1ea30d9894b75369aa50a2" @@ -9918,11 +9423,6 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" -discontinuous-range@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a" - integrity sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ== - docker-compose@0.23.17: version "0.23.17" resolved "https://registry.yarnpkg.com/docker-compose/-/docker-compose-0.23.17.tgz#8816bef82562d9417dc8c790aa4871350f93a2ba" @@ -9937,13 +9437,6 @@ docker-compose@0.24.0: dependencies: yaml "^1.10.2" -docker-compose@^0.23.6: - version "0.23.19" - resolved "https://registry.yarnpkg.com/docker-compose/-/docker-compose-0.23.19.tgz#9947726e2fe67bdfa9e8efe1ff15aa0de2e10eb8" - integrity sha512-v5vNLIdUqwj4my80wxFDkNH+4S85zsRuH29SO7dCWVWPCMt/ohZBsGN6g6KXWifT0pzQ7uOxqEKCYCDPJ8Vz4g== - dependencies: - yaml "^1.10.2" - docker-compose@^0.24.6: version "0.24.6" resolved "https://registry.yarnpkg.com/docker-compose/-/docker-compose-0.24.6.tgz#d1f490a641bdb7ccc07c4d446b264f026f9a1f15" @@ -10152,24 +9645,6 @@ duplexify@^4.0.0, duplexify@^4.1.2: readable-stream "^3.1.1" stream-shift "^1.0.0" -dynalite@^3.2.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/dynalite/-/dynalite-3.2.2.tgz#34b4f4dd69638f17c0f7551a867959972c892441" - integrity sha512-sx9ZjTgMs/D4gHnba4rnBkw29648dHwHmywJet132KAbiq1ZyWx9W1fMd/eP9cPwTKDXyCBuTYOChE0qMDjaXQ== - dependencies: - async "^2.6.3" - big.js "^5.2.2" - buffer-crc32 "^0.2.13" - lazy "^1.0.11" - levelup "^4.4.0" - lock "^1.1.0" - memdown "^5.1.0" - minimist "^1.2.5" - once "^1.4.0" - subleveldown "^5.0.1" - optionalDependencies: - leveldown "^5.6.0" - eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -10263,7 +9738,7 @@ encodeurl@^1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -encoding-down@^6.2.0, encoding-down@^6.3.0: +encoding-down@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-6.3.0.tgz#b1c4eb0e1728c146ecaef8e32963c549e76d082b" integrity sha512-QKrV0iKR6MZVJV08QY0wp1e7vF6QbhnbQhb07bwpEyuz4uZiZgPlEGdkCROuFkUwdxlFaiPIhjyarH1ee/3vhw== @@ -10273,7 +9748,7 @@ encoding-down@^6.2.0, encoding-down@^6.3.0: level-codec "^9.0.0" level-errors "^2.0.0" -encoding@^0.1.12, encoding@^0.1.13: +encoding@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== @@ -10326,7 +9801,7 @@ engine.io@~6.6.0: engine.io-parser "~5.2.1" ws "~8.17.1" -enhanced-resolve@^5.17.1, enhanced-resolve@^5.7.0, enhanced-resolve@^5.8.3: +enhanced-resolve@^5.8.3: version "5.17.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== @@ -10366,11 +9841,6 @@ envinfo@7.8.1: resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== -err-code@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" - integrity sha512-CJAN+O0/yA1CKfRn9SXOGctSpEM7DCon/r/5r2eXFMY2zCCJBasFhcM5I+1kh3Ap11FsQCX+vGHceNPvpWKhoA== - err-code@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" @@ -10529,11 +9999,6 @@ es6-error@^4.0.1, es6-error@^4.1.1: resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== -es6-promise@^4.2.4: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - esbuild-node-externals@^1.14.0: version "1.14.0" resolved "https://registry.yarnpkg.com/esbuild-node-externals/-/esbuild-node-externals-1.14.0.tgz#fc2950c67a068dc2b538fd1381ad7d8e20a6f54d" @@ -10570,35 +10035,6 @@ esbuild@^0.18.10, esbuild@^0.18.17: "@esbuild/win32-ia32" "0.18.20" "@esbuild/win32-x64" "0.18.20" -esbuild@^0.21.3: - version "0.21.5" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" - integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== - optionalDependencies: - "@esbuild/aix-ppc64" "0.21.5" - "@esbuild/android-arm" "0.21.5" - "@esbuild/android-arm64" "0.21.5" - "@esbuild/android-x64" "0.21.5" - "@esbuild/darwin-arm64" "0.21.5" - "@esbuild/darwin-x64" "0.21.5" - "@esbuild/freebsd-arm64" "0.21.5" - "@esbuild/freebsd-x64" "0.21.5" - "@esbuild/linux-arm" "0.21.5" - "@esbuild/linux-arm64" "0.21.5" - "@esbuild/linux-ia32" "0.21.5" - "@esbuild/linux-loong64" "0.21.5" - "@esbuild/linux-mips64el" "0.21.5" - "@esbuild/linux-ppc64" "0.21.5" - "@esbuild/linux-riscv64" "0.21.5" - "@esbuild/linux-s390x" "0.21.5" - "@esbuild/linux-x64" "0.21.5" - "@esbuild/netbsd-x64" "0.21.5" - "@esbuild/openbsd-x64" "0.21.5" - "@esbuild/sunos-x64" "0.21.5" - "@esbuild/win32-arm64" "0.21.5" - "@esbuild/win32-ia32" "0.21.5" - "@esbuild/win32-x64" "0.21.5" - escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -10672,18 +10108,6 @@ eslint-module-utils@^2.8.0: dependencies: debug "^3.2.7" -eslint-plugin-functional@^6.6.3: - version "6.6.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-functional/-/eslint-plugin-functional-6.6.3.tgz#85b895afb91835c5ffa2eb97f473fd4182aa5228" - integrity sha512-sVbbvNvwX3HVkXAykKyoNLv57r4DPF7f1sy+/8j4YtzLYVQPGljMUWv3T6Kd4lwnnjmcKuj0EkIbS+knL6P5jw== - dependencies: - "@typescript-eslint/utils" "^7.3.1" - deepmerge-ts "^5.1.0" - escape-string-regexp "^4.0.0" - is-immutable-type "^4.0.0" - semver "^7.6.0" - ts-api-utils "^1.3.0" - eslint-plugin-import@^2.26.0, eslint-plugin-import@^2.29.0: version "2.29.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" @@ -10753,14 +10177,6 @@ eslint-scope@^7.0.0, eslint-scope@^7.2.2: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-scope@^8.0.2: - version "8.0.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.2.tgz#5cbb33d4384c9136083a71190d548158fe128f94" - integrity sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA== - dependencies: - esrecurse "^4.3.0" - estraverse "^5.2.0" - eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" @@ -10771,11 +10187,6 @@ eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint-visitor-keys@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" - integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== - eslint@^8.52.0, eslint@^8.56.0: version "8.57.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" @@ -10820,60 +10231,11 @@ eslint@^8.52.0, eslint@^8.56.0: strip-ansi "^6.0.1" text-table "^0.2.0" -eslint@^9.7.0: - version "9.9.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.9.1.tgz#147ac9305d56696fb84cf5bdecafd6517ddc77ec" - integrity sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.11.0" - "@eslint/config-array" "^0.18.0" - "@eslint/eslintrc" "^3.1.0" - "@eslint/js" "9.9.1" - "@humanwhocodes/module-importer" "^1.0.1" - "@humanwhocodes/retry" "^0.3.0" - "@nodelib/fs.walk" "^1.2.8" - ajv "^6.12.4" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.3.2" - escape-string-regexp "^4.0.0" - eslint-scope "^8.0.2" - eslint-visitor-keys "^4.0.0" - espree "^10.1.0" - esquery "^1.5.0" - esutils "^2.0.2" - fast-deep-equal "^3.1.3" - file-entry-cache "^8.0.0" - find-up "^5.0.0" - glob-parent "^6.0.2" - ignore "^5.2.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - is-path-inside "^3.0.3" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash.merge "^4.6.2" - minimatch "^3.1.2" - natural-compare "^1.4.0" - optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" - esm@^3.2.25: version "3.2.25" resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== -espree@^10.0.1, espree@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-10.1.0.tgz#8788dae611574c0f070691f522e4116c5a11fc56" - integrity sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA== - dependencies: - acorn "^8.12.0" - acorn-jsx "^5.3.2" - eslint-visitor-keys "^4.0.0" - espree@^9.0.0, espree@^9.6.0, espree@^9.6.1: version "9.6.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" @@ -10903,7 +10265,7 @@ esprima@~3.1.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" integrity sha512-AWwVMNxwhN8+NIPQzAQZCm7RkLC4RbM3B1OobMuyp3i+w73X57KCKaVIxaRZb+DYCojq7rspo+fmuQfAboyhFg== -esquery@^1.4.2, esquery@^1.5.0: +esquery@^1.4.2: version "1.6.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== @@ -11040,21 +10402,6 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" - integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^8.0.1" - human-signals "^5.0.0" - is-stream "^3.0.0" - merge-stream "^2.0.0" - npm-run-path "^5.1.0" - onetime "^6.0.0" - signal-exit "^4.1.0" - strip-final-newline "^3.0.0" - exif-parser@^0.1.12: version "0.1.12" resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922" @@ -11204,7 +10551,7 @@ fast-xml-parser@4.2.5: dependencies: strnum "^1.0.5" -fast-xml-parser@^4.1.3, fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: +fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: version "4.4.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== @@ -11285,13 +10632,6 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -file-entry-cache@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" - integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== - dependencies: - flat-cache "^4.0.0" - file-type@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-11.1.0.tgz#93780f3fed98b599755d846b99a1617a2ad063b8" @@ -11331,11 +10671,6 @@ file-type@^6.1.0: resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - filelist@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" @@ -11426,20 +10761,12 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" -flat-cache@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" - integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== - dependencies: - flatted "^3.2.9" - keyv "^4.5.4" - flat@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== -flatted@^3.1.0, flatted@^3.2.9: +flatted@^3.1.0: version "3.3.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== @@ -11566,7 +10893,7 @@ fs-extra@^11.1.0, fs-extra@^11.1.1: jsonfile "^6.0.1" universalify "^2.0.0" -fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0: +fs-extra@^9.0.0, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== @@ -11595,7 +10922,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@^2.3.2, fsevents@~2.3.2, fsevents@~2.3.3: +fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -11615,7 +10942,7 @@ function.prototype.name@^1.1.6: es-abstract "^1.22.1" functions-have-names "^1.2.3" -functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: +functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= @@ -11836,11 +11163,6 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-stream@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" - integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== - get-symbol-description@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" @@ -11965,7 +11287,7 @@ glob@7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^10.0.0, glob@^10.2.2, glob@^10.3.7: +glob@^10.0.0, glob@^10.2.2: version "10.4.5" resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== @@ -12033,13 +11355,6 @@ global-agent@3.0.0: semver "^7.3.2" serialize-error "^7.0.1" -global-directory@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/global-directory/-/global-directory-4.0.1.tgz#4d7ac7cfd2cb73f304c53b8810891748df5e361e" - integrity sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q== - dependencies: - ini "4.1.1" - global-dirs@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" @@ -12067,11 +11382,6 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" -globals@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" - integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== - globalthis@^1.0.1, globalthis@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" @@ -12175,23 +11485,6 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -got@^11.8.6: - version "11.8.6" - resolved "https://registry.yarnpkg.com/got/-/got-11.8.6.tgz#276e827ead8772eddbcfc97170590b841823233a" - integrity sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g== - dependencies: - "@sindresorhus/is" "^4.0.0" - "@szmarczak/http-timer" "^4.0.5" - "@types/cacheable-request" "^6.0.1" - "@types/responselike" "^1.0.0" - cacheable-lookup "^5.0.3" - cacheable-request "^7.0.2" - decompress-response "^6.0.0" - http2-wrapper "^1.0.0-beta.5.2" - lowercase-keys "^2.0.0" - p-cancelable "^2.0.0" - responselike "^2.0.0" - got@^8.3.1: version "8.3.2" resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" @@ -12574,14 +11867,6 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" -http2-wrapper@^1.0.0-beta.5.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" - integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== - dependencies: - quick-lru "^5.1.1" - resolve-alpn "^1.0.0" - https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -12603,11 +11888,6 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -human-signals@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" - integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== - humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" @@ -12697,7 +11977,7 @@ ignore-walk@^6.0.0: dependencies: minimatch "^7.4.2" -ignore@^5.0.4, ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1, ignore@^5.3.2: +ignore@^5.0.4, ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== @@ -12719,16 +11999,6 @@ immediate@~3.0.5: resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== -immediate@~3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== - -immutable@^4.3.4: - version "4.3.7" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" - integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== - import-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-3.0.0.tgz#20845547718015126ea9b3676b7592fb8bd4cf92" @@ -12751,7 +12021,7 @@ import-from@^3.0.0: dependencies: resolve-from "^5.0.0" -import-in-the-middle@1.11.2: +import-in-the-middle@1.11.2, import-in-the-middle@^1.7.3: version "1.11.2" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz#dd848e72b63ca6cd7c34df8b8d97fc9baee6174f" integrity sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA== @@ -12827,11 +12097,6 @@ ini@2.0.0: resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5" integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== -ini@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" - integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== - ini@^1.3.2, ini@^1.3.4, ini@^1.3.8, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" @@ -12909,11 +12174,6 @@ interpret@^2.2.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== -interpret@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4" - integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ== - into-stream@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" @@ -12975,6 +12235,11 @@ ip@^2.0.0: resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== +ipaddr.js@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== + is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -13028,6 +12293,11 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-buffer@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + is-builtin-module@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" @@ -13085,11 +12355,6 @@ is-docker@^2.0.0, is-docker@^2.1.1: resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== -is-electron@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/is-electron/-/is-electron-2.2.2.tgz#3778902a2044d76de98036f5dc58089ac4d80bb9" - integrity sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg== - is-extendable@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -13139,15 +12404,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" -is-immutable-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-immutable-type/-/is-immutable-type-4.0.0.tgz#d62ad1ff411eef8dfa3a87222960ec3b645db1a1" - integrity sha512-gyFBCXv+NikTs8/PGZhgjbMmFZQ5jvHGZIsVu6+/9Bk4K7imlWBIDN7hTr9fNioGzFg71I4YM3z8f0aKXarTAw== - dependencies: - "@typescript-eslint/type-utils" "^7.2.0" - ts-api-utils "^1.3.0" - ts-declaration-location "^1.0.0" - is-installed-globally@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520" @@ -13156,14 +12412,6 @@ is-installed-globally@^0.4.0: global-dirs "^3.0.0" is-path-inside "^3.0.2" -is-installed-globally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-1.0.0.tgz#08952c43758c33d815692392f7f8437b9e436d5a" - integrity sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ== - dependencies: - global-directory "^4.0.1" - is-path-inside "^4.0.0" - is-interactive@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" @@ -13243,11 +12491,6 @@ is-path-inside@^3.0.2, is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== -is-path-inside@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-4.0.0.tgz#805aeb62c47c1b12fc3fd13bfb3ed1e7430071db" - integrity sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA== - is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -13353,11 +12596,6 @@ is-stream@^2.0.0, is-stream@^2.0.1: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" - integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== - is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -13711,15 +12949,6 @@ jest-docblock@^29.7.0: dependencies: detect-newline "^3.0.0" -jest-dynalite@^3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/jest-dynalite/-/jest-dynalite-3.6.1.tgz#8bae305a3c33d9a8036f563827b173b54a323ca5" - integrity sha512-MERtTt8Pj39vFmbItMC3YuIaqLf1kh/pJIE0DRcjeP/2Fa8Nni9IxwN6XWIMgXNbFKtlOM6ppH+Bsy0rWIdPiw== - dependencies: - "@aws/dynamodb-auto-marshaller" "^0.7.1" - dynalite "^3.2.1" - setimmediate "^1.0.5" - jest-each@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" @@ -14052,17 +13281,6 @@ joi@17.6.0: "@sideway/formula" "^3.0.0" "@sideway/pinpoint" "^2.0.0" -joi@^17.13.1: - version "17.13.3" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.13.3.tgz#0f5cc1169c999b30d344366d384b12d92558bcec" - integrity sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA== - dependencies: - "@hapi/hoek" "^9.3.0" - "@hapi/topo" "^5.1.0" - "@sideway/address" "^4.1.5" - "@sideway/formula" "^3.0.1" - "@sideway/pinpoint" "^2.0.0" - joycon@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" @@ -14210,11 +13428,6 @@ json-buffer@3.0.0: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" integrity sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ== -json-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" - integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== - json-format-highlight@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/json-format-highlight/-/json-format-highlight-1.0.4.tgz#2e44277edabcec79a3d2c84e984c62e2258037b9" @@ -14250,16 +13463,6 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json-stable-stringify@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz#52d4361b47d49168bcc4e564189a42e5a7439454" - integrity sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg== - dependencies: - call-bind "^1.0.5" - isarray "^2.0.5" - jsonify "^0.0.1" - object-keys "^1.1.1" - json-stringify-safe@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -14291,11 +13494,6 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -jsonify@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978" - integrity sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg== - jsonparse@^1.2.0, jsonparse@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" @@ -14376,11 +13574,6 @@ jws@^4.0.0: jwa "^2.0.0" safe-buffer "^5.0.1" -jwt-decode@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-4.0.0.tgz#2270352425fd413785b2faf11f6e755c5151bd4b" - integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA== - keygrip@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/keygrip/-/keygrip-1.1.0.tgz#871b1681d5e159c62a445b0c74b615e0917e7226" @@ -14402,13 +13595,6 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" -keyv@^4.0.0, keyv@^4.5.4: - version "4.5.4" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" - integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== - dependencies: - json-buffer "3.0.1" - kill-port@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/kill-port/-/kill-port-1.6.1.tgz#560fe79484583bdf3a5e908557dae614447618aa" @@ -14517,7 +13703,7 @@ koa-passport@4.1.4: dependencies: passport "^0.4.0" -koa-passport@6.0.0, koa-passport@^6.0.0: +koa-passport@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/koa-passport/-/koa-passport-6.0.0.tgz#c30d2b859eaff8349c553eb479f365244188df53" integrity sha512-bgcrQN7Ylfgi1PVr5l6hHYkr38RHUzx+ty3m7e/xoTte8MR0zbDt6+pvP3/nuF/yXL6Ba7IzX1rSqmCy6OrrIw== @@ -14551,7 +13737,7 @@ koa-send@5.0.1, koa-send@^5.0.0: http-errors "^1.7.3" resolve-path "^1.4.0" -koa-session@5.13.1, koa-session@^5.12.0: +koa-session@5.13.1: version "5.13.1" resolved "https://registry.yarnpkg.com/koa-session/-/koa-session-5.13.1.tgz#a47e39015a4b464e21e3e1e2deeca48eb83916ee" integrity sha512-TfYiun6xiFosyfIJKnEw0aoG5XmLIwM+K3OVWfkz84qY0NP2gbk0F/olRn0/Hrxq0f14s8amHVXeWyKYH3Cx3Q== @@ -14569,7 +13755,7 @@ koa-static@5.0.0, koa-static@^5.0.0: debug "^3.1.0" koa-send "^5.0.0" -koa-useragent@4.1.0, koa-useragent@^4.1.0: +koa-useragent@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/koa-useragent/-/koa-useragent-4.1.0.tgz#d3f128b552c6da3e5e9e9e9c887b2922b16e4468" integrity sha512-x/HUDZ1zAmNNh5hA9hHbPm9p3UVg2prlpHzxCXQCzbibrNS0kmj7MkCResCbAbG7ZT6FVxNSMjR94ZGamdMwxA== @@ -14669,11 +13855,6 @@ latest-version@^5.1.0: dependencies: package-json "^6.3.0" -lazy@^1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/lazy/-/lazy-1.0.11.tgz#daa068206282542c088288e975c297c1ae77b690" - integrity sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA== - lazystream@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" @@ -14790,6 +13971,13 @@ level-codec@9.0.2, level-codec@^9.0.0: dependencies: buffer "^5.6.0" +level-concat-iterator@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-3.1.0.tgz#5235b1f744bc34847ed65a50548aa88d22e881cf" + integrity sha512-BWRCMHBxbIqPxJ8vHOvKUsaO0v1sLYZtjN3K2iZJsRBYtp+ONsY6Jfi6hy9K3+zolgQRryhIn2NRZjZnWJ9NmQ== + dependencies: + catering "^2.1.0" + level-concat-iterator@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/level-concat-iterator/-/level-concat-iterator-2.0.1.tgz#1d1009cf108340252cb38c51f9727311193e6263" @@ -14867,13 +14055,6 @@ level-js@^5.0.0: inherits "^2.0.3" ltgt "^2.1.2" -level-option-wrap@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/level-option-wrap/-/level-option-wrap-1.1.0.tgz#ad20e68d9f3c22c8897531cc6aa7af596b1ed129" - integrity sha512-gQouC22iCqHuBLNl4BHxEZUxLvUKALAtT/Q0c6ziOxZQ8c02G/gyxHWNbLbxUzRNfMrRnbt6TZT3gNe8VBqQeg== - dependencies: - defined "~0.0.0" - level-packager@^5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-5.1.1.tgz#323ec842d6babe7336f70299c14df2e329c18939" @@ -14899,6 +14080,11 @@ level-sublevel@^5.2.0: string-range "~1.2.1" xtend "~2.0.4" +level-supports@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-2.1.0.tgz#9af908d853597ecd592293b2fad124375be79c5f" + integrity sha512-E486g1NCjW5cF78KGPrMDRBYzPuueMZ6VBXHT6gC7A8UYWGiM14fGgp+s/L1oFfDWSPV/+SFkYCmZ0SiESkRKA== + level-supports@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/level-supports/-/level-supports-1.0.1.tgz#2f530a596834c7301622521988e2c36bb77d122d" @@ -14922,7 +14108,7 @@ level@6.0.1: level-packager "^5.1.0" leveldown "^5.4.0" -leveldown@5.6.0, leveldown@^5.4.0, leveldown@^5.6.0: +leveldown@5.6.0, leveldown@^5.4.0: version "5.6.0" resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-5.6.0.tgz#16ba937bb2991c6094e13ac5a6898ee66d3eee98" integrity sha512-iB8O/7Db9lPaITU1aA2txU/cBEXAt4vWwKQRrrWuS6XDgbP4QZGj9BL2aNbwb002atoQ/lIotJkfyzz+ygQnUQ== @@ -14931,7 +14117,16 @@ leveldown@5.6.0, leveldown@^5.4.0, leveldown@^5.6.0: napi-macros "~2.0.0" node-gyp-build "~4.1.0" -levelup@4.4.0, levelup@^4.3.2, levelup@^4.4.0: +leveldown@6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-6.1.1.tgz#0f0e480fa88fd807abf94c33cb7e40966ea4b5ce" + integrity sha512-88c+E+Eizn4CkQOBHwqlCJaTNEjGpaEIikn1S+cINc5E9HEvJ77bqY4JY/HxT5u0caWqsc3P3DcFIKBI1vHt+A== + dependencies: + abstract-leveldown "^7.2.0" + napi-macros "~2.0.0" + node-gyp-build "^4.3.0" + +levelup@4.4.0, levelup@^4.3.2: version "4.4.0" resolved "https://registry.yarnpkg.com/levelup/-/levelup-4.4.0.tgz#f89da3a228c38deb49c48f88a70fb71f01cafed6" integrity sha512-94++VFO3qN95cM/d6eBXvd894oJE0w3cInq9USsyQzzoJxmiYzPAocNcuGCPGGjoXqDVJcr3C1jzt1TSjyaiLQ== @@ -15104,11 +14299,6 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lock@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/lock/-/lock-1.1.0.tgz#53157499d1653b136ca66451071fca615703fa55" - integrity sha512-NZQIJJL5Rb9lMJ0Yl1JoVr9GSdo4HTPsUEWsSFzB8dE8DSoiLCVavWZPi7Rnlv/o73u6I24S/XYc/NmG4l8EKA== - lodash-es@^4.17.15, lodash-es@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" @@ -15249,7 +14439,7 @@ lodash.xor@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.xor/-/lodash.xor-4.5.0.tgz#4d48ed7e98095b0632582ba714d3ff8ae8fb1db6" integrity sha512-sVN2zimthq7aZ5sPGXnSz32rZPuqcparVW50chJQe+mzTYV+IsxSsl/2gnkWWE2Of7K3myBQBqtLKOUEHJKRsQ== -lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.7.0: +lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -15296,11 +14486,6 @@ lookpath@1.1.0: resolved "https://registry.yarnpkg.com/lookpath/-/lookpath-1.1.0.tgz#932d68371a2f0b4a5644f03d6a2b4728edba96d2" integrity sha512-B9NM7XpVfkyWqfOBI/UW0kVhGw7pJztsduch+1wkbYDi90mYK6/InFul3lG0hYko/VEcVMARVBJ5daFRc5aKCw== -lossless-json@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lossless-json/-/lossless-json-4.0.1.tgz#d45229e3abb213a0235812780ca894ea8c5b2c6b" - integrity sha512-l0L+ppmgPDnb+JGxNLndPtJZGNf6+ZmVaQzoxQm3u6TXmhdnsA+YtdVR8DjzZd/em58686CQhOFDPewfJ4l7MA== - lossless-json@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/lossless-json/-/lossless-json-4.0.2.tgz#f00c52815805d1421930a87e2670e27350958a3f" @@ -15313,13 +14498,6 @@ loupe@^2.3.6: dependencies: get-func-name "^2.0.1" -loupe@^3.1.0, loupe@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.1.tgz#71d038d59007d890e3247c5db97c1ec5a92edc54" - integrity sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw== - dependencies: - get-func-name "^2.0.1" - lowercase-keys@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" @@ -15437,7 +14615,7 @@ magic-string@^0.26.7: dependencies: sourcemap-codec "^1.4.8" -magic-string@^0.30.10, magic-string@^0.30.3, magic-string@^0.30.4: +magic-string@^0.30.3, magic-string@^0.30.4: version "0.30.11" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954" integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A== @@ -15451,7 +14629,7 @@ make-dir@4.0.0: dependencies: semver "^7.5.3" -make-dir@^1.0.0, make-dir@^1.3.0: +make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== @@ -15521,28 +14699,6 @@ make-fetch-happen@^11.0.0, make-fetch-happen@^11.0.1, make-fetch-happen@^11.1.0: socks-proxy-agent "^7.0.0" ssri "^10.0.0" -make-fetch-happen@^9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz#53085a09e7971433e6765f7971bf63f4e05cb968" - integrity sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg== - dependencies: - agentkeepalive "^4.1.3" - cacache "^15.2.0" - http-cache-semantics "^4.1.0" - http-proxy-agent "^4.0.1" - https-proxy-agent "^5.0.0" - is-lambda "^1.0.1" - lru-cache "^6.0.0" - minipass "^3.1.3" - minipass-collect "^1.0.2" - minipass-fetch "^1.3.2" - minipass-flush "^1.0.5" - minipass-pipeline "^1.2.4" - negotiator "^0.6.2" - promise-retry "^2.0.1" - socks-proxy-agent "^6.0.0" - ssri "^8.0.0" - makeerror@1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a" @@ -15624,25 +14780,6 @@ memdown@1.4.1: ltgt "~2.2.0" safe-buffer "~5.1.1" -memdown@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-5.1.0.tgz#608e91a9f10f37f5b5fe767667a8674129a833cb" - integrity sha512-B3J+UizMRAlEArDjWHTMmadet+UKwHd3UjMgGBkZcKAxAYVPS9o0Yeiha4qvz7iGiL2Sb3igUft6p7nbFWctpw== - dependencies: - abstract-leveldown "~6.2.1" - functional-red-black-tree "~1.0.1" - immediate "~3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.2.0" - -memoize@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/memoize/-/memoize-10.0.0.tgz#43fa66b2022363c7c50cf5dfab732a808a3d7147" - integrity sha512-H6cBLgsi6vMWOcCpvVCdFFnl3kerEXbrYh9q+lY6VXvQSmM6CkmV08VOwT+WE2tzIEqRPFfAq3fm4v/UIW6mSA== - dependencies: - mimic-function "^5.0.0" - memory-pager@^1.0.2: version "1.5.0" resolved "https://registry.yarnpkg.com/memory-pager/-/memory-pager-1.5.0.tgz#d8751655d22d384682741c972f2c3d6dfa3e66b5" @@ -15746,16 +14883,6 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-fn@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" - integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== - -mimic-function@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/mimic-function/-/mimic-function-5.0.1.tgz#acbe2b3349f99b9deaca7fb70e48b83e94e67076" - integrity sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA== - mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" @@ -15807,13 +14934,6 @@ minimatch@3.0.5: dependencies: brace-expansion "^1.1.7" -minimatch@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b" - integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== - dependencies: - brace-expansion "^2.0.1" - minimatch@^5.0.1, minimatch@^5.1.0: version "5.1.6" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" @@ -15863,17 +14983,6 @@ minipass-collect@^1.0.2: dependencies: minipass "^3.0.0" -minipass-fetch@^1.3.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-1.4.1.tgz#d75e0091daac1b0ffd7e9d41629faff7d0c1f1b6" - integrity sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw== - dependencies: - minipass "^3.1.0" - minipass-sized "^1.0.3" - minizlib "^2.0.0" - optionalDependencies: - encoding "^0.1.12" - minipass-fetch@^2.0.3: version "2.1.2" resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-2.1.2.tgz#95560b50c472d81a3bc76f20ede80eaed76d8add" @@ -15911,7 +15020,7 @@ minipass-json-stream@^1.0.1: jsonparse "^1.3.1" minipass "^3.0.0" -minipass-pipeline@^1.2.2, minipass-pipeline@^1.2.4: +minipass-pipeline@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== @@ -15925,7 +15034,7 @@ minipass-sized@^1.0.3: dependencies: minipass "^3.0.0" -minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3, minipass@^3.1.6: +minipass@^3.0.0, minipass@^3.1.1, minipass@^3.1.6: version "3.3.6" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== @@ -15947,7 +15056,7 @@ minipass@^5.0.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== -minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2: +minizlib@^2.1.1, minizlib@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== @@ -16026,11 +15135,6 @@ moment-timezone@^0.5.15: dependencies: moment "^2.29.4" -moment@^2.27.0: - version "2.30.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" - integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== - moment@^2.29.4: version "2.29.4" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" @@ -16053,11 +15157,6 @@ mongodb@6.7.0: bson "^6.7.0" mongodb-connection-string-url "^3.0.0" -moo@^0.5.0, moo@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c" - integrity sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q== - ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -16175,11 +15274,6 @@ named-placeholders@^1.1.3: dependencies: lru-cache "^7.14.1" -nan@^2.15.0: - version "2.22.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.22.0.tgz#31bc433fc33213c97bad36404bb68063de604de3" - integrity sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw== - nan@^2.17.0, nan@^2.18.0: version "2.18.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.18.0.tgz#26a6faae7ffbeb293a39660e88a76b82e30b7554" @@ -16230,36 +15324,16 @@ ndjson@^1.4.3: split2 "^2.1.0" through2 "^2.0.3" -nearley@^2.19.5: - version "2.20.1" - resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.20.1.tgz#246cd33eff0d012faf197ff6774d7ac78acdd474" - integrity sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ== - dependencies: - commander "^2.19.0" - moo "^0.5.0" - railroad-diagrams "^1.0.0" - randexp "0.4.6" - negotiator@0.6.3, negotiator@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== -negotiator@^0.6.2: - version "0.6.4" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" - integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== - neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -neon-env@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/neon-env/-/neon-env-0.1.3.tgz#071e86fde3c698e9314f057d209e0b79ddab16e9" - integrity sha512-Zo+L6Nm19gJrjyfhxn/ZDm8eIIDzr75o64ZhijBau4LNuhLzjEAteRg3gchIvgaN8XTo5BxN6iTNP5clZQ0agA== - nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -16332,7 +15406,7 @@ node-fetch@^2.6.9, node-fetch@^2.7.0: dependencies: whatwg-url "^5.0.0" -node-forge@^1.2.1, node-forge@^1.3.1: +node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== @@ -16362,22 +15436,6 @@ node-gyp-build@~4.1.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb" integrity sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ== -node-gyp@^8.2.0: - version "8.4.1" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937" - integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w== - dependencies: - env-paths "^2.2.0" - glob "^7.1.4" - graceful-fs "^4.2.6" - make-fetch-happen "^9.1.0" - nopt "^5.0.0" - npmlog "^6.0.0" - rimraf "^3.0.2" - semver "^7.3.5" - tar "^6.1.2" - which "^2.0.2" - node-gyp@^9.0.0: version "9.3.1" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.3.1.tgz#1e19f5f290afcc9c46973d68700cbd21a96192e4" @@ -16439,11 +15497,6 @@ node-source-walk@^5.0.0: dependencies: "@babel/parser" "^7.0.0" -nodemailer@6.9.13: - version "6.9.13" - resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.13.tgz#5b292bf1e92645f4852ca872c56a6ba6c4a3d3d6" - integrity sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA== - nodemailer@6.9.9: version "6.9.9" resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.9.tgz#4549bfbf710cc6addec5064dd0f19874d24248d9" @@ -16657,13 +15710,6 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npm-run-path@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" - integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== - dependencies: - path-key "^4.0.0" - npmlog@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0" @@ -16780,11 +15826,6 @@ object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1 resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-hash@^2.0.3: - version "2.2.0" - resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" - integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== - object-hash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" @@ -16924,13 +15965,6 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -onetime@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" - integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== - dependencies: - mimic-fn "^4.0.0" - only@~0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" @@ -17092,11 +16126,6 @@ p-cancelable@^1.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== -p-cancelable@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" - integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== - p-defer@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" @@ -17415,7 +16444,7 @@ passport-google-oauth20@2.x.x: dependencies: passport-oauth2 "1.x.x" -passport-google-oauth@2.0.0, passport-google-oauth@^2.0.0: +passport-google-oauth@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/passport-google-oauth/-/passport-google-oauth-2.0.0.tgz#f6eb4bc96dd6c16ec0ecfdf4e05ec48ca54d4dae" integrity sha512-JKxZpBx6wBQXX1/a1s7VmdBgwOugohH+IxCy84aPTZNq/iIPX6u7Mqov1zY7MKRz3niFPol0KJz8zPLBoHKtYA== @@ -17430,14 +16459,6 @@ passport-local@1.0.0: dependencies: passport-strategy "1.x.x" -passport-microsoft@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/passport-microsoft/-/passport-microsoft-1.0.0.tgz#78954cf3201fdce61beeb6587a3b158f8e9db86c" - integrity sha512-L1JHeCbSObSZZXiG7jU2KoKie6nzZLwGt38HXz1GasKrsCQdOnf5kH8ltV4BWNUfBL2Pt1csWn1iuBSerprrcg== - dependencies: - passport-oauth2 "1.6.1" - pkginfo "0.4.x" - passport-oauth1@1.x.x: version "1.3.0" resolved "https://registry.yarnpkg.com/passport-oauth1/-/passport-oauth1-1.3.0.tgz#5d57f1415c8e28e46b461a12ec1b492934f7c354" @@ -17452,17 +16473,6 @@ passport-oauth2-refresh@^2.1.0: resolved "https://registry.yarnpkg.com/passport-oauth2-refresh/-/passport-oauth2-refresh-2.1.0.tgz#c31cd133826383f5539d16ad8ab4f35ca73ce4a4" integrity sha512-4ML7ooCESCqiTgdDBzNUFTBcPR8zQq9iM6eppEUGMMvLdsjqRL93jKwWm4Az3OJcI+Q2eIVyI8sVRcPFvxcF/A== -passport-oauth2@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.6.1.tgz#c5aee8f849ce8bd436c7f81d904a3cd1666f181b" - integrity sha512-ZbV43Hq9d/SBSYQ22GOiglFsjsD1YY/qdiptA+8ej+9C1dL1TVB+mBE5kDH/D4AJo50+2i8f4bx0vg4/yDDZCQ== - dependencies: - base64url "3.x.x" - oauth "0.9.x" - passport-strategy "1.x.x" - uid2 "0.0.x" - utils-merge "1.x.x" - passport-oauth2@1.x.x: version "1.7.0" resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.7.0.tgz#5c4766c8531ac45ffe9ec2c09de9809e2c841fc4" @@ -17521,11 +16531,6 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-key@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" - integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== - path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" @@ -17547,7 +16552,14 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@^0.1.10: +path-to-regexp@1.x: + version "1.9.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" + integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== + dependencies: + isarray "0.0.1" + +path-to-regexp@^0.1.10, path-to-regexp@^0.1.2: version "0.1.11" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.11.tgz#a527e662c89efc4646dbfa8100bf3e847e495761" integrity sha512-c0t+KCuUkO/YDLPG4WWzEwx3J5F/GHXsD1h/SNZfySqAIKe/BaP95x8fWtOfRJokpS5yYHRJjMtYlXD8jxnpbw== @@ -17579,11 +16591,6 @@ pathval@^1.1.1: resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== -pathval@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" - integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== - pause@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" @@ -17619,17 +16626,12 @@ periscopic@^3.1.0: estree-walker "^3.0.0" is-reference "^3.0.0" -pg-cloudflare@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98" - integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q== - pg-connection-string@2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.5.0.tgz#538cadd0f7e603fc09a12590f3b8a452c2c0cf34" integrity sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ== -pg-connection-string@^2.5.0, pg-connection-string@^2.7.0: +pg-connection-string@^2.5.0: version "2.7.0" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.7.0.tgz#f1d3489e427c62ece022dba98d5262efcb168b37" integrity sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA== @@ -17639,46 +16641,16 @@ pg-int8@1.0.1: resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== -pg-mem@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/pg-mem/-/pg-mem-3.0.3.tgz#0c8862f9bd096a3dcd2addf97e96675fd687a7ad" - integrity sha512-Bwg8T46AEMjAmqFT5KIuR2ukRE4GzkVSic7U8CAXqlzFr631N9fTGo4JqNgBHrRCT1qR4Nt2bjZA1AL9JhP4uw== - dependencies: - functional-red-black-tree "^1.0.1" - immutable "^4.3.4" - json-stable-stringify "^1.0.1" - lru-cache "^6.0.0" - moment "^2.27.0" - object-hash "^2.0.3" - pgsql-ast-parser "^12.0.1" - -pg-pool@^3.6.0, pg-pool@^3.7.0: +pg-pool@^3.6.0: version "3.7.0" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.7.0.tgz#d4d3c7ad640f8c6a2245adc369bafde4ebb8cbec" integrity sha512-ZOBQForurqh4zZWjrgSwwAtzJ7QiRX0ovFkZr2klsen3Nm0aoh33Ls0fzfv3imeH/nw/O27cjdz5kzYJfeGp/g== -pg-protocol@*, pg-protocol@^1.6.0, pg-protocol@^1.7.0: +pg-protocol@*, pg-protocol@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.7.0.tgz#ec037c87c20515372692edac8b63cf4405448a93" integrity sha512-hTK/mE36i8fDDhgDFjy6xNOG+LCorxLG3WO17tku+ij6sVHXh1jQUJ8hYAnRhNla4QVD2H8er/FOjc/+EgC6yQ== -pg-query-native@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/pg-query-native/-/pg-query-native-1.3.1.tgz#66ac04d6e0a4d3f964cadc4b7b452461f843b004" - integrity sha512-EXajlKmSVIKqZip7VL05lvwsUqq5LfiNKYodhWcTfrTvK1w6TatkVPoyp0rhHv7+msR9hhT9t7BgJaaGK1QFLA== - dependencies: - bindings "^1.5.0" - nan "^2.15.0" - node-gyp "^8.2.0" - -pg-query-parser@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/pg-query-parser/-/pg-query-parser-0.3.0.tgz#f7fc0d909674b02b69c46b91c37d12a9fde90ef6" - integrity sha512-7RF8ijM2PtXTQ0B6TZVtP9fYBc1nc6ULq6f5CGlq29qXQFkTaumlQqSxlNAYOMVQGA1Vt2sSfqeViqM+nQiVEQ== - dependencies: - lodash "^4.17.21" - pg-query-native "^1.3.1" - pg-types@^2.1.0, pg-types@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" @@ -17703,19 +16675,6 @@ pg@8.10.0: pg-types "^2.1.0" pgpass "1.x" -pg@^8.12.0: - version "8.13.0" - resolved "https://registry.yarnpkg.com/pg/-/pg-8.13.0.tgz#e3d245342eb0158112553fcc1890a60720ae2a3d" - integrity sha512-34wkUTh3SxTClfoHB3pQ7bIMvw9dpFU1audQQeZG837fmHfHpr14n/AELVDoOYVDW2h5RDWU78tFjkD+erSBsw== - dependencies: - pg-connection-string "^2.7.0" - pg-pool "^3.7.0" - pg-protocol "^1.7.0" - pg-types "^2.1.0" - pgpass "1.x" - optionalDependencies: - pg-cloudflare "^1.1.1" - pgpass@1.x: version "1.0.5" resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" @@ -17723,14 +16682,6 @@ pgpass@1.x: dependencies: split2 "^4.1.0" -pgsql-ast-parser@^12.0.1: - version "12.0.1" - resolved "https://registry.yarnpkg.com/pgsql-ast-parser/-/pgsql-ast-parser-12.0.1.tgz#7b9d9880cb62df4b4c595c258b8e7a4b5f44ce53" - integrity sha512-pe8C6Zh5MsS+o38WlSu18NhrTjAv1UNMeDTs2/Km2ZReZdYBYtwtbWGZKK2BM2izv5CrQpbmP0oI10wvHOwv4A== - dependencies: - moo "^0.5.1" - nearley "^2.19.5" - phin@^2.9.1: version "2.9.3" resolved "https://registry.yarnpkg.com/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c" @@ -17746,11 +16697,6 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatc resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== - pify@5.0.0, pify@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f" @@ -17916,11 +16862,6 @@ pkg-types@^1.1.1: mlly "^1.7.1" pathe "^1.1.2" -pkginfo@0.4.x: - version "0.4.1" - resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" - integrity sha512-8xCNE/aT/EXKenuMDZ+xTVwkT8gsoHN2z/Q29l80u0ppGEXVvsKRzNMbtKhg8LS8k1tJLAHHylf6p4VFmP6XUQ== - pluralize@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" @@ -18229,7 +17170,7 @@ postcss-values-parser@^6.0.2: is-url-superb "^4.0.0" quote-unquote "^1.0.0" -postcss@^8.1.7, postcss@^8.2.9, postcss@^8.3.11, postcss@^8.4.12, postcss@^8.4.27, postcss@^8.4.29, postcss@^8.4.35, postcss@^8.4.41, postcss@^8.4.5: +postcss@^8.1.7, postcss@^8.2.9, postcss@^8.3.11, postcss@^8.4.12, postcss@^8.4.27, postcss@^8.4.29, postcss@^8.4.35, postcss@^8.4.5: version "8.4.41" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.41.tgz#d6104d3ba272d882fe18fc07d15dc2da62fa2681" integrity sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ== @@ -18260,7 +17201,7 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" -posthog-js@^1.118.0, posthog-js@^1.13.4: +posthog-js@^1.118.0: version "1.160.0" resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.160.0.tgz#ad686f3c161c7dc2ba716281b5cef94c64ce41b1" integrity sha512-K/RRgmPYIpP69nnveCJfkclb8VU+R+jsgqlrKaLGsM5CtQM9g01WOzAiT3u36WLswi58JiFMXgJtECKQuoqTgQ== @@ -18504,7 +17445,27 @@ pouchdb@7.3.0: uuid "8.3.2" vuvuzela "1.0.3" -pprof-format@^2.1.0: +pouchdb@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/pouchdb/-/pouchdb-9.0.0.tgz#569ee3941f7b03dd34b4b4e53132a9772981a35e" + integrity sha512-6wjFc/PzwaWz86rmMXoqdBlR/fBSkNoWO1mEJO7RZNS6n3xf+fhhXWAWtws741KpLKx84IkmmJ48tp+fhFzj4A== + dependencies: + double-ended-queue "2.1.0-0" + fetch-cookie "2.2.0" + level "6.0.1" + level-codec "9.0.2" + level-write-stream "1.0.0" + leveldown "6.1.1" + levelup "4.4.0" + ltgt "2.2.1" + node-fetch "2.6.9" + readable-stream "1.1.14" + spark-md5 "3.0.2" + through2 "3.0.2" + uuid "8.3.2" + vuvuzela "1.0.3" + +pprof-format@^2.0.7, pprof-format@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.1.0.tgz#acc8d7773bcf4faf0a3d3df11bceefba7ac06664" integrity sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw== @@ -18678,14 +17639,6 @@ promise-inflight@^1.0.1: resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== -promise-retry@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" - integrity sha512-StEy2osPr28o17bIW776GtwO6+Q+M9zPiZkYfosciUUMYqjhU/ffwRAH0zN2+uvGyUsn8/YICIHRzLbPacpZGw== - dependencies: - err-code "^1.0.0" - retry "^0.10.0" - promise-retry@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-2.0.1.tgz#ff747a13620ab57ba688f5fc67855410c370da22" @@ -18699,7 +17652,7 @@ promise.series@^0.2.0: resolved "https://registry.yarnpkg.com/promise.series/-/promise.series-0.2.0.tgz#2cc7ebe959fc3a6619c04ab4dbdc9e452d864bbd" integrity sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ== -prompts@^2.0.1, prompts@^2.4.2: +prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -18890,7 +17843,7 @@ querystringify@^2.1.1: resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== -queue-microtask@^1.2.2: +queue-microtask@^1.2.2, queue-microtask@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== @@ -18910,29 +17863,11 @@ quick-lru@^4.0.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== -quick-lru@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" - integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== - quote-unquote@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/quote-unquote/-/quote-unquote-1.0.0.tgz#67a9a77148effeaf81a4d428404a710baaac8a0b" integrity sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg== -railroad-diagrams@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e" - integrity sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A== - -randexp@0.4.6: - version "0.4.6" - resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3" - integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ== - dependencies: - discontinuous-range "1.0.0" - ret "~0.1.10" - randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -18980,11 +17915,6 @@ rc@1.2.8, rc@^1.2.7, rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" -reachdown@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/reachdown/-/reachdown-1.1.0.tgz#c3b85b459dbd0fe2c79782233a0a38e66a9b5454" - integrity sha512-6LsdRe4cZyOjw4NnvbhUd/rGG7WQ9HMopPr+kyL018Uci4kijtxcGR5kVb5Ln13k4PEE+fEFQbjfOvNw7cnXmA== - react-is@^17.0.1: version "17.0.2" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" @@ -19223,11 +18153,6 @@ redlock@4.2.0: dependencies: bluebird "^3.7.2" -reflect-metadata@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" - integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== - regenerate-unicode-properties@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" @@ -19257,11 +18182,6 @@ regenerator-transform@^0.15.1: dependencies: "@babel/runtime" "^7.8.4" -regexp-tree@~0.1.1: - version "0.1.27" - resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" - integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== - regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" @@ -19360,11 +18280,6 @@ resize-observer-polyfill@^1.5.1: resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464" integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg== -resolve-alpn@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" - integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== - resolve-cwd@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" @@ -19416,13 +18331,6 @@ responselike@1.0.2, responselike@^1.0.2: dependencies: lowercase-keys "^1.0.0" -responselike@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.1.tgz#9a0bc8fdc252f3fb1cca68b016591059ba1422bc" - integrity sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw== - dependencies: - lowercase-keys "^2.0.0" - restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -19431,11 +18339,6 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - retry-request@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-5.0.2.tgz#143d85f90c755af407fcc46b7166a4ba520e44da" @@ -19458,11 +18361,6 @@ retry@0.13.1, retry@^0.13.1: resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" integrity "sha1-GFsVh6z2eRnWOzVzSeA1N7JIRlg= sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" -retry@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" - integrity sha512-ZXUSQYTHdl3uS7IuCehYfMzKyIDBNoAuUblvy5oGO5UJSUTmStUUVPXbA9Qxd173Bgre53yCQczQuHgRWAdvJQ== - retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -19497,13 +18395,6 @@ rimraf@^4.4.1: dependencies: glob "^9.2.0" -rimraf@^5.0.7: - version "5.0.10" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.10.tgz#23b9843d3dc92db71f96e1a2ce92e39fd2a8221c" - integrity sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ== - dependencies: - glob "^10.3.7" - ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -19666,7 +18557,7 @@ rollup@^3.27.1: optionalDependencies: fsevents "~2.3.2" -rollup@^4.20.0, rollup@^4.9.4, rollup@^4.9.6: +rollup@^4.9.4, rollup@^4.9.6: version "4.21.2" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.21.2.tgz#f41f277a448d6264e923dd1ea179f0a926aaf9b7" integrity sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw== @@ -19766,13 +18657,6 @@ safe-regex-test@^1.0.3: es-errors "^1.3.0" is-regex "^1.1.4" -safe-regex@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-2.1.1.tgz#f7128f00d056e2fe5c11e81a1324dd974aadced2" - integrity sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A== - dependencies: - regexp-tree "~0.1.1" - safe-stable-stringify@^2.1.0, safe-stable-stringify@^2.3.1: version "2.4.3" resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" @@ -19901,7 +18785,7 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semve resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: +semver@^7.5.4, semver@^7.6.0: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== @@ -19937,7 +18821,7 @@ serialize-javascript@^6.0.1: dependencies: randombytes "^2.1.0" -server-destroy@1.0.1, server-destroy@^1.0.1: +server-destroy@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" integrity sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ== @@ -19974,11 +18858,6 @@ set-function-name@^2.0.1, set-function-name@^2.0.2: functions-have-names "^1.2.3" has-property-descriptors "^1.0.2" -setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" @@ -20077,7 +18956,7 @@ signal-exit@3.0.7, signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, s resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^4.0.1, signal-exit@^4.1.0: +signal-exit@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== @@ -20235,15 +19114,6 @@ socket.io@4.8.1: socket.io-adapter "~2.5.2" socket.io-parser "~4.2.4" -socks-proxy-agent@^6.0.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz#2687a31f9d7185e38d530bef1944fe1f1496d6ce" - integrity sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ== - dependencies: - agent-base "^6.0.2" - debug "^4.3.3" - socks "^2.6.2" - socks-proxy-agent@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz#dc069ecf34436621acb41e3efa66ca1b5fed15b6" @@ -20459,13 +19329,6 @@ ssri@^10.0.0, ssri@^10.0.1: dependencies: minipass "^4.0.0" -ssri@^8.0.0, ssri@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" - integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== - dependencies: - minipass "^3.1.1" - ssri@^9.0.0, ssri@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/ssri/-/ssri-9.0.1.tgz#544d4c357a8d7b71a19700074b6883fcb4eae057" @@ -20478,7 +19341,7 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== -stack-trace@0.0.10, stack-trace@0.0.x: +stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== @@ -20510,7 +19373,7 @@ statuses@2.0.1, statuses@^2.0.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== -std-env@^3.3.1, std-env@^3.7.0: +std-env@^3.3.1: version "3.7.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== @@ -20722,11 +19585,6 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-final-newline@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" - integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== - strip-indent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" @@ -20758,14 +19616,6 @@ strip-outer@^1.0.0: dependencies: escape-string-regexp "^1.0.2" -stripe@9.16.0: - version "9.16.0" - resolved "https://registry.yarnpkg.com/stripe/-/stripe-9.16.0.tgz#94c24549c91fced457b9e3259e8a1a1bdb6dbd0e" - integrity sha512-Dn8K+jSoQcXjxCobRI4HXUdHjOXsiF/KszK49fJnkbeCFjZ3EZxLG2JiM/CX+Hcq27NBDtv/Sxhvy+HhTmvyaQ== - dependencies: - "@types/node" ">=8.1.0" - qs "^6.10.3" - striptags@^3.1.1: version "3.2.0" resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.2.0.tgz#cc74a137db2de8b0b9a370006334161f7dd67052" @@ -20834,18 +19684,6 @@ sublevel-pouchdb@7.2.2: ltgt "2.2.1" readable-stream "1.1.14" -subleveldown@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/subleveldown/-/subleveldown-5.0.1.tgz#aa2b4e4698a48d9a86856b2c4df1b6bce2d2ce53" - integrity sha512-cVqd/URpp7si1HWu5YqQ3vqQkjuolAwHypY1B4itPlS71/lsf6TQPZ2Y0ijT22EYVkvH5ove9JFJf4u7VGPuZw== - dependencies: - abstract-leveldown "^6.3.0" - encoding-down "^6.2.0" - inherits "^2.0.3" - level-option-wrap "^1.1.0" - levelup "^4.4.0" - reachdown "^1.1.0" - superagent@^8.0.5: version "8.1.2" resolved "https://registry.yarnpkg.com/superagent/-/superagent-8.1.2.tgz#03cb7da3ec8b32472c9d20f6c2a57c7f3765f30b" @@ -21132,7 +19970,7 @@ tar@6.1.11: mkdirp "^1.0.3" yallist "^4.0.0" -tar@6.2.1, tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: +tar@6.2.1, tar@^6.1.11, tar@^6.1.2: version "6.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a" integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A== @@ -21149,11 +19987,6 @@ tarn@^3.0.1, tarn@^3.0.2: resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.2.tgz#73b6140fbb881b71559c4f8bfde3d9a4b3d27693" integrity sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ== -teamcity-service-messages@^0.1.14: - version "0.1.14" - resolved "https://registry.yarnpkg.com/teamcity-service-messages/-/teamcity-service-messages-0.1.14.tgz#193d420a5e4aef8e5e50b8c39e7865e08fbb5d8a" - integrity sha512-29aQwaHqm8RMX74u2o/h1KbMLP89FjNiMxD9wbF2BbWOnbM+q+d1sCEC+MqCc4QW3NJykn77OMpTFw/xTHIc0w== - tedious@^16.4.0: version "16.7.1" resolved "https://registry.yarnpkg.com/tedious/-/tedious-16.7.1.tgz#1190f30fd99a413f1dc9250dee4835cf0788b650" @@ -21340,7 +20173,7 @@ tiny-queue@^0.2.0: resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046" integrity sha512-EijGsv7kzd9I9g0ByCl6h42BWNGUZrlCSejfrb3AKeHC33SGbASu1VDf5O3rRiiUOhAC9CHdZxFPbZu0HmR70A== -tinybench@^2.3.1, tinybench@^2.8.0: +tinybench@^2.3.1: version "2.9.0" resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== @@ -21355,26 +20188,11 @@ tinypool@^0.4.0: resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.4.0.tgz#3cf3ebd066717f9f837e8d7d31af3c127fdb5446" integrity sha512-2ksntHOKf893wSAH4z/+JbPpi92esw8Gn9N2deXX+B0EO92hexAVI9GIZZPx7P5aYo5KULfeOSt3kMOmSOy6uA== -tinypool@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.1.tgz#c64233c4fac4304e109a64340178760116dbe1fe" - integrity sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA== - -tinyrainbow@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" - integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ== - tinyspy@^1.0.2: version "1.1.1" resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-1.1.1.tgz#0cb91d5157892af38cb2d217f5c7e8507a5bf092" integrity sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g== -tinyspy@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.0.tgz#cb61644f2713cd84dee184863f4642e06ddf0585" - integrity sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA== - tlhunter-sorted-set@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/tlhunter-sorted-set/-/tlhunter-sorted-set-0.1.0.tgz#1c3eae28c0fa4dff97e9501d2e3c204b86406f4b" @@ -21528,13 +20346,6 @@ ts-api-utils@^1.0.1, ts-api-utils@^1.3.0: resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== -ts-declaration-location@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/ts-declaration-location/-/ts-declaration-location-1.0.4.tgz#60c64133202ec5d171fdf0395f70f786f92f14c0" - integrity sha512-r4JoxYhKULbZuH81Pjrp9OEG5St7XWk7zXwGkLKhmVcjiBVHTJXV5wK6dEa9JKW5QGSTW6b1lOjxAKp8R1SQhg== - dependencies: - minimatch "^10.0.0" - ts-graphviz@^1.5.0: version "1.5.4" resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-1.5.4.tgz#61a3059afeac4f6d4be3c6729a4d88546ca9e095" @@ -21573,39 +20384,6 @@ ts-node@10.8.1: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -ts-node@^10.9.2: - version "10.9.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" - integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== - dependencies: - "@cspotcode/source-map-support" "^0.8.0" - "@tsconfig/node10" "^1.0.7" - "@tsconfig/node12" "^1.0.7" - "@tsconfig/node14" "^1.0.0" - "@tsconfig/node16" "^1.0.2" - acorn "^8.4.1" - acorn-walk "^8.1.1" - arg "^4.1.0" - create-require "^1.1.0" - diff "^4.0.1" - make-error "^1.1.1" - v8-compile-cache-lib "^3.0.1" - yn "3.1.1" - -tsconfck@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/tsconfck/-/tsconfck-3.1.1.tgz#c7284913262c293b43b905b8b034f524de4a3162" - integrity sha512-00eoI6WY57SvZEVjm13stEVE90VkEdJAFGgpFLTsZbJyW/LwFQ7uQxJHWpZ2hzSWgCPKc9AnBnNP+0X7o3hAmQ== - -tsconfig-paths-webpack-plugin@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.1.0.tgz#3c6892c5e7319c146eee1e7302ed9e6f2be4f763" - integrity sha512-xWFISjviPydmtmgeUAuXp4N1fky+VCtfhOkDUFIv5ea7p4wuTomI4QTrXvFBX2S4jZsmyTSrStQl+E+4w+RzxA== - dependencies: - chalk "^4.1.0" - enhanced-resolve "^5.7.0" - tsconfig-paths "^4.1.2" - tsconfig-paths@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.0.0.tgz#1082f5d99fd127b72397eef4809e4dd06d229b64" @@ -21793,11 +20571,6 @@ typed-array-length@^1.0.6: is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" -typed-duration@^1.0.12: - version "1.0.13" - resolved "https://registry.yarnpkg.com/typed-duration/-/typed-duration-1.0.13.tgz#a40f9ba563b6e20674cac491e15ecbf6811d85a7" - integrity sha512-HLwA+hNq/2eXe03isJSfa7YJt6NikplBGdNKvlhyuR6WL5iZi2uXJIZv1SSOMEIukCZbeQ8QwIcQ801S0/Qulw== - typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -21827,7 +20600,7 @@ typeof@^1.0.0: resolved "https://registry.yarnpkg.com/typeof/-/typeof-1.0.0.tgz#9c84403f2323ae5399167275497638ea1d2f2440" integrity sha512-Pze0mIxYXhaJdpw1ayMzOA7rtGr1OmsTY/Z+FWtRKIqXFz6aoDLjqdbWE/tcIBSC8nhnVXiRrEXujodR/xiFAA== -typescript-eslint@^7.16.1, typescript-eslint@^7.3.1: +typescript-eslint@^7.3.1: version "7.18.0" resolved "https://registry.yarnpkg.com/typescript-eslint/-/typescript-eslint-7.18.0.tgz#e90d57649b2ad37a7475875fa3e834a6d9f61eb2" integrity sha512-PonBkP603E3tt05lDkbOMyaxJjvKqQrXsnow72sVeOFINDE/qNmnnd+f9b4N+U7W6MXnnYyrhtmF2t08QWwUbA== @@ -21841,7 +20614,7 @@ typescript@5.5.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.2.tgz#c26f023cb0054e657ce04f72583ea2d85f8d0507" integrity sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew== -"typescript@>=3 < 6", typescript@^5.5.3: +"typescript@>=3 < 6": version "5.5.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== @@ -21947,13 +20720,6 @@ uniq@^1.0.1: resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" integrity sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA== -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - unique-filename@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-2.0.1.tgz#e785f8675a9a7589e0ac77e0b5c34d2eaeac6da2" @@ -21968,13 +20734,6 @@ unique-filename@^3.0.0: dependencies: unique-slug "^4.0.0" -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - unique-slug@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-3.0.0.tgz#6d347cf57c8a7a7a6044aabd0e2d74e4d76dc7c9" @@ -22034,7 +20793,7 @@ update-browserslist-db@^1.0.10: escalade "^3.1.1" picocolors "^1.0.0" -update-dotenv@1.1.1, update-dotenv@^1.1.1: +update-dotenv@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/update-dotenv/-/update-dotenv-1.1.1.tgz#17146f302f216c3c92419d5a327a45be910050ca" integrity sha512-3cIC18In/t0X/yH793c00qqxcKD8jVCgNOPif/fGQkFpYMGecM9YAc+kaAKXuZsM2dE9I9wFI7KvAuNX22SGMQ== @@ -22066,6 +20825,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urijs@^1.19.2: + version "1.19.11" + resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" + integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== + url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -22073,7 +20837,7 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -url-parse@^1.4.3, url-parse@^1.5.3: +url-parse@^1.5.3: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== @@ -22148,11 +20912,6 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^7.0.3: - version "7.0.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" - integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== - uuid@^9.0.0, uuid@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" @@ -22226,17 +20985,6 @@ vite-node@0.29.8: picocolors "^1.0.0" vite "^3.0.0 || ^4.0.0" -vite-node@2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.0.5.tgz#36d909188fc6e3aba3da5fc095b3637d0d18e27b" - integrity sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q== - dependencies: - cac "^6.7.14" - debug "^4.3.5" - pathe "^1.1.2" - tinyrainbow "^1.2.0" - vite "^5.0.0" - vite-plugin-static-copy@^0.17.0: version "0.17.0" resolved "https://registry.yarnpkg.com/vite-plugin-static-copy/-/vite-plugin-static-copy-0.17.0.tgz#e45527da186c4a3818d09635797b6fc7cc9e035f" @@ -22247,15 +20995,6 @@ vite-plugin-static-copy@^0.17.0: fs-extra "^11.1.0" picocolors "^1.0.0" -vite-tsconfig-paths@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz#321f02e4b736a90ff62f9086467faf4e2da857a9" - integrity sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA== - dependencies: - debug "^4.1.1" - globrex "^0.1.2" - tsconfck "^3.0.3" - "vite@^3.0.0 || ^4.0.0", vite@^4.5.0: version "4.5.3" resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.3.tgz#d88a4529ea58bae97294c7e2e6f0eab39a50fb1a" @@ -22267,17 +21006,6 @@ vite-tsconfig-paths@^4.3.2: optionalDependencies: fsevents "~2.3.2" -vite@^5.0.0: - version "5.4.2" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.2.tgz#8acb6ec4bfab823cdfc1cb2d6c53ed311bc4e47e" - integrity sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA== - dependencies: - esbuild "^0.21.3" - postcss "^8.4.41" - rollup "^4.20.0" - optionalDependencies: - fsevents "~2.3.3" - vitefu@^0.2.2: version "0.2.5" resolved "https://registry.yarnpkg.com/vitefu/-/vitefu-0.2.5.tgz#c1b93c377fbdd3e5ddd69840ea3aa70b40d90969" @@ -22313,31 +21041,6 @@ vitest@^0.29.2: vite-node "0.29.8" why-is-node-running "^2.2.2" -vitest@^2.0.4: - version "2.0.5" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.0.5.tgz#2f15a532704a7181528e399cc5b754c7f335fd62" - integrity sha512-8GUxONfauuIdeSl5f9GTgVEpg5BTOlplET4WEDaeY2QBiN8wSm68vxN/tb5z405OwppfoCavnwXafiaYBC/xOA== - dependencies: - "@ampproject/remapping" "^2.3.0" - "@vitest/expect" "2.0.5" - "@vitest/pretty-format" "^2.0.5" - "@vitest/runner" "2.0.5" - "@vitest/snapshot" "2.0.5" - "@vitest/spy" "2.0.5" - "@vitest/utils" "2.0.5" - chai "^5.1.1" - debug "^4.3.5" - execa "^8.0.1" - magic-string "^0.30.10" - pathe "^1.1.2" - std-env "^3.7.0" - tinybench "^2.8.0" - tinypool "^1.0.0" - tinyrainbow "^1.2.0" - vite "^5.0.0" - vite-node "2.0.5" - why-is-node-running "^2.3.0" - vlq@^0.2.2: version "0.2.3" resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26" @@ -22386,11 +21089,6 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" -watskeburt@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/watskeburt/-/watskeburt-4.1.0.tgz#3c0227669be646a97424b631164b1afe3d4d5344" - integrity sha512-KkY5H51ajqy9HYYI+u9SIURcWnqeVVhdH0I+ab6aXPGHfZYxgRCwnR6Lm3+TYB6jJVt5jFqw4GAKmwf1zHmGQw== - wcwidth@^1.0.0, wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" @@ -22553,7 +21251,7 @@ which@^3.0.0: dependencies: isexe "^2.0.0" -why-is-node-running@^2.2.2, why-is-node-running@^2.3.0: +why-is-node-running@^2.2.2: version "2.3.0" resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== @@ -22575,16 +21273,6 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -win-ca@3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/win-ca/-/win-ca-3.5.1.tgz#2ef37ac24b0a1daa2714b4c5ef258c5242429e00" - integrity sha512-RNy9gpBS6cxWHjfbqwBA7odaHyT+YQNhtdpJZwYCFoxB/Dq22oeOZ9YCXMwjhLytKpo7JJMnKdJ/ve7N12zzfQ== - dependencies: - is-electron "^2.2.0" - make-dir "^1.3.0" - node-forge "^1.2.1" - split "^1.0.1" - winston-transport@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" From e1501378a0bafd1323800605cf09d33d5da833ec Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 18 Nov 2024 15:54:40 +0000 Subject: [PATCH 03/40] update azure vuln --- package.json | 5 +- yarn.lock | 260 ++++++++++++++++++++++++--------------------------- 2 files changed, 126 insertions(+), 139 deletions(-) diff --git a/package.json b/package.json index 6dce697a90..0f1045c81d 100644 --- a/package.json +++ b/package.json @@ -123,5 +123,8 @@ "engines": { "node": ">=20.0.0 <21.0.0" }, - "dependencies": {} + "dependencies": { + "@azure/identity": "4.2.1", + "xml2js": "0.5.0" + } } diff --git a/yarn.lock b/yarn.lock index 6a7af6c0ad..b7800de50a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -757,20 +757,20 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/identity@^3.4.1": - version "3.4.2" - resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-3.4.2.tgz#6b01724c9caac7cadab6b63c76584345bda8e2de" - integrity sha512-0q5DL4uyR0EZ4RXQKD8MadGH6zTIcloUoS/RVbCpNpej4pwte0xpqYxk8K97Py2RiuUvI7F4GXpoT4046VfufA== +"@azure/identity@4.2.1", "@azure/identity@^3.4.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" + integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== dependencies: "@azure/abort-controller" "^1.0.0" "@azure/core-auth" "^1.5.0" "@azure/core-client" "^1.4.0" "@azure/core-rest-pipeline" "^1.1.0" "@azure/core-tracing" "^1.0.0" - "@azure/core-util" "^1.6.1" + "@azure/core-util" "^1.3.0" "@azure/logger" "^1.0.0" - "@azure/msal-browser" "^3.5.0" - "@azure/msal-node" "^2.5.1" + "@azure/msal-browser" "^3.11.1" + "@azure/msal-node" "^2.9.2" events "^3.0.0" jws "^4.0.0" open "^8.0.0" @@ -801,7 +801,7 @@ dependencies: tslib "^2.2.0" -"@azure/msal-browser@^3.5.0": +"@azure/msal-browser@^3.11.1": version "3.27.0" resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.27.0.tgz#b6f02f73c8e102d3f115009b4677539fb173fe2b" integrity sha512-+b4ZKSD8+vslCtVRVetkegEhOFMLP3rxDWJY212ct+2r6jVg6OSQKc1Qz3kCoXo0FgwaXkb+76TMZfpHp8QtgA== @@ -813,10 +813,10 @@ resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.16.0.tgz#f3470fcaec788dbe50859952cd499340bda23d7a" integrity sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA== -"@azure/msal-node@^2.5.1": - version "2.16.0" - resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.16.0.tgz#028ac69bc75738d6744dab3e3f20f8240f4f6e2c" - integrity sha512-oww0oJTOOvPKTVXqVyxfcFVjExQKYEkKR5KM0cTG3jnzt6u/MRMx8XaK49L/bxV35r9sCHQFjNlEShad9qGSYA== +"@azure/msal-node@^2.9.2": + version "2.16.1" + resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.16.1.tgz#89828832e8e6c8a88cecc4ef6d8d4e4352116b77" + integrity sha512-1NEFpTmMMT2A7RnZuvRl/hUmJU+GLPjh+ShyIqPktG2PvSd2yvPnzGd/BxIBAAvJG5nr9lH4oYcQXepDbaE7fg== dependencies: "@azure/msal-common" "14.16.0" jsonwebtoken "^9.0.0" @@ -2044,6 +2044,44 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@budibase/backend-core@3.2.4": + version "0.0.0" + dependencies: + "@budibase/nano" "10.1.5" + "@budibase/pouchdb-replication-stream" "1.2.11" + "@budibase/shared-core" "0.0.0" + "@budibase/types" "0.0.0" + aws-cloudfront-sign "3.0.2" + aws-sdk "2.1030.0" + bcrypt "5.1.0" + bcryptjs "2.4.3" + bull "4.10.1" + correlation-id "4.0.0" + dd-trace "5.23.0" + dotenv "16.0.1" + ioredis "5.3.2" + joi "17.6.0" + jsonwebtoken "9.0.2" + knex "2.4.2" + koa-passport "^6.0.0" + koa-pino-logger "4.0.0" + lodash "4.17.21" + node-fetch "2.6.7" + passport-google-oauth "2.0.0" + passport-local "1.0.0" + passport-oauth2-refresh "^2.1.0" + pino "8.11.0" + pino-http "8.3.3" + posthog-node "4.0.1" + pouchdb "^9.0.0" + pouchdb-find "9.0.0" + redlock "4.2.0" + rotating-file-stream "3.1.0" + sanitize-s3-objectkey "0.0.1" + semver "^7.5.4" + tar-fs "2.1.1" + uuid "^8.3.2" + "@budibase/handlebars-helpers@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77" @@ -2086,6 +2124,47 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" +"@budibase/pro@npm:@budibase/pro@latest": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.4.tgz#b6ceb736686bda7069829cbb0eabf9cc775dd435" + integrity sha512-bQhwjbQpjvBrxuE6BSTwGp4JcS0DC2P9kA+NaK8VnVN/L+cJzyk6n7Ogt7jgLZwZcwNz5Wu/eBbrUaoBDDXmjw== + dependencies: + "@anthropic-ai/sdk" "^0.27.3" + "@budibase/backend-core" "3.2.4" + "@budibase/shared-core" "3.2.4" + "@budibase/string-templates" "3.2.4" + "@budibase/types" "3.2.4" + "@koa/router" "8.0.8" + bull "4.10.1" + dd-trace "5.2.0" + joi "17.6.0" + jsonwebtoken "9.0.2" + lru-cache "^7.14.1" + memorystream "^0.3.1" + node-fetch "2.6.7" + openai "4.59.0" + scim-patch "^0.8.1" + scim2-parse-filter "^0.2.8" + +"@budibase/shared-core@3.2.4": + version "0.0.0" + dependencies: + "@budibase/types" "0.0.0" + cron-validate "1.4.5" + +"@budibase/string-templates@3.2.4": + version "0.0.0" + dependencies: + "@budibase/handlebars-helpers" "^0.13.2" + dayjs "^1.10.8" + handlebars "^4.7.8" + lodash.clonedeep "^4.5.0" + +"@budibase/types@3.2.4": + version "0.0.0" + dependencies: + scim-patch "^0.8.1" + "@bull-board/api@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3" @@ -6923,28 +7002,12 @@ aws-sdk@2.1030.0: uuid "3.3.2" xml2js "0.4.19" -axios@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" - integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== +axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.5.0, axios@^1.6.2: + version "1.7.7" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" + integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - -axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.5.0, axios@^1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.3.tgz#7f50f23b3aa246eff43c54834272346c396613f4" - integrity sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww== - dependencies: - follow-redirects "^1.15.0" + follow-redirects "^1.15.6" form-data "^4.0.0" proxy-from-env "^1.1.0" @@ -10544,14 +10607,7 @@ fast-url-parser@^1.1.3: dependencies: punycode "^1.3.2" -fast-xml-parser@4.2.5: - version "4.2.5" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" - integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== - dependencies: - strnum "^1.0.5" - -fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: +fast-xml-parser@4.2.5, fast-xml-parser@4.4.1, fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: version "4.4.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== @@ -10781,16 +10837,11 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.14.0: +follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== -follow-redirects@^1.15.0: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== - for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -11800,12 +11851,7 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== - -http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -12288,11 +12334,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -12742,6 +12783,11 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -13603,14 +13649,7 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@^3.0.2, kind-of@^3.1.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== - dependencies: - is-buffer "^1.1.5" - -kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -15191,7 +15230,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@^1.5.2: +msgpackr@1.10.1, msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -15385,27 +15424,13 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" -node-fetch@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" - integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== - dependencies: - whatwg-url "^5.0.0" - -node-fetch@^2.6.9, node-fetch@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -16489,15 +16514,7 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" - integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - -passport@^0.6.0: +passport@0.6.0, passport@^0.4.0, passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -18768,33 +18785,13 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: +"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.4, semver@^7.6.0: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== - -semver@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" - integrity sha512-abLdIKCosKfpnmhS52NCTjO4RiLspDfsn37prjzGrp9im5DPJOgh82Os92vtwGh6XdQryKI/7SREZnV+aqiXrA== - seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -20279,7 +20276,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: +tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -20775,6 +20772,14 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unset-value@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" + integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== + dependencies: + has-value "^2.0.2" + isobject "^4.0.0" + untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -21461,26 +21466,10 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== - dependencies: - sax ">=0.6.0" - xmlbuilder "~9.0.1" - -xml2js@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" - integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - -xml2js@^0.4.19, xml2js@^0.4.5: - version "0.4.23" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" - integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== +xml2js@0.4.19, xml2js@0.5.0, xml2js@0.6.2, xml2js@^0.4.19, xml2js@^0.4.5: + version "0.6.2" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" + integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== dependencies: sax ">=0.6.0" xmlbuilder "~11.0.0" @@ -21490,11 +21479,6 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== -xmlbuilder@~9.0.1: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ== - xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" From e8d7ed263583ede45c73ffd5b2df9dfdcce6e91d Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 18 Nov 2024 16:09:59 +0000 Subject: [PATCH 04/40] bump pouch in server --- packages/server/package.json | 3 +- yarn.lock | 83 +----------------------------------- 2 files changed, 4 insertions(+), 82 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index ff4a1ee0fd..24d679eb3c 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -105,7 +105,7 @@ "openapi-types": "9.3.1", "oracledb": "6.5.1", "pg": "8.10.0", - "pouchdb": "7.3.0", + "pouchdb": "9.0.0", "pouchdb-all-dbs": "1.1.1", "pouchdb-find": "9.0.0", "redis": "4", @@ -136,6 +136,7 @@ "@types/node-fetch": "2.6.4", "@types/oracledb": "6.5.1", "@types/pg": "8.6.6", + "@types/pouchdb": "^6.4.2", "@types/server-destroy": "1.0.1", "@types/supertest": "2.0.14", "@types/tar": "6.1.5", diff --git a/yarn.lock b/yarn.lock index c7301f3eba..31b24fe04c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2044,44 +2044,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@3.2.4": - version "0.0.0" - dependencies: - "@budibase/nano" "10.1.5" - "@budibase/pouchdb-replication-stream" "1.2.11" - "@budibase/shared-core" "0.0.0" - "@budibase/types" "0.0.0" - aws-cloudfront-sign "3.0.2" - aws-sdk "2.1030.0" - bcrypt "5.1.0" - bcryptjs "2.4.3" - bull "4.10.1" - correlation-id "4.0.0" - dd-trace "5.23.0" - dotenv "16.0.1" - ioredis "5.3.2" - joi "17.6.0" - jsonwebtoken "9.0.2" - knex "2.4.2" - koa-passport "^6.0.0" - koa-pino-logger "4.0.0" - lodash "4.17.21" - node-fetch "2.6.7" - passport-google-oauth "2.0.0" - passport-local "1.0.0" - passport-oauth2-refresh "^2.1.0" - pino "8.11.0" - pino-http "8.3.3" - posthog-node "4.0.1" - pouchdb "^9.0.0" - pouchdb-find "9.0.0" - redlock "4.2.0" - rotating-file-stream "3.1.0" - sanitize-s3-objectkey "0.0.1" - semver "^7.5.4" - tar-fs "2.1.1" - uuid "^8.3.2" - "@budibase/handlebars-helpers@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77" @@ -2124,47 +2086,6 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@npm:@budibase/pro@latest": - version "3.2.4" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.4.tgz#b6ceb736686bda7069829cbb0eabf9cc775dd435" - integrity sha512-bQhwjbQpjvBrxuE6BSTwGp4JcS0DC2P9kA+NaK8VnVN/L+cJzyk6n7Ogt7jgLZwZcwNz5Wu/eBbrUaoBDDXmjw== - dependencies: - "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "3.2.4" - "@budibase/shared-core" "3.2.4" - "@budibase/string-templates" "3.2.4" - "@budibase/types" "3.2.4" - "@koa/router" "8.0.8" - bull "4.10.1" - dd-trace "5.2.0" - joi "17.6.0" - jsonwebtoken "9.0.2" - lru-cache "^7.14.1" - memorystream "^0.3.1" - node-fetch "2.6.7" - openai "4.59.0" - scim-patch "^0.8.1" - scim2-parse-filter "^0.2.8" - -"@budibase/shared-core@3.2.4": - version "0.0.0" - dependencies: - "@budibase/types" "0.0.0" - cron-validate "1.4.5" - -"@budibase/string-templates@3.2.4": - version "0.0.0" - dependencies: - "@budibase/handlebars-helpers" "^0.13.2" - dayjs "^1.10.8" - handlebars "^4.7.8" - lodash.clonedeep "^4.5.0" - -"@budibase/types@3.2.4": - version "0.0.0" - dependencies: - scim-patch "^0.8.1" - "@bull-board/api@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3" @@ -17462,7 +17383,7 @@ pouchdb@7.3.0: uuid "8.3.2" vuvuzela "1.0.3" -pouchdb@^9.0.0: +pouchdb@9.0.0, pouchdb@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/pouchdb/-/pouchdb-9.0.0.tgz#569ee3941f7b03dd34b4b4e53132a9772981a35e" integrity sha512-6wjFc/PzwaWz86rmMXoqdBlR/fBSkNoWO1mEJO7RZNS6n3xf+fhhXWAWtws741KpLKx84IkmmJ48tp+fhFzj4A== @@ -21725,4 +21646,4 @@ zip-stream@^6.0.1: dependencies: archiver-utils "^5.0.0" compress-commons "^6.0.2" - readable-stream "^4.0.0" \ No newline at end of file + readable-stream "^4.0.0" From 2de841407ddd666926a281381c7c63100234c94d Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 18 Nov 2024 16:39:05 +0000 Subject: [PATCH 05/40] pin deps --- packages/backend-core/package.json | 2 +- packages/server/package.json | 2 +- packages/worker/package.json | 2 +- yarn.lock | 207 ++++++++++++++++++++--------- 4 files changed, 146 insertions(+), 67 deletions(-) diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 096997b2a1..4ab7b91a79 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -47,7 +47,7 @@ "pino": "8.11.0", "pino-http": "8.3.3", "posthog-node": "4.0.1", - "pouchdb": "^9.0.0", + "pouchdb": "9.0.0", "pouchdb-find": "9.0.0", "redlock": "4.2.0", "rotating-file-stream": "3.1.0", diff --git a/packages/server/package.json b/packages/server/package.json index 24d679eb3c..dc51689b96 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -130,7 +130,7 @@ "@types/jest": "29.5.5", "@types/koa": "2.13.4", "@types/koa-send": "^4.1.6", - "@types/koa__router": "^12.0.4", + "@types/koa__router": "12.0.4", "@types/lodash": "4.14.200", "@types/mssql": "9.1.4", "@types/node-fetch": "2.6.4", diff --git a/packages/worker/package.json b/packages/worker/package.json index 786ca11c21..e4054209c1 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -77,7 +77,7 @@ "@types/jest": "29.5.5", "@types/jsonwebtoken": "9.0.3", "@types/koa": "2.13.4", - "@types/koa__router": "^12.0.4", + "@types/koa__router": "12.0.4", "@types/lodash": "4.14.200", "@types/node-fetch": "2.6.4", "@types/server-destroy": "1.0.1", diff --git a/yarn.lock b/yarn.lock index 31b24fe04c..7cdba96ec8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -757,7 +757,7 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/identity@4.2.1", "@azure/identity@^3.4.1": +"@azure/identity@4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -777,6 +777,26 @@ stoppable "^1.1.0" tslib "^2.2.0" +"@azure/identity@^3.4.1": + version "3.4.2" + resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-3.4.2.tgz#6b01724c9caac7cadab6b63c76584345bda8e2de" + integrity sha512-0q5DL4uyR0EZ4RXQKD8MadGH6zTIcloUoS/RVbCpNpej4pwte0xpqYxk8K97Py2RiuUvI7F4GXpoT4046VfufA== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-client" "^1.4.0" + "@azure/core-rest-pipeline" "^1.1.0" + "@azure/core-tracing" "^1.0.0" + "@azure/core-util" "^1.6.1" + "@azure/logger" "^1.0.0" + "@azure/msal-browser" "^3.5.0" + "@azure/msal-node" "^2.5.1" + events "^3.0.0" + jws "^4.0.0" + open "^8.0.0" + stoppable "^1.1.0" + tslib "^2.2.0" + "@azure/keyvault-keys@^4.4.0": version "4.7.1" resolved "https://registry.yarnpkg.com/@azure/keyvault-keys/-/keyvault-keys-4.7.1.tgz#c35415610ca5301f92e2ad7b30fd569609d4b32d" @@ -801,7 +821,7 @@ dependencies: tslib "^2.2.0" -"@azure/msal-browser@^3.11.1": +"@azure/msal-browser@^3.11.1", "@azure/msal-browser@^3.5.0": version "3.27.0" resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.27.0.tgz#b6f02f73c8e102d3f115009b4677539fb173fe2b" integrity sha512-+b4ZKSD8+vslCtVRVetkegEhOFMLP3rxDWJY212ct+2r6jVg6OSQKc1Qz3kCoXo0FgwaXkb+76TMZfpHp8QtgA== @@ -813,7 +833,7 @@ resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.16.0.tgz#f3470fcaec788dbe50859952cd499340bda23d7a" integrity sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA== -"@azure/msal-node@^2.9.2": +"@azure/msal-node@^2.5.1", "@azure/msal-node@^2.9.2": version "2.16.1" resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.16.1.tgz#89828832e8e6c8a88cecc4ef6d8d4e4352116b77" integrity sha512-1NEFpTmMMT2A7RnZuvRl/hUmJU+GLPjh+ShyIqPktG2PvSd2yvPnzGd/BxIBAAvJG5nr9lH4oYcQXepDbaE7fg== @@ -3197,19 +3217,7 @@ resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== -"@koa/router@8.0.8": - version "8.0.8" - resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.8.tgz#95f32d11373d03d89dcb63fabe9ac6f471095236" - integrity sha512-FnT93N4NUehnXr+juupDmG2yfi0JnWdCmNEuIXpCG4TtG+9xvtrLambBH3RclycopVUOEYAim2lydiNBI7IRVg== - dependencies: - debug "^4.1.1" - http-errors "^1.7.3" - koa-compose "^4.1.0" - methods "^1.1.2" - path-to-regexp "1.x" - urijs "^1.19.2" - -"@koa/router@^13.1.0": +"@koa/router@13.1.0", "@koa/router@^13.1.0": version "13.1.0" resolved "https://registry.yarnpkg.com/@koa/router/-/router-13.1.0.tgz#43f4c554444ea4f4a148a5735a9525c6d16fd1b5" integrity sha512-mNVu1nvkpSd8Q8gMebGbCkDWJ51ODetrFvLKYusej+V0ByD4btqHYnPIzTBLXnQMVUlm/oxVwqmWBY3zQfZilw== @@ -5377,14 +5385,7 @@ "@types/koa-compose" "*" "@types/node" "*" -"@types/koa__router@8.0.8": - version "8.0.8" - resolved "https://registry.yarnpkg.com/@types/koa__router/-/koa__router-8.0.8.tgz#b1e0e9a512498777d3366bbdf0e853df27ec831c" - integrity sha512-9pGCaDtzCsj4HJ8HmGuqzk8+s57sPj4njWd08GG5o92n5Xp9io2snc40CPpXFhoKcZ8OKhuu6ht4gNou9e1C2w== - dependencies: - "@types/koa" "*" - -"@types/koa__router@^12.0.4": +"@types/koa__router@12.0.4": version "12.0.4" resolved "https://registry.yarnpkg.com/@types/koa__router/-/koa__router-12.0.4.tgz#a1f9afec9dc7e7d9fa1252d1938c44b403e19a28" integrity sha512-Y7YBbSmfXZpa/m5UGGzb7XadJIRBRnwNY9cdAojZGp65Cpe5MAP3mOZE7e3bImt8dfKS4UFcR16SLH8L/z7PBw== @@ -6923,7 +6924,23 @@ aws-sdk@2.1030.0: uuid "3.3.2" xml2js "0.4.19" -axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.5.0, axios@^1.6.2: +axios@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" + integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + +axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.5.0, axios@^1.6.2: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -10528,7 +10545,14 @@ fast-url-parser@^1.1.3: dependencies: punycode "^1.3.2" -fast-xml-parser@4.2.5, fast-xml-parser@4.4.1, fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: +fast-xml-parser@4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" + integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== + dependencies: + strnum "^1.0.5" + +fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: version "4.4.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== @@ -10758,7 +10782,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.15.6: +follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -11772,7 +11796,12 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -12255,6 +12284,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -12704,11 +12738,6 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isobject@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" - integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== - isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -13570,7 +13599,14 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@^3.0.2, kind-of@^3.1.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -15151,7 +15187,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@1.10.1, msgpackr@^1.5.2: +msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -15345,13 +15381,27 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: +node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.9, node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -16435,7 +16485,15 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@0.6.0, passport@^0.4.0, passport@^0.6.0: +passport@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" + integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + +passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -16490,13 +16548,6 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@1.x: - version "1.9.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" - integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== - dependencies: - isarray "0.0.1" - path-to-regexp@^0.1.10, path-to-regexp@^0.1.2: version "0.1.11" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.11.tgz#a527e662c89efc4646dbfa8100bf3e847e495761" @@ -17383,7 +17434,7 @@ pouchdb@7.3.0: uuid "8.3.2" vuvuzela "1.0.3" -pouchdb@9.0.0, pouchdb@^9.0.0: +pouchdb@9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/pouchdb/-/pouchdb-9.0.0.tgz#569ee3941f7b03dd34b4b4e53132a9772981a35e" integrity sha512-6wjFc/PzwaWz86rmMXoqdBlR/fBSkNoWO1mEJO7RZNS6n3xf+fhhXWAWtws741KpLKx84IkmmJ48tp+fhFzj4A== @@ -18706,13 +18757,33 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.4, semver@^7.6.0: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +semver@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" + integrity sha512-abLdIKCosKfpnmhS52NCTjO4RiLspDfsn37prjzGrp9im5DPJOgh82Os92vtwGh6XdQryKI/7SREZnV+aqiXrA== + seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -20197,7 +20268,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -20693,14 +20764,6 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unset-value@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" - integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== - dependencies: - has-value "^2.0.2" - isobject "^4.0.0" - untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -20751,11 +20814,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urijs@^1.19.2: - version "1.19.11" - resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" - integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== - url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -21387,10 +21445,26 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.4.19, xml2js@0.5.0, xml2js@0.6.2, xml2js@^0.4.19, xml2js@^0.4.5: - version "0.6.2" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" - integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== +xml2js@0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" + integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== + dependencies: + sax ">=0.6.0" + xmlbuilder "~9.0.1" + +xml2js@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xml2js@^0.4.19, xml2js@^0.4.5: + version "0.4.23" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" + integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== dependencies: sax ">=0.6.0" xmlbuilder "~11.0.0" @@ -21400,6 +21474,11 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== +xmlbuilder@~9.0.1: + version "9.0.7" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" + integrity sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ== + xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" From eb353498d4f2084159c5a9e8d71a19b516c35639 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 18 Nov 2024 16:40:15 +0000 Subject: [PATCH 06/40] bump pro --- packages/pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pro b/packages/pro index bfeece324a..a2d61705e6 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit bfeece324a03a3a5f25137bf3f8c66d5ed6103d8 +Subproject commit a2d61705e6f75f74b31154f9ae74e4e3166376ca From 1ffeefe93be137a03bb3a01120a0c829dbce1e98 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 18 Nov 2024 16:47:17 +0000 Subject: [PATCH 07/40] update lockfile --- yarn.lock | 273 ++++++++++++++++++++++++++---------------------------- 1 file changed, 133 insertions(+), 140 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7cdba96ec8..0fa0e00436 100644 --- a/yarn.lock +++ b/yarn.lock @@ -757,7 +757,7 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/identity@4.2.1": +"@azure/identity@4.2.1", "@azure/identity@^3.4.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -777,26 +777,6 @@ stoppable "^1.1.0" tslib "^2.2.0" -"@azure/identity@^3.4.1": - version "3.4.2" - resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-3.4.2.tgz#6b01724c9caac7cadab6b63c76584345bda8e2de" - integrity sha512-0q5DL4uyR0EZ4RXQKD8MadGH6zTIcloUoS/RVbCpNpej4pwte0xpqYxk8K97Py2RiuUvI7F4GXpoT4046VfufA== - dependencies: - "@azure/abort-controller" "^1.0.0" - "@azure/core-auth" "^1.5.0" - "@azure/core-client" "^1.4.0" - "@azure/core-rest-pipeline" "^1.1.0" - "@azure/core-tracing" "^1.0.0" - "@azure/core-util" "^1.6.1" - "@azure/logger" "^1.0.0" - "@azure/msal-browser" "^3.5.0" - "@azure/msal-node" "^2.5.1" - events "^3.0.0" - jws "^4.0.0" - open "^8.0.0" - stoppable "^1.1.0" - tslib "^2.2.0" - "@azure/keyvault-keys@^4.4.0": version "4.7.1" resolved "https://registry.yarnpkg.com/@azure/keyvault-keys/-/keyvault-keys-4.7.1.tgz#c35415610ca5301f92e2ad7b30fd569609d4b32d" @@ -821,7 +801,7 @@ dependencies: tslib "^2.2.0" -"@azure/msal-browser@^3.11.1", "@azure/msal-browser@^3.5.0": +"@azure/msal-browser@^3.11.1": version "3.27.0" resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.27.0.tgz#b6f02f73c8e102d3f115009b4677539fb173fe2b" integrity sha512-+b4ZKSD8+vslCtVRVetkegEhOFMLP3rxDWJY212ct+2r6jVg6OSQKc1Qz3kCoXo0FgwaXkb+76TMZfpHp8QtgA== @@ -833,7 +813,7 @@ resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.16.0.tgz#f3470fcaec788dbe50859952cd499340bda23d7a" integrity sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA== -"@azure/msal-node@^2.5.1", "@azure/msal-node@^2.9.2": +"@azure/msal-node@^2.9.2": version "2.16.1" resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.16.1.tgz#89828832e8e6c8a88cecc4ef6d8d4e4352116b77" integrity sha512-1NEFpTmMMT2A7RnZuvRl/hUmJU+GLPjh+ShyIqPktG2PvSd2yvPnzGd/BxIBAAvJG5nr9lH4oYcQXepDbaE7fg== @@ -2064,6 +2044,44 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@budibase/backend-core@3.2.5": + version "0.0.0" + dependencies: + "@budibase/nano" "10.1.5" + "@budibase/pouchdb-replication-stream" "1.2.11" + "@budibase/shared-core" "0.0.0" + "@budibase/types" "0.0.0" + aws-cloudfront-sign "3.0.2" + aws-sdk "2.1030.0" + bcrypt "5.1.0" + bcryptjs "2.4.3" + bull "4.10.1" + correlation-id "4.0.0" + dd-trace "5.23.0" + dotenv "16.0.1" + ioredis "5.3.2" + joi "17.6.0" + jsonwebtoken "9.0.2" + knex "2.4.2" + koa-passport "^6.0.0" + koa-pino-logger "4.0.0" + lodash "4.17.21" + node-fetch "2.6.7" + passport-google-oauth "2.0.0" + passport-local "1.0.0" + passport-oauth2-refresh "^2.1.0" + pino "8.11.0" + pino-http "8.3.3" + posthog-node "4.0.1" + pouchdb "9.0.0" + pouchdb-find "9.0.0" + redlock "4.2.0" + rotating-file-stream "3.1.0" + sanitize-s3-objectkey "0.0.1" + semver "^7.5.4" + tar-fs "2.1.1" + uuid "^8.3.2" + "@budibase/handlebars-helpers@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77" @@ -2106,6 +2124,47 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" +"@budibase/pro@npm:@budibase/pro@latest": + version "3.2.5" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.5.tgz#7d58aca194e2cd23f976ff0241f022aabc62daa4" + integrity sha512-E+P0M4p0hj/FVx2lUmqlXPskqjHCor4RKoBL9dE+wiaIr3PMojnIsy5bxU8z7x2gQrpEp/WvJRo0A6KRPdW6mA== + dependencies: + "@anthropic-ai/sdk" "^0.27.3" + "@budibase/backend-core" "3.2.5" + "@budibase/shared-core" "3.2.5" + "@budibase/string-templates" "3.2.5" + "@budibase/types" "3.2.5" + "@koa/router" "8.0.8" + bull "4.10.1" + dd-trace "5.2.0" + joi "17.6.0" + jsonwebtoken "9.0.2" + lru-cache "^7.14.1" + memorystream "^0.3.1" + node-fetch "2.6.7" + openai "4.59.0" + scim-patch "^0.8.1" + scim2-parse-filter "^0.2.8" + +"@budibase/shared-core@3.2.5": + version "0.0.0" + dependencies: + "@budibase/types" "0.0.0" + cron-validate "1.4.5" + +"@budibase/string-templates@3.2.5": + version "0.0.0" + dependencies: + "@budibase/handlebars-helpers" "^0.13.2" + dayjs "^1.10.8" + handlebars "^4.7.8" + lodash.clonedeep "^4.5.0" + +"@budibase/types@3.2.5": + version "0.0.0" + dependencies: + scim-patch "^0.8.1" + "@bull-board/api@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3" @@ -3226,6 +3285,18 @@ koa-compose "^4.1.0" path-to-regexp "^6.3.0" +"@koa/router@8.0.8": + version "8.0.8" + resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.8.tgz#95f32d11373d03d89dcb63fabe9ac6f471095236" + integrity sha512-FnT93N4NUehnXr+juupDmG2yfi0JnWdCmNEuIXpCG4TtG+9xvtrLambBH3RclycopVUOEYAim2lydiNBI7IRVg== + dependencies: + debug "^4.1.1" + http-errors "^1.7.3" + koa-compose "^4.1.0" + methods "^1.1.2" + path-to-regexp "1.x" + urijs "^1.19.2" + "@lerna/child-process@7.4.2": version "7.4.2" resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-7.4.2.tgz#a2fd013ac2150dc288270d3e0d0b850c06bec511" @@ -6924,23 +6995,7 @@ aws-sdk@2.1030.0: uuid "3.3.2" xml2js "0.4.19" -axios@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" - integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - -axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.5.0, axios@^1.6.2: +axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.5.0, axios@^1.6.2: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -10545,14 +10600,7 @@ fast-url-parser@^1.1.3: dependencies: punycode "^1.3.2" -fast-xml-parser@4.2.5: - version "4.2.5" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" - integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== - dependencies: - strnum "^1.0.5" - -fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: +fast-xml-parser@4.2.5, fast-xml-parser@4.4.1, fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: version "4.4.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== @@ -10782,7 +10830,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: +follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -11796,12 +11844,7 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== - -http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -12284,11 +12327,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -12738,6 +12776,11 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -13599,14 +13642,7 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@^3.0.2, kind-of@^3.1.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== - dependencies: - is-buffer "^1.1.5" - -kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -15187,7 +15223,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@^1.5.2: +msgpackr@1.10.1, msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -15381,27 +15417,13 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" -node-fetch@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" - integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== - dependencies: - whatwg-url "^5.0.0" - -node-fetch@^2.6.9, node-fetch@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - node-forge@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" @@ -16485,15 +16507,7 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" - integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - -passport@^0.6.0: +passport@0.6.0, passport@^0.4.0, passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -16548,6 +16562,13 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-to-regexp@1.x: + version "1.9.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" + integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== + dependencies: + isarray "0.0.1" + path-to-regexp@^0.1.10, path-to-regexp@^0.1.2: version "0.1.11" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.11.tgz#a527e662c89efc4646dbfa8100bf3e847e495761" @@ -18757,33 +18778,13 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: +"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.4, semver@^7.6.0: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== - -semver@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" - integrity sha512-abLdIKCosKfpnmhS52NCTjO4RiLspDfsn37prjzGrp9im5DPJOgh82Os92vtwGh6XdQryKI/7SREZnV+aqiXrA== - seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -20268,7 +20269,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: +tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -20764,6 +20765,14 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unset-value@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" + integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== + dependencies: + has-value "^2.0.2" + isobject "^4.0.0" + untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -20814,6 +20823,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urijs@^1.19.2: + version "1.19.11" + resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" + integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== + url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -21445,26 +21459,10 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== - dependencies: - sax ">=0.6.0" - xmlbuilder "~9.0.1" - -xml2js@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" - integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - -xml2js@^0.4.19, xml2js@^0.4.5: - version "0.4.23" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" - integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== +xml2js@0.4.19, xml2js@0.5.0, xml2js@0.6.2, xml2js@^0.4.19, xml2js@^0.4.5: + version "0.6.2" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" + integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== dependencies: sax ">=0.6.0" xmlbuilder "~11.0.0" @@ -21474,11 +21472,6 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== -xmlbuilder@~9.0.1: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ== - xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" From f25dd387b13bdece0ba134ceffa125917717259f Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 18 Nov 2024 16:56:11 +0000 Subject: [PATCH 08/40] Converting one test case to try using describe directly. --- .../server/src/api/routes/tests/row.spec.ts | 6153 ++++++++--------- .../src/integrations/tests/utils/index.ts | 60 +- 2 files changed, 3097 insertions(+), 3116 deletions(-) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index 5bdd341beb..2eb7c45e58 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -3,6 +3,7 @@ import * as setup from "./utilities" import { DatabaseName, datasourceDescribe, + datasourceProps, } from "../../../integrations/tests/utils" import tk from "timekeeper" @@ -85,310 +86,618 @@ function encodeJS(binding: string) { return `{{ js "${Buffer.from(binding).toString("base64")}"}}` } -datasourceDescribe( - { name: "/rows (%s)", exclude: [DatabaseName.MONGODB] }, - ({ config, dsProvider, isInternal, isMSSQL, isOracle }) => { - let table: Table - let datasource: Datasource | undefined - let client: Knex | undefined +const databases = datasourceDescribe({ exclude: [DatabaseName.MONGODB] }) - beforeAll(async () => { - const ds = await dsProvider() - datasource = ds.datasource - client = ds.client - }) +describe.each(databases)("/rows (%s)", dbName => { + const { config, dsProvider, isInternal, isMSSQL, isOracle } = + datasourceProps(dbName) + let table: Table + let datasource: Datasource | undefined + let client: Knex | undefined - afterAll(async () => { - setup.afterAll() - }) + beforeAll(async () => { + const ds = await dsProvider() + datasource = ds.datasource + client = ds.client + }) - function saveTableRequest( - // We omit the name field here because it's generated in the function with a - // high likelihood to be unique. Tests should not have any reason to control - // the table name they're writing to. - ...overrides: Partial>[] - ): SaveTableRequest { - const defaultSchema: TableSchema = { - id: { - type: FieldType.NUMBER, - name: "id", - autocolumn: true, - constraints: { - presence: true, - }, + afterAll(async () => { + setup.afterAll() + }) + + function saveTableRequest( + // We omit the name field here because it's generated in the function with a + // high likelihood to be unique. Tests should not have any reason to control + // the table name they're writing to. + ...overrides: Partial>[] + ): SaveTableRequest { + const defaultSchema: TableSchema = { + id: { + type: FieldType.NUMBER, + name: "id", + autocolumn: true, + constraints: { + presence: true, }, - } - - for (const override of overrides) { - if (override.primary) { - delete defaultSchema.id - } - } - - const req: SaveTableRequest = { - name: uuid.v4().substring(0, 10), - type: "table", - sourceType: datasource - ? TableSourceType.EXTERNAL - : TableSourceType.INTERNAL, - sourceId: datasource ? datasource._id! : INTERNAL_TABLE_SOURCE_ID, - primary: ["id"], - schema: defaultSchema, - } - const merged = merge(req, ...overrides) - return merged + }, } - function defaultTable( - // We omit the name field here because it's generated in the function with a - // high likelihood to be unique. Tests should not have any reason to control - // the table name they're writing to. - ...overrides: Partial>[] - ): SaveTableRequest { - return saveTableRequest( + for (const override of overrides) { + if (override.primary) { + delete defaultSchema.id + } + } + + const req: SaveTableRequest = { + name: uuid.v4().substring(0, 10), + type: "table", + sourceType: datasource + ? TableSourceType.EXTERNAL + : TableSourceType.INTERNAL, + sourceId: datasource ? datasource._id! : INTERNAL_TABLE_SOURCE_ID, + primary: ["id"], + schema: defaultSchema, + } + const merged = merge(req, ...overrides) + return merged + } + + function defaultTable( + // We omit the name field here because it's generated in the function with a + // high likelihood to be unique. Tests should not have any reason to control + // the table name they're writing to. + ...overrides: Partial>[] + ): SaveTableRequest { + return saveTableRequest( + { + primaryDisplay: "name", + schema: { + name: { + type: FieldType.STRING, + name: "name", + constraints: { + type: "string", + }, + }, + description: { + type: FieldType.STRING, + name: "description", + constraints: { + type: "string", + }, + }, + }, + }, + ...overrides + ) + } + + beforeEach(async () => { + mocks.licenses.useCloudFree() + }) + + const getRowUsage = async () => { + const { total } = await config.doInContext(undefined, () => + quotas.getCurrentUsageValues(QuotaUsageType.STATIC, StaticQuotaName.ROWS) + ) + return total + } + + const assertRowUsage = async (expected: number) => { + const usage = await getRowUsage() + + // Because our quota tracking is not perfect, we allow a 10% margin of + // error. This is to account for the fact that parallel writes can result + // in some quota updates getting lost. We don't have any need to solve this + // right now, so we just allow for some error. + if (expected === 0) { + expect(usage).toEqual(0) + return + } + expect(usage).toBeGreaterThan(expected * 0.9) + expect(usage).toBeLessThan(expected * 1.1) + } + + const defaultRowFields = isInternal + ? { + type: "row", + createdAt: timestamp, + updatedAt: timestamp, + } + : undefined + + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) + }) + + describe("create", () => { + it("creates a new row successfully", async () => { + const rowUsage = await getRowUsage() + const row = await config.api.row.save(table._id!, { + name: "Test Contact", + }) + expect(row.name).toEqual("Test Contact") + expect(row._rev).toBeDefined() + await assertRowUsage(isInternal ? rowUsage + 1 : rowUsage) + }) + + it("fails to create a row for a table that does not exist", async () => { + const rowUsage = await getRowUsage() + await config.api.row.save("1234567", {}, { status: 404 }) + await assertRowUsage(rowUsage) + }) + + it("fails to create a row if required fields are missing", async () => { + const rowUsage = await getRowUsage() + const table = await config.api.table.save( + saveTableRequest({ + schema: { + required: { + type: FieldType.STRING, + name: "required", + constraints: { + type: "string", + presence: true, + }, + }, + }, + }) + ) + await config.api.row.save( + table._id!, + {}, { - primaryDisplay: "name", + status: 500, + body: { + validationErrors: { + required: ["can't be blank"], + }, + }, + } + ) + await assertRowUsage(rowUsage) + }) + + isInternal && + it("increment row autoId per create row request", async () => { + const rowUsage = await getRowUsage() + + const newTable = await config.api.table.save( + saveTableRequest({ + schema: { + "Row ID": { + name: "Row ID", + type: FieldType.NUMBER, + subtype: AutoFieldSubType.AUTO_ID, + icon: "ri-magic-line", + autocolumn: true, + constraints: { + type: "number", + presence: true, + numericality: { + greaterThanOrEqualTo: "", + lessThanOrEqualTo: "", + }, + }, + }, + }, + }) + ) + + let previousId = 0 + for (let i = 0; i < 10; i++) { + const row = await config.api.row.save(newTable._id!, {}) + expect(row["Row ID"]).toBeGreaterThan(previousId) + previousId = row["Row ID"] + } + await assertRowUsage(isInternal ? rowUsage + 10 : rowUsage) + }) + + isInternal && + it("should increment auto ID correctly when creating rows in parallel", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + "Row ID": { + name: "Row ID", + type: FieldType.NUMBER, + subtype: AutoFieldSubType.AUTO_ID, + icon: "ri-magic-line", + autocolumn: true, + constraints: { + type: "number", + presence: true, + numericality: { + greaterThanOrEqualTo: "", + lessThanOrEqualTo: "", + }, + }, + }, + }, + }) + ) + + const sequence = Array(50) + .fill(0) + .map((_, i) => i + 1) + + // This block of code is simulating users creating auto ID rows at the + // same time. It's expected that this operation will sometimes return + // a document conflict error (409), but the idea is to retry in those + // situations. The code below does this a large number of times with + // small, random delays between them to try and get through the list + // as quickly as possible. + await Promise.all( + sequence.map(async () => { + const attempts = 30 + for (let attempt = 0; attempt < attempts; attempt++) { + try { + await config.api.row.save(table._id!, {}) + return + } catch (e) { + await new Promise(r => setTimeout(r, Math.random() * 50)) + } + } + throw new Error(`Failed to create row after ${attempts} attempts`) + }) + ) + + const rows = await config.api.row.fetch(table._id!) + expect(rows).toHaveLength(50) + + // The main purpose of this test is to ensure that even under pressure, + // we maintain data integrity. An auto ID column should hand out + // monotonically increasing unique integers no matter what. + const ids = rows.map(r => r["Row ID"]) + expect(ids).toEqual(expect.arrayContaining(sequence)) + }) + + isInternal && + it("doesn't allow creating in user table", async () => { + const response = await config.api.row.save( + InternalTable.USER_METADATA, + { + firstName: "Joe", + lastName: "Joe", + email: "joe@joe.com", + roles: {}, + }, + { status: 400 } + ) + expect(response.message).toBe("Cannot create new user entry.") + }) + + it("should not mis-parse date string out of JSON", async () => { + const table = await config.api.table.save( + saveTableRequest({ schema: { name: { type: FieldType.STRING, name: "name", - constraints: { - type: "string", - }, - }, - description: { - type: FieldType.STRING, - name: "description", - constraints: { - type: "string", - }, }, }, - }, - ...overrides - ) - } - - beforeEach(async () => { - mocks.licenses.useCloudFree() - }) - - const getRowUsage = async () => { - const { total } = await config.doInContext(undefined, () => - quotas.getCurrentUsageValues( - QuotaUsageType.STATIC, - StaticQuotaName.ROWS - ) - ) - return total - } - - const assertRowUsage = async (expected: number) => { - const usage = await getRowUsage() - - // Because our quota tracking is not perfect, we allow a 10% margin of - // error. This is to account for the fact that parallel writes can result - // in some quota updates getting lost. We don't have any need to solve this - // right now, so we just allow for some error. - if (expected === 0) { - expect(usage).toEqual(0) - return - } - expect(usage).toBeGreaterThan(expected * 0.9) - expect(usage).toBeLessThan(expected * 1.1) - } - - const defaultRowFields = isInternal - ? { - type: "row", - createdAt: timestamp, - updatedAt: timestamp, - } - : undefined - - beforeAll(async () => { - table = await config.api.table.save(defaultTable()) - }) - - describe("create", () => { - it("creates a new row successfully", async () => { - const rowUsage = await getRowUsage() - const row = await config.api.row.save(table._id!, { - name: "Test Contact", }) - expect(row.name).toEqual("Test Contact") - expect(row._rev).toBeDefined() - await assertRowUsage(isInternal ? rowUsage + 1 : rowUsage) + ) + + const row = await config.api.row.save(table._id!, { + name: `{ "foo": "2023-01-26T11:48:57.000Z" }`, }) - it("fails to create a row for a table that does not exist", async () => { - const rowUsage = await getRowUsage() - await config.api.row.save("1234567", {}, { status: 404 }) - await assertRowUsage(rowUsage) - }) + expect(row.name).toEqual(`{ "foo": "2023-01-26T11:48:57.000Z" }`) + }) - it("fails to create a row if required fields are missing", async () => { - const rowUsage = await getRowUsage() - const table = await config.api.table.save( - saveTableRequest({ - schema: { - required: { - type: FieldType.STRING, - name: "required", - constraints: { - type: "string", - presence: true, - }, - }, - }, - }) - ) - await config.api.row.save( - table._id!, - {}, - { - status: 500, - body: { - validationErrors: { - required: ["can't be blank"], - }, - }, - } - ) - await assertRowUsage(rowUsage) - }) + describe("default values", () => { + let table: Table - isInternal && - it("increment row autoId per create row request", async () => { - const rowUsage = await getRowUsage() - - const newTable = await config.api.table.save( + describe("string column", () => { + beforeAll(async () => { + table = await config.api.table.save( saveTableRequest({ schema: { - "Row ID": { - name: "Row ID", - type: FieldType.NUMBER, - subtype: AutoFieldSubType.AUTO_ID, - icon: "ri-magic-line", - autocolumn: true, - constraints: { - type: "number", - presence: true, - numericality: { - greaterThanOrEqualTo: "", - lessThanOrEqualTo: "", - }, - }, + description: { + name: "description", + type: FieldType.STRING, + default: "default description", }, }, }) ) - - let previousId = 0 - for (let i = 0; i < 10; i++) { - const row = await config.api.row.save(newTable._id!, {}) - expect(row["Row ID"]).toBeGreaterThan(previousId) - previousId = row["Row ID"] - } - await assertRowUsage(isInternal ? rowUsage + 10 : rowUsage) }) - isInternal && - it("should increment auto ID correctly when creating rows in parallel", async () => { + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.description).toEqual("default description") + }) + + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + description: "specified description", + }) + expect(row.description).toEqual("specified description") + }) + + it("uses the default value if value is null", async () => { + const row = await config.api.row.save(table._id!, { + description: null, + }) + expect(row.description).toEqual("default description") + }) + + it("uses the default value if value is undefined", async () => { + const row = await config.api.row.save(table._id!, { + description: undefined, + }) + expect(row.description).toEqual("default description") + }) + }) + + describe("number column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + age: { + name: "age", + type: FieldType.NUMBER, + default: "25", + }, + }, + }) + ) + }) + + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.age).toEqual(25) + }) + + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + age: 30, + }) + expect(row.age).toEqual(30) + }) + }) + + describe("date column", () => { + it("creates a row with a default value successfully", async () => { const table = await config.api.table.save( saveTableRequest({ schema: { - "Row ID": { - name: "Row ID", - type: FieldType.NUMBER, - subtype: AutoFieldSubType.AUTO_ID, - icon: "ri-magic-line", - autocolumn: true, + date: { + name: "date", + type: FieldType.DATETIME, + default: "2023-01-26T11:48:57.000Z", + }, + }, + }) + ) + const row = await config.api.row.save(table._id!, {}) + expect(row.date).toEqual("2023-01-26T11:48:57.000Z") + }) + + it("gives an error if the default value is invalid", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + date: { + name: "date", + type: FieldType.DATETIME, + default: "invalid", + }, + }, + }) + ) + await config.api.row.save( + table._id!, + {}, + { + status: 400, + body: { + message: `Invalid default value for field 'date' - Invalid date value: "invalid"`, + }, + } + ) + }) + }) + + describe("options column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + status: { + name: "status", + type: FieldType.OPTIONS, + default: "requested", constraints: { - type: "number", - presence: true, - numericality: { - greaterThanOrEqualTo: "", - lessThanOrEqualTo: "", - }, + inclusion: ["requested", "approved"], }, }, }, }) ) - - const sequence = Array(50) - .fill(0) - .map((_, i) => i + 1) - - // This block of code is simulating users creating auto ID rows at the - // same time. It's expected that this operation will sometimes return - // a document conflict error (409), but the idea is to retry in those - // situations. The code below does this a large number of times with - // small, random delays between them to try and get through the list - // as quickly as possible. - await Promise.all( - sequence.map(async () => { - const attempts = 30 - for (let attempt = 0; attempt < attempts; attempt++) { - try { - await config.api.row.save(table._id!, {}) - return - } catch (e) { - await new Promise(r => setTimeout(r, Math.random() * 50)) - } - } - throw new Error(`Failed to create row after ${attempts} attempts`) - }) - ) - - const rows = await config.api.row.fetch(table._id!) - expect(rows).toHaveLength(50) - - // The main purpose of this test is to ensure that even under pressure, - // we maintain data integrity. An auto ID column should hand out - // monotonically increasing unique integers no matter what. - const ids = rows.map(r => r["Row ID"]) - expect(ids).toEqual(expect.arrayContaining(sequence)) }) - isInternal && - it("doesn't allow creating in user table", async () => { - const response = await config.api.row.save( - InternalTable.USER_METADATA, - { - firstName: "Joe", - lastName: "Joe", - email: "joe@joe.com", - roles: {}, - }, - { status: 400 } - ) - expect(response.message).toBe("Cannot create new user entry.") + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.status).toEqual("requested") }) - it("should not mis-parse date string out of JSON", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - type: FieldType.STRING, - name: "name", - }, - }, + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + status: "approved", }) - ) - - const row = await config.api.row.save(table._id!, { - name: `{ "foo": "2023-01-26T11:48:57.000Z" }`, + expect(row.status).toEqual("approved") }) - - expect(row.name).toEqual(`{ "foo": "2023-01-26T11:48:57.000Z" }`) }) - describe("default values", () => { - let table: Table + describe("array column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + food: { + name: "food", + type: FieldType.ARRAY, + default: ["apple", "orange"], + constraints: { + type: JsonFieldSubType.ARRAY, + inclusion: ["apple", "orange", "banana"], + }, + }, + }, + }) + ) + }) + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.food).toEqual(["apple", "orange"]) + }) + + it("creates a new row with a default value when given an empty list", async () => { + const row = await config.api.row.save(table._id!, { food: [] }) + expect(row.food).toEqual(["apple", "orange"]) + }) + + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + food: ["orange"], + }) + expect(row.food).toEqual(["orange"]) + }) + + it("resets back to its default value when empty", async () => { + let row = await config.api.row.save(table._id!, { + food: ["orange"], + }) + row = await config.api.row.save(table._id!, { ...row, food: [] }) + expect(row.food).toEqual(["apple", "orange"]) + }) + }) + + describe("user column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + user: { + name: "user", + type: FieldType.BB_REFERENCE_SINGLE, + subtype: BBReferenceFieldSubType.USER, + default: "{{ [Current User]._id }}", + }, + }, + }) + ) + }) + + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.user._id).toEqual(config.getUser()._id) + }) + + it("does not use default value if value specified", async () => { + const id = `us_${utils.newid()}` + await config.createUser({ _id: id }) + const row = await config.api.row.save(table._id!, { + user: id, + }) + expect(row.user._id).toEqual(id) + }) + }) + + describe("multi-user column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + users: { + name: "users", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + default: ["{{ [Current User]._id }}"], + }, + }, + }) + ) + }) + + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.users).toHaveLength(1) + expect(row.users[0]._id).toEqual(config.getUser()._id) + }) + + it("does not use default value if value specified", async () => { + const id = `us_${utils.newid()}` + await config.createUser({ _id: id }) + const row = await config.api.row.save(table._id!, { + users: [id], + }) + expect(row.users).toHaveLength(1) + expect(row.users[0]._id).toEqual(id) + }) + }) + + describe("boolean column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + active: { + name: "active", + type: FieldType.BOOLEAN, + default: "true", + }, + }, + }) + ) + }) + + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.active).toEqual(true) + }) + + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + active: false, + }) + expect(row.active).toEqual(false) + }) + }) + + describe("bigint column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + bigNumber: { + name: "bigNumber", + type: FieldType.BIGINT, + default: "1234567890", + }, + }, + }) + ) + }) + + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.bigNumber).toEqual("1234567890") + }) + + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + bigNumber: "9876543210", + }) + expect(row.bigNumber).toEqual("9876543210") + }) + }) + + describe("bindings", () => { describe("string column", () => { beforeAll(async () => { table = await config.api.table.save( @@ -397,16 +706,18 @@ datasourceDescribe( description: { name: "description", type: FieldType.STRING, - default: "default description", + default: `{{ date now "YYYY-MM-DDTHH:mm:ss" }}`, }, }, }) ) }) - it("creates a new row with a default value successfully", async () => { + it("can use bindings in default values", async () => { const row = await config.api.row.save(table._id!, {}) - expect(row.description).toEqual("default description") + expect(row.description).toMatch( + /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/ + ) }) it("does not use default value if value specified", async () => { @@ -416,18 +727,38 @@ datasourceDescribe( expect(row.description).toEqual("specified description") }) - it("uses the default value if value is null", async () => { - const row = await config.api.row.save(table._id!, { - description: null, - }) - expect(row.description).toEqual("default description") + it("can bind the current user", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + user: { + name: "user", + type: FieldType.STRING, + default: `{{ [Current User]._id }}`, + }, + }, + }) + ) + const row = await config.api.row.save(table._id!, {}) + expect(row.user).toEqual(config.getUser()._id) }) - it("uses the default value if value is undefined", async () => { - const row = await config.api.row.save(table._id!, { - description: undefined, - }) - expect(row.description).toEqual("default description") + it("cannot access current user password", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + user: { + name: "user", + type: FieldType.STRING, + default: `{{ user.password }}`, + }, + }, + }) + ) + const row = await config.api.row.save(table._id!, {}) + // For some reason it's null for internal tables, and undefined for + // external. + expect(row.user == null).toBe(true) }) }) @@ -439,330 +770,19 @@ datasourceDescribe( age: { name: "age", type: FieldType.NUMBER, - default: "25", + default: `{{ sum 10 10 5 }}`, }, }, }) ) }) - it("creates a new row with a default value successfully", async () => { + it("can use bindings in default values", async () => { const row = await config.api.row.save(table._id!, {}) expect(row.age).toEqual(25) }) - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - age: 30, - }) - expect(row.age).toEqual(30) - }) - }) - - describe("date column", () => { - it("creates a row with a default value successfully", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - date: { - name: "date", - type: FieldType.DATETIME, - default: "2023-01-26T11:48:57.000Z", - }, - }, - }) - ) - const row = await config.api.row.save(table._id!, {}) - expect(row.date).toEqual("2023-01-26T11:48:57.000Z") - }) - - it("gives an error if the default value is invalid", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - date: { - name: "date", - type: FieldType.DATETIME, - default: "invalid", - }, - }, - }) - ) - await config.api.row.save( - table._id!, - {}, - { - status: 400, - body: { - message: `Invalid default value for field 'date' - Invalid date value: "invalid"`, - }, - } - ) - }) - }) - - describe("options column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - status: { - name: "status", - type: FieldType.OPTIONS, - default: "requested", - constraints: { - inclusion: ["requested", "approved"], - }, - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.status).toEqual("requested") - }) - - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - status: "approved", - }) - expect(row.status).toEqual("approved") - }) - }) - - describe("array column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - food: { - name: "food", - type: FieldType.ARRAY, - default: ["apple", "orange"], - constraints: { - type: JsonFieldSubType.ARRAY, - inclusion: ["apple", "orange", "banana"], - }, - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.food).toEqual(["apple", "orange"]) - }) - - it("creates a new row with a default value when given an empty list", async () => { - const row = await config.api.row.save(table._id!, { food: [] }) - expect(row.food).toEqual(["apple", "orange"]) - }) - - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - food: ["orange"], - }) - expect(row.food).toEqual(["orange"]) - }) - - it("resets back to its default value when empty", async () => { - let row = await config.api.row.save(table._id!, { - food: ["orange"], - }) - row = await config.api.row.save(table._id!, { ...row, food: [] }) - expect(row.food).toEqual(["apple", "orange"]) - }) - }) - - describe("user column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - user: { - name: "user", - type: FieldType.BB_REFERENCE_SINGLE, - subtype: BBReferenceFieldSubType.USER, - default: "{{ [Current User]._id }}", - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.user._id).toEqual(config.getUser()._id) - }) - - it("does not use default value if value specified", async () => { - const id = `us_${utils.newid()}` - await config.createUser({ _id: id }) - const row = await config.api.row.save(table._id!, { - user: id, - }) - expect(row.user._id).toEqual(id) - }) - }) - - describe("multi-user column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - users: { - name: "users", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - default: ["{{ [Current User]._id }}"], - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.users).toHaveLength(1) - expect(row.users[0]._id).toEqual(config.getUser()._id) - }) - - it("does not use default value if value specified", async () => { - const id = `us_${utils.newid()}` - await config.createUser({ _id: id }) - const row = await config.api.row.save(table._id!, { - users: [id], - }) - expect(row.users).toHaveLength(1) - expect(row.users[0]._id).toEqual(id) - }) - }) - - describe("boolean column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - active: { - name: "active", - type: FieldType.BOOLEAN, - default: "true", - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.active).toEqual(true) - }) - - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - active: false, - }) - expect(row.active).toEqual(false) - }) - }) - - describe("bigint column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - bigNumber: { - name: "bigNumber", - type: FieldType.BIGINT, - default: "1234567890", - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.bigNumber).toEqual("1234567890") - }) - - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - bigNumber: "9876543210", - }) - expect(row.bigNumber).toEqual("9876543210") - }) - }) - - describe("bindings", () => { - describe("string column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - description: { - name: "description", - type: FieldType.STRING, - default: `{{ date now "YYYY-MM-DDTHH:mm:ss" }}`, - }, - }, - }) - ) - }) - - it("can use bindings in default values", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.description).toMatch( - /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/ - ) - }) - - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - description: "specified description", - }) - expect(row.description).toEqual("specified description") - }) - - it("can bind the current user", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - user: { - name: "user", - type: FieldType.STRING, - default: `{{ [Current User]._id }}`, - }, - }, - }) - ) - const row = await config.api.row.save(table._id!, {}) - expect(row.user).toEqual(config.getUser()._id) - }) - - it("cannot access current user password", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - user: { - name: "user", - type: FieldType.STRING, - default: `{{ user.password }}`, - }, - }, - }) - ) - const row = await config.api.row.save(table._id!, {}) - // For some reason it's null for internal tables, and undefined for - // external. - expect(row.user == null).toBe(true) - }) - }) - - describe("number column", () => { + describe("invalid default value", () => { beforeAll(async () => { table = await config.api.table.save( saveTableRequest({ @@ -770,885 +790,907 @@ datasourceDescribe( age: { name: "age", type: FieldType.NUMBER, - default: `{{ sum 10 10 5 }}`, + default: `{{ capitalize "invalid" }}`, }, }, }) ) }) - it("can use bindings in default values", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.age).toEqual(25) - }) - - describe("invalid default value", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - age: { - name: "age", - type: FieldType.NUMBER, - default: `{{ capitalize "invalid" }}`, - }, - }, - }) - ) - }) - - it("throws an error when invalid default value", async () => { - await config.api.row.save( - table._id!, - {}, - { - status: 400, - body: { - message: - "Invalid default value for field 'age' - Invalid number value \"Invalid\"", - }, - } - ) - }) - }) - }) - }) - }) - - describe("relations to same table", () => { - let relatedRows: Row[] - - beforeAll(async () => { - const relatedTable = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - }, - }) - ) - const relatedTableId = relatedTable._id! - table = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - related1: { - type: FieldType.LINK, - name: "related1", - fieldName: "main1", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - related2: { - type: FieldType.LINK, - name: "related2", - fieldName: "main2", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - }, - }) - ) - relatedRows = await Promise.all([ - config.api.row.save(relatedTableId, { name: "foo" }), - config.api.row.save(relatedTableId, { name: "bar" }), - config.api.row.save(relatedTableId, { name: "baz" }), - config.api.row.save(relatedTableId, { name: "boo" }), - ]) - }) - - it("can create rows with both relationships", async () => { - const row = await config.api.row.save(table._id!, { - name: "test", - related1: [relatedRows[0]._id!], - related2: [relatedRows[1]._id!], - }) - - expect(row).toEqual( - expect.objectContaining({ - name: "test", - related1: [ + it("throws an error when invalid default value", async () => { + await config.api.row.save( + table._id!, + {}, { - _id: relatedRows[0]._id, - primaryDisplay: relatedRows[0].name, - }, - ], - related2: [ - { - _id: relatedRows[1]._id, - primaryDisplay: relatedRows[1].name, - }, - ], + status: 400, + body: { + message: + "Invalid default value for field 'age' - Invalid number value \"Invalid\"", + }, + } + ) }) - ) - }) - - it("can create rows with no relationships", async () => { - const row = await config.api.row.save(table._id!, { - name: "test", }) - - expect(row.related1).toBeUndefined() - expect(row.related2).toBeUndefined() - }) - - it("can create rows with only one relationships field", async () => { - const row = await config.api.row.save(table._id!, { - name: "test", - related1: [], - related2: [relatedRows[1]._id!], - }) - - expect(row).toEqual( - expect.objectContaining({ - name: "test", - related2: [ - { - _id: relatedRows[1]._id, - primaryDisplay: relatedRows[1].name, - }, - ], - }) - ) - expect(row.related1).toBeUndefined() }) }) }) - describe("get", () => { - it("reads an existing row successfully", async () => { - const existing = await config.api.row.save(table._id!, {}) - - const res = await config.api.row.get(table._id!, existing._id!) - - expect(res).toEqual({ - ...existing, - ...defaultRowFields, - }) - }) - - it("returns 404 when row does not exist", async () => { - const table = await config.api.table.save(defaultTable()) - await config.api.row.save(table._id!, {}) - await config.api.row.get(table._id!, "1234567", { - status: 404, - }) - }) - - isInternal && - it("can search row from user table", async () => { - const res = await config.api.row.get( - InternalTables.USER_METADATA, - config.userMetadataId! - ) - - expect(res).toEqual({ - ...config.getUser(), - _id: config.userMetadataId!, - _rev: expect.any(String), - roles: undefined, - roleId: "ADMIN", - tableId: InternalTables.USER_METADATA, - }) - }) - }) - - describe("fetch", () => { - it("fetches all rows for given tableId", async () => { - const table = await config.api.table.save(defaultTable()) - const rows = await Promise.all([ - config.api.row.save(table._id!, {}), - config.api.row.save(table._id!, {}), - ]) - - const res = await config.api.row.fetch(table._id!) - expect(res.map(r => r._id)).toEqual( - expect.arrayContaining(rows.map(r => r._id)) - ) - }) - - it("returns 404 when table does not exist", async () => { - await config.api.row.fetch("1234567", { status: 404 }) - }) - }) - - describe("update", () => { - it("updates an existing row successfully", async () => { - const existing = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() - - const res = await config.api.row.save(table._id!, { - _id: existing._id, - _rev: existing._rev, - name: "Updated Name", - }) - - expect(res.name).toEqual("Updated Name") - await assertRowUsage(rowUsage) - }) - - !isInternal && - it("can update a row on an external table with a primary key", async () => { - const tableName = uuid.v4().substring(0, 10) - await client!.schema.createTable(tableName, table => { - table.increments("id").primary() - table.string("name") - }) - - const res = await config.api.datasource.fetchSchema({ - datasourceId: datasource!._id!, - }) - const table = res.datasource.entities![tableName] - - const row = await config.api.row.save(table._id!, { - id: 1, - name: "Row 1", - }) - - const updatedRow = await config.api.row.save(table._id!, { - _id: row._id!, - name: "Row 1 Updated", - }) - - expect(updatedRow.name).toEqual("Row 1 Updated") - - const rows = await config.api.row.fetch(table._id!) - expect(rows).toHaveLength(1) - }) - - describe("relations to same table", () => { - let relatedRows: Row[] - - beforeAll(async () => { - const relatedTable = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - }, - }) - ) - const relatedTableId = relatedTable._id! - table = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - related1: { - type: FieldType.LINK, - name: "related1", - fieldName: "main1", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - related2: { - type: FieldType.LINK, - name: "related2", - fieldName: "main2", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - }, - }) - ) - relatedRows = await Promise.all([ - config.api.row.save(relatedTableId, { name: "foo" }), - config.api.row.save(relatedTableId, { name: "bar" }), - config.api.row.save(relatedTableId, { name: "baz" }), - config.api.row.save(relatedTableId, { name: "boo" }), - ]) - }) - - it("can edit rows with both relationships", async () => { - let row = await config.api.row.save(table._id!, { - name: "test", - related1: [relatedRows[0]._id!], - related2: [relatedRows[1]._id!], - }) - - row = await config.api.row.save(table._id!, { - ...row, - related1: [relatedRows[0]._id!, relatedRows[1]._id!], - related2: [relatedRows[2]._id!], - }) - - expect(row).toEqual( - expect.objectContaining({ - name: "test", - related1: expect.arrayContaining([ - { - _id: relatedRows[0]._id, - primaryDisplay: relatedRows[0].name, - }, - { - _id: relatedRows[1]._id, - primaryDisplay: relatedRows[1].name, - }, - ]), - related2: [ - { - _id: relatedRows[2]._id, - primaryDisplay: relatedRows[2].name, - }, - ], - }) - ) - }) - - it("can drop existing relationship", async () => { - let row = await config.api.row.save(table._id!, { - name: "test", - related1: [relatedRows[0]._id!], - related2: [relatedRows[1]._id!], - }) - - row = await config.api.row.save(table._id!, { - ...row, - related1: [], - related2: [relatedRows[2]._id!], - }) - - expect(row).toEqual( - expect.objectContaining({ - name: "test", - related2: [ - { - _id: relatedRows[2]._id, - primaryDisplay: relatedRows[2].name, - }, - ], - }) - ) - expect(row.related1).toBeUndefined() - }) - - it("can drop both relationships", async () => { - let row = await config.api.row.save(table._id!, { - name: "test", - related1: [relatedRows[0]._id!], - related2: [relatedRows[1]._id!], - }) - - row = await config.api.row.save(table._id!, { - ...row, - related1: [], - related2: [], - }) - - expect(row).toEqual( - expect.objectContaining({ - name: "test", - }) - ) - expect(row.related1).toBeUndefined() - expect(row.related2).toBeUndefined() - }) - }) - }) - - describe("patch", () => { - let otherTable: Table + describe("relations to same table", () => { + let relatedRows: Row[] beforeAll(async () => { - table = await config.api.table.save(defaultTable()) - otherTable = await config.api.table.save( + const relatedTable = await config.api.table.save( defaultTable({ schema: { - relationship: { - name: "relationship", - relationshipType: RelationshipType.ONE_TO_MANY, + name: { name: "name", type: FieldType.STRING }, + }, + }) + ) + const relatedTableId = relatedTable._id! + table = await config.api.table.save( + defaultTable({ + schema: { + name: { name: "name", type: FieldType.STRING }, + related1: { type: FieldType.LINK, - tableId: table._id!, - fieldName: "relationship", + name: "related1", + fieldName: "main1", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, + }, + related2: { + type: FieldType.LINK, + name: "related2", + fieldName: "main2", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, }, }, }) ) + relatedRows = await Promise.all([ + config.api.row.save(relatedTableId, { name: "foo" }), + config.api.row.save(relatedTableId, { name: "bar" }), + config.api.row.save(relatedTableId, { name: "baz" }), + config.api.row.save(relatedTableId, { name: "boo" }), + ]) }) - it("should update only the fields that are supplied", async () => { - const existing = await config.api.row.save(table._id!, {}) + it("can create rows with both relationships", async () => { + const row = await config.api.row.save(table._id!, { + name: "test", + related1: [relatedRows[0]._id!], + related2: [relatedRows[1]._id!], + }) - const rowUsage = await getRowUsage() + expect(row).toEqual( + expect.objectContaining({ + name: "test", + related1: [ + { + _id: relatedRows[0]._id, + primaryDisplay: relatedRows[0].name, + }, + ], + related2: [ + { + _id: relatedRows[1]._id, + primaryDisplay: relatedRows[1].name, + }, + ], + }) + ) + }) + + it("can create rows with no relationships", async () => { + const row = await config.api.row.save(table._id!, { + name: "test", + }) + + expect(row.related1).toBeUndefined() + expect(row.related2).toBeUndefined() + }) + + it("can create rows with only one relationships field", async () => { + const row = await config.api.row.save(table._id!, { + name: "test", + related1: [], + related2: [relatedRows[1]._id!], + }) + + expect(row).toEqual( + expect.objectContaining({ + name: "test", + related2: [ + { + _id: relatedRows[1]._id, + primaryDisplay: relatedRows[1].name, + }, + ], + }) + ) + expect(row.related1).toBeUndefined() + }) + }) + }) + + describe("get", () => { + it("reads an existing row successfully", async () => { + const existing = await config.api.row.save(table._id!, {}) + + const res = await config.api.row.get(table._id!, existing._id!) + + expect(res).toEqual({ + ...existing, + ...defaultRowFields, + }) + }) + + it("returns 404 when row does not exist", async () => { + const table = await config.api.table.save(defaultTable()) + await config.api.row.save(table._id!, {}) + await config.api.row.get(table._id!, "1234567", { + status: 404, + }) + }) + + isInternal && + it("can search row from user table", async () => { + const res = await config.api.row.get( + InternalTables.USER_METADATA, + config.userMetadataId! + ) + + expect(res).toEqual({ + ...config.getUser(), + _id: config.userMetadataId!, + _rev: expect.any(String), + roles: undefined, + roleId: "ADMIN", + tableId: InternalTables.USER_METADATA, + }) + }) + }) + + describe("fetch", () => { + it("fetches all rows for given tableId", async () => { + const table = await config.api.table.save(defaultTable()) + const rows = await Promise.all([ + config.api.row.save(table._id!, {}), + config.api.row.save(table._id!, {}), + ]) + + const res = await config.api.row.fetch(table._id!) + expect(res.map(r => r._id)).toEqual( + expect.arrayContaining(rows.map(r => r._id)) + ) + }) + + it("returns 404 when table does not exist", async () => { + await config.api.row.fetch("1234567", { status: 404 }) + }) + }) + + describe("update", () => { + it("updates an existing row successfully", async () => { + const existing = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + + const res = await config.api.row.save(table._id!, { + _id: existing._id, + _rev: existing._rev, + name: "Updated Name", + }) + + expect(res.name).toEqual("Updated Name") + await assertRowUsage(rowUsage) + }) + + !isInternal && + it("can update a row on an external table with a primary key", async () => { + const tableName = uuid.v4().substring(0, 10) + await client!.schema.createTable(tableName, table => { + table.increments("id").primary() + table.string("name") + }) + + const res = await config.api.datasource.fetchSchema({ + datasourceId: datasource!._id!, + }) + const table = res.datasource.entities![tableName] + + const row = await config.api.row.save(table._id!, { + id: 1, + name: "Row 1", + }) + + const updatedRow = await config.api.row.save(table._id!, { + _id: row._id!, + name: "Row 1 Updated", + }) + + expect(updatedRow.name).toEqual("Row 1 Updated") + + const rows = await config.api.row.fetch(table._id!) + expect(rows).toHaveLength(1) + }) + + describe("relations to same table", () => { + let relatedRows: Row[] + + beforeAll(async () => { + const relatedTable = await config.api.table.save( + defaultTable({ + schema: { + name: { name: "name", type: FieldType.STRING }, + }, + }) + ) + const relatedTableId = relatedTable._id! + table = await config.api.table.save( + defaultTable({ + schema: { + name: { name: "name", type: FieldType.STRING }, + related1: { + type: FieldType.LINK, + name: "related1", + fieldName: "main1", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, + }, + related2: { + type: FieldType.LINK, + name: "related2", + fieldName: "main2", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, + }, + }, + }) + ) + relatedRows = await Promise.all([ + config.api.row.save(relatedTableId, { name: "foo" }), + config.api.row.save(relatedTableId, { name: "bar" }), + config.api.row.save(relatedTableId, { name: "baz" }), + config.api.row.save(relatedTableId, { name: "boo" }), + ]) + }) + + it("can edit rows with both relationships", async () => { + let row = await config.api.row.save(table._id!, { + name: "test", + related1: [relatedRows[0]._id!], + related2: [relatedRows[1]._id!], + }) + + row = await config.api.row.save(table._id!, { + ...row, + related1: [relatedRows[0]._id!, relatedRows[1]._id!], + related2: [relatedRows[2]._id!], + }) + + expect(row).toEqual( + expect.objectContaining({ + name: "test", + related1: expect.arrayContaining([ + { + _id: relatedRows[0]._id, + primaryDisplay: relatedRows[0].name, + }, + { + _id: relatedRows[1]._id, + primaryDisplay: relatedRows[1].name, + }, + ]), + related2: [ + { + _id: relatedRows[2]._id, + primaryDisplay: relatedRows[2].name, + }, + ], + }) + ) + }) + + it("can drop existing relationship", async () => { + let row = await config.api.row.save(table._id!, { + name: "test", + related1: [relatedRows[0]._id!], + related2: [relatedRows[1]._id!], + }) + + row = await config.api.row.save(table._id!, { + ...row, + related1: [], + related2: [relatedRows[2]._id!], + }) + + expect(row).toEqual( + expect.objectContaining({ + name: "test", + related2: [ + { + _id: relatedRows[2]._id, + primaryDisplay: relatedRows[2].name, + }, + ], + }) + ) + expect(row.related1).toBeUndefined() + }) + + it("can drop both relationships", async () => { + let row = await config.api.row.save(table._id!, { + name: "test", + related1: [relatedRows[0]._id!], + related2: [relatedRows[1]._id!], + }) + + row = await config.api.row.save(table._id!, { + ...row, + related1: [], + related2: [], + }) + + expect(row).toEqual( + expect.objectContaining({ + name: "test", + }) + ) + expect(row.related1).toBeUndefined() + expect(row.related2).toBeUndefined() + }) + }) + }) + + describe("patch", () => { + let otherTable: Table + + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) + otherTable = await config.api.table.save( + defaultTable({ + schema: { + relationship: { + name: "relationship", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: table._id!, + fieldName: "relationship", + }, + }, + }) + ) + }) + + it("should update only the fields that are supplied", async () => { + const existing = await config.api.row.save(table._id!, {}) + + const rowUsage = await getRowUsage() + + const row = await config.api.row.patch(table._id!, { + _id: existing._id!, + _rev: existing._rev!, + tableId: table._id!, + name: "Updated Name", + }) + + expect(row.name).toEqual("Updated Name") + expect(row.description).toEqual(existing.description) + + const savedRow = await config.api.row.get(table._id!, row._id!) + + expect(savedRow.description).toEqual(existing.description) + expect(savedRow.name).toEqual("Updated Name") + await assertRowUsage(rowUsage) + }) + + it("should update only the fields that are supplied and emit the correct oldRow", async () => { + let beforeRow = await config.api.row.save(table._id!, { + name: "test", + description: "test", + }) + const opts = { + name: "row:update", + matchFn: (event: UpdatedRowEventEmitter) => + event.row._id === beforeRow._id, + } + const event = await waitForEvent(opts, async () => { + await config.api.row.patch(table._id!, { + _id: beforeRow._id!, + _rev: beforeRow._rev!, + tableId: table._id!, + name: "Updated Name", + }) + }) + + expect(event.oldRow).toBeDefined() + expect(event.oldRow.name).toEqual("test") + expect(event.row.name).toEqual("Updated Name") + expect(event.oldRow.description).toEqual(beforeRow.description) + expect(event.row.description).toEqual(beforeRow.description) + }) + + it("should throw an error when given improper types", async () => { + const existing = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + + await config.api.row.patch( + table._id!, + { + _id: existing._id!, + _rev: existing._rev!, + tableId: table._id!, + name: 1, + }, + { status: 400 } + ) + + await assertRowUsage(rowUsage) + }) + + it("should not overwrite links if those links are not set", async () => { + let linkField: FieldSchema = { + type: FieldType.LINK, + name: "", + fieldName: "", + constraints: { + type: "array", + presence: false, + }, + relationshipType: RelationshipType.ONE_TO_MANY, + tableId: InternalTable.USER_METADATA, + } + + let table = await config.api.table.save({ + name: "TestTable", + type: "table", + sourceType: TableSourceType.INTERNAL, + sourceId: INTERNAL_TABLE_SOURCE_ID, + schema: { + user1: { ...linkField, name: "user1", fieldName: "user1" }, + user2: { ...linkField, name: "user2", fieldName: "user2" }, + }, + }) + + let user1 = await config.createUser() + let user2 = await config.createUser() + + let row = await config.api.row.save(table._id!, { + user1: [{ _id: user1._id }], + user2: [{ _id: user2._id }], + }) + + let getResp = await config.api.row.get(table._id!, row._id!) + expect(getResp.user1[0]._id).toEqual(user1._id) + expect(getResp.user2[0]._id).toEqual(user2._id) + + let patchResp = await config.api.row.patch(table._id!, { + _id: row._id!, + _rev: row._rev!, + tableId: table._id!, + user1: [{ _id: user2._id }], + }) + expect(patchResp.user1[0]._id).toEqual(user2._id) + expect(patchResp.user2[0]._id).toEqual(user2._id) + + getResp = await config.api.row.get(table._id!, row._id!) + expect(getResp.user1[0]._id).toEqual(user2._id) + expect(getResp.user2[0]._id).toEqual(user2._id) + }) + + it("should be able to remove a relationship from many side", async () => { + const row = await config.api.row.save(otherTable._id!, { + name: "test", + description: "test", + }) + const row2 = await config.api.row.save(otherTable._id!, { + name: "test", + description: "test", + }) + const { _id } = await config.api.row.save(table._id!, { + relationship: [{ _id: row._id }, { _id: row2._id }], + }) + const relatedRow = await config.api.row.get(table._id!, _id!, { + status: 200, + }) + expect(relatedRow.relationship.length).toEqual(2) + await config.api.row.save(table._id!, { + ...relatedRow, + relationship: [{ _id: row._id }], + }) + const afterRelatedRow = await config.api.row.get(table._id!, _id!, { + status: 200, + }) + expect(afterRelatedRow.relationship.length).toEqual(1) + expect(afterRelatedRow.relationship[0]._id).toEqual(row._id) + }) + + it("should be able to update relationships when both columns are same name", async () => { + let row = await config.api.row.save(table._id!, { + name: "test", + description: "test", + }) + let row2 = await config.api.row.save(otherTable._id!, { + name: "test", + description: "test", + relationship: [row._id], + }) + row = await config.api.row.get(table._id!, row._id!) + expect(row.relationship.length).toBe(1) + const resp = await config.api.row.patch(table._id!, { + _id: row._id!, + _rev: row._rev!, + tableId: row.tableId!, + name: "test2", + relationship: [row2._id], + }) + expect(resp.relationship.length).toBe(1) + }) + + !isInternal && + // MSSQL needs a setting called IDENTITY_INSERT to be set to ON to allow writing + // to identity columns. This is not something Budibase does currently. + !isMSSQL && + it("should support updating fields that are part of a composite key", async () => { + const tableRequest = saveTableRequest({ + primary: ["number", "string"], + schema: { + string: { + type: FieldType.STRING, + name: "string", + }, + number: { + type: FieldType.NUMBER, + name: "number", + }, + }, + }) + + delete tableRequest.schema.id + + const table = await config.api.table.save(tableRequest) + + const stringValue = generator.word() + + // MySQL and MariaDB auto-increment fields have a minimum value of 1. If + // you try to save a row with a value of 0 it will use 1 instead. + const naturalValue = generator.integer({ min: 1, max: 1000 }) + + const existing = await config.api.row.save(table._id!, { + string: stringValue, + number: naturalValue, + }) + + expect(existing._id).toEqual(`%5B${naturalValue}%2C'${stringValue}'%5D`) const row = await config.api.row.patch(table._id!, { _id: existing._id!, _rev: existing._rev!, tableId: table._id!, - name: "Updated Name", + string: stringValue, + number: 1500, }) - expect(row.name).toEqual("Updated Name") - expect(row.description).toEqual(existing.description) + expect(row._id).toEqual(`%5B${"1500"}%2C'${stringValue}'%5D`) + }) + }) - const savedRow = await config.api.row.get(table._id!, row._id!) + describe("destroy", () => { + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) + }) - expect(savedRow.description).toEqual(existing.description) - expect(savedRow.name).toEqual("Updated Name") - await assertRowUsage(rowUsage) + it("should be able to delete a row", async () => { + const createdRow = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + + const res = await config.api.row.bulkDelete(table._id!, { + rows: [createdRow], + }) + expect(res[0]._id).toEqual(createdRow._id) + await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) + }) + + it("should be able to delete a row with ID only", async () => { + const createdRow = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + + const res = await config.api.row.bulkDelete(table._id!, { + rows: [createdRow._id!], + }) + expect(res[0]._id).toEqual(createdRow._id) + expect(res[0].tableId).toEqual(table._id!) + await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) + }) + + it("should be able to bulk delete rows, including a row that doesn't exist", async () => { + const createdRow = await config.api.row.save(table._id!, {}) + const createdRow2 = await config.api.row.save(table._id!, {}) + + const res = await config.api.row.bulkDelete(table._id!, { + rows: [createdRow, createdRow2, { _id: "9999999" }], }) - it("should update only the fields that are supplied and emit the correct oldRow", async () => { - let beforeRow = await config.api.row.save(table._id!, { - name: "test", - description: "test", - }) - const opts = { - name: "row:update", - matchFn: (event: UpdatedRowEventEmitter) => - event.row._id === beforeRow._id, - } - const event = await waitForEvent(opts, async () => { - await config.api.row.patch(table._id!, { - _id: beforeRow._id!, - _rev: beforeRow._rev!, - tableId: table._id!, - name: "Updated Name", - }) - }) + expect(res.map(r => r._id)).toEqual( + expect.arrayContaining([createdRow._id, createdRow2._id]) + ) + expect(res.length).toEqual(2) + }) - expect(event.oldRow).toBeDefined() - expect(event.oldRow.name).toEqual("test") - expect(event.row.name).toEqual("Updated Name") - expect(event.oldRow.description).toEqual(beforeRow.description) - expect(event.row.description).toEqual(beforeRow.description) - }) + describe("relations to same table", () => { + let relatedRows: Row[] - it("should throw an error when given improper types", async () => { - const existing = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() - - await config.api.row.patch( - table._id!, - { - _id: existing._id!, - _rev: existing._rev!, - tableId: table._id!, - name: 1, - }, - { status: 400 } - ) - - await assertRowUsage(rowUsage) - }) - - it("should not overwrite links if those links are not set", async () => { - let linkField: FieldSchema = { - type: FieldType.LINK, - name: "", - fieldName: "", - constraints: { - type: "array", - presence: false, - }, - relationshipType: RelationshipType.ONE_TO_MANY, - tableId: InternalTable.USER_METADATA, - } - - let table = await config.api.table.save({ - name: "TestTable", - type: "table", - sourceType: TableSourceType.INTERNAL, - sourceId: INTERNAL_TABLE_SOURCE_ID, - schema: { - user1: { ...linkField, name: "user1", fieldName: "user1" }, - user2: { ...linkField, name: "user2", fieldName: "user2" }, - }, - }) - - let user1 = await config.createUser() - let user2 = await config.createUser() - - let row = await config.api.row.save(table._id!, { - user1: [{ _id: user1._id }], - user2: [{ _id: user2._id }], - }) - - let getResp = await config.api.row.get(table._id!, row._id!) - expect(getResp.user1[0]._id).toEqual(user1._id) - expect(getResp.user2[0]._id).toEqual(user2._id) - - let patchResp = await config.api.row.patch(table._id!, { - _id: row._id!, - _rev: row._rev!, - tableId: table._id!, - user1: [{ _id: user2._id }], - }) - expect(patchResp.user1[0]._id).toEqual(user2._id) - expect(patchResp.user2[0]._id).toEqual(user2._id) - - getResp = await config.api.row.get(table._id!, row._id!) - expect(getResp.user1[0]._id).toEqual(user2._id) - expect(getResp.user2[0]._id).toEqual(user2._id) - }) - - it("should be able to remove a relationship from many side", async () => { - const row = await config.api.row.save(otherTable._id!, { - name: "test", - description: "test", - }) - const row2 = await config.api.row.save(otherTable._id!, { - name: "test", - description: "test", - }) - const { _id } = await config.api.row.save(table._id!, { - relationship: [{ _id: row._id }, { _id: row2._id }], - }) - const relatedRow = await config.api.row.get(table._id!, _id!, { - status: 200, - }) - expect(relatedRow.relationship.length).toEqual(2) - await config.api.row.save(table._id!, { - ...relatedRow, - relationship: [{ _id: row._id }], - }) - const afterRelatedRow = await config.api.row.get(table._id!, _id!, { - status: 200, - }) - expect(afterRelatedRow.relationship.length).toEqual(1) - expect(afterRelatedRow.relationship[0]._id).toEqual(row._id) - }) - - it("should be able to update relationships when both columns are same name", async () => { - let row = await config.api.row.save(table._id!, { - name: "test", - description: "test", - }) - let row2 = await config.api.row.save(otherTable._id!, { - name: "test", - description: "test", - relationship: [row._id], - }) - row = await config.api.row.get(table._id!, row._id!) - expect(row.relationship.length).toBe(1) - const resp = await config.api.row.patch(table._id!, { - _id: row._id!, - _rev: row._rev!, - tableId: row.tableId!, - name: "test2", - relationship: [row2._id], - }) - expect(resp.relationship.length).toBe(1) - }) - - !isInternal && - // MSSQL needs a setting called IDENTITY_INSERT to be set to ON to allow writing - // to identity columns. This is not something Budibase does currently. - !isMSSQL && - it("should support updating fields that are part of a composite key", async () => { - const tableRequest = saveTableRequest({ - primary: ["number", "string"], + beforeAll(async () => { + const relatedTable = await config.api.table.save( + defaultTable({ schema: { - string: { - type: FieldType.STRING, - name: "string", + name: { name: "name", type: FieldType.STRING }, + }, + }) + ) + const relatedTableId = relatedTable._id! + table = await config.api.table.save( + defaultTable({ + schema: { + name: { name: "name", type: FieldType.STRING }, + related1: { + type: FieldType.LINK, + name: "related1", + fieldName: "main1", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, }, - number: { - type: FieldType.NUMBER, - name: "number", + related2: { + type: FieldType.LINK, + name: "related2", + fieldName: "main2", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, }, }, }) - - delete tableRequest.schema.id - - const table = await config.api.table.save(tableRequest) - - const stringValue = generator.word() - - // MySQL and MariaDB auto-increment fields have a minimum value of 1. If - // you try to save a row with a value of 0 it will use 1 instead. - const naturalValue = generator.integer({ min: 1, max: 1000 }) - - const existing = await config.api.row.save(table._id!, { - string: stringValue, - number: naturalValue, - }) - - expect(existing._id).toEqual( - `%5B${naturalValue}%2C'${stringValue}'%5D` - ) - - const row = await config.api.row.patch(table._id!, { - _id: existing._id!, - _rev: existing._rev!, - tableId: table._id!, - string: stringValue, - number: 1500, - }) - - expect(row._id).toEqual(`%5B${"1500"}%2C'${stringValue}'%5D`) - }) - }) - - describe("destroy", () => { - beforeAll(async () => { - table = await config.api.table.save(defaultTable()) - }) - - it("should be able to delete a row", async () => { - const createdRow = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() - - const res = await config.api.row.bulkDelete(table._id!, { - rows: [createdRow], - }) - expect(res[0]._id).toEqual(createdRow._id) - await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) - }) - - it("should be able to delete a row with ID only", async () => { - const createdRow = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() - - const res = await config.api.row.bulkDelete(table._id!, { - rows: [createdRow._id!], - }) - expect(res[0]._id).toEqual(createdRow._id) - expect(res[0].tableId).toEqual(table._id!) - await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) - }) - - it("should be able to bulk delete rows, including a row that doesn't exist", async () => { - const createdRow = await config.api.row.save(table._id!, {}) - const createdRow2 = await config.api.row.save(table._id!, {}) - - const res = await config.api.row.bulkDelete(table._id!, { - rows: [createdRow, createdRow2, { _id: "9999999" }], - }) - - expect(res.map(r => r._id)).toEqual( - expect.arrayContaining([createdRow._id, createdRow2._id]) ) - expect(res.length).toEqual(2) + relatedRows = await Promise.all([ + config.api.row.save(relatedTableId, { name: "foo" }), + config.api.row.save(relatedTableId, { name: "bar" }), + config.api.row.save(relatedTableId, { name: "baz" }), + config.api.row.save(relatedTableId, { name: "boo" }), + ]) }) - describe("relations to same table", () => { - let relatedRows: Row[] - - beforeAll(async () => { - const relatedTable = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - }, - }) - ) - const relatedTableId = relatedTable._id! - table = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - related1: { - type: FieldType.LINK, - name: "related1", - fieldName: "main1", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - related2: { - type: FieldType.LINK, - name: "related2", - fieldName: "main2", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - }, - }) - ) - relatedRows = await Promise.all([ - config.api.row.save(relatedTableId, { name: "foo" }), - config.api.row.save(relatedTableId, { name: "bar" }), - config.api.row.save(relatedTableId, { name: "baz" }), - config.api.row.save(relatedTableId, { name: "boo" }), - ]) + it("can delete rows with both relationships", async () => { + const row = await config.api.row.save(table._id!, { + name: "test", + related1: [relatedRows[0]._id!], + related2: [relatedRows[1]._id!], }) - it("can delete rows with both relationships", async () => { - const row = await config.api.row.save(table._id!, { - name: "test", - related1: [relatedRows[0]._id!], - related2: [relatedRows[1]._id!], - }) + await config.api.row.delete(table._id!, { _id: row._id! }) - await config.api.row.delete(table._id!, { _id: row._id! }) + await config.api.row.get(table._id!, row._id!, { status: 404 }) + }) - await config.api.row.get(table._id!, row._id!, { status: 404 }) + it("can delete rows with empty relationships", async () => { + const row = await config.api.row.save(table._id!, { + name: "test", + related1: [], + related2: [], }) - it("can delete rows with empty relationships", async () => { - const row = await config.api.row.save(table._id!, { - name: "test", - related1: [], - related2: [], - }) + await config.api.row.delete(table._id!, { _id: row._id! }) - await config.api.row.delete(table._id!, { _id: row._id! }) - - await config.api.row.get(table._id!, row._id!, { status: 404 }) - }) + await config.api.row.get(table._id!, row._id!, { status: 404 }) }) }) + }) - describe("validate", () => { - beforeAll(async () => { - table = await config.api.table.save(defaultTable()) - }) + describe("validate", () => { + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) + }) - it("should return no errors on valid row", async () => { - const rowUsage = await getRowUsage() + it("should return no errors on valid row", async () => { + const rowUsage = await getRowUsage() - const res = await config.api.row.validate(table._id!, { name: "ivan" }) + const res = await config.api.row.validate(table._id!, { name: "ivan" }) + expect(res.valid).toBe(true) + expect(Object.keys(res.errors)).toEqual([]) + await assertRowUsage(rowUsage) + }) + + it("should errors on invalid row", async () => { + const rowUsage = await getRowUsage() + + const res = await config.api.row.validate(table._id!, { name: 1 }) + + if (isInternal) { + expect(res.valid).toBe(false) + expect(Object.keys(res.errors)).toEqual(["name"]) + } else { + // Validation for external is not implemented, so it will always return valid expect(res.valid).toBe(true) expect(Object.keys(res.errors)).toEqual([]) - await assertRowUsage(rowUsage) - }) + } + await assertRowUsage(rowUsage) + }) + }) - it("should errors on invalid row", async () => { - const rowUsage = await getRowUsage() - - const res = await config.api.row.validate(table._id!, { name: 1 }) - - if (isInternal) { - expect(res.valid).toBe(false) - expect(Object.keys(res.errors)).toEqual(["name"]) - } else { - // Validation for external is not implemented, so it will always return valid - expect(res.valid).toBe(true) - expect(Object.keys(res.errors)).toEqual([]) - } - await assertRowUsage(rowUsage) - }) + describe("bulkDelete", () => { + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) }) - describe("bulkDelete", () => { - beforeAll(async () => { - table = await config.api.table.save(defaultTable()) + it("should be able to delete a bulk set of rows", async () => { + const row1 = await config.api.row.save(table._id!, {}) + const row2 = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + + const res = await config.api.row.bulkDelete(table._id!, { + rows: [row1, row2], }) - it("should be able to delete a bulk set of rows", async () => { - const row1 = await config.api.row.save(table._id!, {}) - const row2 = await config.api.row.save(table._id!, {}) + expect(res.length).toEqual(2) + await config.api.row.get(table._id!, row1._id!, { status: 404 }) + await assertRowUsage(isInternal ? rowUsage - 2 : rowUsage) + }) + + it("should be able to delete a variety of row set types", async () => { + const [row1, row2, row3] = await Promise.all([ + config.api.row.save(table._id!, {}), + config.api.row.save(table._id!, {}), + config.api.row.save(table._id!, {}), + ]) + const rowUsage = await getRowUsage() + + const res = await config.api.row.bulkDelete(table._id!, { + rows: [row1, row2._id!, { _id: row3._id }], + }) + + expect(res.length).toEqual(3) + await config.api.row.get(table._id!, row1._id!, { status: 404 }) + await assertRowUsage(isInternal ? rowUsage - 3 : rowUsage) + }) + + it("should accept a valid row object and delete the row", async () => { + const row1 = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + + const res = await config.api.row.delete(table._id!, row1 as DeleteRow) + + expect(res.id).toEqual(row1._id) + await config.api.row.get(table._id!, row1._id!, { status: 404 }) + await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) + }) + + it.each([{ not: "valid" }, { rows: 123 }, "invalid"])( + "should ignore malformed/invalid delete request: %s", + async (request: any) => { const rowUsage = await getRowUsage() - const res = await config.api.row.bulkDelete(table._id!, { - rows: [row1, row2], + await config.api.row.delete(table._id!, request, { + status: 400, + body: { + message: "Invalid delete rows request", + }, }) - expect(res.length).toEqual(2) - await config.api.row.get(table._id!, row1._id!, { status: 404 }) - await assertRowUsage(isInternal ? rowUsage - 2 : rowUsage) - }) + await assertRowUsage(rowUsage) + } + ) + }) - it("should be able to delete a variety of row set types", async () => { - const [row1, row2, row3] = await Promise.all([ - config.api.row.save(table._id!, {}), - config.api.row.save(table._id!, {}), - config.api.row.save(table._id!, {}), - ]) - const rowUsage = await getRowUsage() + describe("bulkImport", () => { + isInternal && + it("should update Auto ID field after bulk import", async () => { + const table = await config.api.table.save( + saveTableRequest({ + primary: ["autoId"], + schema: { + autoId: { + name: "autoId", + type: FieldType.NUMBER, + subtype: AutoFieldSubType.AUTO_ID, + autocolumn: true, + constraints: { + type: "number", + presence: false, + }, + }, + }, + }) + ) - const res = await config.api.row.bulkDelete(table._id!, { - rows: [row1, row2._id!, { _id: row3._id }], + let row = await config.api.row.save(table._id!, {}) + expect(row.autoId).toEqual(1) + + await config.api.row.bulkImport(table._id!, { + rows: [{ autoId: 2 }], }) - expect(res.length).toEqual(3) - await config.api.row.get(table._id!, row1._id!, { status: 404 }) - await assertRowUsage(isInternal ? rowUsage - 3 : rowUsage) + row = await config.api.row.save(table._id!, {}) + expect(row.autoId).toEqual(3) }) - it("should accept a valid row object and delete the row", async () => { - const row1 = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() + isInternal && + it("should reject bulkImporting relationship fields", async () => { + const table1 = await config.api.table.save(saveTableRequest()) + const table2 = await config.api.table.save( + saveTableRequest({ + schema: { + relationship: { + name: "relationship", + type: FieldType.LINK, + tableId: table1._id!, + relationshipType: RelationshipType.ONE_TO_MANY, + fieldName: "relationship", + }, + }, + }) + ) - const res = await config.api.row.delete(table._id!, row1 as DeleteRow) - - expect(res.id).toEqual(row1._id) - await config.api.row.get(table._id!, row1._id!, { status: 404 }) - await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) - }) - - it.each([{ not: "valid" }, { rows: 123 }, "invalid"])( - "should ignore malformed/invalid delete request: %s", - async (request: any) => { - const rowUsage = await getRowUsage() - - await config.api.row.delete(table._id!, request, { + const table1Row1 = await config.api.row.save(table1._id!, {}) + await config.api.row.bulkImport( + table2._id!, + { + rows: [{ relationship: [table1Row1._id!] }], + }, + { status: 400, body: { - message: "Invalid delete rows request", + message: + 'Can\'t bulk import relationship fields for internal databases, found value in field "relationship"', }, - }) + } + ) + }) - await assertRowUsage(rowUsage) - } + it("should be able to bulkImport rows", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + type: FieldType.STRING, + name: "name", + }, + description: { + type: FieldType.STRING, + name: "description", + }, + }, + }) ) + + const rowUsage = await getRowUsage() + + await config.api.row.bulkImport(table._id!, { + rows: [ + { + name: "Row 1", + description: "Row 1 description", + }, + { + name: "Row 2", + description: "Row 2 description", + }, + ], + }) + + const rows = await config.api.row.fetch(table._id!) + expect(rows.length).toEqual(2) + + rows.sort((a, b) => a.name.localeCompare(b.name)) + expect(rows[0].name).toEqual("Row 1") + expect(rows[0].description).toEqual("Row 1 description") + expect(rows[1].name).toEqual("Row 2") + expect(rows[1].description).toEqual("Row 2 description") + + await assertRowUsage(isInternal ? rowUsage + 2 : rowUsage) }) - describe("bulkImport", () => { - isInternal && - it("should update Auto ID field after bulk import", async () => { - const table = await config.api.table.save( - saveTableRequest({ - primary: ["autoId"], - schema: { - autoId: { - name: "autoId", - type: FieldType.NUMBER, - subtype: AutoFieldSubType.AUTO_ID, - autocolumn: true, - constraints: { - type: "number", - presence: false, - }, - }, - }, - }) - ) - - let row = await config.api.row.save(table._id!, {}) - expect(row.autoId).toEqual(1) - - await config.api.row.bulkImport(table._id!, { - rows: [{ autoId: 2 }], - }) - - row = await config.api.row.save(table._id!, {}) - expect(row.autoId).toEqual(3) - }) - - isInternal && - it("should reject bulkImporting relationship fields", async () => { - const table1 = await config.api.table.save(saveTableRequest()) - const table2 = await config.api.table.save( - saveTableRequest({ - schema: { - relationship: { - name: "relationship", - type: FieldType.LINK, - tableId: table1._id!, - relationshipType: RelationshipType.ONE_TO_MANY, - fieldName: "relationship", - }, - }, - }) - ) - - const table1Row1 = await config.api.row.save(table1._id!, {}) - await config.api.row.bulkImport( - table2._id!, - { - rows: [{ relationship: [table1Row1._id!] }], - }, - { - status: 400, - body: { - message: - 'Can\'t bulk import relationship fields for internal databases, found value in field "relationship"', - }, - } - ) - }) - - it("should be able to bulkImport rows", async () => { + isInternal && + it("should be able to update existing rows on bulkImport", async () => { const table = await config.api.table.save( saveTableRequest({ schema: { @@ -1664,6 +1706,11 @@ datasourceDescribe( }) ) + const existingRow = await config.api.row.save(table._id!, { + name: "Existing row", + description: "Existing description", + }) + const rowUsage = await getRowUsage() await config.api.row.bulkImport(table._id!, { @@ -1672,6 +1719,60 @@ datasourceDescribe( name: "Row 1", description: "Row 1 description", }, + { ...existingRow, name: "Updated existing row" }, + { + name: "Row 2", + description: "Row 2 description", + }, + ], + identifierFields: ["_id"], + }) + + const rows = await config.api.row.fetch(table._id!) + expect(rows.length).toEqual(3) + + rows.sort((a, b) => a.name.localeCompare(b.name)) + expect(rows[0].name).toEqual("Row 1") + expect(rows[0].description).toEqual("Row 1 description") + expect(rows[1].name).toEqual("Row 2") + expect(rows[1].description).toEqual("Row 2 description") + expect(rows[2].name).toEqual("Updated existing row") + expect(rows[2].description).toEqual("Existing description") + + await assertRowUsage(rowUsage + 2) + }) + + isInternal && + it("should create new rows if not identifierFields are provided", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + type: FieldType.STRING, + name: "name", + }, + description: { + type: FieldType.STRING, + name: "description", + }, + }, + }) + ) + + const existingRow = await config.api.row.save(table._id!, { + name: "Existing row", + description: "Existing description", + }) + + const rowUsage = await getRowUsage() + + await config.api.row.bulkImport(table._id!, { + rows: [ + { + name: "Row 1", + description: "Row 1 description", + }, + { ...existingRow, name: "Updated existing row" }, { name: "Row 2", description: "Row 2 description", @@ -1680,1658 +1781,1588 @@ datasourceDescribe( }) const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(2) + expect(rows.length).toEqual(4) rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Row 1") - expect(rows[0].description).toEqual("Row 1 description") - expect(rows[1].name).toEqual("Row 2") - expect(rows[1].description).toEqual("Row 2 description") + expect(rows[0].name).toEqual("Existing row") + expect(rows[0].description).toEqual("Existing description") + expect(rows[1].name).toEqual("Row 1") + expect(rows[1].description).toEqual("Row 1 description") + expect(rows[2].name).toEqual("Row 2") + expect(rows[2].description).toEqual("Row 2 description") + expect(rows[3].name).toEqual("Updated existing row") + expect(rows[3].description).toEqual("Existing description") - await assertRowUsage(isInternal ? rowUsage + 2 : rowUsage) + await assertRowUsage(rowUsage + 3) }) - isInternal && - it("should be able to update existing rows on bulkImport", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - type: FieldType.STRING, - name: "name", - }, - description: { - type: FieldType.STRING, - name: "description", - }, - }, - }) - ) - - const existingRow = await config.api.row.save(table._id!, { - name: "Existing row", - description: "Existing description", - }) - - const rowUsage = await getRowUsage() - - await config.api.row.bulkImport(table._id!, { - rows: [ - { - name: "Row 1", - description: "Row 1 description", - }, - { ...existingRow, name: "Updated existing row" }, - { - name: "Row 2", - description: "Row 2 description", - }, - ], - identifierFields: ["_id"], - }) - - const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(3) - - rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Row 1") - expect(rows[0].description).toEqual("Row 1 description") - expect(rows[1].name).toEqual("Row 2") - expect(rows[1].description).toEqual("Row 2 description") - expect(rows[2].name).toEqual("Updated existing row") - expect(rows[2].description).toEqual("Existing description") - - await assertRowUsage(rowUsage + 2) - }) - - isInternal && - it("should create new rows if not identifierFields are provided", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - type: FieldType.STRING, - name: "name", - }, - description: { - type: FieldType.STRING, - name: "description", - }, - }, - }) - ) - - const existingRow = await config.api.row.save(table._id!, { - name: "Existing row", - description: "Existing description", - }) - - const rowUsage = await getRowUsage() - - await config.api.row.bulkImport(table._id!, { - rows: [ - { - name: "Row 1", - description: "Row 1 description", - }, - { ...existingRow, name: "Updated existing row" }, - { - name: "Row 2", - description: "Row 2 description", - }, - ], - }) - - const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(4) - - rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Existing row") - expect(rows[0].description).toEqual("Existing description") - expect(rows[1].name).toEqual("Row 1") - expect(rows[1].description).toEqual("Row 1 description") - expect(rows[2].name).toEqual("Row 2") - expect(rows[2].description).toEqual("Row 2 description") - expect(rows[3].name).toEqual("Updated existing row") - expect(rows[3].description).toEqual("Existing description") - - await assertRowUsage(rowUsage + 3) - }) - - // Upserting isn't yet supported in MSSQL / Oracle, see: - // https://github.com/knex/knex/pull/6050 - !isMSSQL && - !isOracle && - it("should be able to update existing rows with bulkImport", async () => { - const table = await config.api.table.save( - saveTableRequest({ - primary: ["userId"], - schema: { - userId: { - type: FieldType.NUMBER, - name: "userId", - constraints: { - presence: true, - }, - }, - name: { - type: FieldType.STRING, - name: "name", - }, - description: { - type: FieldType.STRING, - name: "description", - }, - }, - }) - ) - - const row1 = await config.api.row.save(table._id!, { - userId: 1, - name: "Row 1", - description: "Row 1 description", - }) - - const row2 = await config.api.row.save(table._id!, { - userId: 2, - name: "Row 2", - description: "Row 2 description", - }) - - await config.api.row.bulkImport(table._id!, { - identifierFields: ["userId"], - rows: [ - { - userId: row1.userId, - name: "Row 1 updated", - description: "Row 1 description updated", - }, - { - userId: row2.userId, - name: "Row 2 updated", - description: "Row 2 description updated", - }, - { - userId: 3, - name: "Row 3", - description: "Row 3 description", - }, - ], - }) - - const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(3) - - rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Row 1 updated") - expect(rows[0].description).toEqual("Row 1 description updated") - expect(rows[1].name).toEqual("Row 2 updated") - expect(rows[1].description).toEqual("Row 2 description updated") - expect(rows[2].name).toEqual("Row 3") - expect(rows[2].description).toEqual("Row 3 description") - }) - - // Upserting isn't yet supported in MSSQL or Oracle, see: - // https://github.com/knex/knex/pull/6050 - !isMSSQL && - !isOracle && - !isInternal && - it("should be able to update existing rows with composite primary keys with bulkImport", async () => { - const tableName = uuid.v4() - await client?.schema.createTable(tableName, table => { - table.integer("companyId") - table.integer("userId") - table.string("name") - table.string("description") - table.primary(["companyId", "userId"]) - }) - - const resp = await config.api.datasource.fetchSchema({ - datasourceId: datasource!._id!, - }) - const table = resp.datasource.entities![tableName] - - const row1 = await config.api.row.save(table._id!, { - companyId: 1, - userId: 1, - name: "Row 1", - description: "Row 1 description", - }) - - const row2 = await config.api.row.save(table._id!, { - companyId: 1, - userId: 2, - name: "Row 2", - description: "Row 2 description", - }) - - await config.api.row.bulkImport(table._id!, { - identifierFields: ["companyId", "userId"], - rows: [ - { - companyId: 1, - userId: row1.userId, - name: "Row 1 updated", - description: "Row 1 description updated", - }, - { - companyId: 1, - userId: row2.userId, - name: "Row 2 updated", - description: "Row 2 description updated", - }, - { - companyId: 1, - userId: 3, - name: "Row 3", - description: "Row 3 description", - }, - ], - }) - - const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(3) - - rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Row 1 updated") - expect(rows[0].description).toEqual("Row 1 description updated") - expect(rows[1].name).toEqual("Row 2 updated") - expect(rows[1].description).toEqual("Row 2 description updated") - expect(rows[2].name).toEqual("Row 3") - expect(rows[2].description).toEqual("Row 3 description") - }) - - // Upserting isn't yet supported in MSSQL/Oracle, see: - // https://github.com/knex/knex/pull/6050 - !isMSSQL && - !isOracle && - !isInternal && - it("should be able to update existing rows an autoID primary key", async () => { - const tableName = uuid.v4() - await client!.schema.createTable(tableName, table => { - table.increments("userId").primary() - table.string("name") - }) - - const resp = await config.api.datasource.fetchSchema({ - datasourceId: datasource!._id!, - }) - const table = resp.datasource.entities![tableName] - - const row1 = await config.api.row.save(table._id!, { - name: "Clare", - }) - - const row2 = await config.api.row.save(table._id!, { - name: "Jeff", - }) - - await config.api.row.bulkImport(table._id!, { - identifierFields: ["userId"], - rows: [ - { - userId: row1.userId, - name: "Clare updated", - }, - { - userId: row2.userId, - name: "Jeff updated", - }, - ], - }) - - const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(2) - - rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Clare updated") - expect(rows[1].name).toEqual("Jeff updated") - }) - }) - - describe("enrich", () => { - beforeAll(async () => { - table = await config.api.table.save(defaultTable()) - }) - - it("should allow enriching some linked rows", async () => { - const { linkedTable, firstRow, secondRow } = await tenancy.doInTenant( - config.getTenantId(), - async () => { - const linkedTable = await config.api.table.save( - defaultTable({ - schema: { - link: { - name: "link", - fieldName: "link", - type: FieldType.LINK, - relationshipType: RelationshipType.ONE_TO_MANY, - tableId: table._id!, - }, - }, - }) - ) - const firstRow = await config.api.row.save(table._id!, { - name: "Test Contact", - description: "original description", - }) - const secondRow = await config.api.row.save(linkedTable._id!, { - name: "Test 2", - description: "og desc", - link: [{ _id: firstRow._id }], - }) - return { linkedTable, firstRow, secondRow } - } - ) - const rowUsage = await getRowUsage() - - // test basic enrichment - const resBasic = await config.api.row.get( - linkedTable._id!, - secondRow._id! - ) - expect(resBasic.link.length).toBe(1) - expect(resBasic.link[0]).toEqual({ - _id: firstRow._id, - primaryDisplay: firstRow.name, - }) - - // test full enrichment - const resEnriched = await config.api.row.getEnriched( - linkedTable._id!, - secondRow._id! - ) - expect(resEnriched.link.length).toBe(1) - expect(resEnriched.link[0]._id).toBe(firstRow._id) - expect(resEnriched.link[0].name).toBe("Test Contact") - expect(resEnriched.link[0].description).toBe("original description") - await assertRowUsage(rowUsage) - }) - }) - - isInternal && - describe("attachments and signatures", () => { - const coreAttachmentEnrichment = async ( - schema: TableSchema, - field: string, - attachmentCfg: string | string[] - ) => { - const testTable = await config.api.table.save( - defaultTable({ - schema, - }) - ) - const attachmentToStoreKey = (attachmentId: string) => { - return { - key: `${config.getAppId()}/attachments/${attachmentId}`, - } - } - const draftRow = { - name: "test", - description: "test", - [field]: - typeof attachmentCfg === "string" - ? attachmentToStoreKey(attachmentCfg) - : attachmentCfg.map(attachmentToStoreKey), - tableId: testTable._id, - } - const row = await config.api.row.save(testTable._id!, draftRow) - - await withEnv({ SELF_HOSTED: "true" }, async () => { - return context.doInAppContext(config.getAppId(), async () => { - const enriched: Row[] = await outputProcessing(testTable, [row]) - const [targetRow] = enriched - const attachmentEntries = Array.isArray(targetRow[field]) - ? targetRow[field] - : [targetRow[field]] - - for (const entry of attachmentEntries) { - const attachmentId = entry.key.split("/").pop() - expect(entry.url.split("?")[0]).toBe( - `/files/signed/prod-budi-app-assets/${config.getProdAppId()}/attachments/${attachmentId}` - ) - } - }) - }) - } - - it("should allow enriching single attachment rows", async () => { - await coreAttachmentEnrichment( - { - attachment: { - type: FieldType.ATTACHMENT_SINGLE, - name: "attachment", - constraints: { presence: false }, - }, - }, - "attachment", - `${uuid.v4()}.csv` - ) - }) - - it("should allow enriching attachment list rows", async () => { - await coreAttachmentEnrichment( - { - attachments: { - type: FieldType.ATTACHMENTS, - name: "attachments", - constraints: { type: "array", presence: false }, - }, - }, - "attachments", - [`${uuid.v4()}.csv`] - ) - }) - - it("should allow enriching signature rows", async () => { - await coreAttachmentEnrichment( - { - signature: { - type: FieldType.SIGNATURE_SINGLE, - name: "signature", - constraints: { presence: false }, - }, - }, - "signature", - `${uuid.v4()}.png` - ) - }) - }) - - describe("exportRows", () => { - beforeEach(async () => { - table = await config.api.table.save(defaultTable()) - }) - - isInternal && - it("should not export internal couchdb fields", async () => { - const existing = await config.api.row.save(table._id!, { - name: generator.guid(), - description: generator.paragraph(), - }) - const res = await config.api.row.exportRows(table._id!, { - rows: [existing._id!], - }) - const results = JSON.parse(res) - expect(results.length).toEqual(1) - const row = results[0] - - expect(Object.keys(row)).toEqual(["_id", "name", "description"]) - }) - - !isInternal && - it("should allow exporting all columns", async () => { - const existing = await config.api.row.save(table._id!, {}) - const res = await config.api.row.exportRows(table._id!, { - rows: [existing._id!], - }) - const results = JSON.parse(res) - expect(results.length).toEqual(1) - const row = results[0] - - // Ensure all original columns were exported - expect(Object.keys(row).length).toBe(Object.keys(existing).length) - Object.keys(existing).forEach(key => { - expect(row[key]).toEqual(existing[key]) - }) - }) - - it("should allow exporting without filtering", async () => { - const existing = await config.api.row.save(table._id!, {}) - const res = await config.api.row.exportRows(table._id!) - const results = JSON.parse(res) - expect(results.length).toEqual(1) - const row = results[0] - - expect(row._id).toEqual(existing._id) - }) - - it("should allow exporting only certain columns", async () => { - const existing = await config.api.row.save(table._id!, {}) - const res = await config.api.row.exportRows(table._id!, { - rows: [existing._id!], - columns: ["_id"], - }) - const results = JSON.parse(res) - expect(results.length).toEqual(1) - const row = results[0] - - // Ensure only the _id column was exported - expect(Object.keys(row).length).toEqual(1) - expect(row._id).toEqual(existing._id) - }) - - it("should handle single quotes in row filtering", async () => { - const existing = await config.api.row.save(table._id!, {}) - const res = await config.api.row.exportRows(table._id!, { - rows: [`['${existing._id!}']`], - }) - const results = JSON.parse(res) - expect(results.length).toEqual(1) - const row = results[0] - expect(row._id).toEqual(existing._id) - }) - - it("should return an error if no table is found", async () => { - const existing = await config.api.row.save(table._id!, {}) - await config.api.row.exportRows( - "1234567", - { rows: [existing._id!] }, - RowExportFormat.JSON, - { status: 404 } - ) - }) - - // MSSQL needs a setting called IDENTITY_INSERT to be set to ON to allow writing - // to identity columns. This is not something Budibase does currently. - !isMSSQL && - it("should handle filtering by composite primary keys", async () => { - const tableRequest = saveTableRequest({ - primary: ["number", "string"], - schema: { - string: { - type: FieldType.STRING, - name: "string", - }, - number: { - type: FieldType.NUMBER, - name: "number", - }, - }, - }) - delete tableRequest.schema.id - - const table = await config.api.table.save(tableRequest) - const toCreate = generator - .unique(() => generator.integer({ min: 0, max: 10000 }), 10) - .map(number => ({ number, string: generator.word({ length: 30 }) })) - - const rows = await Promise.all( - toCreate.map(d => config.api.row.save(table._id!, d)) - ) - - const res = await config.api.row.exportRows(table._id!, { - rows: _.sampleSize(rows, 3).map(r => r._id!), - }) - const results = JSON.parse(res) - expect(results.length).toEqual(3) - }) - - describe("should allow exporting all column types", () => { - let tableId: string - let expectedRowData: Row - - beforeAll(async () => { - const fullSchema = setup.structures.fullSchemaWithoutLinks({ - allRequired: true, - }) - - const table = await config.api.table.save( - saveTableRequest({ - ...setup.structures.basicTable(), - schema: fullSchema, - primary: ["string"], - }) - ) - tableId = table._id! - - const rowValues: Record = { - [FieldType.STRING]: generator.guid(), - [FieldType.LONGFORM]: generator.paragraph(), - [FieldType.OPTIONS]: "option 2", - [FieldType.ARRAY]: ["options 2", "options 4"], - [FieldType.NUMBER]: generator.natural(), - [FieldType.BOOLEAN]: generator.bool(), - [FieldType.DATETIME]: generator.date().toISOString(), - [FieldType.ATTACHMENTS]: [setup.structures.basicAttachment()], - [FieldType.ATTACHMENT_SINGLE]: setup.structures.basicAttachment(), - [FieldType.FORMULA]: undefined, // generated field - [FieldType.AUTO]: undefined, // generated field - [FieldType.AI]: "LLM Output", - [FieldType.JSON]: { name: generator.guid() }, - [FieldType.INTERNAL]: generator.guid(), - [FieldType.BARCODEQR]: generator.guid(), - [FieldType.SIGNATURE_SINGLE]: setup.structures.basicAttachment(), - [FieldType.BIGINT]: generator.integer().toString(), - [FieldType.BB_REFERENCE]: [{ _id: config.getUser()._id }], - [FieldType.BB_REFERENCE_SINGLE]: { _id: config.getUser()._id }, - } - const row = await config.api.row.save(table._id!, rowValues) - expectedRowData = { - _id: row._id, - [FieldType.STRING]: rowValues[FieldType.STRING], - [FieldType.LONGFORM]: rowValues[FieldType.LONGFORM], - [FieldType.OPTIONS]: rowValues[FieldType.OPTIONS], - [FieldType.ARRAY]: rowValues[FieldType.ARRAY], - [FieldType.NUMBER]: rowValues[FieldType.NUMBER], - [FieldType.BOOLEAN]: rowValues[FieldType.BOOLEAN], - [FieldType.DATETIME]: rowValues[FieldType.DATETIME], - [FieldType.ATTACHMENTS]: rowValues[FieldType.ATTACHMENTS].map( - (a: any) => - expect.objectContaining({ - ...a, - url: expect.any(String), - }) - ), - [FieldType.ATTACHMENT_SINGLE]: expect.objectContaining({ - ...rowValues[FieldType.ATTACHMENT_SINGLE], - url: expect.any(String), - }), - [FieldType.FORMULA]: fullSchema[FieldType.FORMULA].formula, - [FieldType.AUTO]: expect.any(Number), - [FieldType.AI]: expect.any(String), - [FieldType.JSON]: rowValues[FieldType.JSON], - [FieldType.INTERNAL]: rowValues[FieldType.INTERNAL], - [FieldType.BARCODEQR]: rowValues[FieldType.BARCODEQR], - [FieldType.SIGNATURE_SINGLE]: expect.objectContaining({ - ...rowValues[FieldType.SIGNATURE_SINGLE], - url: expect.any(String), - }), - [FieldType.BIGINT]: rowValues[FieldType.BIGINT], - [FieldType.BB_REFERENCE]: rowValues[FieldType.BB_REFERENCE].map( - expect.objectContaining - ), - [FieldType.BB_REFERENCE_SINGLE]: expect.objectContaining( - rowValues[FieldType.BB_REFERENCE_SINGLE] - ), - } - }) - - it("as csv", async () => { - const exportedValue = await config.api.row.exportRows( - tableId, - { query: {} }, - RowExportFormat.CSV - ) - - const jsonResult = await config.api.table.csvToJson({ - csvString: exportedValue, - }) - - const stringified = (value: string) => - JSON.stringify(value).replace(/"/g, "'") - - const matchingObject = ( - key: string, - value: any, - isArray: boolean - ) => { - const objectMatcher = `{'${key}':'${value[key]}'.*?}` - if (isArray) { - return expect.stringMatching( - new RegExp(`^\\[${objectMatcher}\\]$`) - ) - } - return expect.stringMatching(new RegExp(`^${objectMatcher}$`)) - } - - expect(jsonResult).toEqual([ - { - ...expectedRowData, - auto: expect.any(String), - array: stringified(expectedRowData["array"]), - attachment: matchingObject( - "key", - expectedRowData["attachment"][0].sample, - true - ), - attachment_single: matchingObject( - "key", - expectedRowData["attachment_single"].sample, - false - ), - boolean: stringified(expectedRowData["boolean"]), - json: stringified(expectedRowData["json"]), - number: stringified(expectedRowData["number"]), - signature_single: matchingObject( - "key", - expectedRowData["signature_single"].sample, - false - ), - bb_reference: matchingObject( - "_id", - expectedRowData["bb_reference"][0].sample, - true - ), - bb_reference_single: matchingObject( - "_id", - expectedRowData["bb_reference_single"].sample, - false - ), - ai: "LLM Output", - }, - ]) - }) - - it("as json", async () => { - const exportedValue = await config.api.row.exportRows( - tableId, - { query: {} }, - RowExportFormat.JSON - ) - - const json = JSON.parse(exportedValue) - expect(json).toEqual([expectedRowData]) - }) - - it("as json with schema", async () => { - const exportedValue = await config.api.row.exportRows( - tableId, - { query: {} }, - RowExportFormat.JSON_WITH_SCHEMA - ) - - const json = JSON.parse(exportedValue) - expect(json).toEqual({ - schema: expect.any(Object), - rows: [expectedRowData], - }) - }) - - it("can handle csv-special characters in strings", async () => { - const badString = 'test":, wow", "test": "wow"' - const table = await config.api.table.save( - saveTableRequest({ - schema: { - string: { - type: FieldType.STRING, - name: "string", - }, - }, - }) - ) - - await config.api.row.save(table._id!, { string: badString }) - - const exportedValue = await config.api.row.exportRows( - table._id!, - { query: {} }, - RowExportFormat.CSV - ) - - const json = await config.api.table.csvToJson( - { - csvString: exportedValue, - }, - { - status: 200, - } - ) - - expect(json).toHaveLength(1) - expect(json[0].string).toEqual(badString) - }) - - it("exported data can be re-imported", async () => { - // export all - const exportedValue = await config.api.row.exportRows( - tableId, - { query: {} }, - RowExportFormat.CSV - ) - - // import all twice - const rows = await config.api.table.csvToJson({ - csvString: exportedValue, - }) - await config.api.row.bulkImport(tableId, { - rows, - }) - await config.api.row.bulkImport(tableId, { - rows, - }) - - const { rows: allRows } = await config.api.row.search(tableId) - - const expectedRow = { - ...expectedRowData, - _id: expect.any(String), - _rev: expect.any(String), - type: "row", - tableId: tableId, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - } - expect(allRows).toEqual([expectedRow, expectedRow, expectedRow]) - }) - }) - }) - - let o2mTable: Table - let m2mTable: Table - beforeAll(async () => { - o2mTable = await config.api.table.save(defaultTable()) - m2mTable = await config.api.table.save(defaultTable()) - }) - - describe.each([ - [ - "relationship fields", - (): Record => ({ - user: { - name: "user", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: o2mTable._id!, - fieldName: "fk_o2m", - }, - users: { - name: "users", - relationshipType: RelationshipType.MANY_TO_MANY, - type: FieldType.LINK, - tableId: m2mTable._id!, - fieldName: "fk_m2m", - }, - }), - (tableId: string) => - config.api.row.save(tableId, { - name: uuid.v4(), - description: generator.paragraph(), - tableId, - }), - (row: Row) => ({ - _id: row._id, - primaryDisplay: row.name, - }), - ], - [ - "bb reference fields", - (): Record => ({ - user: { - name: "user", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - }, - users: { - name: "users", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USERS, - }, - }), - () => config.createUser(), - (row: Row) => ({ - _id: row._id, - primaryDisplay: row.email, - email: row.email, - firstName: row.firstName, - lastName: row.lastName, - }), - ], - ])("links - %s", (__, relSchema, dataGenerator, resultMapper) => { - let tableId: string - let o2mData: Row[] - let m2mData: Row[] - - beforeAll(async () => { + // Upserting isn't yet supported in MSSQL / Oracle, see: + // https://github.com/knex/knex/pull/6050 + !isMSSQL && + !isOracle && + it("should be able to update existing rows with bulkImport", async () => { const table = await config.api.table.save( - defaultTable({ schema: relSchema() }) + saveTableRequest({ + primary: ["userId"], + schema: { + userId: { + type: FieldType.NUMBER, + name: "userId", + constraints: { + presence: true, + }, + }, + name: { + type: FieldType.STRING, + name: "name", + }, + description: { + type: FieldType.STRING, + name: "description", + }, + }, + }) ) - tableId = table._id! - o2mData = [ - await dataGenerator(o2mTable._id!), - await dataGenerator(o2mTable._id!), - await dataGenerator(o2mTable._id!), - await dataGenerator(o2mTable._id!), - ] + const row1 = await config.api.row.save(table._id!, { + userId: 1, + name: "Row 1", + description: "Row 1 description", + }) - m2mData = [ - await dataGenerator(m2mTable._id!), - await dataGenerator(m2mTable._id!), - await dataGenerator(m2mTable._id!), - await dataGenerator(m2mTable._id!), - ] + const row2 = await config.api.row.save(table._id!, { + userId: 2, + name: "Row 2", + description: "Row 2 description", + }) + + await config.api.row.bulkImport(table._id!, { + identifierFields: ["userId"], + rows: [ + { + userId: row1.userId, + name: "Row 1 updated", + description: "Row 1 description updated", + }, + { + userId: row2.userId, + name: "Row 2 updated", + description: "Row 2 description updated", + }, + { + userId: 3, + name: "Row 3", + description: "Row 3 description", + }, + ], + }) + + const rows = await config.api.row.fetch(table._id!) + expect(rows.length).toEqual(3) + + rows.sort((a, b) => a.name.localeCompare(b.name)) + expect(rows[0].name).toEqual("Row 1 updated") + expect(rows[0].description).toEqual("Row 1 description updated") + expect(rows[1].name).toEqual("Row 2 updated") + expect(rows[1].description).toEqual("Row 2 description updated") + expect(rows[2].name).toEqual("Row 3") + expect(rows[2].description).toEqual("Row 3 description") }) - it("can save a row when relationship fields are empty", async () => { - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - }) - - expect(row).toEqual({ - _id: expect.any(String), - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - type: isInternal ? "row" : undefined, - name: "foo", - description: "bar", - tableId, - }) - }) - - it("can save a row with a single relationship field", async () => { - const user = _.sample(o2mData)! - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - user: [user], - }) - - expect(row).toEqual({ - name: "foo", - description: "bar", - tableId, - user: [user].map(u => resultMapper(u)), - _id: expect.any(String), - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - type: isInternal ? "row" : undefined, - [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, - }) - }) - - it("can save a row with a multiple relationship field", async () => { - const selectedUsers = _.sampleSize(m2mData, 2) - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - users: selectedUsers, - }) - - expect(row).toEqual({ - name: "foo", - description: "bar", - tableId, - users: expect.arrayContaining( - selectedUsers.map(u => resultMapper(u)) - ), - _id: expect.any(String), - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - type: isInternal ? "row" : undefined, - }) - }) - - it("can retrieve rows with no populated relationships", async () => { - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - }) - - const retrieved = await config.api.row.get(tableId, row._id!) - expect(retrieved).toEqual({ - name: "foo", - description: "bar", - tableId, - user: undefined, - users: undefined, - _id: row._id, - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - ...defaultRowFields, - }) - }) - - it("can retrieve rows with populated relationships", async () => { - const user1 = _.sample(o2mData)! - const [user2, user3] = _.sampleSize(m2mData, 2) - - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - users: [user2, user3], - user: [user1], - }) - - const retrieved = await config.api.row.get(tableId, row._id!) - expect(retrieved).toEqual({ - name: "foo", - description: "bar", - tableId, - user: expect.arrayContaining([user1].map(u => resultMapper(u))), - users: expect.arrayContaining( - [user2, user3].map(u => resultMapper(u)) - ), - _id: row._id, - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user1.id, - ...defaultRowFields, - }) - }) - - it("can update an existing populated row", async () => { - const user = _.sample(o2mData)! - const [users1, users2, users3] = _.sampleSize(m2mData, 3) - - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - users: [users1, users2], - }) - - const updatedRow = await config.api.row.save(tableId, { - ...row, - user: [user], - users: [users3, users1], - }) - expect(updatedRow).toEqual({ - name: "foo", - description: "bar", - tableId, - user: expect.arrayContaining([user].map(u => resultMapper(u))), - users: expect.arrayContaining( - [users3, users1].map(u => resultMapper(u)) - ), - _id: row._id, - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - type: isInternal ? "row" : undefined, - [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, - }) - }) - - it("can wipe an existing populated relationships in row", async () => { - const [user1, user2] = _.sampleSize(m2mData, 2) - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - users: [user1, user2], - }) - - const updatedRow = await config.api.row.save(tableId, { - ...row, - user: null, - users: null, - }) - expect(updatedRow).toEqual({ - name: "foo", - description: "bar", - tableId, - _id: row._id, - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - type: isInternal ? "row" : undefined, - }) - }) - - it("fetch all will populate the relationships", async () => { - const [user1] = _.sampleSize(o2mData, 1) - const [users1, users2, users3] = _.sampleSize(m2mData, 3) - - const rows = [ - { - name: generator.name(), - description: generator.name(), - users: [users1, users2], - }, - { - name: generator.name(), - description: generator.name(), - user: [user1], - users: [users1, users3], - }, - { - name: generator.name(), - description: generator.name(), - users: [users3], - }, - ] - - await config.api.row.save(tableId, rows[0]) - await config.api.row.save(tableId, rows[1]) - await config.api.row.save(tableId, rows[2]) - - const res = await config.api.row.fetch(tableId) - - expect(res).toEqual( - expect.arrayContaining( - rows.map(r => ({ - name: r.name, - description: r.description, - tableId, - user: r.user?.map(u => resultMapper(u)), - users: r.users?.length - ? expect.arrayContaining(r.users?.map(u => resultMapper(u))) - : undefined, - _id: expect.any(String), - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - [`fk_${o2mTable.name}_fk_o2m`]: - isInternal || !r.user?.length ? undefined : r.user[0].id, - ...defaultRowFields, - })) - ) - ) - }) - - it("search all will populate the relationships", async () => { - const [user1] = _.sampleSize(o2mData, 1) - const [users1, users2, users3] = _.sampleSize(m2mData, 3) - - const rows = [ - { - name: generator.name(), - description: generator.name(), - users: [users1, users2], - }, - { - name: generator.name(), - description: generator.name(), - user: [user1], - users: [users1, users3], - }, - { - name: generator.name(), - description: generator.name(), - users: [users3], - }, - ] - - await config.api.row.save(tableId, rows[0]) - await config.api.row.save(tableId, rows[1]) - await config.api.row.save(tableId, rows[2]) - - const res = await config.api.row.search(tableId) - - expect(res).toEqual({ - rows: expect.arrayContaining( - rows.map(r => ({ - name: r.name, - description: r.description, - tableId, - user: r.user?.map(u => resultMapper(u)), - users: r.users?.length - ? expect.arrayContaining(r.users?.map(u => resultMapper(u))) - : undefined, - _id: expect.any(String), - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - [`fk_${o2mTable.name}_fk_o2m`]: - isInternal || !r.user?.length ? undefined : r.user[0].id, - ...defaultRowFields, - })) - ), - ...(isInternal - ? {} - : { - hasNextPage: false, - }), - }) - }) - }) - // Upserting isn't yet supported in MSSQL or Oracle, see: // https://github.com/knex/knex/pull/6050 !isMSSQL && !isOracle && - describe("relationships", () => { - let tableId: string - let viewId: string + !isInternal && + it("should be able to update existing rows with composite primary keys with bulkImport", async () => { + const tableName = uuid.v4() + await client?.schema.createTable(tableName, table => { + table.integer("companyId") + table.integer("userId") + table.string("name") + table.string("description") + table.primary(["companyId", "userId"]) + }) - let auxData: Row[] = [] + const resp = await config.api.datasource.fetchSchema({ + datasourceId: datasource!._id!, + }) + const table = resp.datasource.entities![tableName] - beforeAll(async () => { - const aux2Table = await config.api.table.save(saveTableRequest()) - const aux2Data = await config.api.row.save(aux2Table._id!, {}) + const row1 = await config.api.row.save(table._id!, { + companyId: 1, + userId: 1, + name: "Row 1", + description: "Row 1 description", + }) - const auxTable = await config.api.table.save( - saveTableRequest({ - primaryDisplay: "name", + const row2 = await config.api.row.save(table._id!, { + companyId: 1, + userId: 2, + name: "Row 2", + description: "Row 2 description", + }) + + await config.api.row.bulkImport(table._id!, { + identifierFields: ["companyId", "userId"], + rows: [ + { + companyId: 1, + userId: row1.userId, + name: "Row 1 updated", + description: "Row 1 description updated", + }, + { + companyId: 1, + userId: row2.userId, + name: "Row 2 updated", + description: "Row 2 description updated", + }, + { + companyId: 1, + userId: 3, + name: "Row 3", + description: "Row 3 description", + }, + ], + }) + + const rows = await config.api.row.fetch(table._id!) + expect(rows.length).toEqual(3) + + rows.sort((a, b) => a.name.localeCompare(b.name)) + expect(rows[0].name).toEqual("Row 1 updated") + expect(rows[0].description).toEqual("Row 1 description updated") + expect(rows[1].name).toEqual("Row 2 updated") + expect(rows[1].description).toEqual("Row 2 description updated") + expect(rows[2].name).toEqual("Row 3") + expect(rows[2].description).toEqual("Row 3 description") + }) + + // Upserting isn't yet supported in MSSQL/Oracle, see: + // https://github.com/knex/knex/pull/6050 + !isMSSQL && + !isOracle && + !isInternal && + it("should be able to update existing rows an autoID primary key", async () => { + const tableName = uuid.v4() + await client!.schema.createTable(tableName, table => { + table.increments("userId").primary() + table.string("name") + }) + + const resp = await config.api.datasource.fetchSchema({ + datasourceId: datasource!._id!, + }) + const table = resp.datasource.entities![tableName] + + const row1 = await config.api.row.save(table._id!, { + name: "Clare", + }) + + const row2 = await config.api.row.save(table._id!, { + name: "Jeff", + }) + + await config.api.row.bulkImport(table._id!, { + identifierFields: ["userId"], + rows: [ + { + userId: row1.userId, + name: "Clare updated", + }, + { + userId: row2.userId, + name: "Jeff updated", + }, + ], + }) + + const rows = await config.api.row.fetch(table._id!) + expect(rows.length).toEqual(2) + + rows.sort((a, b) => a.name.localeCompare(b.name)) + expect(rows[0].name).toEqual("Clare updated") + expect(rows[1].name).toEqual("Jeff updated") + }) + }) + + describe("enrich", () => { + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) + }) + + it("should allow enriching some linked rows", async () => { + const { linkedTable, firstRow, secondRow } = await tenancy.doInTenant( + config.getTenantId(), + async () => { + const linkedTable = await config.api.table.save( + defaultTable({ schema: { - name: { - name: "name", - type: FieldType.STRING, - constraints: { presence: true }, - }, - age: { - name: "age", - type: FieldType.NUMBER, - constraints: { presence: true }, - }, - address: { - name: "address", - type: FieldType.STRING, - constraints: { presence: true }, - visible: false, - }, link: { name: "link", + fieldName: "link", type: FieldType.LINK, - tableId: aux2Table._id!, - relationshipType: RelationshipType.MANY_TO_MANY, - fieldName: "fk_aux", - constraints: { presence: true }, - }, - formula: { - name: "formula", - type: FieldType.FORMULA, - formula: "{{ any }}", - constraints: { presence: true }, + relationshipType: RelationshipType.ONE_TO_MANY, + tableId: table._id!, }, }, }) ) - const auxTableId = auxTable._id! - - for (const name of generator.unique(() => generator.name(), 10)) { - auxData.push( - await config.api.row.save(auxTableId, { - name, - age: generator.age(), - address: generator.address(), - link: [aux2Data], - }) - ) - } - - const table = await config.api.table.save( - saveTableRequest({ - schema: { - title: { - name: "title", - type: FieldType.STRING, - constraints: { presence: true }, - }, - relWithNoSchema: { - name: "relWithNoSchema", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: auxTableId, - fieldName: "fk_relWithNoSchema", - constraints: { presence: true }, - }, - relWithEmptySchema: { - name: "relWithEmptySchema", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: auxTableId, - fieldName: "fk_relWithEmptySchema", - constraints: { presence: true }, - }, - relWithFullSchema: { - name: "relWithFullSchema", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: auxTableId, - fieldName: "fk_relWithFullSchema", - constraints: { presence: true }, - }, - relWithHalfSchema: { - name: "relWithHalfSchema", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: auxTableId, - fieldName: "fk_relWithHalfSchema", - constraints: { presence: true }, - }, - relWithIllegalSchema: { - name: "relWithIllegalSchema", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: auxTableId, - fieldName: "fk_relWithIllegalSchema", - constraints: { presence: true }, - }, - }, - }) - ) - tableId = table._id! - const view = await config.api.viewV2.create({ - name: generator.guid(), - tableId, - schema: { - title: { - visible: true, - }, - relWithNoSchema: { - visible: true, - }, - relWithEmptySchema: { - visible: true, - columns: {}, - }, - relWithFullSchema: { - visible: true, - columns: Object.keys(auxTable.schema).reduce< - Record - >((acc, c) => ({ ...acc, [c]: { visible: true } }), {}), - }, - relWithHalfSchema: { - visible: true, - columns: { - name: { visible: true }, - age: { visible: false, readonly: true }, - }, - }, - relWithIllegalSchema: { - visible: true, - columns: { - name: { visible: true }, - address: { visible: true }, - unexisting: { visible: true }, - }, - }, - }, + const firstRow = await config.api.row.save(table._id!, { + name: "Test Contact", + description: "original description", }) + const secondRow = await config.api.row.save(linkedTable._id!, { + name: "Test 2", + description: "og desc", + link: [{ _id: firstRow._id }], + }) + return { linkedTable, firstRow, secondRow } + } + ) + const rowUsage = await getRowUsage() - viewId = view.id - }) + // test basic enrichment + const resBasic = await config.api.row.get( + linkedTable._id!, + secondRow._id! + ) + expect(resBasic.link.length).toBe(1) + expect(resBasic.link[0]).toEqual({ + _id: firstRow._id, + primaryDisplay: firstRow.name, + }) - const testScenarios: [string, (row: Row) => Promise | Row][] = [ - ["get row", (row: Row) => config.api.row.get(viewId, row._id!)], - [ - "from view search", - async (row: Row) => { - const { rows } = await config.api.viewV2.search(viewId) - return rows.find(r => r._id === row._id!) - }, - ], - ["from original saved row", (row: Row) => row], - ["from updated row", (row: Row) => config.api.row.save(viewId, row)], - ] + // test full enrichment + const resEnriched = await config.api.row.getEnriched( + linkedTable._id!, + secondRow._id! + ) + expect(resEnriched.link.length).toBe(1) + expect(resEnriched.link[0]._id).toBe(firstRow._id) + expect(resEnriched.link[0].name).toBe("Test Contact") + expect(resEnriched.link[0].description).toBe("original description") + await assertRowUsage(rowUsage) + }) + }) - it.each(testScenarios)( - "can retrieve rows with populated relationships (via %s)", - async (__, retrieveDelegate) => { - const otherRows = _.sampleSize(auxData, 5) - - const row = await config.api.row.save(viewId, { - title: generator.word(), - relWithNoSchema: [otherRows[0]], - relWithEmptySchema: [otherRows[1]], - relWithFullSchema: [otherRows[2]], - relWithHalfSchema: [otherRows[3]], - relWithIllegalSchema: [otherRows[4]], - }) - - const retrieved = await retrieveDelegate(row) - - expect(retrieved).toEqual( - expect.objectContaining({ - title: row.title, - relWithNoSchema: [ - { - _id: otherRows[0]._id, - primaryDisplay: otherRows[0].name, - }, - ], - relWithEmptySchema: [ - { - _id: otherRows[1]._id, - primaryDisplay: otherRows[1].name, - }, - ], - relWithFullSchema: [ - { - _id: otherRows[2]._id, - primaryDisplay: otherRows[2].name, - name: otherRows[2].name, - age: otherRows[2].age, - id: otherRows[2].id, - }, - ], - relWithHalfSchema: [ - { - _id: otherRows[3]._id, - primaryDisplay: otherRows[3].name, - name: otherRows[3].name, - }, - ], - relWithIllegalSchema: [ - { - _id: otherRows[4]._id, - primaryDisplay: otherRows[4].name, - name: otherRows[4].name, - }, - ], - }) - ) - } + isInternal && + describe("attachments and signatures", () => { + const coreAttachmentEnrichment = async ( + schema: TableSchema, + field: string, + attachmentCfg: string | string[] + ) => { + const testTable = await config.api.table.save( + defaultTable({ + schema, + }) ) - - it.each([ - [ - "from table fetch", - async (row: Row) => { - const rows = await config.api.row.fetch(tableId) - return rows.find(r => r._id === row._id!) - }, - ], - [ - "from table search", - async (row: Row) => { - const { rows } = await config.api.row.search(tableId) - return rows.find(r => r._id === row._id!) - }, - ], - ])( - "does not enrich when fetching from the table (via %s)", - async (__, retrieveDelegate) => { - const otherRows = _.sampleSize(auxData, 5) - - const row = await config.api.row.save(viewId, { - title: generator.word(), - relWithNoSchema: [otherRows[0]], - relWithEmptySchema: [otherRows[1]], - relWithFullSchema: [otherRows[2]], - relWithHalfSchema: [otherRows[3]], - relWithIllegalSchema: [otherRows[4]], - }) - - const retrieved = await retrieveDelegate(row) - - expect(retrieved).toEqual( - expect.objectContaining({ - title: row.title, - relWithNoSchema: [ - { - _id: otherRows[0]._id, - primaryDisplay: otherRows[0].name, - }, - ], - relWithEmptySchema: [ - { - _id: otherRows[1]._id, - primaryDisplay: otherRows[1].name, - }, - ], - relWithFullSchema: [ - { - _id: otherRows[2]._id, - primaryDisplay: otherRows[2].name, - }, - ], - relWithHalfSchema: [ - { - _id: otherRows[3]._id, - primaryDisplay: otherRows[3].name, - }, - ], - relWithIllegalSchema: [ - { - _id: otherRows[4]._id, - primaryDisplay: otherRows[4].name, - }, - ], - }) - ) + const attachmentToStoreKey = (attachmentId: string) => { + return { + key: `${config.getAppId()}/attachments/${attachmentId}`, } + } + const draftRow = { + name: "test", + description: "test", + [field]: + typeof attachmentCfg === "string" + ? attachmentToStoreKey(attachmentCfg) + : attachmentCfg.map(attachmentToStoreKey), + tableId: testTable._id, + } + const row = await config.api.row.save(testTable._id!, draftRow) + + await withEnv({ SELF_HOSTED: "true" }, async () => { + return context.doInAppContext(config.getAppId(), async () => { + const enriched: Row[] = await outputProcessing(testTable, [row]) + const [targetRow] = enriched + const attachmentEntries = Array.isArray(targetRow[field]) + ? targetRow[field] + : [targetRow[field]] + + for (const entry of attachmentEntries) { + const attachmentId = entry.key.split("/").pop() + expect(entry.url.split("?")[0]).toBe( + `/files/signed/prod-budi-app-assets/${config.getProdAppId()}/attachments/${attachmentId}` + ) + } + }) + }) + } + + it("should allow enriching single attachment rows", async () => { + await coreAttachmentEnrichment( + { + attachment: { + type: FieldType.ATTACHMENT_SINGLE, + name: "attachment", + constraints: { presence: false }, + }, + }, + "attachment", + `${uuid.v4()}.csv` ) }) + it("should allow enriching attachment list rows", async () => { + await coreAttachmentEnrichment( + { + attachments: { + type: FieldType.ATTACHMENTS, + name: "attachments", + constraints: { type: "array", presence: false }, + }, + }, + "attachments", + [`${uuid.v4()}.csv`] + ) + }) + + it("should allow enriching signature rows", async () => { + await coreAttachmentEnrichment( + { + signature: { + type: FieldType.SIGNATURE_SINGLE, + name: "signature", + constraints: { presence: false }, + }, + }, + "signature", + `${uuid.v4()}.png` + ) + }) + }) + + describe("exportRows", () => { + beforeEach(async () => { + table = await config.api.table.save(defaultTable()) + }) + isInternal && - describe("AI fields", () => { - let table: Table - - beforeAll(async () => { - mocks.licenses.useBudibaseAI() - mocks.licenses.useAICustomConfigs() - table = await config.api.table.save( - saveTableRequest({ - schema: { - ai: { - name: "ai", - type: FieldType.AI, - operation: AIOperationEnum.PROMPT, - prompt: "Convert the following to German: '{{ product }}'", - }, - product: { - name: "product", - type: FieldType.STRING, - }, - }, - }) - ) - - await config.api.row.save(table._id!, { - product: generator.word(), - }) + it("should not export internal couchdb fields", async () => { + const existing = await config.api.row.save(table._id!, { + name: generator.guid(), + description: generator.paragraph(), }) - - afterAll(() => { - jest.unmock("@budibase/pro") + const res = await config.api.row.exportRows(table._id!, { + rows: [existing._id!], }) + const results = JSON.parse(res) + expect(results.length).toEqual(1) + const row = results[0] - it("should be able to save a row with an AI column", async () => { - const { rows } = await config.api.row.search(table._id!) - expect(rows.length).toBe(1) - expect(rows[0].ai).toEqual("Mock LLM Response") + expect(Object.keys(row)).toEqual(["_id", "name", "description"]) + }) + + !isInternal && + it("should allow exporting all columns", async () => { + const existing = await config.api.row.save(table._id!, {}) + const res = await config.api.row.exportRows(table._id!, { + rows: [existing._id!], }) + const results = JSON.parse(res) + expect(results.length).toEqual(1) + const row = results[0] - it("should be able to update a row with an AI column", async () => { - const { rows } = await config.api.row.search(table._id!) - expect(rows.length).toBe(1) - await config.api.row.save(table._id!, { - product: generator.word(), - ...rows[0], - }) - expect(rows.length).toBe(1) - expect(rows[0].ai).toEqual("Mock LLM Response") + // Ensure all original columns were exported + expect(Object.keys(row).length).toBe(Object.keys(existing).length) + Object.keys(existing).forEach(key => { + expect(row[key]).toEqual(existing[key]) }) }) - describe("Formula fields", () => { - let table: Table - let otherTable: Table - let relatedRow: Row, mainRow: Row + it("should allow exporting without filtering", async () => { + const existing = await config.api.row.save(table._id!, {}) + const res = await config.api.row.exportRows(table._id!) + const results = JSON.parse(res) + expect(results.length).toEqual(1) + const row = results[0] + + expect(row._id).toEqual(existing._id) + }) + + it("should allow exporting only certain columns", async () => { + const existing = await config.api.row.save(table._id!, {}) + const res = await config.api.row.exportRows(table._id!, { + rows: [existing._id!], + columns: ["_id"], + }) + const results = JSON.parse(res) + expect(results.length).toEqual(1) + const row = results[0] + + // Ensure only the _id column was exported + expect(Object.keys(row).length).toEqual(1) + expect(row._id).toEqual(existing._id) + }) + + it("should handle single quotes in row filtering", async () => { + const existing = await config.api.row.save(table._id!, {}) + const res = await config.api.row.exportRows(table._id!, { + rows: [`['${existing._id!}']`], + }) + const results = JSON.parse(res) + expect(results.length).toEqual(1) + const row = results[0] + expect(row._id).toEqual(existing._id) + }) + + it("should return an error if no table is found", async () => { + const existing = await config.api.row.save(table._id!, {}) + await config.api.row.exportRows( + "1234567", + { rows: [existing._id!] }, + RowExportFormat.JSON, + { status: 404 } + ) + }) + + // MSSQL needs a setting called IDENTITY_INSERT to be set to ON to allow writing + // to identity columns. This is not something Budibase does currently. + !isMSSQL && + it("should handle filtering by composite primary keys", async () => { + const tableRequest = saveTableRequest({ + primary: ["number", "string"], + schema: { + string: { + type: FieldType.STRING, + name: "string", + }, + number: { + type: FieldType.NUMBER, + name: "number", + }, + }, + }) + delete tableRequest.schema.id + + const table = await config.api.table.save(tableRequest) + const toCreate = generator + .unique(() => generator.integer({ min: 0, max: 10000 }), 10) + .map(number => ({ number, string: generator.word({ length: 30 }) })) + + const rows = await Promise.all( + toCreate.map(d => config.api.row.save(table._id!, d)) + ) + + const res = await config.api.row.exportRows(table._id!, { + rows: _.sampleSize(rows, 3).map(r => r._id!), + }) + const results = JSON.parse(res) + expect(results.length).toEqual(3) + }) + + describe("should allow exporting all column types", () => { + let tableId: string + let expectedRowData: Row beforeAll(async () => { - otherTable = await config.api.table.save(defaultTable()) - table = await config.api.table.save( + const fullSchema = setup.structures.fullSchemaWithoutLinks({ + allRequired: true, + }) + + const table = await config.api.table.save( + saveTableRequest({ + ...setup.structures.basicTable(), + schema: fullSchema, + primary: ["string"], + }) + ) + tableId = table._id! + + const rowValues: Record = { + [FieldType.STRING]: generator.guid(), + [FieldType.LONGFORM]: generator.paragraph(), + [FieldType.OPTIONS]: "option 2", + [FieldType.ARRAY]: ["options 2", "options 4"], + [FieldType.NUMBER]: generator.natural(), + [FieldType.BOOLEAN]: generator.bool(), + [FieldType.DATETIME]: generator.date().toISOString(), + [FieldType.ATTACHMENTS]: [setup.structures.basicAttachment()], + [FieldType.ATTACHMENT_SINGLE]: setup.structures.basicAttachment(), + [FieldType.FORMULA]: undefined, // generated field + [FieldType.AUTO]: undefined, // generated field + [FieldType.AI]: "LLM Output", + [FieldType.JSON]: { name: generator.guid() }, + [FieldType.INTERNAL]: generator.guid(), + [FieldType.BARCODEQR]: generator.guid(), + [FieldType.SIGNATURE_SINGLE]: setup.structures.basicAttachment(), + [FieldType.BIGINT]: generator.integer().toString(), + [FieldType.BB_REFERENCE]: [{ _id: config.getUser()._id }], + [FieldType.BB_REFERENCE_SINGLE]: { _id: config.getUser()._id }, + } + const row = await config.api.row.save(table._id!, rowValues) + expectedRowData = { + _id: row._id, + [FieldType.STRING]: rowValues[FieldType.STRING], + [FieldType.LONGFORM]: rowValues[FieldType.LONGFORM], + [FieldType.OPTIONS]: rowValues[FieldType.OPTIONS], + [FieldType.ARRAY]: rowValues[FieldType.ARRAY], + [FieldType.NUMBER]: rowValues[FieldType.NUMBER], + [FieldType.BOOLEAN]: rowValues[FieldType.BOOLEAN], + [FieldType.DATETIME]: rowValues[FieldType.DATETIME], + [FieldType.ATTACHMENTS]: rowValues[FieldType.ATTACHMENTS].map( + (a: any) => + expect.objectContaining({ + ...a, + url: expect.any(String), + }) + ), + [FieldType.ATTACHMENT_SINGLE]: expect.objectContaining({ + ...rowValues[FieldType.ATTACHMENT_SINGLE], + url: expect.any(String), + }), + [FieldType.FORMULA]: fullSchema[FieldType.FORMULA].formula, + [FieldType.AUTO]: expect.any(Number), + [FieldType.AI]: expect.any(String), + [FieldType.JSON]: rowValues[FieldType.JSON], + [FieldType.INTERNAL]: rowValues[FieldType.INTERNAL], + [FieldType.BARCODEQR]: rowValues[FieldType.BARCODEQR], + [FieldType.SIGNATURE_SINGLE]: expect.objectContaining({ + ...rowValues[FieldType.SIGNATURE_SINGLE], + url: expect.any(String), + }), + [FieldType.BIGINT]: rowValues[FieldType.BIGINT], + [FieldType.BB_REFERENCE]: rowValues[FieldType.BB_REFERENCE].map( + expect.objectContaining + ), + [FieldType.BB_REFERENCE_SINGLE]: expect.objectContaining( + rowValues[FieldType.BB_REFERENCE_SINGLE] + ), + } + }) + + it("as csv", async () => { + const exportedValue = await config.api.row.exportRows( + tableId, + { query: {} }, + RowExportFormat.CSV + ) + + const jsonResult = await config.api.table.csvToJson({ + csvString: exportedValue, + }) + + const stringified = (value: string) => + JSON.stringify(value).replace(/"/g, "'") + + const matchingObject = (key: string, value: any, isArray: boolean) => { + const objectMatcher = `{'${key}':'${value[key]}'.*?}` + if (isArray) { + return expect.stringMatching(new RegExp(`^\\[${objectMatcher}\\]$`)) + } + return expect.stringMatching(new RegExp(`^${objectMatcher}$`)) + } + + expect(jsonResult).toEqual([ + { + ...expectedRowData, + auto: expect.any(String), + array: stringified(expectedRowData["array"]), + attachment: matchingObject( + "key", + expectedRowData["attachment"][0].sample, + true + ), + attachment_single: matchingObject( + "key", + expectedRowData["attachment_single"].sample, + false + ), + boolean: stringified(expectedRowData["boolean"]), + json: stringified(expectedRowData["json"]), + number: stringified(expectedRowData["number"]), + signature_single: matchingObject( + "key", + expectedRowData["signature_single"].sample, + false + ), + bb_reference: matchingObject( + "_id", + expectedRowData["bb_reference"][0].sample, + true + ), + bb_reference_single: matchingObject( + "_id", + expectedRowData["bb_reference_single"].sample, + false + ), + ai: "LLM Output", + }, + ]) + }) + + it("as json", async () => { + const exportedValue = await config.api.row.exportRows( + tableId, + { query: {} }, + RowExportFormat.JSON + ) + + const json = JSON.parse(exportedValue) + expect(json).toEqual([expectedRowData]) + }) + + it("as json with schema", async () => { + const exportedValue = await config.api.row.exportRows( + tableId, + { query: {} }, + RowExportFormat.JSON_WITH_SCHEMA + ) + + const json = JSON.parse(exportedValue) + expect(json).toEqual({ + schema: expect.any(Object), + rows: [expectedRowData], + }) + }) + + it("can handle csv-special characters in strings", async () => { + const badString = 'test":, wow", "test": "wow"' + const table = await config.api.table.save( saveTableRequest({ schema: { - links: { - name: "links", - fieldName: "links", + string: { + type: FieldType.STRING, + name: "string", + }, + }, + }) + ) + + await config.api.row.save(table._id!, { string: badString }) + + const exportedValue = await config.api.row.exportRows( + table._id!, + { query: {} }, + RowExportFormat.CSV + ) + + const json = await config.api.table.csvToJson( + { + csvString: exportedValue, + }, + { + status: 200, + } + ) + + expect(json).toHaveLength(1) + expect(json[0].string).toEqual(badString) + }) + + it("exported data can be re-imported", async () => { + // export all + const exportedValue = await config.api.row.exportRows( + tableId, + { query: {} }, + RowExportFormat.CSV + ) + + // import all twice + const rows = await config.api.table.csvToJson({ + csvString: exportedValue, + }) + await config.api.row.bulkImport(tableId, { + rows, + }) + await config.api.row.bulkImport(tableId, { + rows, + }) + + const { rows: allRows } = await config.api.row.search(tableId) + + const expectedRow = { + ...expectedRowData, + _id: expect.any(String), + _rev: expect.any(String), + type: "row", + tableId: tableId, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + } + expect(allRows).toEqual([expectedRow, expectedRow, expectedRow]) + }) + }) + }) + + let o2mTable: Table + let m2mTable: Table + beforeAll(async () => { + o2mTable = await config.api.table.save(defaultTable()) + m2mTable = await config.api.table.save(defaultTable()) + }) + + describe.each([ + [ + "relationship fields", + (): Record => ({ + user: { + name: "user", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: o2mTable._id!, + fieldName: "fk_o2m", + }, + users: { + name: "users", + relationshipType: RelationshipType.MANY_TO_MANY, + type: FieldType.LINK, + tableId: m2mTable._id!, + fieldName: "fk_m2m", + }, + }), + (tableId: string) => + config.api.row.save(tableId, { + name: uuid.v4(), + description: generator.paragraph(), + tableId, + }), + (row: Row) => ({ + _id: row._id, + primaryDisplay: row.name, + }), + ], + [ + "bb reference fields", + (): Record => ({ + user: { + name: "user", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + }, + users: { + name: "users", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USERS, + }, + }), + () => config.createUser(), + (row: Row) => ({ + _id: row._id, + primaryDisplay: row.email, + email: row.email, + firstName: row.firstName, + lastName: row.lastName, + }), + ], + ])("links - %s", (__, relSchema, dataGenerator, resultMapper) => { + let tableId: string + let o2mData: Row[] + let m2mData: Row[] + + beforeAll(async () => { + const table = await config.api.table.save( + defaultTable({ schema: relSchema() }) + ) + tableId = table._id! + + o2mData = [ + await dataGenerator(o2mTable._id!), + await dataGenerator(o2mTable._id!), + await dataGenerator(o2mTable._id!), + await dataGenerator(o2mTable._id!), + ] + + m2mData = [ + await dataGenerator(m2mTable._id!), + await dataGenerator(m2mTable._id!), + await dataGenerator(m2mTable._id!), + await dataGenerator(m2mTable._id!), + ] + }) + + it("can save a row when relationship fields are empty", async () => { + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + }) + + expect(row).toEqual({ + _id: expect.any(String), + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + type: isInternal ? "row" : undefined, + name: "foo", + description: "bar", + tableId, + }) + }) + + it("can save a row with a single relationship field", async () => { + const user = _.sample(o2mData)! + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + user: [user], + }) + + expect(row).toEqual({ + name: "foo", + description: "bar", + tableId, + user: [user].map(u => resultMapper(u)), + _id: expect.any(String), + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + type: isInternal ? "row" : undefined, + [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, + }) + }) + + it("can save a row with a multiple relationship field", async () => { + const selectedUsers = _.sampleSize(m2mData, 2) + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + users: selectedUsers, + }) + + expect(row).toEqual({ + name: "foo", + description: "bar", + tableId, + users: expect.arrayContaining(selectedUsers.map(u => resultMapper(u))), + _id: expect.any(String), + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + type: isInternal ? "row" : undefined, + }) + }) + + it("can retrieve rows with no populated relationships", async () => { + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + }) + + const retrieved = await config.api.row.get(tableId, row._id!) + expect(retrieved).toEqual({ + name: "foo", + description: "bar", + tableId, + user: undefined, + users: undefined, + _id: row._id, + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + ...defaultRowFields, + }) + }) + + it("can retrieve rows with populated relationships", async () => { + const user1 = _.sample(o2mData)! + const [user2, user3] = _.sampleSize(m2mData, 2) + + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + users: [user2, user3], + user: [user1], + }) + + const retrieved = await config.api.row.get(tableId, row._id!) + expect(retrieved).toEqual({ + name: "foo", + description: "bar", + tableId, + user: expect.arrayContaining([user1].map(u => resultMapper(u))), + users: expect.arrayContaining([user2, user3].map(u => resultMapper(u))), + _id: row._id, + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user1.id, + ...defaultRowFields, + }) + }) + + it("can update an existing populated row", async () => { + const user = _.sample(o2mData)! + const [users1, users2, users3] = _.sampleSize(m2mData, 3) + + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + users: [users1, users2], + }) + + const updatedRow = await config.api.row.save(tableId, { + ...row, + user: [user], + users: [users3, users1], + }) + expect(updatedRow).toEqual({ + name: "foo", + description: "bar", + tableId, + user: expect.arrayContaining([user].map(u => resultMapper(u))), + users: expect.arrayContaining( + [users3, users1].map(u => resultMapper(u)) + ), + _id: row._id, + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + type: isInternal ? "row" : undefined, + [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, + }) + }) + + it("can wipe an existing populated relationships in row", async () => { + const [user1, user2] = _.sampleSize(m2mData, 2) + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + users: [user1, user2], + }) + + const updatedRow = await config.api.row.save(tableId, { + ...row, + user: null, + users: null, + }) + expect(updatedRow).toEqual({ + name: "foo", + description: "bar", + tableId, + _id: row._id, + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + type: isInternal ? "row" : undefined, + }) + }) + + it("fetch all will populate the relationships", async () => { + const [user1] = _.sampleSize(o2mData, 1) + const [users1, users2, users3] = _.sampleSize(m2mData, 3) + + const rows = [ + { + name: generator.name(), + description: generator.name(), + users: [users1, users2], + }, + { + name: generator.name(), + description: generator.name(), + user: [user1], + users: [users1, users3], + }, + { + name: generator.name(), + description: generator.name(), + users: [users3], + }, + ] + + await config.api.row.save(tableId, rows[0]) + await config.api.row.save(tableId, rows[1]) + await config.api.row.save(tableId, rows[2]) + + const res = await config.api.row.fetch(tableId) + + expect(res).toEqual( + expect.arrayContaining( + rows.map(r => ({ + name: r.name, + description: r.description, + tableId, + user: r.user?.map(u => resultMapper(u)), + users: r.users?.length + ? expect.arrayContaining(r.users?.map(u => resultMapper(u))) + : undefined, + _id: expect.any(String), + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + [`fk_${o2mTable.name}_fk_o2m`]: + isInternal || !r.user?.length ? undefined : r.user[0].id, + ...defaultRowFields, + })) + ) + ) + }) + + it("search all will populate the relationships", async () => { + const [user1] = _.sampleSize(o2mData, 1) + const [users1, users2, users3] = _.sampleSize(m2mData, 3) + + const rows = [ + { + name: generator.name(), + description: generator.name(), + users: [users1, users2], + }, + { + name: generator.name(), + description: generator.name(), + user: [user1], + users: [users1, users3], + }, + { + name: generator.name(), + description: generator.name(), + users: [users3], + }, + ] + + await config.api.row.save(tableId, rows[0]) + await config.api.row.save(tableId, rows[1]) + await config.api.row.save(tableId, rows[2]) + + const res = await config.api.row.search(tableId) + + expect(res).toEqual({ + rows: expect.arrayContaining( + rows.map(r => ({ + name: r.name, + description: r.description, + tableId, + user: r.user?.map(u => resultMapper(u)), + users: r.users?.length + ? expect.arrayContaining(r.users?.map(u => resultMapper(u))) + : undefined, + _id: expect.any(String), + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + [`fk_${o2mTable.name}_fk_o2m`]: + isInternal || !r.user?.length ? undefined : r.user[0].id, + ...defaultRowFields, + })) + ), + ...(isInternal + ? {} + : { + hasNextPage: false, + }), + }) + }) + }) + + // Upserting isn't yet supported in MSSQL or Oracle, see: + // https://github.com/knex/knex/pull/6050 + !isMSSQL && + !isOracle && + describe("relationships", () => { + let tableId: string + let viewId: string + + let auxData: Row[] = [] + + beforeAll(async () => { + const aux2Table = await config.api.table.save(saveTableRequest()) + const aux2Data = await config.api.row.save(aux2Table._id!, {}) + + const auxTable = await config.api.table.save( + saveTableRequest({ + primaryDisplay: "name", + schema: { + name: { + name: "name", + type: FieldType.STRING, + constraints: { presence: true }, + }, + age: { + name: "age", + type: FieldType.NUMBER, + constraints: { presence: true }, + }, + address: { + name: "address", + type: FieldType.STRING, + constraints: { presence: true }, + visible: false, + }, + link: { + name: "link", type: FieldType.LINK, - tableId: otherTable._id!, - relationshipType: RelationshipType.ONE_TO_MANY, + tableId: aux2Table._id!, + relationshipType: RelationshipType.MANY_TO_MANY, + fieldName: "fk_aux", + constraints: { presence: true }, }, formula: { name: "formula", type: FieldType.FORMULA, - formula: "{{ links.0.name }}", + formula: "{{ any }}", + constraints: { presence: true }, + }, + }, + }) + ) + const auxTableId = auxTable._id! + + for (const name of generator.unique(() => generator.name(), 10)) { + auxData.push( + await config.api.row.save(auxTableId, { + name, + age: generator.age(), + address: generator.address(), + link: [aux2Data], + }) + ) + } + + const table = await config.api.table.save( + saveTableRequest({ + schema: { + title: { + name: "title", + type: FieldType.STRING, + constraints: { presence: true }, + }, + relWithNoSchema: { + name: "relWithNoSchema", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: auxTableId, + fieldName: "fk_relWithNoSchema", + constraints: { presence: true }, + }, + relWithEmptySchema: { + name: "relWithEmptySchema", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: auxTableId, + fieldName: "fk_relWithEmptySchema", + constraints: { presence: true }, + }, + relWithFullSchema: { + name: "relWithFullSchema", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: auxTableId, + fieldName: "fk_relWithFullSchema", + constraints: { presence: true }, + }, + relWithHalfSchema: { + name: "relWithHalfSchema", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: auxTableId, + fieldName: "fk_relWithHalfSchema", + constraints: { presence: true }, + }, + relWithIllegalSchema: { + name: "relWithIllegalSchema", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: auxTableId, + fieldName: "fk_relWithIllegalSchema", + constraints: { presence: true }, + }, + }, + }) + ) + tableId = table._id! + const view = await config.api.viewV2.create({ + name: generator.guid(), + tableId, + schema: { + title: { + visible: true, + }, + relWithNoSchema: { + visible: true, + }, + relWithEmptySchema: { + visible: true, + columns: {}, + }, + relWithFullSchema: { + visible: true, + columns: Object.keys(auxTable.schema).reduce< + Record + >((acc, c) => ({ ...acc, [c]: { visible: true } }), {}), + }, + relWithHalfSchema: { + visible: true, + columns: { + name: { visible: true }, + age: { visible: false, readonly: true }, + }, + }, + relWithIllegalSchema: { + visible: true, + columns: { + name: { visible: true }, + address: { visible: true }, + unexisting: { visible: true }, + }, + }, + }, + }) + + viewId = view.id + }) + + const testScenarios: [string, (row: Row) => Promise | Row][] = [ + ["get row", (row: Row) => config.api.row.get(viewId, row._id!)], + [ + "from view search", + async (row: Row) => { + const { rows } = await config.api.viewV2.search(viewId) + return rows.find(r => r._id === row._id!) + }, + ], + ["from original saved row", (row: Row) => row], + ["from updated row", (row: Row) => config.api.row.save(viewId, row)], + ] + + it.each(testScenarios)( + "can retrieve rows with populated relationships (via %s)", + async (__, retrieveDelegate) => { + const otherRows = _.sampleSize(auxData, 5) + + const row = await config.api.row.save(viewId, { + title: generator.word(), + relWithNoSchema: [otherRows[0]], + relWithEmptySchema: [otherRows[1]], + relWithFullSchema: [otherRows[2]], + relWithHalfSchema: [otherRows[3]], + relWithIllegalSchema: [otherRows[4]], + }) + + const retrieved = await retrieveDelegate(row) + + expect(retrieved).toEqual( + expect.objectContaining({ + title: row.title, + relWithNoSchema: [ + { + _id: otherRows[0]._id, + primaryDisplay: otherRows[0].name, + }, + ], + relWithEmptySchema: [ + { + _id: otherRows[1]._id, + primaryDisplay: otherRows[1].name, + }, + ], + relWithFullSchema: [ + { + _id: otherRows[2]._id, + primaryDisplay: otherRows[2].name, + name: otherRows[2].name, + age: otherRows[2].age, + id: otherRows[2].id, + }, + ], + relWithHalfSchema: [ + { + _id: otherRows[3]._id, + primaryDisplay: otherRows[3].name, + name: otherRows[3].name, + }, + ], + relWithIllegalSchema: [ + { + _id: otherRows[4]._id, + primaryDisplay: otherRows[4].name, + name: otherRows[4].name, + }, + ], + }) + ) + } + ) + + it.each([ + [ + "from table fetch", + async (row: Row) => { + const rows = await config.api.row.fetch(tableId) + return rows.find(r => r._id === row._id!) + }, + ], + [ + "from table search", + async (row: Row) => { + const { rows } = await config.api.row.search(tableId) + return rows.find(r => r._id === row._id!) + }, + ], + ])( + "does not enrich when fetching from the table (via %s)", + async (__, retrieveDelegate) => { + const otherRows = _.sampleSize(auxData, 5) + + const row = await config.api.row.save(viewId, { + title: generator.word(), + relWithNoSchema: [otherRows[0]], + relWithEmptySchema: [otherRows[1]], + relWithFullSchema: [otherRows[2]], + relWithHalfSchema: [otherRows[3]], + relWithIllegalSchema: [otherRows[4]], + }) + + const retrieved = await retrieveDelegate(row) + + expect(retrieved).toEqual( + expect.objectContaining({ + title: row.title, + relWithNoSchema: [ + { + _id: otherRows[0]._id, + primaryDisplay: otherRows[0].name, + }, + ], + relWithEmptySchema: [ + { + _id: otherRows[1]._id, + primaryDisplay: otherRows[1].name, + }, + ], + relWithFullSchema: [ + { + _id: otherRows[2]._id, + primaryDisplay: otherRows[2].name, + }, + ], + relWithHalfSchema: [ + { + _id: otherRows[3]._id, + primaryDisplay: otherRows[3].name, + }, + ], + relWithIllegalSchema: [ + { + _id: otherRows[4]._id, + primaryDisplay: otherRows[4].name, + }, + ], + }) + ) + } + ) + }) + + isInternal && + describe("AI fields", () => { + let table: Table + + beforeAll(async () => { + mocks.licenses.useBudibaseAI() + mocks.licenses.useAICustomConfigs() + table = await config.api.table.save( + saveTableRequest({ + schema: { + ai: { + name: "ai", + type: FieldType.AI, + operation: AIOperationEnum.PROMPT, + prompt: "Convert the following to German: '{{ product }}'", + }, + product: { + name: "product", + type: FieldType.STRING, + }, + }, + }) + ) + + await config.api.row.save(table._id!, { + product: generator.word(), + }) + }) + + afterAll(() => { + jest.unmock("@budibase/pro") + }) + + it("should be able to save a row with an AI column", async () => { + const { rows } = await config.api.row.search(table._id!) + expect(rows.length).toBe(1) + expect(rows[0].ai).toEqual("Mock LLM Response") + }) + + it("should be able to update a row with an AI column", async () => { + const { rows } = await config.api.row.search(table._id!) + expect(rows.length).toBe(1) + await config.api.row.save(table._id!, { + product: generator.word(), + ...rows[0], + }) + expect(rows.length).toBe(1) + expect(rows[0].ai).toEqual("Mock LLM Response") + }) + }) + + describe("Formula fields", () => { + let table: Table + let otherTable: Table + let relatedRow: Row, mainRow: Row + + beforeAll(async () => { + otherTable = await config.api.table.save(defaultTable()) + table = await config.api.table.save( + saveTableRequest({ + schema: { + links: { + name: "links", + fieldName: "links", + type: FieldType.LINK, + tableId: otherTable._id!, + relationshipType: RelationshipType.ONE_TO_MANY, + }, + formula: { + name: "formula", + type: FieldType.FORMULA, + formula: "{{ links.0.name }}", + formulaType: FormulaType.DYNAMIC, + }, + }, + }) + ) + + relatedRow = await config.api.row.save(otherTable._id!, { + name: generator.word(), + description: generator.paragraph(), + }) + mainRow = await config.api.row.save(table._id!, { + name: generator.word(), + description: generator.paragraph(), + tableId: table._id!, + links: [relatedRow._id], + }) + }) + + async function updateFormulaColumn( + formula: string, + opts?: { responseType?: FormulaResponseType; formulaType?: FormulaType } + ) { + table = await config.api.table.save({ + ...table, + schema: { + ...table.schema, + formula: { + name: "formula", + type: FieldType.FORMULA, + formula: formula, + responseType: opts?.responseType, + formulaType: opts?.formulaType || FormulaType.DYNAMIC, + }, + }, + }) + } + + it("should be able to search for rows containing formulas", async () => { + const { rows } = await config.api.row.search(table._id!) + expect(rows.length).toBe(1) + expect(rows[0].links.length).toBe(1) + const row = rows[0] + expect(row.formula).toBe(relatedRow.name) + }) + + it("should coerce - number response type", async () => { + await updateFormulaColumn(encodeJS("return 1"), { + responseType: FieldType.NUMBER, + }) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBe(1) + }) + + it("should coerce - boolean response type", async () => { + await updateFormulaColumn(encodeJS("return true"), { + responseType: FieldType.BOOLEAN, + }) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBe(true) + }) + + it("should coerce - datetime response type", async () => { + await updateFormulaColumn(encodeJS("return new Date()"), { + responseType: FieldType.DATETIME, + }) + const { rows } = await config.api.row.search(table._id!) + expect(isDate(rows[0].formula)).toBe(true) + }) + + it("should coerce - datetime with invalid value", async () => { + await updateFormulaColumn(encodeJS("return 'a'"), { + responseType: FieldType.DATETIME, + }) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBeUndefined() + }) + + it("should coerce handlebars", async () => { + await updateFormulaColumn("{{ add 1 1 }}", { + responseType: FieldType.NUMBER, + }) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBe(2) + }) + + it("should coerce handlebars to string (default)", async () => { + await updateFormulaColumn("{{ add 1 1 }}", { + responseType: FieldType.STRING, + }) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBe("2") + }) + + isInternal && + it("should coerce a static handlebars formula", async () => { + await updateFormulaColumn(encodeJS("return 1"), { + responseType: FieldType.NUMBER, + formulaType: FormulaType.STATIC, + }) + // save the row to store the static value + await config.api.row.save(table._id!, mainRow) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBe(1) + }) + }) + + describe("Formula JS protection", () => { + it("should time out JS execution if a single cell takes too long", async () => { + await withEnv({ JS_PER_INVOCATION_TIMEOUT_MS: 40 }, async () => { + const js = encodeJS( + ` + let i = 0; + while (true) { + i++; + } + return i; + ` + ) + + const table = await config.api.table.save( + saveTableRequest({ + schema: { + text: { + name: "text", + type: FieldType.STRING, + }, + formula: { + name: "formula", + type: FieldType.FORMULA, + formula: js, formulaType: FormulaType.DYNAMIC, }, }, }) ) - relatedRow = await config.api.row.save(otherTable._id!, { - name: generator.word(), - description: generator.paragraph(), - }) - mainRow = await config.api.row.save(table._id!, { - name: generator.word(), - description: generator.paragraph(), - tableId: table._id!, - links: [relatedRow._id], - }) - }) - - async function updateFormulaColumn( - formula: string, - opts?: { responseType?: FormulaResponseType; formulaType?: FormulaType } - ) { - table = await config.api.table.save({ - ...table, - schema: { - ...table.schema, - formula: { - name: "formula", - type: FieldType.FORMULA, - formula: formula, - responseType: opts?.responseType, - formulaType: opts?.formulaType || FormulaType.DYNAMIC, - }, - }, - }) - } - - it("should be able to search for rows containing formulas", async () => { + await config.api.row.save(table._id!, { text: "foo" }) const { rows } = await config.api.row.search(table._id!) - expect(rows.length).toBe(1) - expect(rows[0].links.length).toBe(1) + expect(rows).toHaveLength(1) const row = rows[0] - expect(row.formula).toBe(relatedRow.name) + expect(row.text).toBe("foo") + expect(row.formula).toBe("Timed out while executing JS") }) - - it("should coerce - number response type", async () => { - await updateFormulaColumn(encodeJS("return 1"), { - responseType: FieldType.NUMBER, - }) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBe(1) - }) - - it("should coerce - boolean response type", async () => { - await updateFormulaColumn(encodeJS("return true"), { - responseType: FieldType.BOOLEAN, - }) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBe(true) - }) - - it("should coerce - datetime response type", async () => { - await updateFormulaColumn(encodeJS("return new Date()"), { - responseType: FieldType.DATETIME, - }) - const { rows } = await config.api.row.search(table._id!) - expect(isDate(rows[0].formula)).toBe(true) - }) - - it("should coerce - datetime with invalid value", async () => { - await updateFormulaColumn(encodeJS("return 'a'"), { - responseType: FieldType.DATETIME, - }) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBeUndefined() - }) - - it("should coerce handlebars", async () => { - await updateFormulaColumn("{{ add 1 1 }}", { - responseType: FieldType.NUMBER, - }) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBe(2) - }) - - it("should coerce handlebars to string (default)", async () => { - await updateFormulaColumn("{{ add 1 1 }}", { - responseType: FieldType.STRING, - }) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBe("2") - }) - - isInternal && - it("should coerce a static handlebars formula", async () => { - await updateFormulaColumn(encodeJS("return 1"), { - responseType: FieldType.NUMBER, - formulaType: FormulaType.STATIC, - }) - // save the row to store the static value - await config.api.row.save(table._id!, mainRow) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBe(1) - }) }) - describe("Formula JS protection", () => { - it("should time out JS execution if a single cell takes too long", async () => { - await withEnv({ JS_PER_INVOCATION_TIMEOUT_MS: 40 }, async () => { + it("should time out JS execution if a multiple cells take too long", async () => { + await withEnv( + { + JS_PER_INVOCATION_TIMEOUT_MS: 40, + JS_PER_REQUEST_TIMEOUT_MS: 80, + }, + async () => { const js = encodeJS( ` let i = 0; @@ -3359,127 +3390,83 @@ datasourceDescribe( }) ) - await config.api.row.save(table._id!, { text: "foo" }) - const { rows } = await config.api.row.search(table._id!) - expect(rows).toHaveLength(1) - const row = rows[0] - expect(row.text).toBe("foo") - expect(row.formula).toBe("Timed out while executing JS") - }) - }) + for (let i = 0; i < 10; i++) { + await config.api.row.save(table._id!, { text: "foo" }) + } - it("should time out JS execution if a multiple cells take too long", async () => { - await withEnv( - { - JS_PER_INVOCATION_TIMEOUT_MS: 40, - JS_PER_REQUEST_TIMEOUT_MS: 80, - }, - async () => { - const js = encodeJS( - ` - let i = 0; - while (true) { - i++; + // Run this test 3 times to make sure that there's no cross-request + // pollution of the execution time tracking. + for (let reqs = 0; reqs < 3; reqs++) { + const { rows } = await config.api.row.search(table._id!) + expect(rows).toHaveLength(10) + + let i = 0 + for (; i < 10; i++) { + const row = rows[i] + if (row.formula !== JsTimeoutError.message) { + break } - return i; - ` - ) - - const table = await config.api.table.save( - saveTableRequest({ - schema: { - text: { - name: "text", - type: FieldType.STRING, - }, - formula: { - name: "formula", - type: FieldType.FORMULA, - formula: js, - formulaType: FormulaType.DYNAMIC, - }, - }, - }) - ) - - for (let i = 0; i < 10; i++) { - await config.api.row.save(table._id!, { text: "foo" }) } - // Run this test 3 times to make sure that there's no cross-request - // pollution of the execution time tracking. - for (let reqs = 0; reqs < 3; reqs++) { - const { rows } = await config.api.row.search(table._id!) - expect(rows).toHaveLength(10) + // Given the execution times are not deterministic, we can't be sure + // of the exact number of rows that were executed before the timeout + // but it should absolutely be at least 1. + expect(i).toBeGreaterThan(0) + expect(i).toBeLessThan(5) - let i = 0 - for (; i < 10; i++) { - const row = rows[i] - if (row.formula !== JsTimeoutError.message) { - break - } - } - - // Given the execution times are not deterministic, we can't be sure - // of the exact number of rows that were executed before the timeout - // but it should absolutely be at least 1. - expect(i).toBeGreaterThan(0) - expect(i).toBeLessThan(5) - - for (; i < 10; i++) { - const row = rows[i] - expect(row.text).toBe("foo") - expect(row.formula).toStartWith("CPU time limit exceeded ") - } + for (; i < 10; i++) { + const row = rows[i] + expect(row.text).toBe("foo") + expect(row.formula).toStartWith("CPU time limit exceeded ") } } - ) - }) - - it("should not carry over context between formulas", async () => { - const js = encodeJS(`return $("[text]");`) - const table = await config.api.table.save( - saveTableRequest({ - schema: { - text: { - name: "text", - type: FieldType.STRING, - }, - formula: { - name: "formula", - type: FieldType.FORMULA, - formula: js, - formulaType: FormulaType.DYNAMIC, - }, - }, - }) - ) - - for (let i = 0; i < 10; i++) { - await config.api.row.save(table._id!, { text: `foo${i}` }) } - - const { rows } = await config.api.row.search(table._id!) - expect(rows).toHaveLength(10) - - const formulaValues = rows.map(r => r.formula) - expect(formulaValues).toEqual( - expect.arrayContaining([ - "foo0", - "foo1", - "foo2", - "foo3", - "foo4", - "foo5", - "foo6", - "foo7", - "foo8", - "foo9", - ]) - ) - }) + ) }) - } -) + + it("should not carry over context between formulas", async () => { + const js = encodeJS(`return $("[text]");`) + const table = await config.api.table.save( + saveTableRequest({ + schema: { + text: { + name: "text", + type: FieldType.STRING, + }, + formula: { + name: "formula", + type: FieldType.FORMULA, + formula: js, + formulaType: FormulaType.DYNAMIC, + }, + }, + }) + ) + + for (let i = 0; i < 10; i++) { + await config.api.row.save(table._id!, { text: `foo${i}` }) + } + + const { rows } = await config.api.row.search(table._id!) + expect(rows).toHaveLength(10) + + const formulaValues = rows.map(r => r.formula) + expect(formulaValues).toEqual( + expect.arrayContaining([ + "foo0", + "foo1", + "foo2", + "foo3", + "foo4", + "foo5", + "foo6", + "foo7", + "foo8", + "foo9", + ]) + ) + }) + }) +}) // todo: remove me diff --git a/packages/server/src/integrations/tests/utils/index.ts b/packages/server/src/integrations/tests/utils/index.ts index 5e7316c39a..0c5c308fb2 100644 --- a/packages/server/src/integrations/tests/utils/index.ts +++ b/packages/server/src/integrations/tests/utils/index.ts @@ -35,7 +35,6 @@ const providers: Record = { } export interface DatasourceDescribeOpts { - name: string only?: DatabaseName[] exclude?: DatabaseName[] } @@ -103,15 +102,14 @@ function createDummyTest() { } export function datasourceDescribe( - opts: DatasourceDescribeOpts, - cb: (args: DatasourceDescribeReturn) => void -) { + opts: DatasourceDescribeOpts +): DatabaseName[] { if (process.env.DATASOURCE === "none") { createDummyTest() - return + process.exit(0) } - const { name, only, exclude } = opts + const { only, exclude } = opts if (only && exclude) { throw new Error("you can only supply one of 'only' or 'exclude'") @@ -130,36 +128,32 @@ export function datasourceDescribe( if (databases.length === 0) { createDummyTest() - return + process.exit(0) } - describe.each(databases)(name, name => { - const config = new TestConfiguration() + return databases +} - afterAll(() => { - config.end() - }) - - cb({ - name, - config, - dsProvider: () => createDatasources(config, name), - isInternal: name === DatabaseName.SQS, - isExternal: name !== DatabaseName.SQS, - isSql: [ - DatabaseName.MARIADB, - DatabaseName.MYSQL, - DatabaseName.POSTGRES, - DatabaseName.SQL_SERVER, - DatabaseName.ORACLE, - ].includes(name), - isMySQL: name === DatabaseName.MYSQL, - isPostgres: name === DatabaseName.POSTGRES, - isMongodb: name === DatabaseName.MONGODB, - isMSSQL: name === DatabaseName.SQL_SERVER, - isOracle: name === DatabaseName.ORACLE, - }) - }) +export function datasourceProps(dbName: DatabaseName) { + const config = new TestConfiguration() + return { + config, + dsProvider: () => createDatasources(config, dbName), + isInternal: dbName === DatabaseName.SQS, + isExternal: dbName !== DatabaseName.SQS, + isSql: [ + DatabaseName.MARIADB, + DatabaseName.MYSQL, + DatabaseName.POSTGRES, + DatabaseName.SQL_SERVER, + DatabaseName.ORACLE, + ].includes(dbName), + isMySQL: dbName === DatabaseName.MYSQL, + isPostgres: dbName === DatabaseName.POSTGRES, + isMongodb: dbName === DatabaseName.MONGODB, + isMSSQL: dbName === DatabaseName.SQL_SERVER, + isOracle: dbName === DatabaseName.ORACLE, + } } function getDatasource( From c7a0489b82440c476fe7372ee8387c582ef2846c Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 18 Nov 2024 17:34:35 +0000 Subject: [PATCH 09/40] Single function. --- .../server/src/api/routes/tests/row.spec.ts | 6418 +++++++++-------- .../src/integrations/tests/utils/index.ts | 15 +- 2 files changed, 3227 insertions(+), 3206 deletions(-) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index 2eb7c45e58..02995e6d0a 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -3,7 +3,6 @@ import * as setup from "./utilities" import { DatabaseName, datasourceDescribe, - datasourceProps, } from "../../../integrations/tests/utils" import tk from "timekeeper" @@ -86,404 +85,163 @@ function encodeJS(binding: string) { return `{{ js "${Buffer.from(binding).toString("base64")}"}}` } -const databases = datasourceDescribe({ exclude: [DatabaseName.MONGODB] }) +const descriptions = datasourceDescribe({ exclude: [DatabaseName.MONGODB] }) -describe.each(databases)("/rows (%s)", dbName => { - const { config, dsProvider, isInternal, isMSSQL, isOracle } = - datasourceProps(dbName) - let table: Table - let datasource: Datasource | undefined - let client: Knex | undefined - - beforeAll(async () => { - const ds = await dsProvider() - datasource = ds.datasource - client = ds.client - }) - - afterAll(async () => { - setup.afterAll() - }) - - function saveTableRequest( - // We omit the name field here because it's generated in the function with a - // high likelihood to be unique. Tests should not have any reason to control - // the table name they're writing to. - ...overrides: Partial>[] - ): SaveTableRequest { - const defaultSchema: TableSchema = { - id: { - type: FieldType.NUMBER, - name: "id", - autocolumn: true, - constraints: { - presence: true, - }, - }, - } - - for (const override of overrides) { - if (override.primary) { - delete defaultSchema.id - } - } - - const req: SaveTableRequest = { - name: uuid.v4().substring(0, 10), - type: "table", - sourceType: datasource - ? TableSourceType.EXTERNAL - : TableSourceType.INTERNAL, - sourceId: datasource ? datasource._id! : INTERNAL_TABLE_SOURCE_ID, - primary: ["id"], - schema: defaultSchema, - } - const merged = merge(req, ...overrides) - return merged - } - - function defaultTable( - // We omit the name field here because it's generated in the function with a - // high likelihood to be unique. Tests should not have any reason to control - // the table name they're writing to. - ...overrides: Partial>[] - ): SaveTableRequest { - return saveTableRequest( - { - primaryDisplay: "name", - schema: { - name: { - type: FieldType.STRING, - name: "name", - constraints: { - type: "string", - }, - }, - description: { - type: FieldType.STRING, - name: "description", - constraints: { - type: "string", - }, - }, - }, - }, - ...overrides - ) - } - - beforeEach(async () => { - mocks.licenses.useCloudFree() - }) - - const getRowUsage = async () => { - const { total } = await config.doInContext(undefined, () => - quotas.getCurrentUsageValues(QuotaUsageType.STATIC, StaticQuotaName.ROWS) - ) - return total - } - - const assertRowUsage = async (expected: number) => { - const usage = await getRowUsage() - - // Because our quota tracking is not perfect, we allow a 10% margin of - // error. This is to account for the fact that parallel writes can result - // in some quota updates getting lost. We don't have any need to solve this - // right now, so we just allow for some error. - if (expected === 0) { - expect(usage).toEqual(0) - return - } - expect(usage).toBeGreaterThan(expected * 0.9) - expect(usage).toBeLessThan(expected * 1.1) - } - - const defaultRowFields = isInternal - ? { - type: "row", - createdAt: timestamp, - updatedAt: timestamp, - } - : undefined - - beforeAll(async () => { - table = await config.api.table.save(defaultTable()) - }) - - describe("create", () => { - it("creates a new row successfully", async () => { - const rowUsage = await getRowUsage() - const row = await config.api.row.save(table._id!, { - name: "Test Contact", - }) - expect(row.name).toEqual("Test Contact") - expect(row._rev).toBeDefined() - await assertRowUsage(isInternal ? rowUsage + 1 : rowUsage) - }) - - it("fails to create a row for a table that does not exist", async () => { - const rowUsage = await getRowUsage() - await config.api.row.save("1234567", {}, { status: 404 }) - await assertRowUsage(rowUsage) - }) - - it("fails to create a row if required fields are missing", async () => { - const rowUsage = await getRowUsage() - const table = await config.api.table.save( - saveTableRequest({ - schema: { - required: { - type: FieldType.STRING, - name: "required", - constraints: { - type: "string", - presence: true, - }, - }, - }, - }) - ) - await config.api.row.save( - table._id!, - {}, - { - status: 500, - body: { - validationErrors: { - required: ["can't be blank"], - }, - }, - } - ) - await assertRowUsage(rowUsage) - }) - - isInternal && - it("increment row autoId per create row request", async () => { - const rowUsage = await getRowUsage() - - const newTable = await config.api.table.save( - saveTableRequest({ - schema: { - "Row ID": { - name: "Row ID", - type: FieldType.NUMBER, - subtype: AutoFieldSubType.AUTO_ID, - icon: "ri-magic-line", - autocolumn: true, - constraints: { - type: "number", - presence: true, - numericality: { - greaterThanOrEqualTo: "", - lessThanOrEqualTo: "", - }, - }, - }, - }, - }) - ) - - let previousId = 0 - for (let i = 0; i < 10; i++) { - const row = await config.api.row.save(newTable._id!, {}) - expect(row["Row ID"]).toBeGreaterThan(previousId) - previousId = row["Row ID"] - } - await assertRowUsage(isInternal ? rowUsage + 10 : rowUsage) - }) - - isInternal && - it("should increment auto ID correctly when creating rows in parallel", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - "Row ID": { - name: "Row ID", - type: FieldType.NUMBER, - subtype: AutoFieldSubType.AUTO_ID, - icon: "ri-magic-line", - autocolumn: true, - constraints: { - type: "number", - presence: true, - numericality: { - greaterThanOrEqualTo: "", - lessThanOrEqualTo: "", - }, - }, - }, - }, - }) - ) - - const sequence = Array(50) - .fill(0) - .map((_, i) => i + 1) - - // This block of code is simulating users creating auto ID rows at the - // same time. It's expected that this operation will sometimes return - // a document conflict error (409), but the idea is to retry in those - // situations. The code below does this a large number of times with - // small, random delays between them to try and get through the list - // as quickly as possible. - await Promise.all( - sequence.map(async () => { - const attempts = 30 - for (let attempt = 0; attempt < attempts; attempt++) { - try { - await config.api.row.save(table._id!, {}) - return - } catch (e) { - await new Promise(r => setTimeout(r, Math.random() * 50)) - } - } - throw new Error(`Failed to create row after ${attempts} attempts`) - }) - ) - - const rows = await config.api.row.fetch(table._id!) - expect(rows).toHaveLength(50) - - // The main purpose of this test is to ensure that even under pressure, - // we maintain data integrity. An auto ID column should hand out - // monotonically increasing unique integers no matter what. - const ids = rows.map(r => r["Row ID"]) - expect(ids).toEqual(expect.arrayContaining(sequence)) - }) - - isInternal && - it("doesn't allow creating in user table", async () => { - const response = await config.api.row.save( - InternalTable.USER_METADATA, - { - firstName: "Joe", - lastName: "Joe", - email: "joe@joe.com", - roles: {}, - }, - { status: 400 } - ) - expect(response.message).toBe("Cannot create new user entry.") - }) - - it("should not mis-parse date string out of JSON", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - type: FieldType.STRING, - name: "name", - }, - }, - }) - ) - - const row = await config.api.row.save(table._id!, { - name: `{ "foo": "2023-01-26T11:48:57.000Z" }`, - }) - - expect(row.name).toEqual(`{ "foo": "2023-01-26T11:48:57.000Z" }`) - }) - - describe("default values", () => { +if (descriptions.length) { + describe.each(descriptions)( + "/rows ($dbName)", + ({ config, dsProvider, isInternal, isMSSQL, isOracle }) => { let table: Table + let datasource: Datasource | undefined + let client: Knex | undefined - describe("string column", () => { - beforeAll(async () => { - table = await config.api.table.save( + beforeAll(async () => { + const ds = await dsProvider() + datasource = ds.datasource + client = ds.client + }) + + afterAll(async () => { + setup.afterAll() + }) + + function saveTableRequest( + // We omit the name field here because it's generated in the function with a + // high likelihood to be unique. Tests should not have any reason to control + // the table name they're writing to. + ...overrides: Partial>[] + ): SaveTableRequest { + const defaultSchema: TableSchema = { + id: { + type: FieldType.NUMBER, + name: "id", + autocolumn: true, + constraints: { + presence: true, + }, + }, + } + + for (const override of overrides) { + if (override.primary) { + delete defaultSchema.id + } + } + + const req: SaveTableRequest = { + name: uuid.v4().substring(0, 10), + type: "table", + sourceType: datasource + ? TableSourceType.EXTERNAL + : TableSourceType.INTERNAL, + sourceId: datasource ? datasource._id! : INTERNAL_TABLE_SOURCE_ID, + primary: ["id"], + schema: defaultSchema, + } + const merged = merge(req, ...overrides) + return merged + } + + function defaultTable( + // We omit the name field here because it's generated in the function with a + // high likelihood to be unique. Tests should not have any reason to control + // the table name they're writing to. + ...overrides: Partial>[] + ): SaveTableRequest { + return saveTableRequest( + { + primaryDisplay: "name", + schema: { + name: { + type: FieldType.STRING, + name: "name", + constraints: { + type: "string", + }, + }, + description: { + type: FieldType.STRING, + name: "description", + constraints: { + type: "string", + }, + }, + }, + }, + ...overrides + ) + } + + beforeEach(async () => { + mocks.licenses.useCloudFree() + }) + + const getRowUsage = async () => { + const { total } = await config.doInContext(undefined, () => + quotas.getCurrentUsageValues( + QuotaUsageType.STATIC, + StaticQuotaName.ROWS + ) + ) + return total + } + + const assertRowUsage = async (expected: number) => { + const usage = await getRowUsage() + + // Because our quota tracking is not perfect, we allow a 10% margin of + // error. This is to account for the fact that parallel writes can result + // in some quota updates getting lost. We don't have any need to solve this + // right now, so we just allow for some error. + if (expected === 0) { + expect(usage).toEqual(0) + return + } + expect(usage).toBeGreaterThan(expected * 0.9) + expect(usage).toBeLessThan(expected * 1.1) + } + + const defaultRowFields = isInternal + ? { + type: "row", + createdAt: timestamp, + updatedAt: timestamp, + } + : undefined + + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) + }) + + describe("create", () => { + it("creates a new row successfully", async () => { + const rowUsage = await getRowUsage() + const row = await config.api.row.save(table._id!, { + name: "Test Contact", + }) + expect(row.name).toEqual("Test Contact") + expect(row._rev).toBeDefined() + await assertRowUsage(isInternal ? rowUsage + 1 : rowUsage) + }) + + it("fails to create a row for a table that does not exist", async () => { + const rowUsage = await getRowUsage() + await config.api.row.save("1234567", {}, { status: 404 }) + await assertRowUsage(rowUsage) + }) + + it("fails to create a row if required fields are missing", async () => { + const rowUsage = await getRowUsage() + const table = await config.api.table.save( saveTableRequest({ schema: { - description: { - name: "description", + required: { type: FieldType.STRING, - default: "default description", - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.description).toEqual("default description") - }) - - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - description: "specified description", - }) - expect(row.description).toEqual("specified description") - }) - - it("uses the default value if value is null", async () => { - const row = await config.api.row.save(table._id!, { - description: null, - }) - expect(row.description).toEqual("default description") - }) - - it("uses the default value if value is undefined", async () => { - const row = await config.api.row.save(table._id!, { - description: undefined, - }) - expect(row.description).toEqual("default description") - }) - }) - - describe("number column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - age: { - name: "age", - type: FieldType.NUMBER, - default: "25", - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.age).toEqual(25) - }) - - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - age: 30, - }) - expect(row.age).toEqual(30) - }) - }) - - describe("date column", () => { - it("creates a row with a default value successfully", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - date: { - name: "date", - type: FieldType.DATETIME, - default: "2023-01-26T11:48:57.000Z", - }, - }, - }) - ) - const row = await config.api.row.save(table._id!, {}) - expect(row.date).toEqual("2023-01-26T11:48:57.000Z") - }) - - it("gives an error if the default value is invalid", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - date: { - name: "date", - type: FieldType.DATETIME, - default: "invalid", + name: "required", + constraints: { + type: "string", + presence: true, + }, }, }, }) @@ -492,297 +250,193 @@ describe.each(databases)("/rows (%s)", dbName => { table._id!, {}, { - status: 400, + status: 500, body: { - message: `Invalid default value for field 'date' - Invalid date value: "invalid"`, + validationErrors: { + required: ["can't be blank"], + }, }, } ) - }) - }) - - describe("options column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - status: { - name: "status", - type: FieldType.OPTIONS, - default: "requested", - constraints: { - inclusion: ["requested", "approved"], - }, - }, - }, - }) - ) + await assertRowUsage(rowUsage) }) - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.status).toEqual("requested") - }) + isInternal && + it("increment row autoId per create row request", async () => { + const rowUsage = await getRowUsage() - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - status: "approved", - }) - expect(row.status).toEqual("approved") - }) - }) - - describe("array column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - food: { - name: "food", - type: FieldType.ARRAY, - default: ["apple", "orange"], - constraints: { - type: JsonFieldSubType.ARRAY, - inclusion: ["apple", "orange", "banana"], - }, - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.food).toEqual(["apple", "orange"]) - }) - - it("creates a new row with a default value when given an empty list", async () => { - const row = await config.api.row.save(table._id!, { food: [] }) - expect(row.food).toEqual(["apple", "orange"]) - }) - - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - food: ["orange"], - }) - expect(row.food).toEqual(["orange"]) - }) - - it("resets back to its default value when empty", async () => { - let row = await config.api.row.save(table._id!, { - food: ["orange"], - }) - row = await config.api.row.save(table._id!, { ...row, food: [] }) - expect(row.food).toEqual(["apple", "orange"]) - }) - }) - - describe("user column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - user: { - name: "user", - type: FieldType.BB_REFERENCE_SINGLE, - subtype: BBReferenceFieldSubType.USER, - default: "{{ [Current User]._id }}", - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.user._id).toEqual(config.getUser()._id) - }) - - it("does not use default value if value specified", async () => { - const id = `us_${utils.newid()}` - await config.createUser({ _id: id }) - const row = await config.api.row.save(table._id!, { - user: id, - }) - expect(row.user._id).toEqual(id) - }) - }) - - describe("multi-user column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - users: { - name: "users", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - default: ["{{ [Current User]._id }}"], - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.users).toHaveLength(1) - expect(row.users[0]._id).toEqual(config.getUser()._id) - }) - - it("does not use default value if value specified", async () => { - const id = `us_${utils.newid()}` - await config.createUser({ _id: id }) - const row = await config.api.row.save(table._id!, { - users: [id], - }) - expect(row.users).toHaveLength(1) - expect(row.users[0]._id).toEqual(id) - }) - }) - - describe("boolean column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - active: { - name: "active", - type: FieldType.BOOLEAN, - default: "true", - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.active).toEqual(true) - }) - - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - active: false, - }) - expect(row.active).toEqual(false) - }) - }) - - describe("bigint column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - bigNumber: { - name: "bigNumber", - type: FieldType.BIGINT, - default: "1234567890", - }, - }, - }) - ) - }) - - it("creates a new row with a default value successfully", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.bigNumber).toEqual("1234567890") - }) - - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - bigNumber: "9876543210", - }) - expect(row.bigNumber).toEqual("9876543210") - }) - }) - - describe("bindings", () => { - describe("string column", () => { - beforeAll(async () => { - table = await config.api.table.save( + const newTable = await config.api.table.save( saveTableRequest({ schema: { - description: { - name: "description", - type: FieldType.STRING, - default: `{{ date now "YYYY-MM-DDTHH:mm:ss" }}`, - }, - }, - }) - ) - }) - - it("can use bindings in default values", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.description).toMatch( - /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/ - ) - }) - - it("does not use default value if value specified", async () => { - const row = await config.api.row.save(table._id!, { - description: "specified description", - }) - expect(row.description).toEqual("specified description") - }) - - it("can bind the current user", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - user: { - name: "user", - type: FieldType.STRING, - default: `{{ [Current User]._id }}`, - }, - }, - }) - ) - const row = await config.api.row.save(table._id!, {}) - expect(row.user).toEqual(config.getUser()._id) - }) - - it("cannot access current user password", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - user: { - name: "user", - type: FieldType.STRING, - default: `{{ user.password }}`, - }, - }, - }) - ) - const row = await config.api.row.save(table._id!, {}) - // For some reason it's null for internal tables, and undefined for - // external. - expect(row.user == null).toBe(true) - }) - }) - - describe("number column", () => { - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - age: { - name: "age", + "Row ID": { + name: "Row ID", type: FieldType.NUMBER, - default: `{{ sum 10 10 5 }}`, + subtype: AutoFieldSubType.AUTO_ID, + icon: "ri-magic-line", + autocolumn: true, + constraints: { + type: "number", + presence: true, + numericality: { + greaterThanOrEqualTo: "", + lessThanOrEqualTo: "", + }, + }, }, }, }) ) + + let previousId = 0 + for (let i = 0; i < 10; i++) { + const row = await config.api.row.save(newTable._id!, {}) + expect(row["Row ID"]).toBeGreaterThan(previousId) + previousId = row["Row ID"] + } + await assertRowUsage(isInternal ? rowUsage + 10 : rowUsage) }) - it("can use bindings in default values", async () => { - const row = await config.api.row.save(table._id!, {}) - expect(row.age).toEqual(25) + isInternal && + it("should increment auto ID correctly when creating rows in parallel", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + "Row ID": { + name: "Row ID", + type: FieldType.NUMBER, + subtype: AutoFieldSubType.AUTO_ID, + icon: "ri-magic-line", + autocolumn: true, + constraints: { + type: "number", + presence: true, + numericality: { + greaterThanOrEqualTo: "", + lessThanOrEqualTo: "", + }, + }, + }, + }, + }) + ) + + const sequence = Array(50) + .fill(0) + .map((_, i) => i + 1) + + // This block of code is simulating users creating auto ID rows at the + // same time. It's expected that this operation will sometimes return + // a document conflict error (409), but the idea is to retry in those + // situations. The code below does this a large number of times with + // small, random delays between them to try and get through the list + // as quickly as possible. + await Promise.all( + sequence.map(async () => { + const attempts = 30 + for (let attempt = 0; attempt < attempts; attempt++) { + try { + await config.api.row.save(table._id!, {}) + return + } catch (e) { + await new Promise(r => setTimeout(r, Math.random() * 50)) + } + } + throw new Error( + `Failed to create row after ${attempts} attempts` + ) + }) + ) + + const rows = await config.api.row.fetch(table._id!) + expect(rows).toHaveLength(50) + + // The main purpose of this test is to ensure that even under pressure, + // we maintain data integrity. An auto ID column should hand out + // monotonically increasing unique integers no matter what. + const ids = rows.map(r => r["Row ID"]) + expect(ids).toEqual(expect.arrayContaining(sequence)) }) - describe("invalid default value", () => { + isInternal && + it("doesn't allow creating in user table", async () => { + const response = await config.api.row.save( + InternalTable.USER_METADATA, + { + firstName: "Joe", + lastName: "Joe", + email: "joe@joe.com", + roles: {}, + }, + { status: 400 } + ) + expect(response.message).toBe("Cannot create new user entry.") + }) + + it("should not mis-parse date string out of JSON", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + type: FieldType.STRING, + name: "name", + }, + }, + }) + ) + + const row = await config.api.row.save(table._id!, { + name: `{ "foo": "2023-01-26T11:48:57.000Z" }`, + }) + + expect(row.name).toEqual(`{ "foo": "2023-01-26T11:48:57.000Z" }`) + }) + + describe("default values", () => { + let table: Table + + describe("string column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + description: { + name: "description", + type: FieldType.STRING, + default: "default description", + }, + }, + }) + ) + }) + + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.description).toEqual("default description") + }) + + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + description: "specified description", + }) + expect(row.description).toEqual("specified description") + }) + + it("uses the default value if value is null", async () => { + const row = await config.api.row.save(table._id!, { + description: null, + }) + expect(row.description).toEqual("default description") + }) + + it("uses the default value if value is undefined", async () => { + const row = await config.api.row.save(table._id!, { + description: undefined, + }) + expect(row.description).toEqual("default description") + }) + }) + + describe("number column", () => { beforeAll(async () => { table = await config.api.table.save( saveTableRequest({ @@ -790,2589 +444,3016 @@ describe.each(databases)("/rows (%s)", dbName => { age: { name: "age", type: FieldType.NUMBER, - default: `{{ capitalize "invalid" }}`, + default: "25", }, }, }) ) }) - it("throws an error when invalid default value", async () => { + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.age).toEqual(25) + }) + + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + age: 30, + }) + expect(row.age).toEqual(30) + }) + }) + + describe("date column", () => { + it("creates a row with a default value successfully", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + date: { + name: "date", + type: FieldType.DATETIME, + default: "2023-01-26T11:48:57.000Z", + }, + }, + }) + ) + const row = await config.api.row.save(table._id!, {}) + expect(row.date).toEqual("2023-01-26T11:48:57.000Z") + }) + + it("gives an error if the default value is invalid", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + date: { + name: "date", + type: FieldType.DATETIME, + default: "invalid", + }, + }, + }) + ) await config.api.row.save( table._id!, {}, { status: 400, body: { - message: - "Invalid default value for field 'age' - Invalid number value \"Invalid\"", + message: `Invalid default value for field 'date' - Invalid date value: "invalid"`, }, } ) }) }) - }) - }) - }) - describe("relations to same table", () => { - let relatedRows: Row[] + describe("options column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + status: { + name: "status", + type: FieldType.OPTIONS, + default: "requested", + constraints: { + inclusion: ["requested", "approved"], + }, + }, + }, + }) + ) + }) - beforeAll(async () => { - const relatedTable = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - }, + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.status).toEqual("requested") + }) + + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + status: "approved", + }) + expect(row.status).toEqual("approved") + }) }) - ) - const relatedTableId = relatedTable._id! - table = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - related1: { - type: FieldType.LINK, - name: "related1", - fieldName: "main1", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - related2: { - type: FieldType.LINK, - name: "related2", - fieldName: "main2", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - }, + + describe("array column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + food: { + name: "food", + type: FieldType.ARRAY, + default: ["apple", "orange"], + constraints: { + type: JsonFieldSubType.ARRAY, + inclusion: ["apple", "orange", "banana"], + }, + }, + }, + }) + ) + }) + + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.food).toEqual(["apple", "orange"]) + }) + + it("creates a new row with a default value when given an empty list", async () => { + const row = await config.api.row.save(table._id!, { food: [] }) + expect(row.food).toEqual(["apple", "orange"]) + }) + + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + food: ["orange"], + }) + expect(row.food).toEqual(["orange"]) + }) + + it("resets back to its default value when empty", async () => { + let row = await config.api.row.save(table._id!, { + food: ["orange"], + }) + row = await config.api.row.save(table._id!, { ...row, food: [] }) + expect(row.food).toEqual(["apple", "orange"]) + }) }) - ) - relatedRows = await Promise.all([ - config.api.row.save(relatedTableId, { name: "foo" }), - config.api.row.save(relatedTableId, { name: "bar" }), - config.api.row.save(relatedTableId, { name: "baz" }), - config.api.row.save(relatedTableId, { name: "boo" }), - ]) - }) - it("can create rows with both relationships", async () => { - const row = await config.api.row.save(table._id!, { - name: "test", - related1: [relatedRows[0]._id!], - related2: [relatedRows[1]._id!], - }) + describe("user column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + user: { + name: "user", + type: FieldType.BB_REFERENCE_SINGLE, + subtype: BBReferenceFieldSubType.USER, + default: "{{ [Current User]._id }}", + }, + }, + }) + ) + }) - expect(row).toEqual( - expect.objectContaining({ - name: "test", - related1: [ - { - _id: relatedRows[0]._id, - primaryDisplay: relatedRows[0].name, - }, - ], - related2: [ - { - _id: relatedRows[1]._id, - primaryDisplay: relatedRows[1].name, - }, - ], + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.user._id).toEqual(config.getUser()._id) + }) + + it("does not use default value if value specified", async () => { + const id = `us_${utils.newid()}` + await config.createUser({ _id: id }) + const row = await config.api.row.save(table._id!, { + user: id, + }) + expect(row.user._id).toEqual(id) + }) }) - ) - }) - it("can create rows with no relationships", async () => { - const row = await config.api.row.save(table._id!, { - name: "test", - }) + describe("multi-user column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + users: { + name: "users", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + default: ["{{ [Current User]._id }}"], + }, + }, + }) + ) + }) - expect(row.related1).toBeUndefined() - expect(row.related2).toBeUndefined() - }) + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.users).toHaveLength(1) + expect(row.users[0]._id).toEqual(config.getUser()._id) + }) - it("can create rows with only one relationships field", async () => { - const row = await config.api.row.save(table._id!, { - name: "test", - related1: [], - related2: [relatedRows[1]._id!], - }) - - expect(row).toEqual( - expect.objectContaining({ - name: "test", - related2: [ - { - _id: relatedRows[1]._id, - primaryDisplay: relatedRows[1].name, - }, - ], + it("does not use default value if value specified", async () => { + const id = `us_${utils.newid()}` + await config.createUser({ _id: id }) + const row = await config.api.row.save(table._id!, { + users: [id], + }) + expect(row.users).toHaveLength(1) + expect(row.users[0]._id).toEqual(id) + }) }) - ) - expect(row.related1).toBeUndefined() - }) - }) - }) - describe("get", () => { - it("reads an existing row successfully", async () => { - const existing = await config.api.row.save(table._id!, {}) + describe("boolean column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + active: { + name: "active", + type: FieldType.BOOLEAN, + default: "true", + }, + }, + }) + ) + }) - const res = await config.api.row.get(table._id!, existing._id!) + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.active).toEqual(true) + }) - expect(res).toEqual({ - ...existing, - ...defaultRowFields, - }) - }) - - it("returns 404 when row does not exist", async () => { - const table = await config.api.table.save(defaultTable()) - await config.api.row.save(table._id!, {}) - await config.api.row.get(table._id!, "1234567", { - status: 404, - }) - }) - - isInternal && - it("can search row from user table", async () => { - const res = await config.api.row.get( - InternalTables.USER_METADATA, - config.userMetadataId! - ) - - expect(res).toEqual({ - ...config.getUser(), - _id: config.userMetadataId!, - _rev: expect.any(String), - roles: undefined, - roleId: "ADMIN", - tableId: InternalTables.USER_METADATA, - }) - }) - }) - - describe("fetch", () => { - it("fetches all rows for given tableId", async () => { - const table = await config.api.table.save(defaultTable()) - const rows = await Promise.all([ - config.api.row.save(table._id!, {}), - config.api.row.save(table._id!, {}), - ]) - - const res = await config.api.row.fetch(table._id!) - expect(res.map(r => r._id)).toEqual( - expect.arrayContaining(rows.map(r => r._id)) - ) - }) - - it("returns 404 when table does not exist", async () => { - await config.api.row.fetch("1234567", { status: 404 }) - }) - }) - - describe("update", () => { - it("updates an existing row successfully", async () => { - const existing = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() - - const res = await config.api.row.save(table._id!, { - _id: existing._id, - _rev: existing._rev, - name: "Updated Name", - }) - - expect(res.name).toEqual("Updated Name") - await assertRowUsage(rowUsage) - }) - - !isInternal && - it("can update a row on an external table with a primary key", async () => { - const tableName = uuid.v4().substring(0, 10) - await client!.schema.createTable(tableName, table => { - table.increments("id").primary() - table.string("name") - }) - - const res = await config.api.datasource.fetchSchema({ - datasourceId: datasource!._id!, - }) - const table = res.datasource.entities![tableName] - - const row = await config.api.row.save(table._id!, { - id: 1, - name: "Row 1", - }) - - const updatedRow = await config.api.row.save(table._id!, { - _id: row._id!, - name: "Row 1 Updated", - }) - - expect(updatedRow.name).toEqual("Row 1 Updated") - - const rows = await config.api.row.fetch(table._id!) - expect(rows).toHaveLength(1) - }) - - describe("relations to same table", () => { - let relatedRows: Row[] - - beforeAll(async () => { - const relatedTable = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - }, + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + active: false, + }) + expect(row.active).toEqual(false) + }) }) - ) - const relatedTableId = relatedTable._id! - table = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - related1: { - type: FieldType.LINK, - name: "related1", - fieldName: "main1", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - related2: { - type: FieldType.LINK, - name: "related2", - fieldName: "main2", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - }, + + describe("bigint column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + bigNumber: { + name: "bigNumber", + type: FieldType.BIGINT, + default: "1234567890", + }, + }, + }) + ) + }) + + it("creates a new row with a default value successfully", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.bigNumber).toEqual("1234567890") + }) + + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + bigNumber: "9876543210", + }) + expect(row.bigNumber).toEqual("9876543210") + }) }) - ) - relatedRows = await Promise.all([ - config.api.row.save(relatedTableId, { name: "foo" }), - config.api.row.save(relatedTableId, { name: "bar" }), - config.api.row.save(relatedTableId, { name: "baz" }), - config.api.row.save(relatedTableId, { name: "boo" }), - ]) - }) - it("can edit rows with both relationships", async () => { - let row = await config.api.row.save(table._id!, { - name: "test", - related1: [relatedRows[0]._id!], - related2: [relatedRows[1]._id!], - }) + describe("bindings", () => { + describe("string column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + description: { + name: "description", + type: FieldType.STRING, + default: `{{ date now "YYYY-MM-DDTHH:mm:ss" }}`, + }, + }, + }) + ) + }) - row = await config.api.row.save(table._id!, { - ...row, - related1: [relatedRows[0]._id!, relatedRows[1]._id!], - related2: [relatedRows[2]._id!], - }) + it("can use bindings in default values", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.description).toMatch( + /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/ + ) + }) - expect(row).toEqual( - expect.objectContaining({ - name: "test", - related1: expect.arrayContaining([ - { - _id: relatedRows[0]._id, - primaryDisplay: relatedRows[0].name, - }, - { - _id: relatedRows[1]._id, - primaryDisplay: relatedRows[1].name, - }, - ]), - related2: [ - { - _id: relatedRows[2]._id, - primaryDisplay: relatedRows[2].name, - }, - ], + it("does not use default value if value specified", async () => { + const row = await config.api.row.save(table._id!, { + description: "specified description", + }) + expect(row.description).toEqual("specified description") + }) + + it("can bind the current user", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + user: { + name: "user", + type: FieldType.STRING, + default: `{{ [Current User]._id }}`, + }, + }, + }) + ) + const row = await config.api.row.save(table._id!, {}) + expect(row.user).toEqual(config.getUser()._id) + }) + + it("cannot access current user password", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + user: { + name: "user", + type: FieldType.STRING, + default: `{{ user.password }}`, + }, + }, + }) + ) + const row = await config.api.row.save(table._id!, {}) + // For some reason it's null for internal tables, and undefined for + // external. + expect(row.user == null).toBe(true) + }) + }) + + describe("number column", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + age: { + name: "age", + type: FieldType.NUMBER, + default: `{{ sum 10 10 5 }}`, + }, + }, + }) + ) + }) + + it("can use bindings in default values", async () => { + const row = await config.api.row.save(table._id!, {}) + expect(row.age).toEqual(25) + }) + + describe("invalid default value", () => { + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + age: { + name: "age", + type: FieldType.NUMBER, + default: `{{ capitalize "invalid" }}`, + }, + }, + }) + ) + }) + + it("throws an error when invalid default value", async () => { + await config.api.row.save( + table._id!, + {}, + { + status: 400, + body: { + message: + "Invalid default value for field 'age' - Invalid number value \"Invalid\"", + }, + } + ) + }) + }) + }) }) - ) - }) - - it("can drop existing relationship", async () => { - let row = await config.api.row.save(table._id!, { - name: "test", - related1: [relatedRows[0]._id!], - related2: [relatedRows[1]._id!], }) - row = await config.api.row.save(table._id!, { - ...row, - related1: [], - related2: [relatedRows[2]._id!], - }) - - expect(row).toEqual( - expect.objectContaining({ - name: "test", - related2: [ - { - _id: relatedRows[2]._id, - primaryDisplay: relatedRows[2].name, - }, - ], - }) - ) - expect(row.related1).toBeUndefined() - }) - - it("can drop both relationships", async () => { - let row = await config.api.row.save(table._id!, { - name: "test", - related1: [relatedRows[0]._id!], - related2: [relatedRows[1]._id!], - }) - - row = await config.api.row.save(table._id!, { - ...row, - related1: [], - related2: [], - }) - - expect(row).toEqual( - expect.objectContaining({ - name: "test", - }) - ) - expect(row.related1).toBeUndefined() - expect(row.related2).toBeUndefined() - }) - }) - }) - - describe("patch", () => { - let otherTable: Table - - beforeAll(async () => { - table = await config.api.table.save(defaultTable()) - otherTable = await config.api.table.save( - defaultTable({ - schema: { - relationship: { - name: "relationship", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: table._id!, - fieldName: "relationship", - }, - }, - }) - ) - }) - - it("should update only the fields that are supplied", async () => { - const existing = await config.api.row.save(table._id!, {}) - - const rowUsage = await getRowUsage() - - const row = await config.api.row.patch(table._id!, { - _id: existing._id!, - _rev: existing._rev!, - tableId: table._id!, - name: "Updated Name", - }) - - expect(row.name).toEqual("Updated Name") - expect(row.description).toEqual(existing.description) - - const savedRow = await config.api.row.get(table._id!, row._id!) - - expect(savedRow.description).toEqual(existing.description) - expect(savedRow.name).toEqual("Updated Name") - await assertRowUsage(rowUsage) - }) - - it("should update only the fields that are supplied and emit the correct oldRow", async () => { - let beforeRow = await config.api.row.save(table._id!, { - name: "test", - description: "test", - }) - const opts = { - name: "row:update", - matchFn: (event: UpdatedRowEventEmitter) => - event.row._id === beforeRow._id, - } - const event = await waitForEvent(opts, async () => { - await config.api.row.patch(table._id!, { - _id: beforeRow._id!, - _rev: beforeRow._rev!, - tableId: table._id!, - name: "Updated Name", - }) - }) - - expect(event.oldRow).toBeDefined() - expect(event.oldRow.name).toEqual("test") - expect(event.row.name).toEqual("Updated Name") - expect(event.oldRow.description).toEqual(beforeRow.description) - expect(event.row.description).toEqual(beforeRow.description) - }) - - it("should throw an error when given improper types", async () => { - const existing = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() - - await config.api.row.patch( - table._id!, - { - _id: existing._id!, - _rev: existing._rev!, - tableId: table._id!, - name: 1, - }, - { status: 400 } - ) - - await assertRowUsage(rowUsage) - }) - - it("should not overwrite links if those links are not set", async () => { - let linkField: FieldSchema = { - type: FieldType.LINK, - name: "", - fieldName: "", - constraints: { - type: "array", - presence: false, - }, - relationshipType: RelationshipType.ONE_TO_MANY, - tableId: InternalTable.USER_METADATA, - } - - let table = await config.api.table.save({ - name: "TestTable", - type: "table", - sourceType: TableSourceType.INTERNAL, - sourceId: INTERNAL_TABLE_SOURCE_ID, - schema: { - user1: { ...linkField, name: "user1", fieldName: "user1" }, - user2: { ...linkField, name: "user2", fieldName: "user2" }, - }, - }) - - let user1 = await config.createUser() - let user2 = await config.createUser() - - let row = await config.api.row.save(table._id!, { - user1: [{ _id: user1._id }], - user2: [{ _id: user2._id }], - }) - - let getResp = await config.api.row.get(table._id!, row._id!) - expect(getResp.user1[0]._id).toEqual(user1._id) - expect(getResp.user2[0]._id).toEqual(user2._id) - - let patchResp = await config.api.row.patch(table._id!, { - _id: row._id!, - _rev: row._rev!, - tableId: table._id!, - user1: [{ _id: user2._id }], - }) - expect(patchResp.user1[0]._id).toEqual(user2._id) - expect(patchResp.user2[0]._id).toEqual(user2._id) - - getResp = await config.api.row.get(table._id!, row._id!) - expect(getResp.user1[0]._id).toEqual(user2._id) - expect(getResp.user2[0]._id).toEqual(user2._id) - }) - - it("should be able to remove a relationship from many side", async () => { - const row = await config.api.row.save(otherTable._id!, { - name: "test", - description: "test", - }) - const row2 = await config.api.row.save(otherTable._id!, { - name: "test", - description: "test", - }) - const { _id } = await config.api.row.save(table._id!, { - relationship: [{ _id: row._id }, { _id: row2._id }], - }) - const relatedRow = await config.api.row.get(table._id!, _id!, { - status: 200, - }) - expect(relatedRow.relationship.length).toEqual(2) - await config.api.row.save(table._id!, { - ...relatedRow, - relationship: [{ _id: row._id }], - }) - const afterRelatedRow = await config.api.row.get(table._id!, _id!, { - status: 200, - }) - expect(afterRelatedRow.relationship.length).toEqual(1) - expect(afterRelatedRow.relationship[0]._id).toEqual(row._id) - }) - - it("should be able to update relationships when both columns are same name", async () => { - let row = await config.api.row.save(table._id!, { - name: "test", - description: "test", - }) - let row2 = await config.api.row.save(otherTable._id!, { - name: "test", - description: "test", - relationship: [row._id], - }) - row = await config.api.row.get(table._id!, row._id!) - expect(row.relationship.length).toBe(1) - const resp = await config.api.row.patch(table._id!, { - _id: row._id!, - _rev: row._rev!, - tableId: row.tableId!, - name: "test2", - relationship: [row2._id], - }) - expect(resp.relationship.length).toBe(1) - }) - - !isInternal && - // MSSQL needs a setting called IDENTITY_INSERT to be set to ON to allow writing - // to identity columns. This is not something Budibase does currently. - !isMSSQL && - it("should support updating fields that are part of a composite key", async () => { - const tableRequest = saveTableRequest({ - primary: ["number", "string"], - schema: { - string: { - type: FieldType.STRING, - name: "string", - }, - number: { - type: FieldType.NUMBER, - name: "number", - }, - }, - }) - - delete tableRequest.schema.id - - const table = await config.api.table.save(tableRequest) - - const stringValue = generator.word() - - // MySQL and MariaDB auto-increment fields have a minimum value of 1. If - // you try to save a row with a value of 0 it will use 1 instead. - const naturalValue = generator.integer({ min: 1, max: 1000 }) - - const existing = await config.api.row.save(table._id!, { - string: stringValue, - number: naturalValue, - }) - - expect(existing._id).toEqual(`%5B${naturalValue}%2C'${stringValue}'%5D`) - - const row = await config.api.row.patch(table._id!, { - _id: existing._id!, - _rev: existing._rev!, - tableId: table._id!, - string: stringValue, - number: 1500, - }) - - expect(row._id).toEqual(`%5B${"1500"}%2C'${stringValue}'%5D`) - }) - }) - - describe("destroy", () => { - beforeAll(async () => { - table = await config.api.table.save(defaultTable()) - }) - - it("should be able to delete a row", async () => { - const createdRow = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() - - const res = await config.api.row.bulkDelete(table._id!, { - rows: [createdRow], - }) - expect(res[0]._id).toEqual(createdRow._id) - await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) - }) - - it("should be able to delete a row with ID only", async () => { - const createdRow = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() - - const res = await config.api.row.bulkDelete(table._id!, { - rows: [createdRow._id!], - }) - expect(res[0]._id).toEqual(createdRow._id) - expect(res[0].tableId).toEqual(table._id!) - await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) - }) - - it("should be able to bulk delete rows, including a row that doesn't exist", async () => { - const createdRow = await config.api.row.save(table._id!, {}) - const createdRow2 = await config.api.row.save(table._id!, {}) - - const res = await config.api.row.bulkDelete(table._id!, { - rows: [createdRow, createdRow2, { _id: "9999999" }], - }) - - expect(res.map(r => r._id)).toEqual( - expect.arrayContaining([createdRow._id, createdRow2._id]) - ) - expect(res.length).toEqual(2) - }) - - describe("relations to same table", () => { - let relatedRows: Row[] - - beforeAll(async () => { - const relatedTable = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - }, - }) - ) - const relatedTableId = relatedTable._id! - table = await config.api.table.save( - defaultTable({ - schema: { - name: { name: "name", type: FieldType.STRING }, - related1: { - type: FieldType.LINK, - name: "related1", - fieldName: "main1", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - related2: { - type: FieldType.LINK, - name: "related2", - fieldName: "main2", - tableId: relatedTableId, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - }, - }) - ) - relatedRows = await Promise.all([ - config.api.row.save(relatedTableId, { name: "foo" }), - config.api.row.save(relatedTableId, { name: "bar" }), - config.api.row.save(relatedTableId, { name: "baz" }), - config.api.row.save(relatedTableId, { name: "boo" }), - ]) - }) - - it("can delete rows with both relationships", async () => { - const row = await config.api.row.save(table._id!, { - name: "test", - related1: [relatedRows[0]._id!], - related2: [relatedRows[1]._id!], - }) - - await config.api.row.delete(table._id!, { _id: row._id! }) - - await config.api.row.get(table._id!, row._id!, { status: 404 }) - }) - - it("can delete rows with empty relationships", async () => { - const row = await config.api.row.save(table._id!, { - name: "test", - related1: [], - related2: [], - }) - - await config.api.row.delete(table._id!, { _id: row._id! }) - - await config.api.row.get(table._id!, row._id!, { status: 404 }) - }) - }) - }) - - describe("validate", () => { - beforeAll(async () => { - table = await config.api.table.save(defaultTable()) - }) - - it("should return no errors on valid row", async () => { - const rowUsage = await getRowUsage() - - const res = await config.api.row.validate(table._id!, { name: "ivan" }) - - expect(res.valid).toBe(true) - expect(Object.keys(res.errors)).toEqual([]) - await assertRowUsage(rowUsage) - }) - - it("should errors on invalid row", async () => { - const rowUsage = await getRowUsage() - - const res = await config.api.row.validate(table._id!, { name: 1 }) - - if (isInternal) { - expect(res.valid).toBe(false) - expect(Object.keys(res.errors)).toEqual(["name"]) - } else { - // Validation for external is not implemented, so it will always return valid - expect(res.valid).toBe(true) - expect(Object.keys(res.errors)).toEqual([]) - } - await assertRowUsage(rowUsage) - }) - }) - - describe("bulkDelete", () => { - beforeAll(async () => { - table = await config.api.table.save(defaultTable()) - }) - - it("should be able to delete a bulk set of rows", async () => { - const row1 = await config.api.row.save(table._id!, {}) - const row2 = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() - - const res = await config.api.row.bulkDelete(table._id!, { - rows: [row1, row2], - }) - - expect(res.length).toEqual(2) - await config.api.row.get(table._id!, row1._id!, { status: 404 }) - await assertRowUsage(isInternal ? rowUsage - 2 : rowUsage) - }) - - it("should be able to delete a variety of row set types", async () => { - const [row1, row2, row3] = await Promise.all([ - config.api.row.save(table._id!, {}), - config.api.row.save(table._id!, {}), - config.api.row.save(table._id!, {}), - ]) - const rowUsage = await getRowUsage() - - const res = await config.api.row.bulkDelete(table._id!, { - rows: [row1, row2._id!, { _id: row3._id }], - }) - - expect(res.length).toEqual(3) - await config.api.row.get(table._id!, row1._id!, { status: 404 }) - await assertRowUsage(isInternal ? rowUsage - 3 : rowUsage) - }) - - it("should accept a valid row object and delete the row", async () => { - const row1 = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() - - const res = await config.api.row.delete(table._id!, row1 as DeleteRow) - - expect(res.id).toEqual(row1._id) - await config.api.row.get(table._id!, row1._id!, { status: 404 }) - await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) - }) - - it.each([{ not: "valid" }, { rows: 123 }, "invalid"])( - "should ignore malformed/invalid delete request: %s", - async (request: any) => { - const rowUsage = await getRowUsage() - - await config.api.row.delete(table._id!, request, { - status: 400, - body: { - message: "Invalid delete rows request", - }, - }) - - await assertRowUsage(rowUsage) - } - ) - }) - - describe("bulkImport", () => { - isInternal && - it("should update Auto ID field after bulk import", async () => { - const table = await config.api.table.save( - saveTableRequest({ - primary: ["autoId"], - schema: { - autoId: { - name: "autoId", - type: FieldType.NUMBER, - subtype: AutoFieldSubType.AUTO_ID, - autocolumn: true, - constraints: { - type: "number", - presence: false, + describe("relations to same table", () => { + let relatedRows: Row[] + + beforeAll(async () => { + const relatedTable = await config.api.table.save( + defaultTable({ + schema: { + name: { name: "name", type: FieldType.STRING }, }, - }, - }, - }) - ) - - let row = await config.api.row.save(table._id!, {}) - expect(row.autoId).toEqual(1) - - await config.api.row.bulkImport(table._id!, { - rows: [{ autoId: 2 }], - }) - - row = await config.api.row.save(table._id!, {}) - expect(row.autoId).toEqual(3) - }) - - isInternal && - it("should reject bulkImporting relationship fields", async () => { - const table1 = await config.api.table.save(saveTableRequest()) - const table2 = await config.api.table.save( - saveTableRequest({ - schema: { - relationship: { - name: "relationship", - type: FieldType.LINK, - tableId: table1._id!, - relationshipType: RelationshipType.ONE_TO_MANY, - fieldName: "relationship", - }, - }, - }) - ) - - const table1Row1 = await config.api.row.save(table1._id!, {}) - await config.api.row.bulkImport( - table2._id!, - { - rows: [{ relationship: [table1Row1._id!] }], - }, - { - status: 400, - body: { - message: - 'Can\'t bulk import relationship fields for internal databases, found value in field "relationship"', - }, - } - ) - }) - - it("should be able to bulkImport rows", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - type: FieldType.STRING, - name: "name", - }, - description: { - type: FieldType.STRING, - name: "description", - }, - }, - }) - ) - - const rowUsage = await getRowUsage() - - await config.api.row.bulkImport(table._id!, { - rows: [ - { - name: "Row 1", - description: "Row 1 description", - }, - { - name: "Row 2", - description: "Row 2 description", - }, - ], - }) - - const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(2) - - rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Row 1") - expect(rows[0].description).toEqual("Row 1 description") - expect(rows[1].name).toEqual("Row 2") - expect(rows[1].description).toEqual("Row 2 description") - - await assertRowUsage(isInternal ? rowUsage + 2 : rowUsage) - }) - - isInternal && - it("should be able to update existing rows on bulkImport", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - type: FieldType.STRING, - name: "name", - }, - description: { - type: FieldType.STRING, - name: "description", - }, - }, - }) - ) - - const existingRow = await config.api.row.save(table._id!, { - name: "Existing row", - description: "Existing description", - }) - - const rowUsage = await getRowUsage() - - await config.api.row.bulkImport(table._id!, { - rows: [ - { - name: "Row 1", - description: "Row 1 description", - }, - { ...existingRow, name: "Updated existing row" }, - { - name: "Row 2", - description: "Row 2 description", - }, - ], - identifierFields: ["_id"], - }) - - const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(3) - - rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Row 1") - expect(rows[0].description).toEqual("Row 1 description") - expect(rows[1].name).toEqual("Row 2") - expect(rows[1].description).toEqual("Row 2 description") - expect(rows[2].name).toEqual("Updated existing row") - expect(rows[2].description).toEqual("Existing description") - - await assertRowUsage(rowUsage + 2) - }) - - isInternal && - it("should create new rows if not identifierFields are provided", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - type: FieldType.STRING, - name: "name", - }, - description: { - type: FieldType.STRING, - name: "description", - }, - }, - }) - ) - - const existingRow = await config.api.row.save(table._id!, { - name: "Existing row", - description: "Existing description", - }) - - const rowUsage = await getRowUsage() - - await config.api.row.bulkImport(table._id!, { - rows: [ - { - name: "Row 1", - description: "Row 1 description", - }, - { ...existingRow, name: "Updated existing row" }, - { - name: "Row 2", - description: "Row 2 description", - }, - ], - }) - - const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(4) - - rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Existing row") - expect(rows[0].description).toEqual("Existing description") - expect(rows[1].name).toEqual("Row 1") - expect(rows[1].description).toEqual("Row 1 description") - expect(rows[2].name).toEqual("Row 2") - expect(rows[2].description).toEqual("Row 2 description") - expect(rows[3].name).toEqual("Updated existing row") - expect(rows[3].description).toEqual("Existing description") - - await assertRowUsage(rowUsage + 3) - }) - - // Upserting isn't yet supported in MSSQL / Oracle, see: - // https://github.com/knex/knex/pull/6050 - !isMSSQL && - !isOracle && - it("should be able to update existing rows with bulkImport", async () => { - const table = await config.api.table.save( - saveTableRequest({ - primary: ["userId"], - schema: { - userId: { - type: FieldType.NUMBER, - name: "userId", - constraints: { - presence: true, + }) + ) + const relatedTableId = relatedTable._id! + table = await config.api.table.save( + defaultTable({ + schema: { + name: { name: "name", type: FieldType.STRING }, + related1: { + type: FieldType.LINK, + name: "related1", + fieldName: "main1", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, + }, + related2: { + type: FieldType.LINK, + name: "related2", + fieldName: "main2", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, + }, }, - }, - name: { - type: FieldType.STRING, - name: "name", - }, - description: { - type: FieldType.STRING, - name: "description", - }, - }, + }) + ) + relatedRows = await Promise.all([ + config.api.row.save(relatedTableId, { name: "foo" }), + config.api.row.save(relatedTableId, { name: "bar" }), + config.api.row.save(relatedTableId, { name: "baz" }), + config.api.row.save(relatedTableId, { name: "boo" }), + ]) }) - ) - const row1 = await config.api.row.save(table._id!, { - userId: 1, - name: "Row 1", - description: "Row 1 description", + it("can create rows with both relationships", async () => { + const row = await config.api.row.save(table._id!, { + name: "test", + related1: [relatedRows[0]._id!], + related2: [relatedRows[1]._id!], + }) + + expect(row).toEqual( + expect.objectContaining({ + name: "test", + related1: [ + { + _id: relatedRows[0]._id, + primaryDisplay: relatedRows[0].name, + }, + ], + related2: [ + { + _id: relatedRows[1]._id, + primaryDisplay: relatedRows[1].name, + }, + ], + }) + ) + }) + + it("can create rows with no relationships", async () => { + const row = await config.api.row.save(table._id!, { + name: "test", + }) + + expect(row.related1).toBeUndefined() + expect(row.related2).toBeUndefined() + }) + + it("can create rows with only one relationships field", async () => { + const row = await config.api.row.save(table._id!, { + name: "test", + related1: [], + related2: [relatedRows[1]._id!], + }) + + expect(row).toEqual( + expect.objectContaining({ + name: "test", + related2: [ + { + _id: relatedRows[1]._id, + primaryDisplay: relatedRows[1].name, + }, + ], + }) + ) + expect(row.related1).toBeUndefined() + }) }) - - const row2 = await config.api.row.save(table._id!, { - userId: 2, - name: "Row 2", - description: "Row 2 description", - }) - - await config.api.row.bulkImport(table._id!, { - identifierFields: ["userId"], - rows: [ - { - userId: row1.userId, - name: "Row 1 updated", - description: "Row 1 description updated", - }, - { - userId: row2.userId, - name: "Row 2 updated", - description: "Row 2 description updated", - }, - { - userId: 3, - name: "Row 3", - description: "Row 3 description", - }, - ], - }) - - const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(3) - - rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Row 1 updated") - expect(rows[0].description).toEqual("Row 1 description updated") - expect(rows[1].name).toEqual("Row 2 updated") - expect(rows[1].description).toEqual("Row 2 description updated") - expect(rows[2].name).toEqual("Row 3") - expect(rows[2].description).toEqual("Row 3 description") }) - // Upserting isn't yet supported in MSSQL or Oracle, see: - // https://github.com/knex/knex/pull/6050 - !isMSSQL && - !isOracle && - !isInternal && - it("should be able to update existing rows with composite primary keys with bulkImport", async () => { - const tableName = uuid.v4() - await client?.schema.createTable(tableName, table => { - table.integer("companyId") - table.integer("userId") - table.string("name") - table.string("description") - table.primary(["companyId", "userId"]) + describe("get", () => { + it("reads an existing row successfully", async () => { + const existing = await config.api.row.save(table._id!, {}) + + const res = await config.api.row.get(table._id!, existing._id!) + + expect(res).toEqual({ + ...existing, + ...defaultRowFields, + }) }) - const resp = await config.api.datasource.fetchSchema({ - datasourceId: datasource!._id!, - }) - const table = resp.datasource.entities![tableName] - - const row1 = await config.api.row.save(table._id!, { - companyId: 1, - userId: 1, - name: "Row 1", - description: "Row 1 description", + it("returns 404 when row does not exist", async () => { + const table = await config.api.table.save(defaultTable()) + await config.api.row.save(table._id!, {}) + await config.api.row.get(table._id!, "1234567", { + status: 404, + }) }) - const row2 = await config.api.row.save(table._id!, { - companyId: 1, - userId: 2, - name: "Row 2", - description: "Row 2 description", - }) + isInternal && + it("can search row from user table", async () => { + const res = await config.api.row.get( + InternalTables.USER_METADATA, + config.userMetadataId! + ) - await config.api.row.bulkImport(table._id!, { - identifierFields: ["companyId", "userId"], - rows: [ - { - companyId: 1, - userId: row1.userId, - name: "Row 1 updated", - description: "Row 1 description updated", - }, - { - companyId: 1, - userId: row2.userId, - name: "Row 2 updated", - description: "Row 2 description updated", - }, - { - companyId: 1, - userId: 3, - name: "Row 3", - description: "Row 3 description", - }, - ], - }) - - const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(3) - - rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Row 1 updated") - expect(rows[0].description).toEqual("Row 1 description updated") - expect(rows[1].name).toEqual("Row 2 updated") - expect(rows[1].description).toEqual("Row 2 description updated") - expect(rows[2].name).toEqual("Row 3") - expect(rows[2].description).toEqual("Row 3 description") + expect(res).toEqual({ + ...config.getUser(), + _id: config.userMetadataId!, + _rev: expect.any(String), + roles: undefined, + roleId: "ADMIN", + tableId: InternalTables.USER_METADATA, + }) + }) }) - // Upserting isn't yet supported in MSSQL/Oracle, see: - // https://github.com/knex/knex/pull/6050 - !isMSSQL && - !isOracle && - !isInternal && - it("should be able to update existing rows an autoID primary key", async () => { - const tableName = uuid.v4() - await client!.schema.createTable(tableName, table => { - table.increments("userId").primary() - table.string("name") + describe("fetch", () => { + it("fetches all rows for given tableId", async () => { + const table = await config.api.table.save(defaultTable()) + const rows = await Promise.all([ + config.api.row.save(table._id!, {}), + config.api.row.save(table._id!, {}), + ]) + + const res = await config.api.row.fetch(table._id!) + expect(res.map(r => r._id)).toEqual( + expect.arrayContaining(rows.map(r => r._id)) + ) }) - const resp = await config.api.datasource.fetchSchema({ - datasourceId: datasource!._id!, + it("returns 404 when table does not exist", async () => { + await config.api.row.fetch("1234567", { status: 404 }) }) - const table = resp.datasource.entities![tableName] - - const row1 = await config.api.row.save(table._id!, { - name: "Clare", - }) - - const row2 = await config.api.row.save(table._id!, { - name: "Jeff", - }) - - await config.api.row.bulkImport(table._id!, { - identifierFields: ["userId"], - rows: [ - { - userId: row1.userId, - name: "Clare updated", - }, - { - userId: row2.userId, - name: "Jeff updated", - }, - ], - }) - - const rows = await config.api.row.fetch(table._id!) - expect(rows.length).toEqual(2) - - rows.sort((a, b) => a.name.localeCompare(b.name)) - expect(rows[0].name).toEqual("Clare updated") - expect(rows[1].name).toEqual("Jeff updated") }) - }) - describe("enrich", () => { - beforeAll(async () => { - table = await config.api.table.save(defaultTable()) - }) + describe("update", () => { + it("updates an existing row successfully", async () => { + const existing = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() - it("should allow enriching some linked rows", async () => { - const { linkedTable, firstRow, secondRow } = await tenancy.doInTenant( - config.getTenantId(), - async () => { - const linkedTable = await config.api.table.save( + const res = await config.api.row.save(table._id!, { + _id: existing._id, + _rev: existing._rev, + name: "Updated Name", + }) + + expect(res.name).toEqual("Updated Name") + await assertRowUsage(rowUsage) + }) + + !isInternal && + it("can update a row on an external table with a primary key", async () => { + const tableName = uuid.v4().substring(0, 10) + await client!.schema.createTable(tableName, table => { + table.increments("id").primary() + table.string("name") + }) + + const res = await config.api.datasource.fetchSchema({ + datasourceId: datasource!._id!, + }) + const table = res.datasource.entities![tableName] + + const row = await config.api.row.save(table._id!, { + id: 1, + name: "Row 1", + }) + + const updatedRow = await config.api.row.save(table._id!, { + _id: row._id!, + name: "Row 1 Updated", + }) + + expect(updatedRow.name).toEqual("Row 1 Updated") + + const rows = await config.api.row.fetch(table._id!) + expect(rows).toHaveLength(1) + }) + + describe("relations to same table", () => { + let relatedRows: Row[] + + beforeAll(async () => { + const relatedTable = await config.api.table.save( + defaultTable({ + schema: { + name: { name: "name", type: FieldType.STRING }, + }, + }) + ) + const relatedTableId = relatedTable._id! + table = await config.api.table.save( + defaultTable({ + schema: { + name: { name: "name", type: FieldType.STRING }, + related1: { + type: FieldType.LINK, + name: "related1", + fieldName: "main1", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, + }, + related2: { + type: FieldType.LINK, + name: "related2", + fieldName: "main2", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, + }, + }, + }) + ) + relatedRows = await Promise.all([ + config.api.row.save(relatedTableId, { name: "foo" }), + config.api.row.save(relatedTableId, { name: "bar" }), + config.api.row.save(relatedTableId, { name: "baz" }), + config.api.row.save(relatedTableId, { name: "boo" }), + ]) + }) + + it("can edit rows with both relationships", async () => { + let row = await config.api.row.save(table._id!, { + name: "test", + related1: [relatedRows[0]._id!], + related2: [relatedRows[1]._id!], + }) + + row = await config.api.row.save(table._id!, { + ...row, + related1: [relatedRows[0]._id!, relatedRows[1]._id!], + related2: [relatedRows[2]._id!], + }) + + expect(row).toEqual( + expect.objectContaining({ + name: "test", + related1: expect.arrayContaining([ + { + _id: relatedRows[0]._id, + primaryDisplay: relatedRows[0].name, + }, + { + _id: relatedRows[1]._id, + primaryDisplay: relatedRows[1].name, + }, + ]), + related2: [ + { + _id: relatedRows[2]._id, + primaryDisplay: relatedRows[2].name, + }, + ], + }) + ) + }) + + it("can drop existing relationship", async () => { + let row = await config.api.row.save(table._id!, { + name: "test", + related1: [relatedRows[0]._id!], + related2: [relatedRows[1]._id!], + }) + + row = await config.api.row.save(table._id!, { + ...row, + related1: [], + related2: [relatedRows[2]._id!], + }) + + expect(row).toEqual( + expect.objectContaining({ + name: "test", + related2: [ + { + _id: relatedRows[2]._id, + primaryDisplay: relatedRows[2].name, + }, + ], + }) + ) + expect(row.related1).toBeUndefined() + }) + + it("can drop both relationships", async () => { + let row = await config.api.row.save(table._id!, { + name: "test", + related1: [relatedRows[0]._id!], + related2: [relatedRows[1]._id!], + }) + + row = await config.api.row.save(table._id!, { + ...row, + related1: [], + related2: [], + }) + + expect(row).toEqual( + expect.objectContaining({ + name: "test", + }) + ) + expect(row.related1).toBeUndefined() + expect(row.related2).toBeUndefined() + }) + }) + }) + + describe("patch", () => { + let otherTable: Table + + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) + otherTable = await config.api.table.save( defaultTable({ schema: { - link: { - name: "link", - fieldName: "link", - type: FieldType.LINK, + relationship: { + name: "relationship", relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, tableId: table._id!, + fieldName: "relationship", }, }, }) ) - const firstRow = await config.api.row.save(table._id!, { - name: "Test Contact", - description: "original description", - }) - const secondRow = await config.api.row.save(linkedTable._id!, { - name: "Test 2", - description: "og desc", - link: [{ _id: firstRow._id }], - }) - return { linkedTable, firstRow, secondRow } - } - ) - const rowUsage = await getRowUsage() + }) - // test basic enrichment - const resBasic = await config.api.row.get( - linkedTable._id!, - secondRow._id! - ) - expect(resBasic.link.length).toBe(1) - expect(resBasic.link[0]).toEqual({ - _id: firstRow._id, - primaryDisplay: firstRow.name, + it("should update only the fields that are supplied", async () => { + const existing = await config.api.row.save(table._id!, {}) + + const rowUsage = await getRowUsage() + + const row = await config.api.row.patch(table._id!, { + _id: existing._id!, + _rev: existing._rev!, + tableId: table._id!, + name: "Updated Name", + }) + + expect(row.name).toEqual("Updated Name") + expect(row.description).toEqual(existing.description) + + const savedRow = await config.api.row.get(table._id!, row._id!) + + expect(savedRow.description).toEqual(existing.description) + expect(savedRow.name).toEqual("Updated Name") + await assertRowUsage(rowUsage) + }) + + it("should update only the fields that are supplied and emit the correct oldRow", async () => { + let beforeRow = await config.api.row.save(table._id!, { + name: "test", + description: "test", + }) + const opts = { + name: "row:update", + matchFn: (event: UpdatedRowEventEmitter) => + event.row._id === beforeRow._id, + } + const event = await waitForEvent(opts, async () => { + await config.api.row.patch(table._id!, { + _id: beforeRow._id!, + _rev: beforeRow._rev!, + tableId: table._id!, + name: "Updated Name", + }) + }) + + expect(event.oldRow).toBeDefined() + expect(event.oldRow.name).toEqual("test") + expect(event.row.name).toEqual("Updated Name") + expect(event.oldRow.description).toEqual(beforeRow.description) + expect(event.row.description).toEqual(beforeRow.description) + }) + + it("should throw an error when given improper types", async () => { + const existing = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + + await config.api.row.patch( + table._id!, + { + _id: existing._id!, + _rev: existing._rev!, + tableId: table._id!, + name: 1, + }, + { status: 400 } + ) + + await assertRowUsage(rowUsage) + }) + + it("should not overwrite links if those links are not set", async () => { + let linkField: FieldSchema = { + type: FieldType.LINK, + name: "", + fieldName: "", + constraints: { + type: "array", + presence: false, + }, + relationshipType: RelationshipType.ONE_TO_MANY, + tableId: InternalTable.USER_METADATA, + } + + let table = await config.api.table.save({ + name: "TestTable", + type: "table", + sourceType: TableSourceType.INTERNAL, + sourceId: INTERNAL_TABLE_SOURCE_ID, + schema: { + user1: { ...linkField, name: "user1", fieldName: "user1" }, + user2: { ...linkField, name: "user2", fieldName: "user2" }, + }, + }) + + let user1 = await config.createUser() + let user2 = await config.createUser() + + let row = await config.api.row.save(table._id!, { + user1: [{ _id: user1._id }], + user2: [{ _id: user2._id }], + }) + + let getResp = await config.api.row.get(table._id!, row._id!) + expect(getResp.user1[0]._id).toEqual(user1._id) + expect(getResp.user2[0]._id).toEqual(user2._id) + + let patchResp = await config.api.row.patch(table._id!, { + _id: row._id!, + _rev: row._rev!, + tableId: table._id!, + user1: [{ _id: user2._id }], + }) + expect(patchResp.user1[0]._id).toEqual(user2._id) + expect(patchResp.user2[0]._id).toEqual(user2._id) + + getResp = await config.api.row.get(table._id!, row._id!) + expect(getResp.user1[0]._id).toEqual(user2._id) + expect(getResp.user2[0]._id).toEqual(user2._id) + }) + + it("should be able to remove a relationship from many side", async () => { + const row = await config.api.row.save(otherTable._id!, { + name: "test", + description: "test", + }) + const row2 = await config.api.row.save(otherTable._id!, { + name: "test", + description: "test", + }) + const { _id } = await config.api.row.save(table._id!, { + relationship: [{ _id: row._id }, { _id: row2._id }], + }) + const relatedRow = await config.api.row.get(table._id!, _id!, { + status: 200, + }) + expect(relatedRow.relationship.length).toEqual(2) + await config.api.row.save(table._id!, { + ...relatedRow, + relationship: [{ _id: row._id }], + }) + const afterRelatedRow = await config.api.row.get(table._id!, _id!, { + status: 200, + }) + expect(afterRelatedRow.relationship.length).toEqual(1) + expect(afterRelatedRow.relationship[0]._id).toEqual(row._id) + }) + + it("should be able to update relationships when both columns are same name", async () => { + let row = await config.api.row.save(table._id!, { + name: "test", + description: "test", + }) + let row2 = await config.api.row.save(otherTable._id!, { + name: "test", + description: "test", + relationship: [row._id], + }) + row = await config.api.row.get(table._id!, row._id!) + expect(row.relationship.length).toBe(1) + const resp = await config.api.row.patch(table._id!, { + _id: row._id!, + _rev: row._rev!, + tableId: row.tableId!, + name: "test2", + relationship: [row2._id], + }) + expect(resp.relationship.length).toBe(1) + }) + + !isInternal && + // MSSQL needs a setting called IDENTITY_INSERT to be set to ON to allow writing + // to identity columns. This is not something Budibase does currently. + !isMSSQL && + it("should support updating fields that are part of a composite key", async () => { + const tableRequest = saveTableRequest({ + primary: ["number", "string"], + schema: { + string: { + type: FieldType.STRING, + name: "string", + }, + number: { + type: FieldType.NUMBER, + name: "number", + }, + }, + }) + + delete tableRequest.schema.id + + const table = await config.api.table.save(tableRequest) + + const stringValue = generator.word() + + // MySQL and MariaDB auto-increment fields have a minimum value of 1. If + // you try to save a row with a value of 0 it will use 1 instead. + const naturalValue = generator.integer({ min: 1, max: 1000 }) + + const existing = await config.api.row.save(table._id!, { + string: stringValue, + number: naturalValue, + }) + + expect(existing._id).toEqual( + `%5B${naturalValue}%2C'${stringValue}'%5D` + ) + + const row = await config.api.row.patch(table._id!, { + _id: existing._id!, + _rev: existing._rev!, + tableId: table._id!, + string: stringValue, + number: 1500, + }) + + expect(row._id).toEqual(`%5B${"1500"}%2C'${stringValue}'%5D`) + }) }) - // test full enrichment - const resEnriched = await config.api.row.getEnriched( - linkedTable._id!, - secondRow._id! - ) - expect(resEnriched.link.length).toBe(1) - expect(resEnriched.link[0]._id).toBe(firstRow._id) - expect(resEnriched.link[0].name).toBe("Test Contact") - expect(resEnriched.link[0].description).toBe("original description") - await assertRowUsage(rowUsage) - }) - }) + describe("destroy", () => { + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) + }) - isInternal && - describe("attachments and signatures", () => { - const coreAttachmentEnrichment = async ( - schema: TableSchema, - field: string, - attachmentCfg: string | string[] - ) => { - const testTable = await config.api.table.save( - defaultTable({ - schema, + it("should be able to delete a row", async () => { + const createdRow = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + + const res = await config.api.row.bulkDelete(table._id!, { + rows: [createdRow], }) - ) - const attachmentToStoreKey = (attachmentId: string) => { - return { - key: `${config.getAppId()}/attachments/${attachmentId}`, + expect(res[0]._id).toEqual(createdRow._id) + await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) + }) + + it("should be able to delete a row with ID only", async () => { + const createdRow = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + + const res = await config.api.row.bulkDelete(table._id!, { + rows: [createdRow._id!], + }) + expect(res[0]._id).toEqual(createdRow._id) + expect(res[0].tableId).toEqual(table._id!) + await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) + }) + + it("should be able to bulk delete rows, including a row that doesn't exist", async () => { + const createdRow = await config.api.row.save(table._id!, {}) + const createdRow2 = await config.api.row.save(table._id!, {}) + + const res = await config.api.row.bulkDelete(table._id!, { + rows: [createdRow, createdRow2, { _id: "9999999" }], + }) + + expect(res.map(r => r._id)).toEqual( + expect.arrayContaining([createdRow._id, createdRow2._id]) + ) + expect(res.length).toEqual(2) + }) + + describe("relations to same table", () => { + let relatedRows: Row[] + + beforeAll(async () => { + const relatedTable = await config.api.table.save( + defaultTable({ + schema: { + name: { name: "name", type: FieldType.STRING }, + }, + }) + ) + const relatedTableId = relatedTable._id! + table = await config.api.table.save( + defaultTable({ + schema: { + name: { name: "name", type: FieldType.STRING }, + related1: { + type: FieldType.LINK, + name: "related1", + fieldName: "main1", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, + }, + related2: { + type: FieldType.LINK, + name: "related2", + fieldName: "main2", + tableId: relatedTableId, + relationshipType: RelationshipType.MANY_TO_MANY, + }, + }, + }) + ) + relatedRows = await Promise.all([ + config.api.row.save(relatedTableId, { name: "foo" }), + config.api.row.save(relatedTableId, { name: "bar" }), + config.api.row.save(relatedTableId, { name: "baz" }), + config.api.row.save(relatedTableId, { name: "boo" }), + ]) + }) + + it("can delete rows with both relationships", async () => { + const row = await config.api.row.save(table._id!, { + name: "test", + related1: [relatedRows[0]._id!], + related2: [relatedRows[1]._id!], + }) + + await config.api.row.delete(table._id!, { _id: row._id! }) + + await config.api.row.get(table._id!, row._id!, { status: 404 }) + }) + + it("can delete rows with empty relationships", async () => { + const row = await config.api.row.save(table._id!, { + name: "test", + related1: [], + related2: [], + }) + + await config.api.row.delete(table._id!, { _id: row._id! }) + + await config.api.row.get(table._id!, row._id!, { status: 404 }) + }) + }) + }) + + describe("validate", () => { + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) + }) + + it("should return no errors on valid row", async () => { + const rowUsage = await getRowUsage() + + const res = await config.api.row.validate(table._id!, { + name: "ivan", + }) + + expect(res.valid).toBe(true) + expect(Object.keys(res.errors)).toEqual([]) + await assertRowUsage(rowUsage) + }) + + it("should errors on invalid row", async () => { + const rowUsage = await getRowUsage() + + const res = await config.api.row.validate(table._id!, { name: 1 }) + + if (isInternal) { + expect(res.valid).toBe(false) + expect(Object.keys(res.errors)).toEqual(["name"]) + } else { + // Validation for external is not implemented, so it will always return valid + expect(res.valid).toBe(true) + expect(Object.keys(res.errors)).toEqual([]) } - } - const draftRow = { - name: "test", - description: "test", - [field]: - typeof attachmentCfg === "string" - ? attachmentToStoreKey(attachmentCfg) - : attachmentCfg.map(attachmentToStoreKey), - tableId: testTable._id, - } - const row = await config.api.row.save(testTable._id!, draftRow) + await assertRowUsage(rowUsage) + }) + }) - await withEnv({ SELF_HOSTED: "true" }, async () => { - return context.doInAppContext(config.getAppId(), async () => { - const enriched: Row[] = await outputProcessing(testTable, [row]) - const [targetRow] = enriched - const attachmentEntries = Array.isArray(targetRow[field]) - ? targetRow[field] - : [targetRow[field]] + describe("bulkDelete", () => { + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) + }) - for (const entry of attachmentEntries) { - const attachmentId = entry.key.split("/").pop() - expect(entry.url.split("?")[0]).toBe( - `/files/signed/prod-budi-app-assets/${config.getProdAppId()}/attachments/${attachmentId}` + it("should be able to delete a bulk set of rows", async () => { + const row1 = await config.api.row.save(table._id!, {}) + const row2 = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + + const res = await config.api.row.bulkDelete(table._id!, { + rows: [row1, row2], + }) + + expect(res.length).toEqual(2) + await config.api.row.get(table._id!, row1._id!, { status: 404 }) + await assertRowUsage(isInternal ? rowUsage - 2 : rowUsage) + }) + + it("should be able to delete a variety of row set types", async () => { + const [row1, row2, row3] = await Promise.all([ + config.api.row.save(table._id!, {}), + config.api.row.save(table._id!, {}), + config.api.row.save(table._id!, {}), + ]) + const rowUsage = await getRowUsage() + + const res = await config.api.row.bulkDelete(table._id!, { + rows: [row1, row2._id!, { _id: row3._id }], + }) + + expect(res.length).toEqual(3) + await config.api.row.get(table._id!, row1._id!, { status: 404 }) + await assertRowUsage(isInternal ? rowUsage - 3 : rowUsage) + }) + + it("should accept a valid row object and delete the row", async () => { + const row1 = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + + const res = await config.api.row.delete(table._id!, row1 as DeleteRow) + + expect(res.id).toEqual(row1._id) + await config.api.row.get(table._id!, row1._id!, { status: 404 }) + await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) + }) + + it.each([{ not: "valid" }, { rows: 123 }, "invalid"])( + "should ignore malformed/invalid delete request: %s", + async (request: any) => { + const rowUsage = await getRowUsage() + + await config.api.row.delete(table._id!, request, { + status: 400, + body: { + message: "Invalid delete rows request", + }, + }) + + await assertRowUsage(rowUsage) + } + ) + }) + + describe("bulkImport", () => { + isInternal && + it("should update Auto ID field after bulk import", async () => { + const table = await config.api.table.save( + saveTableRequest({ + primary: ["autoId"], + schema: { + autoId: { + name: "autoId", + type: FieldType.NUMBER, + subtype: AutoFieldSubType.AUTO_ID, + autocolumn: true, + constraints: { + type: "number", + presence: false, + }, + }, + }, + }) + ) + + let row = await config.api.row.save(table._id!, {}) + expect(row.autoId).toEqual(1) + + await config.api.row.bulkImport(table._id!, { + rows: [{ autoId: 2 }], + }) + + row = await config.api.row.save(table._id!, {}) + expect(row.autoId).toEqual(3) + }) + + isInternal && + it("should reject bulkImporting relationship fields", async () => { + const table1 = await config.api.table.save(saveTableRequest()) + const table2 = await config.api.table.save( + saveTableRequest({ + schema: { + relationship: { + name: "relationship", + type: FieldType.LINK, + tableId: table1._id!, + relationshipType: RelationshipType.ONE_TO_MANY, + fieldName: "relationship", + }, + }, + }) + ) + + const table1Row1 = await config.api.row.save(table1._id!, {}) + await config.api.row.bulkImport( + table2._id!, + { + rows: [{ relationship: [table1Row1._id!] }], + }, + { + status: 400, + body: { + message: + 'Can\'t bulk import relationship fields for internal databases, found value in field "relationship"', + }, + } + ) + }) + + it("should be able to bulkImport rows", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + type: FieldType.STRING, + name: "name", + }, + description: { + type: FieldType.STRING, + name: "description", + }, + }, + }) + ) + + const rowUsage = await getRowUsage() + + await config.api.row.bulkImport(table._id!, { + rows: [ + { + name: "Row 1", + description: "Row 1 description", + }, + { + name: "Row 2", + description: "Row 2 description", + }, + ], + }) + + const rows = await config.api.row.fetch(table._id!) + expect(rows.length).toEqual(2) + + rows.sort((a, b) => a.name.localeCompare(b.name)) + expect(rows[0].name).toEqual("Row 1") + expect(rows[0].description).toEqual("Row 1 description") + expect(rows[1].name).toEqual("Row 2") + expect(rows[1].description).toEqual("Row 2 description") + + await assertRowUsage(isInternal ? rowUsage + 2 : rowUsage) + }) + + isInternal && + it("should be able to update existing rows on bulkImport", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + type: FieldType.STRING, + name: "name", + }, + description: { + type: FieldType.STRING, + name: "description", + }, + }, + }) + ) + + const existingRow = await config.api.row.save(table._id!, { + name: "Existing row", + description: "Existing description", + }) + + const rowUsage = await getRowUsage() + + await config.api.row.bulkImport(table._id!, { + rows: [ + { + name: "Row 1", + description: "Row 1 description", + }, + { ...existingRow, name: "Updated existing row" }, + { + name: "Row 2", + description: "Row 2 description", + }, + ], + identifierFields: ["_id"], + }) + + const rows = await config.api.row.fetch(table._id!) + expect(rows.length).toEqual(3) + + rows.sort((a, b) => a.name.localeCompare(b.name)) + expect(rows[0].name).toEqual("Row 1") + expect(rows[0].description).toEqual("Row 1 description") + expect(rows[1].name).toEqual("Row 2") + expect(rows[1].description).toEqual("Row 2 description") + expect(rows[2].name).toEqual("Updated existing row") + expect(rows[2].description).toEqual("Existing description") + + await assertRowUsage(rowUsage + 2) + }) + + isInternal && + it("should create new rows if not identifierFields are provided", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + type: FieldType.STRING, + name: "name", + }, + description: { + type: FieldType.STRING, + name: "description", + }, + }, + }) + ) + + const existingRow = await config.api.row.save(table._id!, { + name: "Existing row", + description: "Existing description", + }) + + const rowUsage = await getRowUsage() + + await config.api.row.bulkImport(table._id!, { + rows: [ + { + name: "Row 1", + description: "Row 1 description", + }, + { ...existingRow, name: "Updated existing row" }, + { + name: "Row 2", + description: "Row 2 description", + }, + ], + }) + + const rows = await config.api.row.fetch(table._id!) + expect(rows.length).toEqual(4) + + rows.sort((a, b) => a.name.localeCompare(b.name)) + expect(rows[0].name).toEqual("Existing row") + expect(rows[0].description).toEqual("Existing description") + expect(rows[1].name).toEqual("Row 1") + expect(rows[1].description).toEqual("Row 1 description") + expect(rows[2].name).toEqual("Row 2") + expect(rows[2].description).toEqual("Row 2 description") + expect(rows[3].name).toEqual("Updated existing row") + expect(rows[3].description).toEqual("Existing description") + + await assertRowUsage(rowUsage + 3) + }) + + // Upserting isn't yet supported in MSSQL / Oracle, see: + // https://github.com/knex/knex/pull/6050 + !isMSSQL && + !isOracle && + it("should be able to update existing rows with bulkImport", async () => { + const table = await config.api.table.save( + saveTableRequest({ + primary: ["userId"], + schema: { + userId: { + type: FieldType.NUMBER, + name: "userId", + constraints: { + presence: true, + }, + }, + name: { + type: FieldType.STRING, + name: "name", + }, + description: { + type: FieldType.STRING, + name: "description", + }, + }, + }) + ) + + const row1 = await config.api.row.save(table._id!, { + userId: 1, + name: "Row 1", + description: "Row 1 description", + }) + + const row2 = await config.api.row.save(table._id!, { + userId: 2, + name: "Row 2", + description: "Row 2 description", + }) + + await config.api.row.bulkImport(table._id!, { + identifierFields: ["userId"], + rows: [ + { + userId: row1.userId, + name: "Row 1 updated", + description: "Row 1 description updated", + }, + { + userId: row2.userId, + name: "Row 2 updated", + description: "Row 2 description updated", + }, + { + userId: 3, + name: "Row 3", + description: "Row 3 description", + }, + ], + }) + + const rows = await config.api.row.fetch(table._id!) + expect(rows.length).toEqual(3) + + rows.sort((a, b) => a.name.localeCompare(b.name)) + expect(rows[0].name).toEqual("Row 1 updated") + expect(rows[0].description).toEqual("Row 1 description updated") + expect(rows[1].name).toEqual("Row 2 updated") + expect(rows[1].description).toEqual("Row 2 description updated") + expect(rows[2].name).toEqual("Row 3") + expect(rows[2].description).toEqual("Row 3 description") + }) + + // Upserting isn't yet supported in MSSQL or Oracle, see: + // https://github.com/knex/knex/pull/6050 + !isMSSQL && + !isOracle && + !isInternal && + it("should be able to update existing rows with composite primary keys with bulkImport", async () => { + const tableName = uuid.v4() + await client?.schema.createTable(tableName, table => { + table.integer("companyId") + table.integer("userId") + table.string("name") + table.string("description") + table.primary(["companyId", "userId"]) + }) + + const resp = await config.api.datasource.fetchSchema({ + datasourceId: datasource!._id!, + }) + const table = resp.datasource.entities![tableName] + + const row1 = await config.api.row.save(table._id!, { + companyId: 1, + userId: 1, + name: "Row 1", + description: "Row 1 description", + }) + + const row2 = await config.api.row.save(table._id!, { + companyId: 1, + userId: 2, + name: "Row 2", + description: "Row 2 description", + }) + + await config.api.row.bulkImport(table._id!, { + identifierFields: ["companyId", "userId"], + rows: [ + { + companyId: 1, + userId: row1.userId, + name: "Row 1 updated", + description: "Row 1 description updated", + }, + { + companyId: 1, + userId: row2.userId, + name: "Row 2 updated", + description: "Row 2 description updated", + }, + { + companyId: 1, + userId: 3, + name: "Row 3", + description: "Row 3 description", + }, + ], + }) + + const rows = await config.api.row.fetch(table._id!) + expect(rows.length).toEqual(3) + + rows.sort((a, b) => a.name.localeCompare(b.name)) + expect(rows[0].name).toEqual("Row 1 updated") + expect(rows[0].description).toEqual("Row 1 description updated") + expect(rows[1].name).toEqual("Row 2 updated") + expect(rows[1].description).toEqual("Row 2 description updated") + expect(rows[2].name).toEqual("Row 3") + expect(rows[2].description).toEqual("Row 3 description") + }) + + // Upserting isn't yet supported in MSSQL/Oracle, see: + // https://github.com/knex/knex/pull/6050 + !isMSSQL && + !isOracle && + !isInternal && + it("should be able to update existing rows an autoID primary key", async () => { + const tableName = uuid.v4() + await client!.schema.createTable(tableName, table => { + table.increments("userId").primary() + table.string("name") + }) + + const resp = await config.api.datasource.fetchSchema({ + datasourceId: datasource!._id!, + }) + const table = resp.datasource.entities![tableName] + + const row1 = await config.api.row.save(table._id!, { + name: "Clare", + }) + + const row2 = await config.api.row.save(table._id!, { + name: "Jeff", + }) + + await config.api.row.bulkImport(table._id!, { + identifierFields: ["userId"], + rows: [ + { + userId: row1.userId, + name: "Clare updated", + }, + { + userId: row2.userId, + name: "Jeff updated", + }, + ], + }) + + const rows = await config.api.row.fetch(table._id!) + expect(rows.length).toEqual(2) + + rows.sort((a, b) => a.name.localeCompare(b.name)) + expect(rows[0].name).toEqual("Clare updated") + expect(rows[1].name).toEqual("Jeff updated") + }) + }) + + describe("enrich", () => { + beforeAll(async () => { + table = await config.api.table.save(defaultTable()) + }) + + it("should allow enriching some linked rows", async () => { + const { linkedTable, firstRow, secondRow } = await tenancy.doInTenant( + config.getTenantId(), + async () => { + const linkedTable = await config.api.table.save( + defaultTable({ + schema: { + link: { + name: "link", + fieldName: "link", + type: FieldType.LINK, + relationshipType: RelationshipType.ONE_TO_MANY, + tableId: table._id!, + }, + }, + }) ) + const firstRow = await config.api.row.save(table._id!, { + name: "Test Contact", + description: "original description", + }) + const secondRow = await config.api.row.save(linkedTable._id!, { + name: "Test 2", + description: "og desc", + link: [{ _id: firstRow._id }], + }) + return { linkedTable, firstRow, secondRow } + } + ) + const rowUsage = await getRowUsage() + + // test basic enrichment + const resBasic = await config.api.row.get( + linkedTable._id!, + secondRow._id! + ) + expect(resBasic.link.length).toBe(1) + expect(resBasic.link[0]).toEqual({ + _id: firstRow._id, + primaryDisplay: firstRow.name, + }) + + // test full enrichment + const resEnriched = await config.api.row.getEnriched( + linkedTable._id!, + secondRow._id! + ) + expect(resEnriched.link.length).toBe(1) + expect(resEnriched.link[0]._id).toBe(firstRow._id) + expect(resEnriched.link[0].name).toBe("Test Contact") + expect(resEnriched.link[0].description).toBe("original description") + await assertRowUsage(rowUsage) + }) + }) + + isInternal && + describe("attachments and signatures", () => { + const coreAttachmentEnrichment = async ( + schema: TableSchema, + field: string, + attachmentCfg: string | string[] + ) => { + const testTable = await config.api.table.save( + defaultTable({ + schema, + }) + ) + const attachmentToStoreKey = (attachmentId: string) => { + return { + key: `${config.getAppId()}/attachments/${attachmentId}`, + } + } + const draftRow = { + name: "test", + description: "test", + [field]: + typeof attachmentCfg === "string" + ? attachmentToStoreKey(attachmentCfg) + : attachmentCfg.map(attachmentToStoreKey), + tableId: testTable._id, + } + const row = await config.api.row.save(testTable._id!, draftRow) + + await withEnv({ SELF_HOSTED: "true" }, async () => { + return context.doInAppContext(config.getAppId(), async () => { + const enriched: Row[] = await outputProcessing(testTable, [row]) + const [targetRow] = enriched + const attachmentEntries = Array.isArray(targetRow[field]) + ? targetRow[field] + : [targetRow[field]] + + for (const entry of attachmentEntries) { + const attachmentId = entry.key.split("/").pop() + expect(entry.url.split("?")[0]).toBe( + `/files/signed/prod-budi-app-assets/${config.getProdAppId()}/attachments/${attachmentId}` + ) + } + }) + }) + } + + it("should allow enriching single attachment rows", async () => { + await coreAttachmentEnrichment( + { + attachment: { + type: FieldType.ATTACHMENT_SINGLE, + name: "attachment", + constraints: { presence: false }, + }, + }, + "attachment", + `${uuid.v4()}.csv` + ) + }) + + it("should allow enriching attachment list rows", async () => { + await coreAttachmentEnrichment( + { + attachments: { + type: FieldType.ATTACHMENTS, + name: "attachments", + constraints: { type: "array", presence: false }, + }, + }, + "attachments", + [`${uuid.v4()}.csv`] + ) + }) + + it("should allow enriching signature rows", async () => { + await coreAttachmentEnrichment( + { + signature: { + type: FieldType.SIGNATURE_SINGLE, + name: "signature", + constraints: { presence: false }, + }, + }, + "signature", + `${uuid.v4()}.png` + ) + }) + }) + + describe("exportRows", () => { + beforeEach(async () => { + table = await config.api.table.save(defaultTable()) + }) + + isInternal && + it("should not export internal couchdb fields", async () => { + const existing = await config.api.row.save(table._id!, { + name: generator.guid(), + description: generator.paragraph(), + }) + const res = await config.api.row.exportRows(table._id!, { + rows: [existing._id!], + }) + const results = JSON.parse(res) + expect(results.length).toEqual(1) + const row = results[0] + + expect(Object.keys(row)).toEqual(["_id", "name", "description"]) + }) + + !isInternal && + it("should allow exporting all columns", async () => { + const existing = await config.api.row.save(table._id!, {}) + const res = await config.api.row.exportRows(table._id!, { + rows: [existing._id!], + }) + const results = JSON.parse(res) + expect(results.length).toEqual(1) + const row = results[0] + + // Ensure all original columns were exported + expect(Object.keys(row).length).toBe(Object.keys(existing).length) + Object.keys(existing).forEach(key => { + expect(row[key]).toEqual(existing[key]) + }) + }) + + it("should allow exporting without filtering", async () => { + const existing = await config.api.row.save(table._id!, {}) + const res = await config.api.row.exportRows(table._id!) + const results = JSON.parse(res) + expect(results.length).toEqual(1) + const row = results[0] + + expect(row._id).toEqual(existing._id) + }) + + it("should allow exporting only certain columns", async () => { + const existing = await config.api.row.save(table._id!, {}) + const res = await config.api.row.exportRows(table._id!, { + rows: [existing._id!], + columns: ["_id"], + }) + const results = JSON.parse(res) + expect(results.length).toEqual(1) + const row = results[0] + + // Ensure only the _id column was exported + expect(Object.keys(row).length).toEqual(1) + expect(row._id).toEqual(existing._id) + }) + + it("should handle single quotes in row filtering", async () => { + const existing = await config.api.row.save(table._id!, {}) + const res = await config.api.row.exportRows(table._id!, { + rows: [`['${existing._id!}']`], + }) + const results = JSON.parse(res) + expect(results.length).toEqual(1) + const row = results[0] + expect(row._id).toEqual(existing._id) + }) + + it("should return an error if no table is found", async () => { + const existing = await config.api.row.save(table._id!, {}) + await config.api.row.exportRows( + "1234567", + { rows: [existing._id!] }, + RowExportFormat.JSON, + { status: 404 } + ) + }) + + // MSSQL needs a setting called IDENTITY_INSERT to be set to ON to allow writing + // to identity columns. This is not something Budibase does currently. + !isMSSQL && + it("should handle filtering by composite primary keys", async () => { + const tableRequest = saveTableRequest({ + primary: ["number", "string"], + schema: { + string: { + type: FieldType.STRING, + name: "string", + }, + number: { + type: FieldType.NUMBER, + name: "number", + }, + }, + }) + delete tableRequest.schema.id + + const table = await config.api.table.save(tableRequest) + const toCreate = generator + .unique(() => generator.integer({ min: 0, max: 10000 }), 10) + .map(number => ({ + number, + string: generator.word({ length: 30 }), + })) + + const rows = await Promise.all( + toCreate.map(d => config.api.row.save(table._id!, d)) + ) + + const res = await config.api.row.exportRows(table._id!, { + rows: _.sampleSize(rows, 3).map(r => r._id!), + }) + const results = JSON.parse(res) + expect(results.length).toEqual(3) + }) + + describe("should allow exporting all column types", () => { + let tableId: string + let expectedRowData: Row + + beforeAll(async () => { + const fullSchema = setup.structures.fullSchemaWithoutLinks({ + allRequired: true, + }) + + const table = await config.api.table.save( + saveTableRequest({ + ...setup.structures.basicTable(), + schema: fullSchema, + primary: ["string"], + }) + ) + tableId = table._id! + + const rowValues: Record = { + [FieldType.STRING]: generator.guid(), + [FieldType.LONGFORM]: generator.paragraph(), + [FieldType.OPTIONS]: "option 2", + [FieldType.ARRAY]: ["options 2", "options 4"], + [FieldType.NUMBER]: generator.natural(), + [FieldType.BOOLEAN]: generator.bool(), + [FieldType.DATETIME]: generator.date().toISOString(), + [FieldType.ATTACHMENTS]: [setup.structures.basicAttachment()], + [FieldType.ATTACHMENT_SINGLE]: setup.structures.basicAttachment(), + [FieldType.FORMULA]: undefined, // generated field + [FieldType.AUTO]: undefined, // generated field + [FieldType.AI]: "LLM Output", + [FieldType.JSON]: { name: generator.guid() }, + [FieldType.INTERNAL]: generator.guid(), + [FieldType.BARCODEQR]: generator.guid(), + [FieldType.SIGNATURE_SINGLE]: setup.structures.basicAttachment(), + [FieldType.BIGINT]: generator.integer().toString(), + [FieldType.BB_REFERENCE]: [{ _id: config.getUser()._id }], + [FieldType.BB_REFERENCE_SINGLE]: { _id: config.getUser()._id }, + } + const row = await config.api.row.save(table._id!, rowValues) + expectedRowData = { + _id: row._id, + [FieldType.STRING]: rowValues[FieldType.STRING], + [FieldType.LONGFORM]: rowValues[FieldType.LONGFORM], + [FieldType.OPTIONS]: rowValues[FieldType.OPTIONS], + [FieldType.ARRAY]: rowValues[FieldType.ARRAY], + [FieldType.NUMBER]: rowValues[FieldType.NUMBER], + [FieldType.BOOLEAN]: rowValues[FieldType.BOOLEAN], + [FieldType.DATETIME]: rowValues[FieldType.DATETIME], + [FieldType.ATTACHMENTS]: rowValues[FieldType.ATTACHMENTS].map( + (a: any) => + expect.objectContaining({ + ...a, + url: expect.any(String), + }) + ), + [FieldType.ATTACHMENT_SINGLE]: expect.objectContaining({ + ...rowValues[FieldType.ATTACHMENT_SINGLE], + url: expect.any(String), + }), + [FieldType.FORMULA]: fullSchema[FieldType.FORMULA].formula, + [FieldType.AUTO]: expect.any(Number), + [FieldType.AI]: expect.any(String), + [FieldType.JSON]: rowValues[FieldType.JSON], + [FieldType.INTERNAL]: rowValues[FieldType.INTERNAL], + [FieldType.BARCODEQR]: rowValues[FieldType.BARCODEQR], + [FieldType.SIGNATURE_SINGLE]: expect.objectContaining({ + ...rowValues[FieldType.SIGNATURE_SINGLE], + url: expect.any(String), + }), + [FieldType.BIGINT]: rowValues[FieldType.BIGINT], + [FieldType.BB_REFERENCE]: rowValues[FieldType.BB_REFERENCE].map( + expect.objectContaining + ), + [FieldType.BB_REFERENCE_SINGLE]: expect.objectContaining( + rowValues[FieldType.BB_REFERENCE_SINGLE] + ), } }) - }) - } - it("should allow enriching single attachment rows", async () => { - await coreAttachmentEnrichment( - { - attachment: { - type: FieldType.ATTACHMENT_SINGLE, - name: "attachment", - constraints: { presence: false }, - }, - }, - "attachment", - `${uuid.v4()}.csv` - ) - }) + it("as csv", async () => { + const exportedValue = await config.api.row.exportRows( + tableId, + { query: {} }, + RowExportFormat.CSV + ) - it("should allow enriching attachment list rows", async () => { - await coreAttachmentEnrichment( - { - attachments: { - type: FieldType.ATTACHMENTS, - name: "attachments", - constraints: { type: "array", presence: false }, - }, - }, - "attachments", - [`${uuid.v4()}.csv`] - ) - }) + const jsonResult = await config.api.table.csvToJson({ + csvString: exportedValue, + }) - it("should allow enriching signature rows", async () => { - await coreAttachmentEnrichment( - { - signature: { - type: FieldType.SIGNATURE_SINGLE, - name: "signature", - constraints: { presence: false }, - }, - }, - "signature", - `${uuid.v4()}.png` - ) - }) - }) + const stringified = (value: string) => + JSON.stringify(value).replace(/"/g, "'") - describe("exportRows", () => { - beforeEach(async () => { - table = await config.api.table.save(defaultTable()) - }) + const matchingObject = ( + key: string, + value: any, + isArray: boolean + ) => { + const objectMatcher = `{'${key}':'${value[key]}'.*?}` + if (isArray) { + return expect.stringMatching( + new RegExp(`^\\[${objectMatcher}\\]$`) + ) + } + return expect.stringMatching(new RegExp(`^${objectMatcher}$`)) + } - isInternal && - it("should not export internal couchdb fields", async () => { - const existing = await config.api.row.save(table._id!, { - name: generator.guid(), - description: generator.paragraph(), - }) - const res = await config.api.row.exportRows(table._id!, { - rows: [existing._id!], - }) - const results = JSON.parse(res) - expect(results.length).toEqual(1) - const row = results[0] - - expect(Object.keys(row)).toEqual(["_id", "name", "description"]) - }) - - !isInternal && - it("should allow exporting all columns", async () => { - const existing = await config.api.row.save(table._id!, {}) - const res = await config.api.row.exportRows(table._id!, { - rows: [existing._id!], - }) - const results = JSON.parse(res) - expect(results.length).toEqual(1) - const row = results[0] - - // Ensure all original columns were exported - expect(Object.keys(row).length).toBe(Object.keys(existing).length) - Object.keys(existing).forEach(key => { - expect(row[key]).toEqual(existing[key]) - }) - }) - - it("should allow exporting without filtering", async () => { - const existing = await config.api.row.save(table._id!, {}) - const res = await config.api.row.exportRows(table._id!) - const results = JSON.parse(res) - expect(results.length).toEqual(1) - const row = results[0] - - expect(row._id).toEqual(existing._id) - }) - - it("should allow exporting only certain columns", async () => { - const existing = await config.api.row.save(table._id!, {}) - const res = await config.api.row.exportRows(table._id!, { - rows: [existing._id!], - columns: ["_id"], - }) - const results = JSON.parse(res) - expect(results.length).toEqual(1) - const row = results[0] - - // Ensure only the _id column was exported - expect(Object.keys(row).length).toEqual(1) - expect(row._id).toEqual(existing._id) - }) - - it("should handle single quotes in row filtering", async () => { - const existing = await config.api.row.save(table._id!, {}) - const res = await config.api.row.exportRows(table._id!, { - rows: [`['${existing._id!}']`], - }) - const results = JSON.parse(res) - expect(results.length).toEqual(1) - const row = results[0] - expect(row._id).toEqual(existing._id) - }) - - it("should return an error if no table is found", async () => { - const existing = await config.api.row.save(table._id!, {}) - await config.api.row.exportRows( - "1234567", - { rows: [existing._id!] }, - RowExportFormat.JSON, - { status: 404 } - ) - }) - - // MSSQL needs a setting called IDENTITY_INSERT to be set to ON to allow writing - // to identity columns. This is not something Budibase does currently. - !isMSSQL && - it("should handle filtering by composite primary keys", async () => { - const tableRequest = saveTableRequest({ - primary: ["number", "string"], - schema: { - string: { - type: FieldType.STRING, - name: "string", - }, - number: { - type: FieldType.NUMBER, - name: "number", - }, - }, - }) - delete tableRequest.schema.id - - const table = await config.api.table.save(tableRequest) - const toCreate = generator - .unique(() => generator.integer({ min: 0, max: 10000 }), 10) - .map(number => ({ number, string: generator.word({ length: 30 }) })) - - const rows = await Promise.all( - toCreate.map(d => config.api.row.save(table._id!, d)) - ) - - const res = await config.api.row.exportRows(table._id!, { - rows: _.sampleSize(rows, 3).map(r => r._id!), - }) - const results = JSON.parse(res) - expect(results.length).toEqual(3) - }) - - describe("should allow exporting all column types", () => { - let tableId: string - let expectedRowData: Row - - beforeAll(async () => { - const fullSchema = setup.structures.fullSchemaWithoutLinks({ - allRequired: true, - }) - - const table = await config.api.table.save( - saveTableRequest({ - ...setup.structures.basicTable(), - schema: fullSchema, - primary: ["string"], + expect(jsonResult).toEqual([ + { + ...expectedRowData, + auto: expect.any(String), + array: stringified(expectedRowData["array"]), + attachment: matchingObject( + "key", + expectedRowData["attachment"][0].sample, + true + ), + attachment_single: matchingObject( + "key", + expectedRowData["attachment_single"].sample, + false + ), + boolean: stringified(expectedRowData["boolean"]), + json: stringified(expectedRowData["json"]), + number: stringified(expectedRowData["number"]), + signature_single: matchingObject( + "key", + expectedRowData["signature_single"].sample, + false + ), + bb_reference: matchingObject( + "_id", + expectedRowData["bb_reference"][0].sample, + true + ), + bb_reference_single: matchingObject( + "_id", + expectedRowData["bb_reference_single"].sample, + false + ), + ai: "LLM Output", + }, + ]) }) - ) - tableId = table._id! - const rowValues: Record = { - [FieldType.STRING]: generator.guid(), - [FieldType.LONGFORM]: generator.paragraph(), - [FieldType.OPTIONS]: "option 2", - [FieldType.ARRAY]: ["options 2", "options 4"], - [FieldType.NUMBER]: generator.natural(), - [FieldType.BOOLEAN]: generator.bool(), - [FieldType.DATETIME]: generator.date().toISOString(), - [FieldType.ATTACHMENTS]: [setup.structures.basicAttachment()], - [FieldType.ATTACHMENT_SINGLE]: setup.structures.basicAttachment(), - [FieldType.FORMULA]: undefined, // generated field - [FieldType.AUTO]: undefined, // generated field - [FieldType.AI]: "LLM Output", - [FieldType.JSON]: { name: generator.guid() }, - [FieldType.INTERNAL]: generator.guid(), - [FieldType.BARCODEQR]: generator.guid(), - [FieldType.SIGNATURE_SINGLE]: setup.structures.basicAttachment(), - [FieldType.BIGINT]: generator.integer().toString(), - [FieldType.BB_REFERENCE]: [{ _id: config.getUser()._id }], - [FieldType.BB_REFERENCE_SINGLE]: { _id: config.getUser()._id }, - } - const row = await config.api.row.save(table._id!, rowValues) - expectedRowData = { - _id: row._id, - [FieldType.STRING]: rowValues[FieldType.STRING], - [FieldType.LONGFORM]: rowValues[FieldType.LONGFORM], - [FieldType.OPTIONS]: rowValues[FieldType.OPTIONS], - [FieldType.ARRAY]: rowValues[FieldType.ARRAY], - [FieldType.NUMBER]: rowValues[FieldType.NUMBER], - [FieldType.BOOLEAN]: rowValues[FieldType.BOOLEAN], - [FieldType.DATETIME]: rowValues[FieldType.DATETIME], - [FieldType.ATTACHMENTS]: rowValues[FieldType.ATTACHMENTS].map( - (a: any) => - expect.objectContaining({ - ...a, - url: expect.any(String), + it("as json", async () => { + const exportedValue = await config.api.row.exportRows( + tableId, + { query: {} }, + RowExportFormat.JSON + ) + + const json = JSON.parse(exportedValue) + expect(json).toEqual([expectedRowData]) + }) + + it("as json with schema", async () => { + const exportedValue = await config.api.row.exportRows( + tableId, + { query: {} }, + RowExportFormat.JSON_WITH_SCHEMA + ) + + const json = JSON.parse(exportedValue) + expect(json).toEqual({ + schema: expect.any(Object), + rows: [expectedRowData], + }) + }) + + it("can handle csv-special characters in strings", async () => { + const badString = 'test":, wow", "test": "wow"' + const table = await config.api.table.save( + saveTableRequest({ + schema: { + string: { + type: FieldType.STRING, + name: "string", + }, + }, }) - ), - [FieldType.ATTACHMENT_SINGLE]: expect.objectContaining({ - ...rowValues[FieldType.ATTACHMENT_SINGLE], - url: expect.any(String), - }), - [FieldType.FORMULA]: fullSchema[FieldType.FORMULA].formula, - [FieldType.AUTO]: expect.any(Number), - [FieldType.AI]: expect.any(String), - [FieldType.JSON]: rowValues[FieldType.JSON], - [FieldType.INTERNAL]: rowValues[FieldType.INTERNAL], - [FieldType.BARCODEQR]: rowValues[FieldType.BARCODEQR], - [FieldType.SIGNATURE_SINGLE]: expect.objectContaining({ - ...rowValues[FieldType.SIGNATURE_SINGLE], - url: expect.any(String), - }), - [FieldType.BIGINT]: rowValues[FieldType.BIGINT], - [FieldType.BB_REFERENCE]: rowValues[FieldType.BB_REFERENCE].map( - expect.objectContaining - ), - [FieldType.BB_REFERENCE_SINGLE]: expect.objectContaining( - rowValues[FieldType.BB_REFERENCE_SINGLE] - ), - } - }) + ) - it("as csv", async () => { - const exportedValue = await config.api.row.exportRows( - tableId, - { query: {} }, - RowExportFormat.CSV - ) + await config.api.row.save(table._id!, { string: badString }) - const jsonResult = await config.api.table.csvToJson({ - csvString: exportedValue, - }) + const exportedValue = await config.api.row.exportRows( + table._id!, + { query: {} }, + RowExportFormat.CSV + ) - const stringified = (value: string) => - JSON.stringify(value).replace(/"/g, "'") - - const matchingObject = (key: string, value: any, isArray: boolean) => { - const objectMatcher = `{'${key}':'${value[key]}'.*?}` - if (isArray) { - return expect.stringMatching(new RegExp(`^\\[${objectMatcher}\\]$`)) - } - return expect.stringMatching(new RegExp(`^${objectMatcher}$`)) - } - - expect(jsonResult).toEqual([ - { - ...expectedRowData, - auto: expect.any(String), - array: stringified(expectedRowData["array"]), - attachment: matchingObject( - "key", - expectedRowData["attachment"][0].sample, - true - ), - attachment_single: matchingObject( - "key", - expectedRowData["attachment_single"].sample, - false - ), - boolean: stringified(expectedRowData["boolean"]), - json: stringified(expectedRowData["json"]), - number: stringified(expectedRowData["number"]), - signature_single: matchingObject( - "key", - expectedRowData["signature_single"].sample, - false - ), - bb_reference: matchingObject( - "_id", - expectedRowData["bb_reference"][0].sample, - true - ), - bb_reference_single: matchingObject( - "_id", - expectedRowData["bb_reference_single"].sample, - false - ), - ai: "LLM Output", - }, - ]) - }) - - it("as json", async () => { - const exportedValue = await config.api.row.exportRows( - tableId, - { query: {} }, - RowExportFormat.JSON - ) - - const json = JSON.parse(exportedValue) - expect(json).toEqual([expectedRowData]) - }) - - it("as json with schema", async () => { - const exportedValue = await config.api.row.exportRows( - tableId, - { query: {} }, - RowExportFormat.JSON_WITH_SCHEMA - ) - - const json = JSON.parse(exportedValue) - expect(json).toEqual({ - schema: expect.any(Object), - rows: [expectedRowData], - }) - }) - - it("can handle csv-special characters in strings", async () => { - const badString = 'test":, wow", "test": "wow"' - const table = await config.api.table.save( - saveTableRequest({ - schema: { - string: { - type: FieldType.STRING, - name: "string", + const json = await config.api.table.csvToJson( + { + csvString: exportedValue, }, - }, + { + status: 200, + } + ) + + expect(json).toHaveLength(1) + expect(json[0].string).toEqual(badString) }) - ) - await config.api.row.save(table._id!, { string: badString }) + it("exported data can be re-imported", async () => { + // export all + const exportedValue = await config.api.row.exportRows( + tableId, + { query: {} }, + RowExportFormat.CSV + ) - const exportedValue = await config.api.row.exportRows( - table._id!, - { query: {} }, - RowExportFormat.CSV - ) + // import all twice + const rows = await config.api.table.csvToJson({ + csvString: exportedValue, + }) + await config.api.row.bulkImport(tableId, { + rows, + }) + await config.api.row.bulkImport(tableId, { + rows, + }) - const json = await config.api.table.csvToJson( - { - csvString: exportedValue, - }, - { - status: 200, - } - ) + const { rows: allRows } = await config.api.row.search(tableId) - expect(json).toHaveLength(1) - expect(json[0].string).toEqual(badString) - }) - - it("exported data can be re-imported", async () => { - // export all - const exportedValue = await config.api.row.exportRows( - tableId, - { query: {} }, - RowExportFormat.CSV - ) - - // import all twice - const rows = await config.api.table.csvToJson({ - csvString: exportedValue, + const expectedRow = { + ...expectedRowData, + _id: expect.any(String), + _rev: expect.any(String), + type: "row", + tableId: tableId, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + } + expect(allRows).toEqual([expectedRow, expectedRow, expectedRow]) + }) }) - await config.api.row.bulkImport(tableId, { - rows, - }) - await config.api.row.bulkImport(tableId, { - rows, - }) - - const { rows: allRows } = await config.api.row.search(tableId) - - const expectedRow = { - ...expectedRowData, - _id: expect.any(String), - _rev: expect.any(String), - type: "row", - tableId: tableId, - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - } - expect(allRows).toEqual([expectedRow, expectedRow, expectedRow]) - }) - }) - }) - - let o2mTable: Table - let m2mTable: Table - beforeAll(async () => { - o2mTable = await config.api.table.save(defaultTable()) - m2mTable = await config.api.table.save(defaultTable()) - }) - - describe.each([ - [ - "relationship fields", - (): Record => ({ - user: { - name: "user", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: o2mTable._id!, - fieldName: "fk_o2m", - }, - users: { - name: "users", - relationshipType: RelationshipType.MANY_TO_MANY, - type: FieldType.LINK, - tableId: m2mTable._id!, - fieldName: "fk_m2m", - }, - }), - (tableId: string) => - config.api.row.save(tableId, { - name: uuid.v4(), - description: generator.paragraph(), - tableId, - }), - (row: Row) => ({ - _id: row._id, - primaryDisplay: row.name, - }), - ], - [ - "bb reference fields", - (): Record => ({ - user: { - name: "user", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - }, - users: { - name: "users", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USERS, - }, - }), - () => config.createUser(), - (row: Row) => ({ - _id: row._id, - primaryDisplay: row.email, - email: row.email, - firstName: row.firstName, - lastName: row.lastName, - }), - ], - ])("links - %s", (__, relSchema, dataGenerator, resultMapper) => { - let tableId: string - let o2mData: Row[] - let m2mData: Row[] - - beforeAll(async () => { - const table = await config.api.table.save( - defaultTable({ schema: relSchema() }) - ) - tableId = table._id! - - o2mData = [ - await dataGenerator(o2mTable._id!), - await dataGenerator(o2mTable._id!), - await dataGenerator(o2mTable._id!), - await dataGenerator(o2mTable._id!), - ] - - m2mData = [ - await dataGenerator(m2mTable._id!), - await dataGenerator(m2mTable._id!), - await dataGenerator(m2mTable._id!), - await dataGenerator(m2mTable._id!), - ] - }) - - it("can save a row when relationship fields are empty", async () => { - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", }) - expect(row).toEqual({ - _id: expect.any(String), - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - type: isInternal ? "row" : undefined, - name: "foo", - description: "bar", - tableId, - }) - }) - - it("can save a row with a single relationship field", async () => { - const user = _.sample(o2mData)! - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - user: [user], - }) - - expect(row).toEqual({ - name: "foo", - description: "bar", - tableId, - user: [user].map(u => resultMapper(u)), - _id: expect.any(String), - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - type: isInternal ? "row" : undefined, - [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, - }) - }) - - it("can save a row with a multiple relationship field", async () => { - const selectedUsers = _.sampleSize(m2mData, 2) - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - users: selectedUsers, - }) - - expect(row).toEqual({ - name: "foo", - description: "bar", - tableId, - users: expect.arrayContaining(selectedUsers.map(u => resultMapper(u))), - _id: expect.any(String), - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - type: isInternal ? "row" : undefined, - }) - }) - - it("can retrieve rows with no populated relationships", async () => { - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - }) - - const retrieved = await config.api.row.get(tableId, row._id!) - expect(retrieved).toEqual({ - name: "foo", - description: "bar", - tableId, - user: undefined, - users: undefined, - _id: row._id, - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - ...defaultRowFields, - }) - }) - - it("can retrieve rows with populated relationships", async () => { - const user1 = _.sample(o2mData)! - const [user2, user3] = _.sampleSize(m2mData, 2) - - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - users: [user2, user3], - user: [user1], - }) - - const retrieved = await config.api.row.get(tableId, row._id!) - expect(retrieved).toEqual({ - name: "foo", - description: "bar", - tableId, - user: expect.arrayContaining([user1].map(u => resultMapper(u))), - users: expect.arrayContaining([user2, user3].map(u => resultMapper(u))), - _id: row._id, - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user1.id, - ...defaultRowFields, - }) - }) - - it("can update an existing populated row", async () => { - const user = _.sample(o2mData)! - const [users1, users2, users3] = _.sampleSize(m2mData, 3) - - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - users: [users1, users2], - }) - - const updatedRow = await config.api.row.save(tableId, { - ...row, - user: [user], - users: [users3, users1], - }) - expect(updatedRow).toEqual({ - name: "foo", - description: "bar", - tableId, - user: expect.arrayContaining([user].map(u => resultMapper(u))), - users: expect.arrayContaining( - [users3, users1].map(u => resultMapper(u)) - ), - _id: row._id, - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - type: isInternal ? "row" : undefined, - [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, - }) - }) - - it("can wipe an existing populated relationships in row", async () => { - const [user1, user2] = _.sampleSize(m2mData, 2) - const row = await config.api.row.save(tableId, { - name: "foo", - description: "bar", - users: [user1, user2], - }) - - const updatedRow = await config.api.row.save(tableId, { - ...row, - user: null, - users: null, - }) - expect(updatedRow).toEqual({ - name: "foo", - description: "bar", - tableId, - _id: row._id, - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - type: isInternal ? "row" : undefined, - }) - }) - - it("fetch all will populate the relationships", async () => { - const [user1] = _.sampleSize(o2mData, 1) - const [users1, users2, users3] = _.sampleSize(m2mData, 3) - - const rows = [ - { - name: generator.name(), - description: generator.name(), - users: [users1, users2], - }, - { - name: generator.name(), - description: generator.name(), - user: [user1], - users: [users1, users3], - }, - { - name: generator.name(), - description: generator.name(), - users: [users3], - }, - ] - - await config.api.row.save(tableId, rows[0]) - await config.api.row.save(tableId, rows[1]) - await config.api.row.save(tableId, rows[2]) - - const res = await config.api.row.fetch(tableId) - - expect(res).toEqual( - expect.arrayContaining( - rows.map(r => ({ - name: r.name, - description: r.description, - tableId, - user: r.user?.map(u => resultMapper(u)), - users: r.users?.length - ? expect.arrayContaining(r.users?.map(u => resultMapper(u))) - : undefined, - _id: expect.any(String), - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - [`fk_${o2mTable.name}_fk_o2m`]: - isInternal || !r.user?.length ? undefined : r.user[0].id, - ...defaultRowFields, - })) - ) - ) - }) - - it("search all will populate the relationships", async () => { - const [user1] = _.sampleSize(o2mData, 1) - const [users1, users2, users3] = _.sampleSize(m2mData, 3) - - const rows = [ - { - name: generator.name(), - description: generator.name(), - users: [users1, users2], - }, - { - name: generator.name(), - description: generator.name(), - user: [user1], - users: [users1, users3], - }, - { - name: generator.name(), - description: generator.name(), - users: [users3], - }, - ] - - await config.api.row.save(tableId, rows[0]) - await config.api.row.save(tableId, rows[1]) - await config.api.row.save(tableId, rows[2]) - - const res = await config.api.row.search(tableId) - - expect(res).toEqual({ - rows: expect.arrayContaining( - rows.map(r => ({ - name: r.name, - description: r.description, - tableId, - user: r.user?.map(u => resultMapper(u)), - users: r.users?.length - ? expect.arrayContaining(r.users?.map(u => resultMapper(u))) - : undefined, - _id: expect.any(String), - _rev: expect.any(String), - id: isInternal ? undefined : expect.any(Number), - [`fk_${o2mTable.name}_fk_o2m`]: - isInternal || !r.user?.length ? undefined : r.user[0].id, - ...defaultRowFields, - })) - ), - ...(isInternal - ? {} - : { - hasNextPage: false, - }), - }) - }) - }) - - // Upserting isn't yet supported in MSSQL or Oracle, see: - // https://github.com/knex/knex/pull/6050 - !isMSSQL && - !isOracle && - describe("relationships", () => { - let tableId: string - let viewId: string - - let auxData: Row[] = [] - + let o2mTable: Table + let m2mTable: Table beforeAll(async () => { - const aux2Table = await config.api.table.save(saveTableRequest()) - const aux2Data = await config.api.row.save(aux2Table._id!, {}) - - const auxTable = await config.api.table.save( - saveTableRequest({ - primaryDisplay: "name", - schema: { - name: { - name: "name", - type: FieldType.STRING, - constraints: { presence: true }, - }, - age: { - name: "age", - type: FieldType.NUMBER, - constraints: { presence: true }, - }, - address: { - name: "address", - type: FieldType.STRING, - constraints: { presence: true }, - visible: false, - }, - link: { - name: "link", - type: FieldType.LINK, - tableId: aux2Table._id!, - relationshipType: RelationshipType.MANY_TO_MANY, - fieldName: "fk_aux", - constraints: { presence: true }, - }, - formula: { - name: "formula", - type: FieldType.FORMULA, - formula: "{{ any }}", - constraints: { presence: true }, - }, - }, - }) - ) - const auxTableId = auxTable._id! - - for (const name of generator.unique(() => generator.name(), 10)) { - auxData.push( - await config.api.row.save(auxTableId, { - name, - age: generator.age(), - address: generator.address(), - link: [aux2Data], - }) - ) - } - - const table = await config.api.table.save( - saveTableRequest({ - schema: { - title: { - name: "title", - type: FieldType.STRING, - constraints: { presence: true }, - }, - relWithNoSchema: { - name: "relWithNoSchema", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: auxTableId, - fieldName: "fk_relWithNoSchema", - constraints: { presence: true }, - }, - relWithEmptySchema: { - name: "relWithEmptySchema", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: auxTableId, - fieldName: "fk_relWithEmptySchema", - constraints: { presence: true }, - }, - relWithFullSchema: { - name: "relWithFullSchema", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: auxTableId, - fieldName: "fk_relWithFullSchema", - constraints: { presence: true }, - }, - relWithHalfSchema: { - name: "relWithHalfSchema", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: auxTableId, - fieldName: "fk_relWithHalfSchema", - constraints: { presence: true }, - }, - relWithIllegalSchema: { - name: "relWithIllegalSchema", - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: auxTableId, - fieldName: "fk_relWithIllegalSchema", - constraints: { presence: true }, - }, - }, - }) - ) - tableId = table._id! - const view = await config.api.viewV2.create({ - name: generator.guid(), - tableId, - schema: { - title: { - visible: true, - }, - relWithNoSchema: { - visible: true, - }, - relWithEmptySchema: { - visible: true, - columns: {}, - }, - relWithFullSchema: { - visible: true, - columns: Object.keys(auxTable.schema).reduce< - Record - >((acc, c) => ({ ...acc, [c]: { visible: true } }), {}), - }, - relWithHalfSchema: { - visible: true, - columns: { - name: { visible: true }, - age: { visible: false, readonly: true }, - }, - }, - relWithIllegalSchema: { - visible: true, - columns: { - name: { visible: true }, - address: { visible: true }, - unexisting: { visible: true }, - }, - }, - }, - }) - - viewId = view.id + o2mTable = await config.api.table.save(defaultTable()) + m2mTable = await config.api.table.save(defaultTable()) }) - const testScenarios: [string, (row: Row) => Promise | Row][] = [ - ["get row", (row: Row) => config.api.row.get(viewId, row._id!)], + describe.each([ [ - "from view search", - async (row: Row) => { - const { rows } = await config.api.viewV2.search(viewId) - return rows.find(r => r._id === row._id!) - }, - ], - ["from original saved row", (row: Row) => row], - ["from updated row", (row: Row) => config.api.row.save(viewId, row)], - ] - - it.each(testScenarios)( - "can retrieve rows with populated relationships (via %s)", - async (__, retrieveDelegate) => { - const otherRows = _.sampleSize(auxData, 5) - - const row = await config.api.row.save(viewId, { - title: generator.word(), - relWithNoSchema: [otherRows[0]], - relWithEmptySchema: [otherRows[1]], - relWithFullSchema: [otherRows[2]], - relWithHalfSchema: [otherRows[3]], - relWithIllegalSchema: [otherRows[4]], - }) - - const retrieved = await retrieveDelegate(row) - - expect(retrieved).toEqual( - expect.objectContaining({ - title: row.title, - relWithNoSchema: [ - { - _id: otherRows[0]._id, - primaryDisplay: otherRows[0].name, - }, - ], - relWithEmptySchema: [ - { - _id: otherRows[1]._id, - primaryDisplay: otherRows[1].name, - }, - ], - relWithFullSchema: [ - { - _id: otherRows[2]._id, - primaryDisplay: otherRows[2].name, - name: otherRows[2].name, - age: otherRows[2].age, - id: otherRows[2].id, - }, - ], - relWithHalfSchema: [ - { - _id: otherRows[3]._id, - primaryDisplay: otherRows[3].name, - name: otherRows[3].name, - }, - ], - relWithIllegalSchema: [ - { - _id: otherRows[4]._id, - primaryDisplay: otherRows[4].name, - name: otherRows[4].name, - }, - ], - }) - ) - } - ) - - it.each([ - [ - "from table fetch", - async (row: Row) => { - const rows = await config.api.row.fetch(tableId) - return rows.find(r => r._id === row._id!) - }, - ], - [ - "from table search", - async (row: Row) => { - const { rows } = await config.api.row.search(tableId) - return rows.find(r => r._id === row._id!) - }, - ], - ])( - "does not enrich when fetching from the table (via %s)", - async (__, retrieveDelegate) => { - const otherRows = _.sampleSize(auxData, 5) - - const row = await config.api.row.save(viewId, { - title: generator.word(), - relWithNoSchema: [otherRows[0]], - relWithEmptySchema: [otherRows[1]], - relWithFullSchema: [otherRows[2]], - relWithHalfSchema: [otherRows[3]], - relWithIllegalSchema: [otherRows[4]], - }) - - const retrieved = await retrieveDelegate(row) - - expect(retrieved).toEqual( - expect.objectContaining({ - title: row.title, - relWithNoSchema: [ - { - _id: otherRows[0]._id, - primaryDisplay: otherRows[0].name, - }, - ], - relWithEmptySchema: [ - { - _id: otherRows[1]._id, - primaryDisplay: otherRows[1].name, - }, - ], - relWithFullSchema: [ - { - _id: otherRows[2]._id, - primaryDisplay: otherRows[2].name, - }, - ], - relWithHalfSchema: [ - { - _id: otherRows[3]._id, - primaryDisplay: otherRows[3].name, - }, - ], - relWithIllegalSchema: [ - { - _id: otherRows[4]._id, - primaryDisplay: otherRows[4].name, - }, - ], - }) - ) - } - ) - }) - - isInternal && - describe("AI fields", () => { - let table: Table - - beforeAll(async () => { - mocks.licenses.useBudibaseAI() - mocks.licenses.useAICustomConfigs() - table = await config.api.table.save( - saveTableRequest({ - schema: { - ai: { - name: "ai", - type: FieldType.AI, - operation: AIOperationEnum.PROMPT, - prompt: "Convert the following to German: '{{ product }}'", - }, - product: { - name: "product", - type: FieldType.STRING, - }, - }, - }) - ) - - await config.api.row.save(table._id!, { - product: generator.word(), - }) - }) - - afterAll(() => { - jest.unmock("@budibase/pro") - }) - - it("should be able to save a row with an AI column", async () => { - const { rows } = await config.api.row.search(table._id!) - expect(rows.length).toBe(1) - expect(rows[0].ai).toEqual("Mock LLM Response") - }) - - it("should be able to update a row with an AI column", async () => { - const { rows } = await config.api.row.search(table._id!) - expect(rows.length).toBe(1) - await config.api.row.save(table._id!, { - product: generator.word(), - ...rows[0], - }) - expect(rows.length).toBe(1) - expect(rows[0].ai).toEqual("Mock LLM Response") - }) - }) - - describe("Formula fields", () => { - let table: Table - let otherTable: Table - let relatedRow: Row, mainRow: Row - - beforeAll(async () => { - otherTable = await config.api.table.save(defaultTable()) - table = await config.api.table.save( - saveTableRequest({ - schema: { - links: { - name: "links", - fieldName: "links", - type: FieldType.LINK, - tableId: otherTable._id!, + "relationship fields", + (): Record => ({ + user: { + name: "user", relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: o2mTable._id!, + fieldName: "fk_o2m", }, - formula: { - name: "formula", - type: FieldType.FORMULA, - formula: "{{ links.0.name }}", - formulaType: FormulaType.DYNAMIC, + users: { + name: "users", + relationshipType: RelationshipType.MANY_TO_MANY, + type: FieldType.LINK, + tableId: m2mTable._id!, + fieldName: "fk_m2m", }, - }, + }), + (tableId: string) => + config.api.row.save(tableId, { + name: uuid.v4(), + description: generator.paragraph(), + tableId, + }), + (row: Row) => ({ + _id: row._id, + primaryDisplay: row.name, + }), + ], + [ + "bb reference fields", + (): Record => ({ + user: { + name: "user", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + }, + users: { + name: "users", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USERS, + }, + }), + () => config.createUser(), + (row: Row) => ({ + _id: row._id, + primaryDisplay: row.email, + email: row.email, + firstName: row.firstName, + lastName: row.lastName, + }), + ], + ])("links - %s", (__, relSchema, dataGenerator, resultMapper) => { + let tableId: string + let o2mData: Row[] + let m2mData: Row[] + + beforeAll(async () => { + const table = await config.api.table.save( + defaultTable({ schema: relSchema() }) + ) + tableId = table._id! + + o2mData = [ + await dataGenerator(o2mTable._id!), + await dataGenerator(o2mTable._id!), + await dataGenerator(o2mTable._id!), + await dataGenerator(o2mTable._id!), + ] + + m2mData = [ + await dataGenerator(m2mTable._id!), + await dataGenerator(m2mTable._id!), + await dataGenerator(m2mTable._id!), + await dataGenerator(m2mTable._id!), + ] }) - ) - relatedRow = await config.api.row.save(otherTable._id!, { - name: generator.word(), - description: generator.paragraph(), - }) - mainRow = await config.api.row.save(table._id!, { - name: generator.word(), - description: generator.paragraph(), - tableId: table._id!, - links: [relatedRow._id], - }) - }) + it("can save a row when relationship fields are empty", async () => { + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + }) - async function updateFormulaColumn( - formula: string, - opts?: { responseType?: FormulaResponseType; formulaType?: FormulaType } - ) { - table = await config.api.table.save({ - ...table, - schema: { - ...table.schema, - formula: { - name: "formula", - type: FieldType.FORMULA, - formula: formula, - responseType: opts?.responseType, - formulaType: opts?.formulaType || FormulaType.DYNAMIC, - }, - }, - }) - } - - it("should be able to search for rows containing formulas", async () => { - const { rows } = await config.api.row.search(table._id!) - expect(rows.length).toBe(1) - expect(rows[0].links.length).toBe(1) - const row = rows[0] - expect(row.formula).toBe(relatedRow.name) - }) - - it("should coerce - number response type", async () => { - await updateFormulaColumn(encodeJS("return 1"), { - responseType: FieldType.NUMBER, - }) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBe(1) - }) - - it("should coerce - boolean response type", async () => { - await updateFormulaColumn(encodeJS("return true"), { - responseType: FieldType.BOOLEAN, - }) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBe(true) - }) - - it("should coerce - datetime response type", async () => { - await updateFormulaColumn(encodeJS("return new Date()"), { - responseType: FieldType.DATETIME, - }) - const { rows } = await config.api.row.search(table._id!) - expect(isDate(rows[0].formula)).toBe(true) - }) - - it("should coerce - datetime with invalid value", async () => { - await updateFormulaColumn(encodeJS("return 'a'"), { - responseType: FieldType.DATETIME, - }) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBeUndefined() - }) - - it("should coerce handlebars", async () => { - await updateFormulaColumn("{{ add 1 1 }}", { - responseType: FieldType.NUMBER, - }) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBe(2) - }) - - it("should coerce handlebars to string (default)", async () => { - await updateFormulaColumn("{{ add 1 1 }}", { - responseType: FieldType.STRING, - }) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBe("2") - }) - - isInternal && - it("should coerce a static handlebars formula", async () => { - await updateFormulaColumn(encodeJS("return 1"), { - responseType: FieldType.NUMBER, - formulaType: FormulaType.STATIC, + expect(row).toEqual({ + _id: expect.any(String), + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + type: isInternal ? "row" : undefined, + name: "foo", + description: "bar", + tableId, + }) + }) + + it("can save a row with a single relationship field", async () => { + const user = _.sample(o2mData)! + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + user: [user], + }) + + expect(row).toEqual({ + name: "foo", + description: "bar", + tableId, + user: [user].map(u => resultMapper(u)), + _id: expect.any(String), + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + type: isInternal ? "row" : undefined, + [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, + }) + }) + + it("can save a row with a multiple relationship field", async () => { + const selectedUsers = _.sampleSize(m2mData, 2) + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + users: selectedUsers, + }) + + expect(row).toEqual({ + name: "foo", + description: "bar", + tableId, + users: expect.arrayContaining( + selectedUsers.map(u => resultMapper(u)) + ), + _id: expect.any(String), + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + type: isInternal ? "row" : undefined, + }) + }) + + it("can retrieve rows with no populated relationships", async () => { + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + }) + + const retrieved = await config.api.row.get(tableId, row._id!) + expect(retrieved).toEqual({ + name: "foo", + description: "bar", + tableId, + user: undefined, + users: undefined, + _id: row._id, + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + ...defaultRowFields, + }) + }) + + it("can retrieve rows with populated relationships", async () => { + const user1 = _.sample(o2mData)! + const [user2, user3] = _.sampleSize(m2mData, 2) + + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + users: [user2, user3], + user: [user1], + }) + + const retrieved = await config.api.row.get(tableId, row._id!) + expect(retrieved).toEqual({ + name: "foo", + description: "bar", + tableId, + user: expect.arrayContaining([user1].map(u => resultMapper(u))), + users: expect.arrayContaining( + [user2, user3].map(u => resultMapper(u)) + ), + _id: row._id, + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user1.id, + ...defaultRowFields, + }) + }) + + it("can update an existing populated row", async () => { + const user = _.sample(o2mData)! + const [users1, users2, users3] = _.sampleSize(m2mData, 3) + + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + users: [users1, users2], + }) + + const updatedRow = await config.api.row.save(tableId, { + ...row, + user: [user], + users: [users3, users1], + }) + expect(updatedRow).toEqual({ + name: "foo", + description: "bar", + tableId, + user: expect.arrayContaining([user].map(u => resultMapper(u))), + users: expect.arrayContaining( + [users3, users1].map(u => resultMapper(u)) + ), + _id: row._id, + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + type: isInternal ? "row" : undefined, + [`fk_${o2mTable.name}_fk_o2m`]: isInternal ? undefined : user.id, + }) + }) + + it("can wipe an existing populated relationships in row", async () => { + const [user1, user2] = _.sampleSize(m2mData, 2) + const row = await config.api.row.save(tableId, { + name: "foo", + description: "bar", + users: [user1, user2], + }) + + const updatedRow = await config.api.row.save(tableId, { + ...row, + user: null, + users: null, + }) + expect(updatedRow).toEqual({ + name: "foo", + description: "bar", + tableId, + _id: row._id, + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + type: isInternal ? "row" : undefined, + }) + }) + + it("fetch all will populate the relationships", async () => { + const [user1] = _.sampleSize(o2mData, 1) + const [users1, users2, users3] = _.sampleSize(m2mData, 3) + + const rows = [ + { + name: generator.name(), + description: generator.name(), + users: [users1, users2], + }, + { + name: generator.name(), + description: generator.name(), + user: [user1], + users: [users1, users3], + }, + { + name: generator.name(), + description: generator.name(), + users: [users3], + }, + ] + + await config.api.row.save(tableId, rows[0]) + await config.api.row.save(tableId, rows[1]) + await config.api.row.save(tableId, rows[2]) + + const res = await config.api.row.fetch(tableId) + + expect(res).toEqual( + expect.arrayContaining( + rows.map(r => ({ + name: r.name, + description: r.description, + tableId, + user: r.user?.map(u => resultMapper(u)), + users: r.users?.length + ? expect.arrayContaining(r.users?.map(u => resultMapper(u))) + : undefined, + _id: expect.any(String), + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + [`fk_${o2mTable.name}_fk_o2m`]: + isInternal || !r.user?.length ? undefined : r.user[0].id, + ...defaultRowFields, + })) + ) + ) + }) + + it("search all will populate the relationships", async () => { + const [user1] = _.sampleSize(o2mData, 1) + const [users1, users2, users3] = _.sampleSize(m2mData, 3) + + const rows = [ + { + name: generator.name(), + description: generator.name(), + users: [users1, users2], + }, + { + name: generator.name(), + description: generator.name(), + user: [user1], + users: [users1, users3], + }, + { + name: generator.name(), + description: generator.name(), + users: [users3], + }, + ] + + await config.api.row.save(tableId, rows[0]) + await config.api.row.save(tableId, rows[1]) + await config.api.row.save(tableId, rows[2]) + + const res = await config.api.row.search(tableId) + + expect(res).toEqual({ + rows: expect.arrayContaining( + rows.map(r => ({ + name: r.name, + description: r.description, + tableId, + user: r.user?.map(u => resultMapper(u)), + users: r.users?.length + ? expect.arrayContaining(r.users?.map(u => resultMapper(u))) + : undefined, + _id: expect.any(String), + _rev: expect.any(String), + id: isInternal ? undefined : expect.any(Number), + [`fk_${o2mTable.name}_fk_o2m`]: + isInternal || !r.user?.length ? undefined : r.user[0].id, + ...defaultRowFields, + })) + ), + ...(isInternal + ? {} + : { + hasNextPage: false, + }), + }) }) - // save the row to store the static value - await config.api.row.save(table._id!, mainRow) - const { rows } = await config.api.row.search(table._id!) - expect(rows[0].formula).toBe(1) }) - }) - describe("Formula JS protection", () => { - it("should time out JS execution if a single cell takes too long", async () => { - await withEnv({ JS_PER_INVOCATION_TIMEOUT_MS: 40 }, async () => { - const js = encodeJS( - ` - let i = 0; - while (true) { - i++; - } - return i; - ` - ) + // Upserting isn't yet supported in MSSQL or Oracle, see: + // https://github.com/knex/knex/pull/6050 + !isMSSQL && + !isOracle && + describe("relationships", () => { + let tableId: string + let viewId: string - const table = await config.api.table.save( - saveTableRequest({ - schema: { - text: { - name: "text", - type: FieldType.STRING, + let auxData: Row[] = [] + + beforeAll(async () => { + const aux2Table = await config.api.table.save(saveTableRequest()) + const aux2Data = await config.api.row.save(aux2Table._id!, {}) + + const auxTable = await config.api.table.save( + saveTableRequest({ + primaryDisplay: "name", + schema: { + name: { + name: "name", + type: FieldType.STRING, + constraints: { presence: true }, + }, + age: { + name: "age", + type: FieldType.NUMBER, + constraints: { presence: true }, + }, + address: { + name: "address", + type: FieldType.STRING, + constraints: { presence: true }, + visible: false, + }, + link: { + name: "link", + type: FieldType.LINK, + tableId: aux2Table._id!, + relationshipType: RelationshipType.MANY_TO_MANY, + fieldName: "fk_aux", + constraints: { presence: true }, + }, + formula: { + name: "formula", + type: FieldType.FORMULA, + formula: "{{ any }}", + constraints: { presence: true }, + }, + }, + }) + ) + const auxTableId = auxTable._id! + + for (const name of generator.unique(() => generator.name(), 10)) { + auxData.push( + await config.api.row.save(auxTableId, { + name, + age: generator.age(), + address: generator.address(), + link: [aux2Data], + }) + ) + } + + const table = await config.api.table.save( + saveTableRequest({ + schema: { + title: { + name: "title", + type: FieldType.STRING, + constraints: { presence: true }, + }, + relWithNoSchema: { + name: "relWithNoSchema", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: auxTableId, + fieldName: "fk_relWithNoSchema", + constraints: { presence: true }, + }, + relWithEmptySchema: { + name: "relWithEmptySchema", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: auxTableId, + fieldName: "fk_relWithEmptySchema", + constraints: { presence: true }, + }, + relWithFullSchema: { + name: "relWithFullSchema", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: auxTableId, + fieldName: "fk_relWithFullSchema", + constraints: { presence: true }, + }, + relWithHalfSchema: { + name: "relWithHalfSchema", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: auxTableId, + fieldName: "fk_relWithHalfSchema", + constraints: { presence: true }, + }, + relWithIllegalSchema: { + name: "relWithIllegalSchema", + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: auxTableId, + fieldName: "fk_relWithIllegalSchema", + constraints: { presence: true }, + }, + }, + }) + ) + tableId = table._id! + const view = await config.api.viewV2.create({ + name: generator.guid(), + tableId, + schema: { + title: { + visible: true, + }, + relWithNoSchema: { + visible: true, + }, + relWithEmptySchema: { + visible: true, + columns: {}, + }, + relWithFullSchema: { + visible: true, + columns: Object.keys(auxTable.schema).reduce< + Record + >((acc, c) => ({ ...acc, [c]: { visible: true } }), {}), + }, + relWithHalfSchema: { + visible: true, + columns: { + name: { visible: true }, + age: { visible: false, readonly: true }, + }, + }, + relWithIllegalSchema: { + visible: true, + columns: { + name: { visible: true }, + address: { visible: true }, + unexisting: { visible: true }, + }, + }, }, + }) + + viewId = view.id + }) + + const testScenarios: [string, (row: Row) => Promise | Row][] = [ + ["get row", (row: Row) => config.api.row.get(viewId, row._id!)], + [ + "from view search", + async (row: Row) => { + const { rows } = await config.api.viewV2.search(viewId) + return rows.find(r => r._id === row._id!) + }, + ], + ["from original saved row", (row: Row) => row], + [ + "from updated row", + (row: Row) => config.api.row.save(viewId, row), + ], + ] + + it.each(testScenarios)( + "can retrieve rows with populated relationships (via %s)", + async (__, retrieveDelegate) => { + const otherRows = _.sampleSize(auxData, 5) + + const row = await config.api.row.save(viewId, { + title: generator.word(), + relWithNoSchema: [otherRows[0]], + relWithEmptySchema: [otherRows[1]], + relWithFullSchema: [otherRows[2]], + relWithHalfSchema: [otherRows[3]], + relWithIllegalSchema: [otherRows[4]], + }) + + const retrieved = await retrieveDelegate(row) + + expect(retrieved).toEqual( + expect.objectContaining({ + title: row.title, + relWithNoSchema: [ + { + _id: otherRows[0]._id, + primaryDisplay: otherRows[0].name, + }, + ], + relWithEmptySchema: [ + { + _id: otherRows[1]._id, + primaryDisplay: otherRows[1].name, + }, + ], + relWithFullSchema: [ + { + _id: otherRows[2]._id, + primaryDisplay: otherRows[2].name, + name: otherRows[2].name, + age: otherRows[2].age, + id: otherRows[2].id, + }, + ], + relWithHalfSchema: [ + { + _id: otherRows[3]._id, + primaryDisplay: otherRows[3].name, + name: otherRows[3].name, + }, + ], + relWithIllegalSchema: [ + { + _id: otherRows[4]._id, + primaryDisplay: otherRows[4].name, + name: otherRows[4].name, + }, + ], + }) + ) + } + ) + + it.each([ + [ + "from table fetch", + async (row: Row) => { + const rows = await config.api.row.fetch(tableId) + return rows.find(r => r._id === row._id!) + }, + ], + [ + "from table search", + async (row: Row) => { + const { rows } = await config.api.row.search(tableId) + return rows.find(r => r._id === row._id!) + }, + ], + ])( + "does not enrich when fetching from the table (via %s)", + async (__, retrieveDelegate) => { + const otherRows = _.sampleSize(auxData, 5) + + const row = await config.api.row.save(viewId, { + title: generator.word(), + relWithNoSchema: [otherRows[0]], + relWithEmptySchema: [otherRows[1]], + relWithFullSchema: [otherRows[2]], + relWithHalfSchema: [otherRows[3]], + relWithIllegalSchema: [otherRows[4]], + }) + + const retrieved = await retrieveDelegate(row) + + expect(retrieved).toEqual( + expect.objectContaining({ + title: row.title, + relWithNoSchema: [ + { + _id: otherRows[0]._id, + primaryDisplay: otherRows[0].name, + }, + ], + relWithEmptySchema: [ + { + _id: otherRows[1]._id, + primaryDisplay: otherRows[1].name, + }, + ], + relWithFullSchema: [ + { + _id: otherRows[2]._id, + primaryDisplay: otherRows[2].name, + }, + ], + relWithHalfSchema: [ + { + _id: otherRows[3]._id, + primaryDisplay: otherRows[3].name, + }, + ], + relWithIllegalSchema: [ + { + _id: otherRows[4]._id, + primaryDisplay: otherRows[4].name, + }, + ], + }) + ) + } + ) + }) + + isInternal && + describe("AI fields", () => { + let table: Table + + beforeAll(async () => { + mocks.licenses.useBudibaseAI() + mocks.licenses.useAICustomConfigs() + table = await config.api.table.save( + saveTableRequest({ + schema: { + ai: { + name: "ai", + type: FieldType.AI, + operation: AIOperationEnum.PROMPT, + prompt: "Convert the following to German: '{{ product }}'", + }, + product: { + name: "product", + type: FieldType.STRING, + }, + }, + }) + ) + + await config.api.row.save(table._id!, { + product: generator.word(), + }) + }) + + afterAll(() => { + jest.unmock("@budibase/pro") + }) + + it("should be able to save a row with an AI column", async () => { + const { rows } = await config.api.row.search(table._id!) + expect(rows.length).toBe(1) + expect(rows[0].ai).toEqual("Mock LLM Response") + }) + + it("should be able to update a row with an AI column", async () => { + const { rows } = await config.api.row.search(table._id!) + expect(rows.length).toBe(1) + await config.api.row.save(table._id!, { + product: generator.word(), + ...rows[0], + }) + expect(rows.length).toBe(1) + expect(rows[0].ai).toEqual("Mock LLM Response") + }) + }) + + describe("Formula fields", () => { + let table: Table + let otherTable: Table + let relatedRow: Row, mainRow: Row + + beforeAll(async () => { + otherTable = await config.api.table.save(defaultTable()) + table = await config.api.table.save( + saveTableRequest({ + schema: { + links: { + name: "links", + fieldName: "links", + type: FieldType.LINK, + tableId: otherTable._id!, + relationshipType: RelationshipType.ONE_TO_MANY, + }, + formula: { + name: "formula", + type: FieldType.FORMULA, + formula: "{{ links.0.name }}", + formulaType: FormulaType.DYNAMIC, + }, + }, + }) + ) + + relatedRow = await config.api.row.save(otherTable._id!, { + name: generator.word(), + description: generator.paragraph(), + }) + mainRow = await config.api.row.save(table._id!, { + name: generator.word(), + description: generator.paragraph(), + tableId: table._id!, + links: [relatedRow._id], + }) + }) + + async function updateFormulaColumn( + formula: string, + opts?: { + responseType?: FormulaResponseType + formulaType?: FormulaType + } + ) { + table = await config.api.table.save({ + ...table, + schema: { + ...table.schema, formula: { name: "formula", type: FieldType.FORMULA, - formula: js, - formulaType: FormulaType.DYNAMIC, + formula: formula, + responseType: opts?.responseType, + formulaType: opts?.formulaType || FormulaType.DYNAMIC, }, }, }) - ) + } - await config.api.row.save(table._id!, { text: "foo" }) - const { rows } = await config.api.row.search(table._id!) - expect(rows).toHaveLength(1) - const row = rows[0] - expect(row.text).toBe("foo") - expect(row.formula).toBe("Timed out while executing JS") + it("should be able to search for rows containing formulas", async () => { + const { rows } = await config.api.row.search(table._id!) + expect(rows.length).toBe(1) + expect(rows[0].links.length).toBe(1) + const row = rows[0] + expect(row.formula).toBe(relatedRow.name) + }) + + it("should coerce - number response type", async () => { + await updateFormulaColumn(encodeJS("return 1"), { + responseType: FieldType.NUMBER, + }) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBe(1) + }) + + it("should coerce - boolean response type", async () => { + await updateFormulaColumn(encodeJS("return true"), { + responseType: FieldType.BOOLEAN, + }) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBe(true) + }) + + it("should coerce - datetime response type", async () => { + await updateFormulaColumn(encodeJS("return new Date()"), { + responseType: FieldType.DATETIME, + }) + const { rows } = await config.api.row.search(table._id!) + expect(isDate(rows[0].formula)).toBe(true) + }) + + it("should coerce - datetime with invalid value", async () => { + await updateFormulaColumn(encodeJS("return 'a'"), { + responseType: FieldType.DATETIME, + }) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBeUndefined() + }) + + it("should coerce handlebars", async () => { + await updateFormulaColumn("{{ add 1 1 }}", { + responseType: FieldType.NUMBER, + }) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBe(2) + }) + + it("should coerce handlebars to string (default)", async () => { + await updateFormulaColumn("{{ add 1 1 }}", { + responseType: FieldType.STRING, + }) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBe("2") + }) + + isInternal && + it("should coerce a static handlebars formula", async () => { + await updateFormulaColumn(encodeJS("return 1"), { + responseType: FieldType.NUMBER, + formulaType: FormulaType.STATIC, + }) + // save the row to store the static value + await config.api.row.save(table._id!, mainRow) + const { rows } = await config.api.row.search(table._id!) + expect(rows[0].formula).toBe(1) + }) }) - }) - it("should time out JS execution if a multiple cells take too long", async () => { - await withEnv( - { - JS_PER_INVOCATION_TIMEOUT_MS: 40, - JS_PER_REQUEST_TIMEOUT_MS: 80, - }, - async () => { - const js = encodeJS( - ` + describe("Formula JS protection", () => { + it("should time out JS execution if a single cell takes too long", async () => { + await withEnv({ JS_PER_INVOCATION_TIMEOUT_MS: 40 }, async () => { + const js = encodeJS( + ` let i = 0; while (true) { i++; } return i; ` - ) + ) + const table = await config.api.table.save( + saveTableRequest({ + schema: { + text: { + name: "text", + type: FieldType.STRING, + }, + formula: { + name: "formula", + type: FieldType.FORMULA, + formula: js, + formulaType: FormulaType.DYNAMIC, + }, + }, + }) + ) + + await config.api.row.save(table._id!, { text: "foo" }) + const { rows } = await config.api.row.search(table._id!) + expect(rows).toHaveLength(1) + const row = rows[0] + expect(row.text).toBe("foo") + expect(row.formula).toBe("Timed out while executing JS") + }) + }) + + it("should time out JS execution if a multiple cells take too long", async () => { + await withEnv( + { + JS_PER_INVOCATION_TIMEOUT_MS: 40, + JS_PER_REQUEST_TIMEOUT_MS: 80, + }, + async () => { + const js = encodeJS( + ` + let i = 0; + while (true) { + i++; + } + return i; + ` + ) + + const table = await config.api.table.save( + saveTableRequest({ + schema: { + text: { + name: "text", + type: FieldType.STRING, + }, + formula: { + name: "formula", + type: FieldType.FORMULA, + formula: js, + formulaType: FormulaType.DYNAMIC, + }, + }, + }) + ) + + for (let i = 0; i < 10; i++) { + await config.api.row.save(table._id!, { text: "foo" }) + } + + // Run this test 3 times to make sure that there's no cross-request + // pollution of the execution time tracking. + for (let reqs = 0; reqs < 3; reqs++) { + const { rows } = await config.api.row.search(table._id!) + expect(rows).toHaveLength(10) + + let i = 0 + for (; i < 10; i++) { + const row = rows[i] + if (row.formula !== JsTimeoutError.message) { + break + } + } + + // Given the execution times are not deterministic, we can't be sure + // of the exact number of rows that were executed before the timeout + // but it should absolutely be at least 1. + expect(i).toBeGreaterThan(0) + expect(i).toBeLessThan(5) + + for (; i < 10; i++) { + const row = rows[i] + expect(row.text).toBe("foo") + expect(row.formula).toStartWith("CPU time limit exceeded ") + } + } + } + ) + }) + + it("should not carry over context between formulas", async () => { + const js = encodeJS(`return $("[text]");`) const table = await config.api.table.save( saveTableRequest({ schema: { @@ -3391,82 +3472,29 @@ describe.each(databases)("/rows (%s)", dbName => { ) for (let i = 0; i < 10; i++) { - await config.api.row.save(table._id!, { text: "foo" }) + await config.api.row.save(table._id!, { text: `foo${i}` }) } - // Run this test 3 times to make sure that there's no cross-request - // pollution of the execution time tracking. - for (let reqs = 0; reqs < 3; reqs++) { - const { rows } = await config.api.row.search(table._id!) - expect(rows).toHaveLength(10) + const { rows } = await config.api.row.search(table._id!) + expect(rows).toHaveLength(10) - let i = 0 - for (; i < 10; i++) { - const row = rows[i] - if (row.formula !== JsTimeoutError.message) { - break - } - } - - // Given the execution times are not deterministic, we can't be sure - // of the exact number of rows that were executed before the timeout - // but it should absolutely be at least 1. - expect(i).toBeGreaterThan(0) - expect(i).toBeLessThan(5) - - for (; i < 10; i++) { - const row = rows[i] - expect(row.text).toBe("foo") - expect(row.formula).toStartWith("CPU time limit exceeded ") - } - } - } - ) - }) - - it("should not carry over context between formulas", async () => { - const js = encodeJS(`return $("[text]");`) - const table = await config.api.table.save( - saveTableRequest({ - schema: { - text: { - name: "text", - type: FieldType.STRING, - }, - formula: { - name: "formula", - type: FieldType.FORMULA, - formula: js, - formulaType: FormulaType.DYNAMIC, - }, - }, + const formulaValues = rows.map(r => r.formula) + expect(formulaValues).toEqual( + expect.arrayContaining([ + "foo0", + "foo1", + "foo2", + "foo3", + "foo4", + "foo5", + "foo6", + "foo7", + "foo8", + "foo9", + ]) + ) }) - ) - - for (let i = 0; i < 10; i++) { - await config.api.row.save(table._id!, { text: `foo${i}` }) - } - - const { rows } = await config.api.row.search(table._id!) - expect(rows).toHaveLength(10) - - const formulaValues = rows.map(r => r.formula) - expect(formulaValues).toEqual( - expect.arrayContaining([ - "foo0", - "foo1", - "foo2", - "foo3", - "foo4", - "foo5", - "foo6", - "foo7", - "foo8", - "foo9", - ]) - ) - }) - }) -}) - -// todo: remove me + }) + } + ) +} diff --git a/packages/server/src/integrations/tests/utils/index.ts b/packages/server/src/integrations/tests/utils/index.ts index 0c5c308fb2..dcdaece191 100644 --- a/packages/server/src/integrations/tests/utils/index.ts +++ b/packages/server/src/integrations/tests/utils/index.ts @@ -101,12 +101,9 @@ function createDummyTest() { }) } -export function datasourceDescribe( - opts: DatasourceDescribeOpts -): DatabaseName[] { +export function datasourceDescribe(opts: DatasourceDescribeOpts) { if (process.env.DATASOURCE === "none") { createDummyTest() - process.exit(0) } const { only, exclude } = opts @@ -128,15 +125,11 @@ export function datasourceDescribe( if (databases.length === 0) { createDummyTest() - process.exit(0) } - return databases -} - -export function datasourceProps(dbName: DatabaseName) { const config = new TestConfiguration() - return { + return databases.map(dbName => ({ + dbName, config, dsProvider: () => createDatasources(config, dbName), isInternal: dbName === DatabaseName.SQS, @@ -153,7 +146,7 @@ export function datasourceProps(dbName: DatabaseName) { isMongodb: dbName === DatabaseName.MONGODB, isMSSQL: dbName === DatabaseName.SQL_SERVER, isOracle: dbName === DatabaseName.ORACLE, - } + })) } function getDatasource( From 66ade79ff92b76b38fd969fd95778a6574468c6f Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 18 Nov 2024 17:55:40 +0000 Subject: [PATCH 10/40] Updating rest of test cases. --- .../src/api/routes/tests/datasource.spec.ts | 13 +- .../routes/tests/queries/generic-sql.spec.ts | 1692 ++-- .../api/routes/tests/queries/mongodb.spec.ts | 1252 +-- .../src/api/routes/tests/rowAction.spec.ts | 110 +- .../src/api/routes/tests/search.spec.ts | 7201 ++++++++------- .../server/src/api/routes/tests/table.spec.ts | 2672 +++--- .../src/api/routes/tests/viewV2.spec.ts | 8180 +++++++++-------- .../automations/tests/executeQuery.spec.ts | 125 +- .../tests/scenarios/scenarios.spec.ts | 11 +- .../server/src/integration-test/mysql.spec.ts | 204 +- .../src/integration-test/postgres.spec.ts | 477 +- .../sdk/app/rows/search/tests/search.spec.ts | 364 +- 12 files changed, 11243 insertions(+), 11058 deletions(-) diff --git a/packages/server/src/api/routes/tests/datasource.spec.ts b/packages/server/src/api/routes/tests/datasource.spec.ts index 6b811cc716..f3fac5b99b 100644 --- a/packages/server/src/api/routes/tests/datasource.spec.ts +++ b/packages/server/src/api/routes/tests/datasource.spec.ts @@ -164,9 +164,12 @@ describe("/datasources", () => { }) }) -datasourceDescribe( - { name: "%s", exclude: [DatabaseName.MONGODB, DatabaseName.SQS] }, - ({ config, dsProvider }) => { +const descriptions = datasourceDescribe({ + exclude: [DatabaseName.MONGODB, DatabaseName.SQS], +}) + +if (descriptions.length) { + describe.each(descriptions)("$dbName", ({ config, dsProvider }) => { let datasource: Datasource let rawDatasource: Datasource let client: Knex @@ -492,5 +495,5 @@ datasourceDescribe( ) }) }) - } -) + }) +} diff --git a/packages/server/src/api/routes/tests/queries/generic-sql.spec.ts b/packages/server/src/api/routes/tests/queries/generic-sql.spec.ts index aea4e5b2a2..44b21e0350 100644 --- a/packages/server/src/api/routes/tests/queries/generic-sql.spec.ts +++ b/packages/server/src/api/routes/tests/queries/generic-sql.spec.ts @@ -14,583 +14,479 @@ import { events } from "@budibase/backend-core" import { Knex } from "knex" import { generator } from "@budibase/backend-core/tests" -datasourceDescribe( - { name: "queries (%s)", exclude: [DatabaseName.MONGODB, DatabaseName.SQS] }, - ({ config, dsProvider, isOracle, isMSSQL, isPostgres }) => { - let rawDatasource: Datasource - let datasource: Datasource - let client: Knex +const descriptions = datasourceDescribe({ + exclude: [DatabaseName.MONGODB, DatabaseName.SQS], +}) - let tableName: string +if (descriptions.length) { + describe.each(descriptions)( + "queries ($dbName)", + ({ config, dsProvider, isOracle, isMSSQL, isPostgres }) => { + let rawDatasource: Datasource + let datasource: Datasource + let client: Knex - async function createQuery( - query: Partial, - expectations?: Expectations - ): Promise { - const defaultQuery: Query = { - datasourceId: datasource._id!, - name: "New Query", - parameters: [], - fields: {}, - schema: {}, - queryVerb: "read", - transformer: "return data", - readable: true, - } - if (query.fields?.sql && typeof query.fields.sql !== "string") { - throw new Error("Unable to create with knex structure in 'sql' field") - } - return await config.api.query.save( - { ...defaultQuery, ...query }, - expectations - ) - } + let tableName: string - beforeAll(async () => { - const ds = await dsProvider() - rawDatasource = ds.rawDatasource! - datasource = ds.datasource! - client = ds.client! - }) - - beforeEach(async () => { - // The Datasource API doesn ot return the password, but we need it later to - // connect to the underlying database, so we fill it back in here. - datasource.config!.password = rawDatasource.config!.password - - tableName = generator.guid() - - await client.schema.dropTableIfExists(tableName) - await client.schema.createTable(tableName, table => { - table.increments("id").primary() - table.string("name") - table.timestamp("birthday") - table.integer("number") - }) - - await client(tableName).insert([ - { name: "one" }, - { name: "two" }, - { name: "three" }, - { name: "four" }, - { name: "five" }, - ]) - - jest.clearAllMocks() - }) - - describe("query admin", () => { - describe("create", () => { - it("should be able to create a query", async () => { - const query = await createQuery({ - name: "New Query", - fields: { - sql: client(tableName).select("*").toString(), - }, - }) - - expect(query).toMatchObject({ - datasourceId: datasource._id!, - name: "New Query", - parameters: [], - fields: { - sql: client(tableName).select("*").toString(), - }, - schema: {}, - queryVerb: "read", - transformer: "return data", - readable: true, - createdAt: expect.any(String), - updatedAt: expect.any(String), - }) - - expect(events.query.created).toHaveBeenCalledTimes(1) - expect(events.query.updated).not.toHaveBeenCalled() - }) - }) - - describe("update", () => { - it("should be able to update a query", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName).select("*").toString(), - }, - }) - - jest.clearAllMocks() - - const updatedQuery = await config.api.query.save({ - ...query, - name: "Updated Query", - fields: { - sql: client(tableName).where({ id: 1 }).toString(), - }, - }) - - expect(updatedQuery).toMatchObject({ - datasourceId: datasource._id!, - name: "Updated Query", - parameters: [], - fields: { - sql: client(tableName).where({ id: 1 }).toString(), - }, - schema: {}, - queryVerb: "read", - transformer: "return data", - readable: true, - }) - - expect(events.query.created).not.toHaveBeenCalled() - expect(events.query.updated).toHaveBeenCalledTimes(1) - }) - }) - - describe("delete", () => { - it("should be able to delete a query", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName).select("*").toString(), - }, - }) - - await config.api.query.delete(query) - await config.api.query.get(query._id!, { status: 404 }) - - const queries = await config.api.query.fetch() - expect(queries).not.toContainEqual(query) - - expect(events.query.deleted).toHaveBeenCalledTimes(1) - expect(events.query.deleted).toHaveBeenCalledWith(datasource, query) - }) - }) - - describe("read", () => { - it("should be able to list queries", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName).select("*").toString(), - }, - }) - - const queries = await config.api.query.fetch() - expect(queries).toContainEqual(query) - }) - - it("should strip sensitive fields for prod apps", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName).select("*").toString(), - }, - }) - - await config.api.application.publish(config.getAppId()) - const prodQuery = await config.api.query.getProd(query._id!) - - expect(prodQuery._id).toEqual(query._id) - expect(prodQuery.fields).toBeUndefined() - expect(prodQuery.parameters).toBeUndefined() - expect(prodQuery.schema).toBeDefined() - }) - - isPostgres && - it("should be able to handle a JSON aggregate with newlines", async () => { - const jsonStatement = `COALESCE(json_build_object('name', name),'{"name":{}}'::json)` - const query = await createQuery({ - fields: { - sql: client(tableName) - .select([ - "*", - client.raw( - `${jsonStatement} as json,\n${jsonStatement} as json2` - ), - ]) - .toString(), - }, - }) - const res = await config.api.query.execute( - query._id!, - {}, - { - status: 200, - } - ) - expect(res).toBeDefined() - }) - }) - }) - - describe("preview", () => { - it("should be able to preview a query", async () => { - const request: QueryPreview = { + async function createQuery( + query: Partial, + expectations?: Expectations + ): Promise { + const defaultQuery: Query = { datasourceId: datasource._id!, - queryVerb: "read", - fields: { - sql: client(tableName).where({ id: 1 }).toString(), - }, + name: "New Query", parameters: [], - transformer: "return data", - name: datasource.name!, + fields: {}, schema: {}, + queryVerb: "read", + transformer: "return data", readable: true, } - const response = await config.api.query.preview(request) - expect(response.schema).toEqual({ - birthday: { - name: "birthday", - type: "string", - }, - id: { - name: "id", - type: "number", - }, - name: { - name: "name", - type: "string", - }, - number: { - name: "number", - type: "string", - }, - }) - expect(response.rows).toEqual([ - { - birthday: null, - id: 1, - name: "one", - number: null, - }, - ]) - expect(events.query.previewed).toHaveBeenCalledTimes(1) + if (query.fields?.sql && typeof query.fields.sql !== "string") { + throw new Error("Unable to create with knex structure in 'sql' field") + } + return await config.api.query.save( + { ...defaultQuery, ...query }, + expectations + ) + } + + beforeAll(async () => { + const ds = await dsProvider() + rawDatasource = ds.rawDatasource! + datasource = ds.datasource! + client = ds.client! }) - it("should update schema when column type changes from number to string", async () => { - const tableName = "schema_change_test" - await client.schema.dropTableIfExists(tableName) + beforeEach(async () => { + // The Datasource API doesn ot return the password, but we need it later to + // connect to the underlying database, so we fill it back in here. + datasource.config!.password = rawDatasource.config!.password + tableName = generator.guid() + + await client.schema.dropTableIfExists(tableName) await client.schema.createTable(tableName, table => { table.increments("id").primary() table.string("name") - table.integer("data") + table.timestamp("birthday") + table.integer("number") }) - await client(tableName).insert({ - name: "test", - data: 123, - }) - - const firstPreview = await config.api.query.preview({ - datasourceId: datasource._id!, - name: "Test Query", - queryVerb: "read", - fields: { - sql: client(tableName).select("*").toString(), - }, - parameters: [], - transformer: "return data", - schema: {}, - readable: true, - }) - - expect(firstPreview.schema).toEqual( - expect.objectContaining({ - data: { type: "number", name: "data" }, - }) - ) - - await client(tableName).delete() - await client.schema.alterTable(tableName, table => { - table.string("data").alter() - }) - - await client(tableName).insert({ - name: "test", - data: "string value", - }) - - const secondPreview = await config.api.query.preview({ - datasourceId: datasource._id!, - name: "Test Query", - queryVerb: "read", - fields: { - sql: client(tableName).select("*").toString(), - }, - parameters: [], - transformer: "return data", - schema: firstPreview.schema, - readable: true, - }) - - expect(secondPreview.schema).toEqual( - expect.objectContaining({ - data: { type: "string", name: "data" }, - }) - ) - }) - - it("should work with static variables", async () => { - const datasource = await config.api.datasource.create({ - ...rawDatasource, - config: { - ...rawDatasource.config, - staticVariables: { - foo: "bar", - }, - }, - }) - - const request: QueryPreview = { - datasourceId: datasource._id!, - queryVerb: "read", - fields: { - sql: `SELECT '{{ foo }}' AS foo ${isOracle ? "FROM dual" : ""}`, - }, - parameters: [], - transformer: "return data", - name: datasource.name!, - schema: {}, - readable: true, - } - - const response = await config.api.query.preview(request) - - let key = isOracle ? "FOO" : "foo" - expect(response.schema).toEqual({ - [key]: { - name: key, - type: "string", - }, - }) - - expect(response.rows).toEqual([ - { - [key]: "bar", - }, + await client(tableName).insert([ + { name: "one" }, + { name: "two" }, + { name: "three" }, + { name: "four" }, + { name: "five" }, ]) + + jest.clearAllMocks() }) - it("should work with dynamic variables", async () => { - const datasource = await config.api.datasource.create(rawDatasource) - - const basedOnQuery = await createQuery({ - datasourceId: datasource._id!, - fields: { - sql: client(tableName).select("name").where({ id: 1 }).toString(), - }, - }) - - await config.api.datasource.update({ - ...datasource, - config: { - ...datasource.config, - dynamicVariables: [ - { - queryId: basedOnQuery._id!, - name: "foo", - value: "{{ data[0].name }}", + describe("query admin", () => { + describe("create", () => { + it("should be able to create a query", async () => { + const query = await createQuery({ + name: "New Query", + fields: { + sql: client(tableName).select("*").toString(), }, - ], - }, - }) + }) - const preview = await config.api.query.preview({ - datasourceId: datasource._id!, - queryVerb: "read", - fields: { - sql: `SELECT '{{ foo }}' AS foo ${isOracle ? "FROM dual" : ""}`, - }, - parameters: [], - transformer: "return data", - name: datasource.name!, - schema: {}, - readable: true, - }) - - let key = isOracle ? "FOO" : "foo" - expect(preview.schema).toEqual({ - [key]: { - name: key, - type: "string", - }, - }) - - expect(preview.rows).toEqual([ - { - [key]: "one", - }, - ]) - }) - - it("should handle the dynamic base query being deleted", async () => { - const datasource = await config.api.datasource.create(rawDatasource) - - const basedOnQuery = await createQuery({ - datasourceId: datasource._id!, - fields: { - sql: client(tableName).select("name").where({ id: 1 }).toString(), - }, - }) - - await config.api.datasource.update({ - ...datasource, - config: { - ...datasource.config, - dynamicVariables: [ - { - queryId: basedOnQuery._id!, - name: "foo", - value: "{{ data[0].name }}", + expect(query).toMatchObject({ + datasourceId: datasource._id!, + name: "New Query", + parameters: [], + fields: { + sql: client(tableName).select("*").toString(), }, - ], - }, + schema: {}, + queryVerb: "read", + transformer: "return data", + readable: true, + createdAt: expect.any(String), + updatedAt: expect.any(String), + }) + + expect(events.query.created).toHaveBeenCalledTimes(1) + expect(events.query.updated).not.toHaveBeenCalled() + }) }) - await config.api.query.delete(basedOnQuery) - - const preview = await config.api.query.preview({ - datasourceId: datasource._id!, - queryVerb: "read", - fields: { - sql: `SELECT '{{ foo }}' AS foo ${isOracle ? "FROM dual" : ""}`, - }, - parameters: [], - transformer: "return data", - name: datasource.name!, - schema: {}, - readable: true, - }) - - let key = isOracle ? "FOO" : "foo" - expect(preview.schema).toEqual({ - [key]: { - name: key, - type: "string", - }, - }) - - expect(preview.rows).toEqual([{ [key]: isMSSQL ? "" : null }]) - }) - }) - - describe("query verbs", () => { - describe("create", () => { - it("should be able to insert with bindings", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName).insert({ name: "{{ foo }}" }).toString(), - }, - parameters: [ - { - name: "foo", - default: "bar", + describe("update", () => { + it("should be able to update a query", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName).select("*").toString(), }, - ], - queryVerb: "create", + }) + + jest.clearAllMocks() + + const updatedQuery = await config.api.query.save({ + ...query, + name: "Updated Query", + fields: { + sql: client(tableName).where({ id: 1 }).toString(), + }, + }) + + expect(updatedQuery).toMatchObject({ + datasourceId: datasource._id!, + name: "Updated Query", + parameters: [], + fields: { + sql: client(tableName).where({ id: 1 }).toString(), + }, + schema: {}, + queryVerb: "read", + transformer: "return data", + readable: true, + }) + + expect(events.query.created).not.toHaveBeenCalled() + expect(events.query.updated).toHaveBeenCalledTimes(1) + }) + }) + + describe("delete", () => { + it("should be able to delete a query", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName).select("*").toString(), + }, + }) + + await config.api.query.delete(query) + await config.api.query.get(query._id!, { status: 404 }) + + const queries = await config.api.query.fetch() + expect(queries).not.toContainEqual(query) + + expect(events.query.deleted).toHaveBeenCalledTimes(1) + expect(events.query.deleted).toHaveBeenCalledWith(datasource, query) + }) + }) + + describe("read", () => { + it("should be able to list queries", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName).select("*").toString(), + }, + }) + + const queries = await config.api.query.fetch() + expect(queries).toContainEqual(query) }) - const result = await config.api.query.execute(query._id!, { - parameters: { - foo: "baz", - }, + it("should strip sensitive fields for prod apps", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName).select("*").toString(), + }, + }) + + await config.api.application.publish(config.getAppId()) + const prodQuery = await config.api.query.getProd(query._id!) + + expect(prodQuery._id).toEqual(query._id) + expect(prodQuery.fields).toBeUndefined() + expect(prodQuery.parameters).toBeUndefined() + expect(prodQuery.schema).toBeDefined() }) - expect(result.data).toEqual([ - { - created: true, - }, - ]) - - const rows = await client(tableName).where({ name: "baz" }).select() - expect(rows).toHaveLength(1) - for (const row of rows) { - expect(row).toMatchObject({ name: "baz" }) - } - }) - - it("should not allow handlebars as parameters", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName).insert({ name: "{{ foo }}" }).toString(), - }, - parameters: [ - { - name: "foo", - default: "bar", - }, - ], - queryVerb: "create", - }) - - await config.api.query.execute( - query._id!, - { - parameters: { - foo: "{{ 'test' }}", - }, - }, - { - status: 400, - body: { - message: - "Parameter 'foo' input contains a handlebars binding - this is not allowed.", - }, - } - ) - }) - - // Oracle doesn't automatically coerce strings into dates. - !isOracle && - it.each(["2021-02-05T12:01:00.000Z", "2021-02-05"])( - "should coerce %s into a date", - async datetimeStr => { - const date = new Date(datetimeStr) + isPostgres && + it("should be able to handle a JSON aggregate with newlines", async () => { + const jsonStatement = `COALESCE(json_build_object('name', name),'{"name":{}}'::json)` const query = await createQuery({ fields: { sql: client(tableName) - .insert({ - name: "foo", - birthday: client.raw("{{ birthday }}"), - }) + .select([ + "*", + client.raw( + `${jsonStatement} as json,\n${jsonStatement} as json2` + ), + ]) .toString(), }, - parameters: [ - { - name: "birthday", - default: "", - }, - ], - queryVerb: "create", }) + const res = await config.api.query.execute( + query._id!, + {}, + { + status: 200, + } + ) + expect(res).toBeDefined() + }) + }) + }) - const result = await config.api.query.execute(query._id!, { - parameters: { birthday: datetimeStr }, - }) + describe("preview", () => { + it("should be able to preview a query", async () => { + const request: QueryPreview = { + datasourceId: datasource._id!, + queryVerb: "read", + fields: { + sql: client(tableName).where({ id: 1 }).toString(), + }, + parameters: [], + transformer: "return data", + name: datasource.name!, + schema: {}, + readable: true, + } + const response = await config.api.query.preview(request) + expect(response.schema).toEqual({ + birthday: { + name: "birthday", + type: "string", + }, + id: { + name: "id", + type: "number", + }, + name: { + name: "name", + type: "string", + }, + number: { + name: "number", + type: "string", + }, + }) + expect(response.rows).toEqual([ + { + birthday: null, + id: 1, + name: "one", + number: null, + }, + ]) + expect(events.query.previewed).toHaveBeenCalledTimes(1) + }) - expect(result.data).toEqual([{ created: true }]) + it("should update schema when column type changes from number to string", async () => { + const tableName = "schema_change_test" + await client.schema.dropTableIfExists(tableName) - const rows = await client(tableName) - .where({ birthday: datetimeStr }) - .select() - expect(rows).toHaveLength(1) + await client.schema.createTable(tableName, table => { + table.increments("id").primary() + table.string("name") + table.integer("data") + }) - for (const row of rows) { - expect(new Date(row.birthday)).toEqual(date) - } - } + await client(tableName).insert({ + name: "test", + data: 123, + }) + + const firstPreview = await config.api.query.preview({ + datasourceId: datasource._id!, + name: "Test Query", + queryVerb: "read", + fields: { + sql: client(tableName).select("*").toString(), + }, + parameters: [], + transformer: "return data", + schema: {}, + readable: true, + }) + + expect(firstPreview.schema).toEqual( + expect.objectContaining({ + data: { type: "number", name: "data" }, + }) ) - it.each(["2021,02,05", "202205-1500"])( - "should not coerce %s as a date", - async notDateStr => { + await client(tableName).delete() + await client.schema.alterTable(tableName, table => { + table.string("data").alter() + }) + + await client(tableName).insert({ + name: "test", + data: "string value", + }) + + const secondPreview = await config.api.query.preview({ + datasourceId: datasource._id!, + name: "Test Query", + queryVerb: "read", + fields: { + sql: client(tableName).select("*").toString(), + }, + parameters: [], + transformer: "return data", + schema: firstPreview.schema, + readable: true, + }) + + expect(secondPreview.schema).toEqual( + expect.objectContaining({ + data: { type: "string", name: "data" }, + }) + ) + }) + + it("should work with static variables", async () => { + const datasource = await config.api.datasource.create({ + ...rawDatasource, + config: { + ...rawDatasource.config, + staticVariables: { + foo: "bar", + }, + }, + }) + + const request: QueryPreview = { + datasourceId: datasource._id!, + queryVerb: "read", + fields: { + sql: `SELECT '{{ foo }}' AS foo ${isOracle ? "FROM dual" : ""}`, + }, + parameters: [], + transformer: "return data", + name: datasource.name!, + schema: {}, + readable: true, + } + + const response = await config.api.query.preview(request) + + let key = isOracle ? "FOO" : "foo" + expect(response.schema).toEqual({ + [key]: { + name: key, + type: "string", + }, + }) + + expect(response.rows).toEqual([ + { + [key]: "bar", + }, + ]) + }) + + it("should work with dynamic variables", async () => { + const datasource = await config.api.datasource.create(rawDatasource) + + const basedOnQuery = await createQuery({ + datasourceId: datasource._id!, + fields: { + sql: client(tableName).select("name").where({ id: 1 }).toString(), + }, + }) + + await config.api.datasource.update({ + ...datasource, + config: { + ...datasource.config, + dynamicVariables: [ + { + queryId: basedOnQuery._id!, + name: "foo", + value: "{{ data[0].name }}", + }, + ], + }, + }) + + const preview = await config.api.query.preview({ + datasourceId: datasource._id!, + queryVerb: "read", + fields: { + sql: `SELECT '{{ foo }}' AS foo ${isOracle ? "FROM dual" : ""}`, + }, + parameters: [], + transformer: "return data", + name: datasource.name!, + schema: {}, + readable: true, + }) + + let key = isOracle ? "FOO" : "foo" + expect(preview.schema).toEqual({ + [key]: { + name: key, + type: "string", + }, + }) + + expect(preview.rows).toEqual([ + { + [key]: "one", + }, + ]) + }) + + it("should handle the dynamic base query being deleted", async () => { + const datasource = await config.api.datasource.create(rawDatasource) + + const basedOnQuery = await createQuery({ + datasourceId: datasource._id!, + fields: { + sql: client(tableName).select("name").where({ id: 1 }).toString(), + }, + }) + + await config.api.datasource.update({ + ...datasource, + config: { + ...datasource.config, + dynamicVariables: [ + { + queryId: basedOnQuery._id!, + name: "foo", + value: "{{ data[0].name }}", + }, + ], + }, + }) + + await config.api.query.delete(basedOnQuery) + + const preview = await config.api.query.preview({ + datasourceId: datasource._id!, + queryVerb: "read", + fields: { + sql: `SELECT '{{ foo }}' AS foo ${isOracle ? "FROM dual" : ""}`, + }, + parameters: [], + transformer: "return data", + name: datasource.name!, + schema: {}, + readable: true, + }) + + let key = isOracle ? "FOO" : "foo" + expect(preview.schema).toEqual({ + [key]: { + name: key, + type: "string", + }, + }) + + expect(preview.rows).toEqual([{ [key]: isMSSQL ? "" : null }]) + }) + }) + + describe("query verbs", () => { + describe("create", () => { + it("should be able to insert with bindings", async () => { const query = await createQuery({ fields: { - sql: client(tableName) - .insert({ name: client.raw("{{ name }}") }) - .toString(), + sql: client(tableName).insert({ name: "{{ foo }}" }).toString(), }, parameters: [ { - name: "name", - default: "", + name: "foo", + default: "bar", }, ], queryVerb: "create", @@ -598,274 +494,442 @@ datasourceDescribe( const result = await config.api.query.execute(query._id!, { parameters: { - name: notDateStr, + foo: "baz", }, }) - expect(result.data).toEqual([{ created: true }]) + expect(result.data).toEqual([ + { + created: true, + }, + ]) - const rows = await client(tableName) - .where({ name: notDateStr }) - .select() + const rows = await client(tableName).where({ name: "baz" }).select() expect(rows).toHaveLength(1) - } - ) - }) - - describe("read", () => { - it("should execute a query", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName).select("*").orderBy("id").toString(), - }, + for (const row of rows) { + expect(row).toMatchObject({ name: "baz" }) + } }) - const result = await config.api.query.execute(query._id!) + it("should not allow handlebars as parameters", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName).insert({ name: "{{ foo }}" }).toString(), + }, + parameters: [ + { + name: "foo", + default: "bar", + }, + ], + queryVerb: "create", + }) - expect(result.data).toEqual([ - { - id: 1, - name: "one", - birthday: null, - number: null, - }, - { - id: 2, - name: "two", - birthday: null, - number: null, - }, - { - id: 3, - name: "three", - birthday: null, - number: null, - }, - { - id: 4, - name: "four", - birthday: null, - number: null, - }, - { - id: 5, - name: "five", - birthday: null, - number: null, - }, - ]) + await config.api.query.execute( + query._id!, + { + parameters: { + foo: "{{ 'test' }}", + }, + }, + { + status: 400, + body: { + message: + "Parameter 'foo' input contains a handlebars binding - this is not allowed.", + }, + } + ) + }) + + // Oracle doesn't automatically coerce strings into dates. + !isOracle && + it.each(["2021-02-05T12:01:00.000Z", "2021-02-05"])( + "should coerce %s into a date", + async datetimeStr => { + const date = new Date(datetimeStr) + const query = await createQuery({ + fields: { + sql: client(tableName) + .insert({ + name: "foo", + birthday: client.raw("{{ birthday }}"), + }) + .toString(), + }, + parameters: [ + { + name: "birthday", + default: "", + }, + ], + queryVerb: "create", + }) + + const result = await config.api.query.execute(query._id!, { + parameters: { birthday: datetimeStr }, + }) + + expect(result.data).toEqual([{ created: true }]) + + const rows = await client(tableName) + .where({ birthday: datetimeStr }) + .select() + expect(rows).toHaveLength(1) + + for (const row of rows) { + expect(new Date(row.birthday)).toEqual(date) + } + } + ) + + it.each(["2021,02,05", "202205-1500"])( + "should not coerce %s as a date", + async notDateStr => { + const query = await createQuery({ + fields: { + sql: client(tableName) + .insert({ name: client.raw("{{ name }}") }) + .toString(), + }, + parameters: [ + { + name: "name", + default: "", + }, + ], + queryVerb: "create", + }) + + const result = await config.api.query.execute(query._id!, { + parameters: { + name: notDateStr, + }, + }) + + expect(result.data).toEqual([{ created: true }]) + + const rows = await client(tableName) + .where({ name: notDateStr }) + .select() + expect(rows).toHaveLength(1) + } + ) }) - it("should be able to transform a query", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName).where({ id: 1 }).select("*").toString(), - }, - transformer: ` + describe("read", () => { + it("should execute a query", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName).select("*").orderBy("id").toString(), + }, + }) + + const result = await config.api.query.execute(query._id!) + + expect(result.data).toEqual([ + { + id: 1, + name: "one", + birthday: null, + number: null, + }, + { + id: 2, + name: "two", + birthday: null, + number: null, + }, + { + id: 3, + name: "three", + birthday: null, + number: null, + }, + { + id: 4, + name: "four", + birthday: null, + number: null, + }, + { + id: 5, + name: "five", + birthday: null, + number: null, + }, + ]) + }) + + it("should be able to transform a query", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName).where({ id: 1 }).select("*").toString(), + }, + transformer: ` data[0].id = data[0].id + 1; return data; `, + }) + + const result = await config.api.query.execute(query._id!) + + expect(result.data).toEqual([ + { + id: 2, + name: "one", + birthday: null, + number: null, + }, + ]) }) - const result = await config.api.query.execute(query._id!) + it("should coerce numeric bindings", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName) + .where({ id: client.raw("{{ id }}") }) + .select("*") + .toString(), + }, + parameters: [ + { + name: "id", + default: "", + }, + ], + }) - expect(result.data).toEqual([ - { - id: 2, - name: "one", - birthday: null, - number: null, - }, - ]) + const result = await config.api.query.execute(query._id!, { + parameters: { + id: "1", + }, + }) + + expect(result.data).toEqual([ + { + id: 1, + name: "one", + birthday: null, + number: null, + }, + ]) + }) }) - it("should coerce numeric bindings", async () => { + describe("update", () => { + it("should be able to update rows", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName) + .update({ name: client.raw("{{ name }}") }) + .where({ id: client.raw("{{ id }}") }) + .toString(), + }, + parameters: [ + { + name: "id", + default: "", + }, + { + name: "name", + default: "updated", + }, + ], + queryVerb: "update", + }) + + await config.api.query.execute(query._id!, { + parameters: { + id: "1", + name: "foo", + }, + }) + + const rows = await client(tableName).where({ id: 1 }).select() + expect(rows).toEqual([ + { id: 1, name: "foo", birthday: null, number: null }, + ]) + }) + + it("should be able to execute an update that updates no rows", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName) + .update({ name: "updated" }) + .where({ id: 100 }) + .toString(), + }, + queryVerb: "update", + }) + + await config.api.query.execute(query._id!) + + const rows = await client(tableName).select() + for (const row of rows) { + expect(row.name).not.toEqual("updated") + } + }) + + it("should be able to execute a delete that deletes no rows", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName).where({ id: 100 }).delete().toString(), + }, + queryVerb: "delete", + }) + + await config.api.query.execute(query._id!) + + const rows = await client(tableName).select() + expect(rows).toHaveLength(5) + }) + }) + + describe("delete", () => { + it("should be able to delete rows", async () => { + const query = await createQuery({ + fields: { + sql: client(tableName) + .where({ id: client.raw("{{ id }}") }) + .delete() + .toString(), + }, + parameters: [ + { + name: "id", + default: "", + }, + ], + queryVerb: "delete", + }) + + await config.api.query.execute(query._id!, { + parameters: { + id: "1", + }, + }) + + const rows = await client(tableName).where({ id: 1 }).select() + expect(rows).toHaveLength(0) + }) + }) + }) + + describe("query through datasource", () => { + it("should be able to query the datasource", async () => { + const datasource = await config.api.datasource.create(rawDatasource) + + const entityId = tableName + await config.api.datasource.update({ + ...datasource, + entities: { + [entityId]: { + name: entityId, + schema: {}, + type: "table", + primary: ["id"], + sourceId: datasource._id!, + sourceType: TableSourceType.EXTERNAL, + }, + }, + }) + + const res = await config.api.datasource.query({ + endpoint: { + datasourceId: datasource._id!, + operation: Operation.READ, + entityId, + }, + resource: { + fields: ["id", "name"], + }, + filters: { + string: { + name: "two", + }, + }, + }) + expect(res).toHaveLength(1) + expect(res[0]).toEqual({ + id: 2, + name: "two", + // the use of table.* introduces the possibility of nulls being returned + birthday: null, + number: null, + }) + }) + + // this parameter really only impacts SQL queries + describe("confirm nullDefaultSupport", () => { + let queryParams: Partial + beforeAll(async () => { + queryParams = { + fields: { + sql: client(tableName) + .insert({ + name: client.raw("{{ bindingName }}"), + number: client.raw("{{ bindingNumber }}"), + }) + .toString(), + }, + parameters: [ + { + name: "bindingName", + default: "", + }, + { + name: "bindingNumber", + default: "", + }, + ], + queryVerb: "create", + } + }) + + it("should error for old queries", async () => { + const query = await createQuery(queryParams) + await config.api.query.save({ ...query, nullDefaultSupport: false }) + let error: string | undefined + try { + await config.api.query.execute(query._id!, { + parameters: { + bindingName: "testing", + }, + }) + } catch (err: any) { + error = err.message + } + if (isMSSQL || isOracle) { + expect(error).toBeUndefined() + } else { + expect(error).toBeDefined() + expect(error).toContain("integer") + } + }) + + it("should not error for new queries", async () => { + const query = await createQuery(queryParams) + const results = await config.api.query.execute(query._id!, { + parameters: { + bindingName: "testing", + }, + }) + expect(results).toEqual({ data: [{ created: true }] }) + }) + }) + }) + + describe("edge cases", () => { + it("should find rows with a binding containing a slash", async () => { + const slashValue = "1/10" + await client(tableName).insert([{ name: slashValue }]) + const query = await createQuery({ fields: { sql: client(tableName) - .where({ id: client.raw("{{ id }}") }) .select("*") - .toString(), - }, - parameters: [ - { - name: "id", - default: "", - }, - ], - }) - - const result = await config.api.query.execute(query._id!, { - parameters: { - id: "1", - }, - }) - - expect(result.data).toEqual([ - { - id: 1, - name: "one", - birthday: null, - number: null, - }, - ]) - }) - }) - - describe("update", () => { - it("should be able to update rows", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName) - .update({ name: client.raw("{{ name }}") }) - .where({ id: client.raw("{{ id }}") }) - .toString(), - }, - parameters: [ - { - name: "id", - default: "", - }, - { - name: "name", - default: "updated", - }, - ], - queryVerb: "update", - }) - - await config.api.query.execute(query._id!, { - parameters: { - id: "1", - name: "foo", - }, - }) - - const rows = await client(tableName).where({ id: 1 }).select() - expect(rows).toEqual([ - { id: 1, name: "foo", birthday: null, number: null }, - ]) - }) - - it("should be able to execute an update that updates no rows", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName) - .update({ name: "updated" }) - .where({ id: 100 }) - .toString(), - }, - queryVerb: "update", - }) - - await config.api.query.execute(query._id!) - - const rows = await client(tableName).select() - for (const row of rows) { - expect(row.name).not.toEqual("updated") - } - }) - - it("should be able to execute a delete that deletes no rows", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName).where({ id: 100 }).delete().toString(), - }, - queryVerb: "delete", - }) - - await config.api.query.execute(query._id!) - - const rows = await client(tableName).select() - expect(rows).toHaveLength(5) - }) - }) - - describe("delete", () => { - it("should be able to delete rows", async () => { - const query = await createQuery({ - fields: { - sql: client(tableName) - .where({ id: client.raw("{{ id }}") }) - .delete() - .toString(), - }, - parameters: [ - { - name: "id", - default: "", - }, - ], - queryVerb: "delete", - }) - - await config.api.query.execute(query._id!, { - parameters: { - id: "1", - }, - }) - - const rows = await client(tableName).where({ id: 1 }).select() - expect(rows).toHaveLength(0) - }) - }) - }) - - describe("query through datasource", () => { - it("should be able to query the datasource", async () => { - const datasource = await config.api.datasource.create(rawDatasource) - - const entityId = tableName - await config.api.datasource.update({ - ...datasource, - entities: { - [entityId]: { - name: entityId, - schema: {}, - type: "table", - primary: ["id"], - sourceId: datasource._id!, - sourceType: TableSourceType.EXTERNAL, - }, - }, - }) - - const res = await config.api.datasource.query({ - endpoint: { - datasourceId: datasource._id!, - operation: Operation.READ, - entityId, - }, - resource: { - fields: ["id", "name"], - }, - filters: { - string: { - name: "two", - }, - }, - }) - expect(res).toHaveLength(1) - expect(res[0]).toEqual({ - id: 2, - name: "two", - // the use of table.* introduces the possibility of nulls being returned - birthday: null, - number: null, - }) - }) - - // this parameter really only impacts SQL queries - describe("confirm nullDefaultSupport", () => { - let queryParams: Partial - beforeAll(async () => { - queryParams = { - fields: { - sql: client(tableName) - .insert({ - name: client.raw("{{ bindingName }}"), - number: client.raw("{{ bindingNumber }}"), - }) + .where("name", "=", client.raw("{{ bindingName }}")) .toString(), }, parameters: [ @@ -873,76 +937,18 @@ datasourceDescribe( name: "bindingName", default: "", }, - { - name: "bindingNumber", - default: "", - }, ], - queryVerb: "create", - } - }) - - it("should error for old queries", async () => { - const query = await createQuery(queryParams) - await config.api.query.save({ ...query, nullDefaultSupport: false }) - let error: string | undefined - try { - await config.api.query.execute(query._id!, { - parameters: { - bindingName: "testing", - }, - }) - } catch (err: any) { - error = err.message - } - if (isMSSQL || isOracle) { - expect(error).toBeUndefined() - } else { - expect(error).toBeDefined() - expect(error).toContain("integer") - } - }) - - it("should not error for new queries", async () => { - const query = await createQuery(queryParams) + queryVerb: "read", + }) const results = await config.api.query.execute(query._id!, { parameters: { - bindingName: "testing", + bindingName: slashValue, }, }) - expect(results).toEqual({ data: [{ created: true }] }) + expect(results).toBeDefined() + expect(results.data.length).toEqual(1) }) }) - }) - - describe("edge cases", () => { - it("should find rows with a binding containing a slash", async () => { - const slashValue = "1/10" - await client(tableName).insert([{ name: slashValue }]) - - const query = await createQuery({ - fields: { - sql: client(tableName) - .select("*") - .where("name", "=", client.raw("{{ bindingName }}")) - .toString(), - }, - parameters: [ - { - name: "bindingName", - default: "", - }, - ], - queryVerb: "read", - }) - const results = await config.api.query.execute(query._id!, { - parameters: { - bindingName: slashValue, - }, - }) - expect(results).toBeDefined() - expect(results.data.length).toEqual(1) - }) - }) - } -) + } + ) +} diff --git a/packages/server/src/api/routes/tests/queries/mongodb.spec.ts b/packages/server/src/api/routes/tests/queries/mongodb.spec.ts index 44d1553f9b..a37957fe7e 100644 --- a/packages/server/src/api/routes/tests/queries/mongodb.spec.ts +++ b/packages/server/src/api/routes/tests/queries/mongodb.spec.ts @@ -9,465 +9,698 @@ import { generator } from "@budibase/backend-core/tests" const expectValidId = expect.stringMatching(/^\w{24}$/) const expectValidBsonObjectId = expect.any(BSON.ObjectId) -datasourceDescribe( - { name: "/queries", only: [DatabaseName.MONGODB] }, - ({ config, dsProvider }) => { - let collection: string - let datasource: Datasource +const descriptions = datasourceDescribe({ only: [DatabaseName.MONGODB] }) - async function createQuery(query: Partial): Promise { - const defaultQuery: Query = { - datasourceId: datasource._id!, - name: "New Query", - parameters: [], - fields: {}, - schema: {}, - queryVerb: "read", - transformer: "return data", - readable: true, - } - const combinedQuery = { ...defaultQuery, ...query } - if ( - combinedQuery.fields && - combinedQuery.fields.extra && - !combinedQuery.fields.extra.collection - ) { - combinedQuery.fields.extra.collection = collection - } - return await config.api.query.save(combinedQuery) - } +if (descriptions.length) { + describe.each(descriptions)( + "/queries ($dbName)", + ({ config, dsProvider }) => { + let collection: string + let datasource: Datasource - async function withClient( - callback: (client: MongoClient) => Promise - ): Promise { - const client = new MongoClient(datasource.config!.connectionString) - await client.connect() - try { - return await callback(client) - } finally { - await client.close() - } - } - - async function withDb(callback: (db: Db) => Promise): Promise { - return await withClient(async client => { - return await callback(client.db(datasource.config!.db)) - }) - } - - async function withCollection( - callback: (collection: Collection) => Promise - ): Promise { - return await withDb(async db => { - return await callback(db.collection(collection)) - }) - } - - beforeAll(async () => { - const ds = await dsProvider() - datasource = ds.datasource! - }) - - beforeEach(async () => { - collection = generator.guid() - await withCollection(async collection => { - await collection.insertMany([ - { name: "one" }, - { name: "two" }, - { name: "three" }, - { name: "four" }, - { name: "five" }, - ]) - }) - }) - - afterEach(async () => { - await withCollection(collection => collection.drop()) - }) - - describe("preview", () => { - it("should generate a nested schema with an empty array", async () => { - const name = generator.guid() - await withCollection( - async collection => await collection.insertOne({ name, nested: [] }) - ) - - const preview = await config.api.query.preview({ + async function createQuery(query: Partial): Promise { + const defaultQuery: Query = { + datasourceId: datasource._id!, name: "New Query", - datasourceId: datasource._id!, - fields: { - json: { - name: { $eq: name }, - }, - extra: { - collection, - actionType: "findOne", - }, - }, + parameters: [], + fields: {}, schema: {}, queryVerb: "read", - parameters: [], transformer: "return data", readable: true, - }) - - expect(preview).toEqual({ - nestedSchemaFields: {}, - rows: [{ _id: expect.any(String), name, nested: [] }], - schema: { - _id: { - type: "string", - name: "_id", - }, - name: { - type: "string", - name: "name", - }, - nested: { - type: "array", - name: "nested", - }, - }, - }) - }) - - it("should update schema when structure changes from object to array", async () => { - const name = generator.guid() - - await withCollection(async collection => { - await collection.insertOne({ name, field: { subfield: "value" } }) - }) - - const firstPreview = await config.api.query.preview({ - name: "Test Query", - datasourceId: datasource._id!, - fields: { - json: { name: { $eq: name } }, - extra: { - collection, - actionType: "findOne", - }, - }, - schema: {}, - queryVerb: "read", - parameters: [], - transformer: "return data", - readable: true, - }) - - expect(firstPreview.schema).toEqual( - expect.objectContaining({ - field: { type: "json", name: "field" }, - }) - ) - - await withCollection(async collection => { - await collection.updateOne( - { name }, - { $set: { field: ["value1", "value2"] } } - ) - }) - - const secondPreview = await config.api.query.preview({ - name: "Test Query", - datasourceId: datasource._id!, - fields: { - json: { name: { $eq: name } }, - extra: { - collection, - actionType: "findOne", - }, - }, - schema: firstPreview.schema, - queryVerb: "read", - parameters: [], - transformer: "return data", - readable: true, - }) - - expect(secondPreview.schema).toEqual( - expect.objectContaining({ - field: { type: "array", name: "field" }, - }) - ) - }) - - it("should generate a nested schema based on all of the nested items", async () => { - const name = generator.guid() - const item = { - name, - contacts: [ - { - address: "123 Lane", - }, - { - address: "456 Drive", - }, - { - postcode: "BT1 12N", - lat: 54.59, - long: -5.92, - }, - { - city: "Belfast", - }, - { - address: "789 Avenue", - phoneNumber: "0800-999-5555", - }, - { - name: "Name", - isActive: false, - }, - ], } + const combinedQuery = { ...defaultQuery, ...query } + if ( + combinedQuery.fields && + combinedQuery.fields.extra && + !combinedQuery.fields.extra.collection + ) { + combinedQuery.fields.extra.collection = collection + } + return await config.api.query.save(combinedQuery) + } - await withCollection(collection => collection.insertOne(item)) + async function withClient( + callback: (client: MongoClient) => Promise + ): Promise { + const client = new MongoClient(datasource.config!.connectionString) + await client.connect() + try { + return await callback(client) + } finally { + await client.close() + } + } - const preview = await config.api.query.preview({ - name: "New Query", - datasourceId: datasource._id!, - fields: { - json: { - name: { $eq: name }, - }, - extra: { - collection, - actionType: "findOne", - }, - }, - schema: {}, - queryVerb: "read", - parameters: [], - transformer: "return data", - readable: true, + async function withDb(callback: (db: Db) => Promise): Promise { + return await withClient(async client => { + return await callback(client.db(datasource.config!.db)) }) + } - expect(preview).toEqual({ - nestedSchemaFields: { - contacts: { - address: { + async function withCollection( + callback: (collection: Collection) => Promise + ): Promise { + return await withDb(async db => { + return await callback(db.collection(collection)) + }) + } + + beforeAll(async () => { + const ds = await dsProvider() + datasource = ds.datasource! + }) + + beforeEach(async () => { + collection = generator.guid() + await withCollection(async collection => { + await collection.insertMany([ + { name: "one" }, + { name: "two" }, + { name: "three" }, + { name: "four" }, + { name: "five" }, + ]) + }) + }) + + afterEach(async () => { + await withCollection(collection => collection.drop()) + }) + + describe("preview", () => { + it("should generate a nested schema with an empty array", async () => { + const name = generator.guid() + await withCollection( + async collection => await collection.insertOne({ name, nested: [] }) + ) + + const preview = await config.api.query.preview({ + name: "New Query", + datasourceId: datasource._id!, + fields: { + json: { + name: { $eq: name }, + }, + extra: { + collection, + actionType: "findOne", + }, + }, + schema: {}, + queryVerb: "read", + parameters: [], + transformer: "return data", + readable: true, + }) + + expect(preview).toEqual({ + nestedSchemaFields: {}, + rows: [{ _id: expect.any(String), name, nested: [] }], + schema: { + _id: { type: "string", - name: "address", - }, - postcode: { - type: "string", - name: "postcode", - }, - lat: { - type: "number", - name: "lat", - }, - long: { - type: "number", - name: "long", - }, - city: { - type: "string", - name: "city", - }, - phoneNumber: { - type: "string", - name: "phoneNumber", + name: "_id", }, name: { type: "string", name: "name", }, - isActive: { - type: "boolean", - name: "isActive", + nested: { + type: "array", + name: "nested", }, }, - }, - rows: [{ ...item, _id: expect.any(String) }], - schema: { - _id: { type: "string", name: "_id" }, - name: { type: "string", name: "name" }, - contacts: { type: "json", name: "contacts", subtype: "array" }, - }, - }) - }) - }) - - describe("execute", () => { - it("a count query", async () => { - const query = await createQuery({ - fields: { - json: {}, - extra: { - actionType: "count", - }, - }, + }) }) - const result = await config.api.query.execute(query._id!) + it("should update schema when structure changes from object to array", async () => { + const name = generator.guid() - expect(result.data).toEqual([{ value: 5 }]) - }) + await withCollection(async collection => { + await collection.insertOne({ name, field: { subfield: "value" } }) + }) - it("should be able to updateOne by ObjectId", async () => { - const insertResult = await withCollection(c => - c.insertOne({ name: "one" }) - ) - const query = await createQuery({ - fields: { - json: { - filter: { - _id: { $eq: `ObjectId("${insertResult.insertedId}")` }, + const firstPreview = await config.api.query.preview({ + name: "Test Query", + datasourceId: datasource._id!, + fields: { + json: { name: { $eq: name } }, + extra: { + collection, + actionType: "findOne", }, - update: { $set: { name: "newName" } }, }, - extra: { - actionType: "updateOne", + schema: {}, + queryVerb: "read", + parameters: [], + transformer: "return data", + readable: true, + }) + + expect(firstPreview.schema).toEqual( + expect.objectContaining({ + field: { type: "json", name: "field" }, + }) + ) + + await withCollection(async collection => { + await collection.updateOne( + { name }, + { $set: { field: ["value1", "value2"] } } + ) + }) + + const secondPreview = await config.api.query.preview({ + name: "Test Query", + datasourceId: datasource._id!, + fields: { + json: { name: { $eq: name } }, + extra: { + collection, + actionType: "findOne", + }, }, - }, - queryVerb: "update", + schema: firstPreview.schema, + queryVerb: "read", + parameters: [], + transformer: "return data", + readable: true, + }) + + expect(secondPreview.schema).toEqual( + expect.objectContaining({ + field: { type: "array", name: "field" }, + }) + ) }) - const result = await config.api.query.execute(query._id!) + it("should generate a nested schema based on all of the nested items", async () => { + const name = generator.guid() + const item = { + name, + contacts: [ + { + address: "123 Lane", + }, + { + address: "456 Drive", + }, + { + postcode: "BT1 12N", + lat: 54.59, + long: -5.92, + }, + { + city: "Belfast", + }, + { + address: "789 Avenue", + phoneNumber: "0800-999-5555", + }, + { + name: "Name", + isActive: false, + }, + ], + } - expect(result.data).toEqual([ - { - acknowledged: true, - matchedCount: 1, - modifiedCount: 1, - upsertedCount: 0, - upsertedId: null, - }, - ]) + await withCollection(collection => collection.insertOne(item)) - await withCollection(async collection => { - const doc = await collection.findOne({ name: { $eq: "newName" } }) - expect(doc).toEqual({ - _id: insertResult.insertedId, - name: "newName", + const preview = await config.api.query.preview({ + name: "New Query", + datasourceId: datasource._id!, + fields: { + json: { + name: { $eq: name }, + }, + extra: { + collection, + actionType: "findOne", + }, + }, + schema: {}, + queryVerb: "read", + parameters: [], + transformer: "return data", + readable: true, + }) + + expect(preview).toEqual({ + nestedSchemaFields: { + contacts: { + address: { + type: "string", + name: "address", + }, + postcode: { + type: "string", + name: "postcode", + }, + lat: { + type: "number", + name: "lat", + }, + long: { + type: "number", + name: "long", + }, + city: { + type: "string", + name: "city", + }, + phoneNumber: { + type: "string", + name: "phoneNumber", + }, + name: { + type: "string", + name: "name", + }, + isActive: { + type: "boolean", + name: "isActive", + }, + }, + }, + rows: [{ ...item, _id: expect.any(String) }], + schema: { + _id: { type: "string", name: "_id" }, + name: { type: "string", name: "name" }, + contacts: { type: "json", name: "contacts", subtype: "array" }, + }, }) }) }) - it("a count query with a transformer", async () => { - const query = await createQuery({ - fields: { - json: {}, - extra: { - actionType: "count", + describe("execute", () => { + it("a count query", async () => { + const query = await createQuery({ + fields: { + json: {}, + extra: { + actionType: "count", + }, }, - }, - transformer: "return data + 1", + }) + + const result = await config.api.query.execute(query._id!) + + expect(result.data).toEqual([{ value: 5 }]) }) - const result = await config.api.query.execute(query._id!) - - expect(result.data).toEqual([{ value: 6 }]) - }) - - it("a find query", async () => { - const query = await createQuery({ - fields: { - json: {}, - extra: { - actionType: "find", + it("should be able to updateOne by ObjectId", async () => { + const insertResult = await withCollection(c => + c.insertOne({ name: "one" }) + ) + const query = await createQuery({ + fields: { + json: { + filter: { + _id: { $eq: `ObjectId("${insertResult.insertedId}")` }, + }, + update: { $set: { name: "newName" } }, + }, + extra: { + actionType: "updateOne", + }, }, - }, + queryVerb: "update", + }) + + const result = await config.api.query.execute(query._id!) + + expect(result.data).toEqual([ + { + acknowledged: true, + matchedCount: 1, + modifiedCount: 1, + upsertedCount: 0, + upsertedId: null, + }, + ]) + + await withCollection(async collection => { + const doc = await collection.findOne({ name: { $eq: "newName" } }) + expect(doc).toEqual({ + _id: insertResult.insertedId, + name: "newName", + }) + }) }) - const result = await config.api.query.execute(query._id!) - - expect(result.data).toEqual([ - { _id: expectValidId, name: "one" }, - { _id: expectValidId, name: "two" }, - { _id: expectValidId, name: "three" }, - { _id: expectValidId, name: "four" }, - { _id: expectValidId, name: "five" }, - ]) - }) - - it("a findOne query", async () => { - const query = await createQuery({ - fields: { - json: {}, - extra: { - actionType: "findOne", + it("a count query with a transformer", async () => { + const query = await createQuery({ + fields: { + json: {}, + extra: { + actionType: "count", + }, }, - }, + transformer: "return data + 1", + }) + + const result = await config.api.query.execute(query._id!) + + expect(result.data).toEqual([{ value: 6 }]) }) - const result = await config.api.query.execute(query._id!) - - expect(result.data).toEqual([{ _id: expectValidId, name: "one" }]) - }) - - it("a findOneAndUpdate query", async () => { - const query = await createQuery({ - fields: { - json: { - filter: { name: { $eq: "one" } }, - update: { $set: { name: "newName" } }, + it("a find query", async () => { + const query = await createQuery({ + fields: { + json: {}, + extra: { + actionType: "find", + }, }, - extra: { - actionType: "findOneAndUpdate", - }, - }, + }) + + const result = await config.api.query.execute(query._id!) + + expect(result.data).toEqual([ + { _id: expectValidId, name: "one" }, + { _id: expectValidId, name: "two" }, + { _id: expectValidId, name: "three" }, + { _id: expectValidId, name: "four" }, + { _id: expectValidId, name: "five" }, + ]) }) - const result = await config.api.query.execute(query._id!) + it("a findOne query", async () => { + const query = await createQuery({ + fields: { + json: {}, + extra: { + actionType: "findOne", + }, + }, + }) - expect(result.data).toEqual([ - { - lastErrorObject: { n: 1, updatedExisting: true }, - ok: 1, - value: { _id: expectValidId, name: "one" }, - }, - ]) + const result = await config.api.query.execute(query._id!) - await withCollection(async collection => { - expect(await collection.countDocuments()).toBe(5) + expect(result.data).toEqual([{ _id: expectValidId, name: "one" }]) + }) - const doc = await collection.findOne({ name: { $eq: "newName" } }) - expect(doc).toEqual({ - _id: expectValidBsonObjectId, - name: "newName", + it("a findOneAndUpdate query", async () => { + const query = await createQuery({ + fields: { + json: { + filter: { name: { $eq: "one" } }, + update: { $set: { name: "newName" } }, + }, + extra: { + actionType: "findOneAndUpdate", + }, + }, + }) + + const result = await config.api.query.execute(query._id!) + + expect(result.data).toEqual([ + { + lastErrorObject: { n: 1, updatedExisting: true }, + ok: 1, + value: { _id: expectValidId, name: "one" }, + }, + ]) + + await withCollection(async collection => { + expect(await collection.countDocuments()).toBe(5) + + const doc = await collection.findOne({ name: { $eq: "newName" } }) + expect(doc).toEqual({ + _id: expectValidBsonObjectId, + name: "newName", + }) + }) + }) + + it("a distinct query", async () => { + const query = await createQuery({ + fields: { + json: "name", + extra: { + actionType: "distinct", + }, + }, + }) + + const result = await config.api.query.execute(query._id!) + const values = result.data.map(o => o.value).sort() + expect(values).toEqual(["five", "four", "one", "three", "two"]) + }) + + it("a create query with parameters", async () => { + const query = await createQuery({ + fields: { + json: { foo: "{{ foo }}" }, + extra: { + actionType: "insertOne", + }, + }, + queryVerb: "create", + parameters: [ + { + name: "foo", + default: "default", + }, + ], + }) + + const result = await config.api.query.execute(query._id!, { + parameters: { foo: "bar" }, + }) + + expect(result.data).toEqual([ + { + acknowledged: true, + insertedId: expectValidId, + }, + ]) + + await withCollection(async collection => { + const doc = await collection.findOne({ foo: { $eq: "bar" } }) + expect(doc).toEqual({ + _id: expectValidBsonObjectId, + foo: "bar", + }) + }) + }) + + it("a delete query with parameters", async () => { + const query = await createQuery({ + fields: { + json: { name: { $eq: "{{ name }}" } }, + extra: { + actionType: "deleteOne", + }, + }, + queryVerb: "delete", + parameters: [ + { + name: "name", + default: "", + }, + ], + }) + + const result = await config.api.query.execute(query._id!, { + parameters: { name: "one" }, + }) + + expect(result.data).toEqual([ + { + acknowledged: true, + deletedCount: 1, + }, + ]) + + await withCollection(async collection => { + const doc = await collection.findOne({ name: { $eq: "one" } }) + expect(doc).toBeNull() + }) + }) + + it("an update query with parameters", async () => { + const query = await createQuery({ + fields: { + json: { + filter: { name: { $eq: "{{ name }}" } }, + update: { $set: { name: "{{ newName }}" } }, + }, + extra: { + actionType: "updateOne", + }, + }, + queryVerb: "update", + parameters: [ + { + name: "name", + default: "", + }, + { + name: "newName", + default: "", + }, + ], + }) + + const result = await config.api.query.execute(query._id!, { + parameters: { name: "one", newName: "newOne" }, + }) + + expect(result.data).toEqual([ + { + acknowledged: true, + matchedCount: 1, + modifiedCount: 1, + upsertedCount: 0, + upsertedId: null, + }, + ]) + + await withCollection(async collection => { + const doc = await collection.findOne({ name: { $eq: "newOne" } }) + expect(doc).toEqual({ + _id: expectValidBsonObjectId, + name: "newOne", + }) + + const oldDoc = await collection.findOne({ name: { $eq: "one" } }) + expect(oldDoc).toBeNull() + }) + }) + + it("should be able to delete all records", async () => { + const query = await createQuery({ + fields: { + json: {}, + extra: { + actionType: "deleteMany", + }, + }, + queryVerb: "delete", + }) + + const result = await config.api.query.execute(query._id!) + + expect(result.data).toEqual([ + { + acknowledged: true, + deletedCount: 5, + }, + ]) + + await withCollection(async collection => { + const docs = await collection.find().toArray() + expect(docs).toHaveLength(0) + }) + }) + + it("should be able to update all documents", async () => { + const query = await createQuery({ + fields: { + json: { + filter: {}, + update: { $set: { name: "newName" } }, + }, + extra: { + actionType: "updateMany", + }, + }, + queryVerb: "update", + }) + + const result = await config.api.query.execute(query._id!) + + expect(result.data).toEqual([ + { + acknowledged: true, + matchedCount: 5, + modifiedCount: 5, + upsertedCount: 0, + upsertedId: null, + }, + ]) + + await withCollection(async collection => { + const docs = await collection.find().toArray() + expect(docs).toHaveLength(5) + for (const doc of docs) { + expect(doc).toEqual({ + _id: expectValidBsonObjectId, + name: "newName", + }) + } }) }) }) - it("a distinct query", async () => { - const query = await createQuery({ - fields: { - json: "name", - extra: { - actionType: "distinct", - }, - }, - }) - - const result = await config.api.query.execute(query._id!) - const values = result.data.map(o => o.value).sort() - expect(values).toEqual(["five", "four", "one", "three", "two"]) + it("should throw an error if the incorrect actionType is specified", async () => { + const verbs = ["read", "create", "update", "delete"] + for (const verb of verbs) { + const query = await createQuery({ + fields: { json: {}, extra: { actionType: "invalid" } }, + queryVerb: verb, + }) + await config.api.query.execute(query._id!, undefined, { status: 400 }) + } }) - it("a create query with parameters", async () => { + it("should ignore extra brackets in query", async () => { const query = await createQuery({ fields: { - json: { foo: "{{ foo }}" }, + json: { foo: "te}st" }, extra: { actionType: "insertOne", }, }, queryVerb: "create", - parameters: [ + }) + + const result = await config.api.query.execute(query._id!) + expect(result.data).toEqual([ + { + acknowledged: true, + insertedId: expectValidId, + }, + ]) + + await withCollection(async collection => { + const doc = await collection.findOne({ foo: { $eq: "te}st" } }) + expect(doc).toEqual({ + _id: expectValidBsonObjectId, + foo: "te}st", + }) + }) + }) + + it("should be able to save deeply nested data", async () => { + const data = { + foo: "bar", + data: [ + { cid: 1 }, + { cid: 2 }, { - name: "foo", - default: "default", + nested: { + name: "test", + ary: [1, 2, 3], + aryOfObjects: [{ a: 1 }, { b: 2 }], + }, }, ], + } + const query = await createQuery({ + fields: { + json: data, + extra: { + actionType: "insertOne", + }, + }, + queryVerb: "create", }) - const result = await config.api.query.execute(query._id!, { - parameters: { foo: "bar" }, - }) - + const result = await config.api.query.execute(query._id!) expect(result.data).toEqual([ { acknowledged: true, @@ -479,239 +712,10 @@ datasourceDescribe( const doc = await collection.findOne({ foo: { $eq: "bar" } }) expect(doc).toEqual({ _id: expectValidBsonObjectId, - foo: "bar", + ...data, }) }) }) - - it("a delete query with parameters", async () => { - const query = await createQuery({ - fields: { - json: { name: { $eq: "{{ name }}" } }, - extra: { - actionType: "deleteOne", - }, - }, - queryVerb: "delete", - parameters: [ - { - name: "name", - default: "", - }, - ], - }) - - const result = await config.api.query.execute(query._id!, { - parameters: { name: "one" }, - }) - - expect(result.data).toEqual([ - { - acknowledged: true, - deletedCount: 1, - }, - ]) - - await withCollection(async collection => { - const doc = await collection.findOne({ name: { $eq: "one" } }) - expect(doc).toBeNull() - }) - }) - - it("an update query with parameters", async () => { - const query = await createQuery({ - fields: { - json: { - filter: { name: { $eq: "{{ name }}" } }, - update: { $set: { name: "{{ newName }}" } }, - }, - extra: { - actionType: "updateOne", - }, - }, - queryVerb: "update", - parameters: [ - { - name: "name", - default: "", - }, - { - name: "newName", - default: "", - }, - ], - }) - - const result = await config.api.query.execute(query._id!, { - parameters: { name: "one", newName: "newOne" }, - }) - - expect(result.data).toEqual([ - { - acknowledged: true, - matchedCount: 1, - modifiedCount: 1, - upsertedCount: 0, - upsertedId: null, - }, - ]) - - await withCollection(async collection => { - const doc = await collection.findOne({ name: { $eq: "newOne" } }) - expect(doc).toEqual({ - _id: expectValidBsonObjectId, - name: "newOne", - }) - - const oldDoc = await collection.findOne({ name: { $eq: "one" } }) - expect(oldDoc).toBeNull() - }) - }) - - it("should be able to delete all records", async () => { - const query = await createQuery({ - fields: { - json: {}, - extra: { - actionType: "deleteMany", - }, - }, - queryVerb: "delete", - }) - - const result = await config.api.query.execute(query._id!) - - expect(result.data).toEqual([ - { - acknowledged: true, - deletedCount: 5, - }, - ]) - - await withCollection(async collection => { - const docs = await collection.find().toArray() - expect(docs).toHaveLength(0) - }) - }) - - it("should be able to update all documents", async () => { - const query = await createQuery({ - fields: { - json: { - filter: {}, - update: { $set: { name: "newName" } }, - }, - extra: { - actionType: "updateMany", - }, - }, - queryVerb: "update", - }) - - const result = await config.api.query.execute(query._id!) - - expect(result.data).toEqual([ - { - acknowledged: true, - matchedCount: 5, - modifiedCount: 5, - upsertedCount: 0, - upsertedId: null, - }, - ]) - - await withCollection(async collection => { - const docs = await collection.find().toArray() - expect(docs).toHaveLength(5) - for (const doc of docs) { - expect(doc).toEqual({ - _id: expectValidBsonObjectId, - name: "newName", - }) - } - }) - }) - }) - - it("should throw an error if the incorrect actionType is specified", async () => { - const verbs = ["read", "create", "update", "delete"] - for (const verb of verbs) { - const query = await createQuery({ - fields: { json: {}, extra: { actionType: "invalid" } }, - queryVerb: verb, - }) - await config.api.query.execute(query._id!, undefined, { status: 400 }) - } - }) - - it("should ignore extra brackets in query", async () => { - const query = await createQuery({ - fields: { - json: { foo: "te}st" }, - extra: { - actionType: "insertOne", - }, - }, - queryVerb: "create", - }) - - const result = await config.api.query.execute(query._id!) - expect(result.data).toEqual([ - { - acknowledged: true, - insertedId: expectValidId, - }, - ]) - - await withCollection(async collection => { - const doc = await collection.findOne({ foo: { $eq: "te}st" } }) - expect(doc).toEqual({ - _id: expectValidBsonObjectId, - foo: "te}st", - }) - }) - }) - - it("should be able to save deeply nested data", async () => { - const data = { - foo: "bar", - data: [ - { cid: 1 }, - { cid: 2 }, - { - nested: { - name: "test", - ary: [1, 2, 3], - aryOfObjects: [{ a: 1 }, { b: 2 }], - }, - }, - ], - } - const query = await createQuery({ - fields: { - json: data, - extra: { - actionType: "insertOne", - }, - }, - queryVerb: "create", - }) - - const result = await config.api.query.execute(query._id!) - expect(result.data).toEqual([ - { - acknowledged: true, - insertedId: expectValidId, - }, - ]) - - await withCollection(async collection => { - const doc = await collection.findOne({ foo: { $eq: "bar" } }) - expect(doc).toEqual({ - _id: expectValidBsonObjectId, - ...data, - }) - }) - }) - } -) + } + ) +} diff --git a/packages/server/src/api/routes/tests/rowAction.spec.ts b/packages/server/src/api/routes/tests/rowAction.spec.ts index 58d7509798..dabcd11b73 100644 --- a/packages/server/src/api/routes/tests/rowAction.spec.ts +++ b/packages/server/src/api/routes/tests/rowAction.spec.ts @@ -977,63 +977,69 @@ describe("/rowsActions", () => { }) }) -datasourceDescribe( - { name: "row actions (%s)", only: [DatabaseName.SQS, DatabaseName.POSTGRES] }, - ({ config, dsProvider, isInternal }) => { - let datasource: Datasource | undefined +const descriptions = datasourceDescribe({ + exclude: [DatabaseName.SQS, DatabaseName.POSTGRES], +}) - beforeAll(async () => { - const ds = await dsProvider() - datasource = ds.datasource - }) +if (descriptions.length) { + describe.each(descriptions)( + "row actions ($dbName)", + ({ config, dsProvider, isInternal }) => { + let datasource: Datasource | undefined - async function getTable(): Promise { - if (isInternal) { - await config.api.application.addSampleData(config.getAppId()) - const tables = await config.api.table.fetch() - return tables.find(t => t.sourceId === DEFAULT_BB_DATASOURCE_ID)! - } else { - const table = await config.api.table.save( - setup.structures.tableForDatasource(datasource!) - ) - return table - } - } + beforeAll(async () => { + const ds = await dsProvider() + datasource = ds.datasource + }) - it("should delete all the row actions (and automations) for its tables when a datasource is deleted", async () => { - async function getRowActionsFromDb(tableId: string) { - return await context.doInAppContext(config.getAppId(), async () => { - const db = context.getAppDB() - const tableDoc = await db.tryGet( - generateRowActionsID(tableId) + async function getTable(): Promise
{ + if (isInternal) { + await config.api.application.addSampleData(config.getAppId()) + const tables = await config.api.table.fetch() + return tables.find(t => t.sourceId === DEFAULT_BB_DATASOURCE_ID)! + } else { + const table = await config.api.table.save( + setup.structures.tableForDatasource(datasource!) ) - return tableDoc - }) + return table + } } - const table = await getTable() - const tableId = table._id! + it("should delete all the row actions (and automations) for its tables when a datasource is deleted", async () => { + async function getRowActionsFromDb(tableId: string) { + return await context.doInAppContext(config.getAppId(), async () => { + const db = context.getAppDB() + const tableDoc = await db.tryGet( + generateRowActionsID(tableId) + ) + return tableDoc + }) + } - await config.api.rowAction.save(tableId, { - name: generator.guid(), + const table = await getTable() + const tableId = table._id! + + await config.api.rowAction.save(tableId, { + name: generator.guid(), + }) + await config.api.rowAction.save(tableId, { + name: generator.guid(), + }) + + const { actions } = (await getRowActionsFromDb(tableId))! + expect(Object.entries(actions)).toHaveLength(2) + + const { automations } = await config.api.automation.fetch() + expect(automations).toHaveLength(2) + + const datasource = await config.api.datasource.get(table.sourceId) + await config.api.datasource.delete(datasource) + + const automationsResp = await config.api.automation.fetch() + expect(automationsResp.automations).toHaveLength(0) + + expect(await getRowActionsFromDb(tableId)).toBeUndefined() }) - await config.api.rowAction.save(tableId, { - name: generator.guid(), - }) - - const { actions } = (await getRowActionsFromDb(tableId))! - expect(Object.entries(actions)).toHaveLength(2) - - const { automations } = await config.api.automation.fetch() - expect(automations).toHaveLength(2) - - const datasource = await config.api.datasource.get(table.sourceId) - await config.api.datasource.delete(datasource) - - const automationsResp = await config.api.automation.fetch() - expect(automationsResp.automations).toHaveLength(0) - - expect(await getRowActionsFromDb(tableId)).toBeUndefined() - }) - } -) + } + ) +} diff --git a/packages/server/src/api/routes/tests/search.spec.ts b/packages/server/src/api/routes/tests/search.spec.ts index fe13e5311f..5384444067 100644 --- a/packages/server/src/api/routes/tests/search.spec.ts +++ b/packages/server/src/api/routes/tests/search.spec.ts @@ -59,3676 +59,3781 @@ jest.mock("@budibase/pro", () => ({ }, })) -datasourceDescribe( - { - name: "search (%s)", - exclude: [DatabaseName.MONGODB], - }, - ({ config, dsProvider, isInternal, isOracle, isSql }) => { - let datasource: Datasource | undefined - let client: Knex | undefined - let tableOrViewId: string - let rows: Row[] +const descriptions = datasourceDescribe({ exclude: [DatabaseName.MONGODB] }) - async function basicRelationshipTables(type: RelationshipType) { - const relatedTable = await createTable({ - name: { name: "name", type: FieldType.STRING }, - }) - const tableId = await createTable({ - name: { name: "name", type: FieldType.STRING }, - //@ts-ignore - API accepts this structure, will build out rest of definition - productCat: { - type: FieldType.LINK, - relationshipType: type, - name: "productCat", - fieldName: "product", - tableId: relatedTable, - constraints: { - type: "array", +if (descriptions.length) { + describe.each(descriptions)( + "search ($dbName)", + ({ config, dsProvider, isInternal, isOracle, isSql }) => { + let datasource: Datasource | undefined + let client: Knex | undefined + let tableOrViewId: string + let rows: Row[] + + async function basicRelationshipTables(type: RelationshipType) { + const relatedTable = await createTable({ + name: { name: "name", type: FieldType.STRING }, + }) + const tableId = await createTable({ + name: { name: "name", type: FieldType.STRING }, + //@ts-ignore - API accepts this structure, will build out rest of definition + productCat: { + type: FieldType.LINK, + relationshipType: type, + name: "productCat", + fieldName: "product", + tableId: relatedTable, + constraints: { + type: "array", + }, }, - }, - }) - return { - relatedTable: await config.api.table.get(relatedTable), - tableId, + }) + return { + relatedTable: await config.api.table.get(relatedTable), + tableId, + } } - } - beforeAll(async () => { - const ds = await dsProvider() - datasource = ds.datasource - client = ds.client + beforeAll(async () => { + const ds = await dsProvider() + datasource = ds.datasource + client = ds.client - config.app = await config.api.application.update(config.getAppId(), { - snippets: [ - { - name: "WeeksAgo", - code: ` + config.app = await config.api.application.update(config.getAppId(), { + snippets: [ + { + name: "WeeksAgo", + code: ` return function (weeks) { const currentTime = new Date(${Date.now()}); currentTime.setDate(currentTime.getDate()-(7 * (weeks || 1))); return currentTime.toISOString(); } `, - }, - ], - }) - }) - - async function createTable(schema?: TableSchema) { - const table = await config.api.table.save( - tableForDatasource(datasource, { schema }) - ) - return table._id! - } - - async function createView(tableId: string, schema?: ViewV2Schema) { - const view = await config.api.viewV2.create({ - tableId: tableId, - name: generator.guid(), - schema, - }) - return view.id - } - - async function createRows(arr: Record[]) { - // Shuffling to avoid false positives given a fixed order - for (const row of _.shuffle(arr)) { - await config.api.row.save(tableOrViewId, row) - } - rows = await config.api.row.fetch(tableOrViewId) - } - - async function getTable(tableOrViewId: string): Promise
{ - if (docIds.isViewId(tableOrViewId)) { - const view = await config.api.viewV2.get(tableOrViewId) - return await config.api.table.get(view.tableId) - } else { - return await config.api.table.get(tableOrViewId) - } - } - - async function assertTableExists(nameOrTable: string | Table) { - const name = - typeof nameOrTable === "string" ? nameOrTable : nameOrTable.name - expect(await client!.schema.hasTable(name)).toBeTrue() - } - - async function assertTableNumRows( - nameOrTable: string | Table, - numRows: number - ) { - const name = - typeof nameOrTable === "string" ? nameOrTable : nameOrTable.name - const row = await client!.from(name).count() - const count = parseInt(Object.values(row[0])[0] as string) - expect(count).toEqual(numRows) - } - - describe.each([true, false])("in-memory: %s", isInMemory => { - // We only run the in-memory tests during the SQS (isInternal) run - if (isInMemory && !isInternal) { - return - } - - type CreateFn = (schema?: TableSchema) => Promise - let tableOrView: [string, CreateFn][] = [["table", createTable]] - - if (!isInMemory) { - tableOrView.push([ - "view", - async (schema?: TableSchema) => { - const tableId = await createTable(schema) - const viewId = await createView( - tableId, - Object.keys(schema || {}).reduce( - (viewSchema, fieldName) => { - const field = schema![fieldName] - viewSchema[fieldName] = { - visible: field.visible ?? true, - readonly: false, - } - return viewSchema - }, - {} - ) - ) - return viewId - }, - ]) - } - - describe.each(tableOrView)("from %s", (sourceType, createTableOrView) => { - const isView = sourceType === "view" - - class SearchAssertion { - constructor(private readonly query: SearchRowRequest) {} - - private async performSearch(): Promise> { - if (isInMemory) { - return dataFilters.search(_.cloneDeep(rows), { - ...this.query, - }) - } else { - return config.api.row.search(tableOrViewId, this.query) - } - } - - // We originally used _.isMatch to compare rows, but found that when - // comparing arrays it would return true if the source array was a subset of - // the target array. This would sometimes create false matches. This - // function is a more strict version of _.isMatch that only returns true if - // the source array is an exact match of the target. - // - // _.isMatch("100", "1") also returns true which is not what we want. - private isMatch>( - expected: T, - found: T - ) { - if (!expected) { - throw new Error("Expected is undefined") - } - if (!found) { - return false - } - - for (const key of Object.keys(expected)) { - if (Array.isArray(expected[key])) { - if (!Array.isArray(found[key])) { - return false - } - if (expected[key].length !== found[key].length) { - return false - } - if (!_.isMatch(found[key], expected[key])) { - return false - } - } else if (typeof expected[key] === "object") { - if (!this.isMatch(expected[key], found[key])) { - return false - } - } else { - if (expected[key] !== found[key]) { - return false - } - } - } - return true - } - - // This function exists to ensure that the same row is not matched twice. - // When a row gets matched, we make sure to remove it from the list of rows - // we're matching against. - private popRow( - expectedRow: T, - foundRows: T[] - ): NonNullable { - const row = foundRows.find(row => this.isMatch(expectedRow, row)) - if (!row) { - const fields = Object.keys(expectedRow) - // To make the error message more readable, we only include the fields - // that are present in the expected row. - const searchedObjects = foundRows.map(row => _.pick(row, fields)) - throw new Error( - `Failed to find row:\n\n${JSON.stringify( - expectedRow, - null, - 2 - )}\n\nin\n\n${JSON.stringify(searchedObjects, null, 2)}` - ) - } - - foundRows.splice(foundRows.indexOf(row), 1) - return row - } - - // Asserts that the query returns rows matching exactly the set of rows - // passed in. The order of the rows matters. Rows returned in an order - // different to the one passed in will cause the assertion to fail. Extra - // rows returned by the query will also cause the assertion to fail. - async toMatchExactly(expectedRows: any[]) { - const response = await this.performSearch() - const cloned = cloneDeep(response) - const foundRows = response.rows - - // eslint-disable-next-line jest/no-standalone-expect - expect(foundRows).toHaveLength(expectedRows.length) - // eslint-disable-next-line jest/no-standalone-expect - expect([...foundRows]).toEqual( - expectedRows.map((expectedRow: any) => - expect.objectContaining(this.popRow(expectedRow, foundRows)) - ) - ) - return cloned - } - - // Asserts that the query returns rows matching exactly the set of rows - // passed in. The order of the rows is not important, but extra rows will - // cause the assertion to fail. - async toContainExactly(expectedRows: any[]) { - const response = await this.performSearch() - const cloned = cloneDeep(response) - const foundRows = response.rows - - // eslint-disable-next-line jest/no-standalone-expect - expect(foundRows).toHaveLength(expectedRows.length) - // eslint-disable-next-line jest/no-standalone-expect - expect([...foundRows]).toEqual( - expect.arrayContaining( - expectedRows.map((expectedRow: any) => - expect.objectContaining(this.popRow(expectedRow, foundRows)) - ) - ) - ) - return cloned - } - - // Asserts that the query returns some property values - this cannot be used - // to check row values, however this shouldn't be important for checking properties - // typing for this has to be any, Jest doesn't expose types for matchers like expect.any(...) - async toMatch(properties: Record) { - const response = await this.performSearch() - const cloned = cloneDeep(response) - const keys = Object.keys(properties) as Array< - keyof SearchResponse - > - for (let key of keys) { - // eslint-disable-next-line jest/no-standalone-expect - expect(response[key]).toBeDefined() - if (properties[key]) { - // eslint-disable-next-line jest/no-standalone-expect - expect(response[key]).toEqual(properties[key]) - } - } - return cloned - } - - // Asserts that the query doesn't return a property, e.g. pagination parameters. - async toNotHaveProperty(properties: (keyof SearchResponse)[]) { - const response = await this.performSearch() - const cloned = cloneDeep(response) - for (let property of properties) { - // eslint-disable-next-line jest/no-standalone-expect - expect(response[property]).toBeUndefined() - } - return cloned - } - - // Asserts that the query returns rows matching the set of rows passed in. - // The order of the rows is not important. Extra rows will not cause the - // assertion to fail. - async toContain(expectedRows: any[]) { - const response = await this.performSearch() - const cloned = cloneDeep(response) - const foundRows = response.rows - - // eslint-disable-next-line jest/no-standalone-expect - expect([...foundRows]).toEqual( - expect.arrayContaining( - expectedRows.map((expectedRow: any) => - expect.objectContaining(this.popRow(expectedRow, foundRows)) - ) - ) - ) - return cloned - } - - async toFindNothing() { - await this.toContainExactly([]) - } - - async toHaveLength(length: number) { - const { rows: foundRows } = await this.performSearch() - - // eslint-disable-next-line jest/no-standalone-expect - expect(foundRows).toHaveLength(length) - } - } - - function expectSearch(query: SearchRowRequest) { - return new SearchAssertion(query) - } - - function expectQuery(query: SearchFilters) { - return expectSearch({ query }) - } - - describe("boolean", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - isTrue: { name: "isTrue", type: FieldType.BOOLEAN }, - }) - await createRows([{ isTrue: true }, { isTrue: false }]) - }) - - describe("equal", () => { - it("successfully finds true row", async () => { - await expectQuery({ equal: { isTrue: true } }).toMatchExactly([ - { isTrue: true }, - ]) - }) - - it("successfully finds false row", async () => { - await expectQuery({ equal: { isTrue: false } }).toMatchExactly([ - { isTrue: false }, - ]) - }) - }) - - describe("notEqual", () => { - it("successfully finds false row", async () => { - await expectQuery({ - notEqual: { isTrue: true }, - }).toContainExactly([{ isTrue: false }]) - }) - - it("successfully finds true row", async () => { - await expectQuery({ - notEqual: { isTrue: false }, - }).toContainExactly([{ isTrue: true }]) - }) - }) - - describe("oneOf", () => { - it("successfully finds true row", async () => { - await expectQuery({ oneOf: { isTrue: [true] } }).toContainExactly( - [{ isTrue: true }] - ) - }) - - it("successfully finds false row", async () => { - await expectQuery({ - oneOf: { isTrue: [false] }, - }).toContainExactly([{ isTrue: false }]) - }) - }) - - describe("sort", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "isTrue", - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([{ isTrue: false }, { isTrue: true }]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "isTrue", - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([{ isTrue: true }, { isTrue: false }]) - }) - }) + }, + ], }) + }) - !isInMemory && - describe("bindings", () => { - let globalUsers: any = [] + async function createTable(schema?: TableSchema) { + const table = await config.api.table.save( + tableForDatasource(datasource, { schema }) + ) + return table._id! + } - const serverTime = new Date() + async function createView(tableId: string, schema?: ViewV2Schema) { + const view = await config.api.viewV2.create({ + tableId: tableId, + name: generator.guid(), + schema, + }) + return view.id + } - // In MariaDB and MySQL we only store dates to second precision, so we need - // to remove milliseconds from the server time to ensure searches work as - // expected. - serverTime.setMilliseconds(0) + async function createRows(arr: Record[]) { + // Shuffling to avoid false positives given a fixed order + for (const row of _.shuffle(arr)) { + await config.api.row.save(tableOrViewId, row) + } + rows = await config.api.row.fetch(tableOrViewId) + } - const future = new Date( - serverTime.getTime() + 1000 * 60 * 60 * 24 * 30 - ) + async function getTable(tableOrViewId: string): Promise
{ + if (docIds.isViewId(tableOrViewId)) { + const view = await config.api.viewV2.get(tableOrViewId) + return await config.api.table.get(view.tableId) + } else { + return await config.api.table.get(tableOrViewId) + } + } - const rows = (currentUser: User) => { - return [ - { name: "foo", appointment: "1982-01-05T00:00:00.000Z" }, - { name: "bar", appointment: "1995-05-06T00:00:00.000Z" }, - { - name: currentUser.firstName, - appointment: future.toISOString(), - }, - { name: "serverDate", appointment: serverTime.toISOString() }, - { - name: "single user, session user", - single_user: currentUser, - }, - { - name: "single user", - single_user: globalUsers[0], - }, - { - name: "deprecated single user, session user", - deprecated_single_user: [currentUser], - }, - { - name: "deprecated single user", - deprecated_single_user: [globalUsers[0]], - }, - { - name: "multi user", - multi_user: globalUsers, - }, - { - name: "multi user with session user", - multi_user: [...globalUsers, currentUser], - }, - { - name: "deprecated multi user", - deprecated_multi_user: globalUsers, - }, - { - name: "deprecated multi user with session user", - deprecated_multi_user: [...globalUsers, currentUser], - }, - ] + async function assertTableExists(nameOrTable: string | Table) { + const name = + typeof nameOrTable === "string" ? nameOrTable : nameOrTable.name + expect(await client!.schema.hasTable(name)).toBeTrue() + } + + async function assertTableNumRows( + nameOrTable: string | Table, + numRows: number + ) { + const name = + typeof nameOrTable === "string" ? nameOrTable : nameOrTable.name + const row = await client!.from(name).count() + const count = parseInt(Object.values(row[0])[0] as string) + expect(count).toEqual(numRows) + } + + describe.each([true, false])("in-memory: %s", isInMemory => { + // We only run the in-memory tests during the SQS (isInternal) run + if (isInMemory && !isInternal) { + return + } + + type CreateFn = (schema?: TableSchema) => Promise + let tableOrView: [string, CreateFn][] = [["table", createTable]] + + if (!isInMemory) { + tableOrView.push([ + "view", + async (schema?: TableSchema) => { + const tableId = await createTable(schema) + const viewId = await createView( + tableId, + Object.keys(schema || {}).reduce( + (viewSchema, fieldName) => { + const field = schema![fieldName] + viewSchema[fieldName] = { + visible: field.visible ?? true, + readonly: false, + } + return viewSchema + }, + {} + ) + ) + return viewId + }, + ]) + } + + describe.each(tableOrView)( + "from %s", + (sourceType, createTableOrView) => { + const isView = sourceType === "view" + + class SearchAssertion { + constructor(private readonly query: SearchRowRequest) {} + + private async performSearch(): Promise> { + if (isInMemory) { + return dataFilters.search(_.cloneDeep(rows), { + ...this.query, + }) + } else { + return config.api.row.search(tableOrViewId, this.query) + } + } + + // We originally used _.isMatch to compare rows, but found that when + // comparing arrays it would return true if the source array was a subset of + // the target array. This would sometimes create false matches. This + // function is a more strict version of _.isMatch that only returns true if + // the source array is an exact match of the target. + // + // _.isMatch("100", "1") also returns true which is not what we want. + private isMatch>( + expected: T, + found: T + ) { + if (!expected) { + throw new Error("Expected is undefined") + } + if (!found) { + return false + } + + for (const key of Object.keys(expected)) { + if (Array.isArray(expected[key])) { + if (!Array.isArray(found[key])) { + return false + } + if (expected[key].length !== found[key].length) { + return false + } + if (!_.isMatch(found[key], expected[key])) { + return false + } + } else if (typeof expected[key] === "object") { + if (!this.isMatch(expected[key], found[key])) { + return false + } + } else { + if (expected[key] !== found[key]) { + return false + } + } + } + return true + } + + // This function exists to ensure that the same row is not matched twice. + // When a row gets matched, we make sure to remove it from the list of rows + // we're matching against. + private popRow( + expectedRow: T, + foundRows: T[] + ): NonNullable { + const row = foundRows.find(row => + this.isMatch(expectedRow, row) + ) + if (!row) { + const fields = Object.keys(expectedRow) + // To make the error message more readable, we only include the fields + // that are present in the expected row. + const searchedObjects = foundRows.map(row => + _.pick(row, fields) + ) + throw new Error( + `Failed to find row:\n\n${JSON.stringify( + expectedRow, + null, + 2 + )}\n\nin\n\n${JSON.stringify(searchedObjects, null, 2)}` + ) + } + + foundRows.splice(foundRows.indexOf(row), 1) + return row + } + + // Asserts that the query returns rows matching exactly the set of rows + // passed in. The order of the rows matters. Rows returned in an order + // different to the one passed in will cause the assertion to fail. Extra + // rows returned by the query will also cause the assertion to fail. + async toMatchExactly(expectedRows: any[]) { + const response = await this.performSearch() + const cloned = cloneDeep(response) + const foundRows = response.rows + + // eslint-disable-next-line jest/no-standalone-expect + expect(foundRows).toHaveLength(expectedRows.length) + // eslint-disable-next-line jest/no-standalone-expect + expect([...foundRows]).toEqual( + expectedRows.map((expectedRow: any) => + expect.objectContaining(this.popRow(expectedRow, foundRows)) + ) + ) + return cloned + } + + // Asserts that the query returns rows matching exactly the set of rows + // passed in. The order of the rows is not important, but extra rows will + // cause the assertion to fail. + async toContainExactly(expectedRows: any[]) { + const response = await this.performSearch() + const cloned = cloneDeep(response) + const foundRows = response.rows + + // eslint-disable-next-line jest/no-standalone-expect + expect(foundRows).toHaveLength(expectedRows.length) + // eslint-disable-next-line jest/no-standalone-expect + expect([...foundRows]).toEqual( + expect.arrayContaining( + expectedRows.map((expectedRow: any) => + expect.objectContaining( + this.popRow(expectedRow, foundRows) + ) + ) + ) + ) + return cloned + } + + // Asserts that the query returns some property values - this cannot be used + // to check row values, however this shouldn't be important for checking properties + // typing for this has to be any, Jest doesn't expose types for matchers like expect.any(...) + async toMatch(properties: Record) { + const response = await this.performSearch() + const cloned = cloneDeep(response) + const keys = Object.keys(properties) as Array< + keyof SearchResponse + > + for (let key of keys) { + // eslint-disable-next-line jest/no-standalone-expect + expect(response[key]).toBeDefined() + if (properties[key]) { + // eslint-disable-next-line jest/no-standalone-expect + expect(response[key]).toEqual(properties[key]) + } + } + return cloned + } + + // Asserts that the query doesn't return a property, e.g. pagination parameters. + async toNotHaveProperty( + properties: (keyof SearchResponse)[] + ) { + const response = await this.performSearch() + const cloned = cloneDeep(response) + for (let property of properties) { + // eslint-disable-next-line jest/no-standalone-expect + expect(response[property]).toBeUndefined() + } + return cloned + } + + // Asserts that the query returns rows matching the set of rows passed in. + // The order of the rows is not important. Extra rows will not cause the + // assertion to fail. + async toContain(expectedRows: any[]) { + const response = await this.performSearch() + const cloned = cloneDeep(response) + const foundRows = response.rows + + // eslint-disable-next-line jest/no-standalone-expect + expect([...foundRows]).toEqual( + expect.arrayContaining( + expectedRows.map((expectedRow: any) => + expect.objectContaining( + this.popRow(expectedRow, foundRows) + ) + ) + ) + ) + return cloned + } + + async toFindNothing() { + await this.toContainExactly([]) + } + + async toHaveLength(length: number) { + const { rows: foundRows } = await this.performSearch() + + // eslint-disable-next-line jest/no-standalone-expect + expect(foundRows).toHaveLength(length) + } } - beforeAll(async () => { - // Set up some global users - globalUsers = await Promise.all( - Array(2) - .fill(0) - .map(async () => { - const globalUser = await config.globalUser() - const userMedataId = globalUser._id - ? dbCore.generateUserMetadataID(globalUser._id) - : null - return { - _id: globalUser._id, - _meta: userMedataId, - } - }) - ) + function expectSearch(query: SearchRowRequest) { + return new SearchAssertion(query) + } - tableOrViewId = await createTableOrView({ - name: { name: "name", type: FieldType.STRING }, - appointment: { name: "appointment", type: FieldType.DATETIME }, - single_user: { - name: "single_user", - type: FieldType.BB_REFERENCE_SINGLE, - subtype: BBReferenceFieldSubType.USER, - }, - deprecated_single_user: { - name: "deprecated_single_user", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - }, - multi_user: { - name: "multi_user", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - constraints: { - type: "array", - }, - }, - deprecated_multi_user: { - name: "deprecated_multi_user", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USERS, - constraints: { - type: "array", - }, - }, - }) - await createRows(rows(config.getUser())) - }) + function expectQuery(query: SearchFilters) { + return expectSearch({ query }) + } - // !! Current User is auto generated per run - it("should return all rows matching the session user firstname", async () => { - await expectQuery({ - equal: { name: "{{ [user].firstName }}" }, - }).toContainExactly([ - { - name: config.getUser().firstName, - appointment: future.toISOString(), - }, - ]) - }) - - it("should return all rows matching the session user firstname when logical operator used", async () => { - await expectQuery({ - $and: { - conditions: [{ equal: { name: "{{ [user].firstName }}" } }], - }, - }).toContainExactly([ - { - name: config.getUser().firstName, - appointment: future.toISOString(), - }, - ]) - }) - - it("should parse the date binding and return all rows after the resolved value", async () => { - await tk.withFreeze(serverTime, async () => { - await expectQuery({ - range: { - appointment: { - low: "{{ [now] }}", - high: "9999-00-00T00:00:00.000Z", - }, - }, - }).toContainExactly([ - { - name: config.getUser().firstName, - appointment: future.toISOString(), - }, - { name: "serverDate", appointment: serverTime.toISOString() }, - ]) - }) - }) - - it("should parse the date binding and return all rows before the resolved value", async () => { - await expectQuery({ - range: { - appointment: { - low: "0000-00-00T00:00:00.000Z", - high: "{{ [now] }}", - }, - }, - }).toContainExactly([ - { name: "foo", appointment: "1982-01-05T00:00:00.000Z" }, - { name: "bar", appointment: "1995-05-06T00:00:00.000Z" }, - { name: "serverDate", appointment: serverTime.toISOString() }, - ]) - }) - - it("should parse the encoded js snippet. Return rows with appointments up to 1 week in the past", async () => { - const jsBinding = "return snippets.WeeksAgo();" - const encodedBinding = encodeJSBinding(jsBinding) - - await expectQuery({ - range: { - appointment: { - low: "0000-00-00T00:00:00.000Z", - high: encodedBinding, - }, - }, - }).toContainExactly([ - { name: "foo", appointment: "1982-01-05T00:00:00.000Z" }, - { name: "bar", appointment: "1995-05-06T00:00:00.000Z" }, - ]) - }) - - it("should parse the encoded js binding. Return rows with appointments 2 weeks in the past", async () => { - const jsBinding = `const currentTime = new Date(${Date.now()})\ncurrentTime.setDate(currentTime.getDate()-14);\nreturn currentTime.toISOString();` - const encodedBinding = encodeJSBinding(jsBinding) - - await expectQuery({ - range: { - appointment: { - low: "0000-00-00T00:00:00.000Z", - high: encodedBinding, - }, - }, - }).toContainExactly([ - { name: "foo", appointment: "1982-01-05T00:00:00.000Z" }, - { name: "bar", appointment: "1995-05-06T00:00:00.000Z" }, - ]) - }) - - it("should match a single user row by the session user id", async () => { - await expectQuery({ - equal: { single_user: "{{ [user]._id }}" }, - }).toContainExactly([ - { - name: "single user, session user", - single_user: { _id: config.getUser()._id }, - }, - ]) - }) - - it("should match a deprecated single user row by the session user id", async () => { - await expectQuery({ - equal: { deprecated_single_user: "{{ [user]._id }}" }, - }).toContainExactly([ - { - name: "deprecated single user, session user", - deprecated_single_user: [{ _id: config.getUser()._id }], - }, - ]) - }) - - it("should match the session user id in a multi user field", async () => { - const allUsers = [...globalUsers, config.getUser()].map( - (user: any) => { - return { _id: user._id } - } - ) - - await expectQuery({ - contains: { multi_user: ["{{ [user]._id }}"] }, - }).toContainExactly([ - { - name: "multi user with session user", - multi_user: allUsers, - }, - ]) - }) - - it("should match the session user id in a deprecated multi user field", async () => { - const allUsers = [...globalUsers, config.getUser()].map( - (user: any) => { - return { _id: user._id } - } - ) - - await expectQuery({ - contains: { deprecated_multi_user: ["{{ [user]._id }}"] }, - }).toContainExactly([ - { - name: "deprecated multi user with session user", - deprecated_multi_user: allUsers, - }, - ]) - }) - - it("should not match the session user id in a multi user field", async () => { - await expectQuery({ - notContains: { multi_user: ["{{ [user]._id }}"] }, - notEmpty: { multi_user: true }, - }).toContainExactly([ - { - name: "multi user", - multi_user: globalUsers.map((user: any) => { - return { _id: user._id } - }), - }, - ]) - }) - - it("should not match the session user id in a deprecated multi user field", async () => { - await expectQuery({ - notContains: { deprecated_multi_user: ["{{ [user]._id }}"] }, - notEmpty: { deprecated_multi_user: true }, - }).toContainExactly([ - { - name: "deprecated multi user", - deprecated_multi_user: globalUsers.map((user: any) => { - return { _id: user._id } - }), - }, - ]) - }) - - it("should match the session user id and a user table row id using helpers, user binding and a static user id.", async () => { - await expectQuery({ - oneOf: { - single_user: [ - "{{ default [user]._id '_empty_' }}", - globalUsers[0]._id, - ], - }, - }).toContainExactly([ - { - name: "single user, session user", - single_user: { _id: config.getUser()._id }, - }, - { - name: "single user", - single_user: { _id: globalUsers[0]._id }, - }, - ]) - }) - - it("should match the session user id and a user table row id using helpers, user binding and a static user id. (deprecated single user)", async () => { - await expectQuery({ - oneOf: { - deprecated_single_user: [ - "{{ default [user]._id '_empty_' }}", - globalUsers[0]._id, - ], - }, - }).toContainExactly([ - { - name: "deprecated single user, session user", - deprecated_single_user: [{ _id: config.getUser()._id }], - }, - { - name: "deprecated single user", - deprecated_single_user: [{ _id: globalUsers[0]._id }], - }, - ]) - }) - - it("should resolve 'default' helper to '_empty_' when binding resolves to nothing", async () => { - await expectQuery({ - oneOf: { - single_user: [ - "{{ default [user]._idx '_empty_' }}", - globalUsers[0]._id, - ], - }, - }).toContainExactly([ - { - name: "single user", - single_user: { _id: globalUsers[0]._id }, - }, - ]) - }) - - it("should resolve 'default' helper to '_empty_' when binding resolves to nothing (deprecated single user)", async () => { - await expectQuery({ - oneOf: { - deprecated_single_user: [ - "{{ default [user]._idx '_empty_' }}", - globalUsers[0]._id, - ], - }, - }).toContainExactly([ - { - name: "deprecated single user", - deprecated_single_user: [{ _id: globalUsers[0]._id }], - }, - ]) - }) - }) - - const stringTypes = [FieldType.STRING, FieldType.LONGFORM] as const - describe.each(stringTypes)("%s", type => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - name: { name: "name", type }, - }) - await createRows([{ name: "foo" }, { name: "bar" }]) - }) - - describe("misc", () => { - it("should return all if no query is passed", async () => { - await expectSearch({} as RowSearchParams).toContainExactly([ - { name: "foo" }, - { name: "bar" }, - ]) - }) - - it("should return all if empty query is passed", async () => { - await expectQuery({}).toContainExactly([ - { name: "foo" }, - { name: "bar" }, - ]) - }) - - it("should return all if onEmptyFilter is RETURN_ALL", async () => { - await expectQuery({ - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - }).toContainExactly([{ name: "foo" }, { name: "bar" }]) - }) - - // onEmptyFilter cannot be sent to view searches - !isView && - it("should return nothing if onEmptyFilter is RETURN_NONE", async () => { - await expectQuery({ - onEmptyFilter: EmptyFilterOption.RETURN_NONE, - }).toFindNothing() + describe("boolean", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + isTrue: { name: "isTrue", type: FieldType.BOOLEAN }, + }) + await createRows([{ isTrue: true }, { isTrue: false }]) }) - it("should respect limit", async () => { - await expectSearch({ - limit: 1, - paginate: true, - query: {}, - }).toHaveLength(1) - }) - }) - - describe("equal", () => { - it("successfully finds a row", async () => { - await expectQuery({ equal: { name: "foo" } }).toContainExactly([ - { name: "foo" }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ equal: { name: "none" } }).toFindNothing() - }) - - it("works as an or condition", async () => { - await expectQuery({ - allOr: true, - equal: { name: "foo" }, - oneOf: { name: ["bar"] }, - }).toContainExactly([{ name: "foo" }, { name: "bar" }]) - }) - - it("can have multiple values for same column", async () => { - await expectQuery({ - allOr: true, - equal: { "1:name": "foo", "2:name": "bar" }, - }).toContainExactly([{ name: "foo" }, { name: "bar" }]) - }) - }) - - describe("notEqual", () => { - it("successfully finds a row", async () => { - await expectQuery({ notEqual: { name: "foo" } }).toContainExactly( - [{ name: "bar" }] - ) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ notEqual: { name: "bar" } }).toContainExactly( - [{ name: "foo" }] - ) - }) - }) - - describe("oneOf", () => { - it("successfully finds a row", async () => { - await expectQuery({ oneOf: { name: ["foo"] } }).toContainExactly([ - { name: "foo" }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ oneOf: { name: ["none"] } }).toFindNothing() - }) - - it("can have multiple values for same column", async () => { - await expectQuery({ - oneOf: { - name: ["foo", "bar"], - }, - }).toContainExactly([{ name: "foo" }, { name: "bar" }]) - }) - - it("splits comma separated strings", async () => { - await expectQuery({ - oneOf: { - // @ts-ignore - name: "foo,bar", - }, - }).toContainExactly([{ name: "foo" }, { name: "bar" }]) - }) - - it("trims whitespace", async () => { - await expectQuery({ - oneOf: { - // @ts-ignore - name: "foo, bar", - }, - }).toContainExactly([{ name: "foo" }, { name: "bar" }]) - }) - - it("empty arrays returns all when onEmptyFilter is set to return 'all'", async () => { - await expectQuery({ - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - oneOf: { name: [] }, - }).toContainExactly([{ name: "foo" }, { name: "bar" }]) - }) - - // onEmptyFilter cannot be sent to view searches - !isView && - it("empty arrays returns all when onEmptyFilter is set to return 'none'", async () => { - await expectQuery({ - onEmptyFilter: EmptyFilterOption.RETURN_NONE, - oneOf: { name: [] }, - }).toContainExactly([]) - }) - }) - - describe("fuzzy", () => { - it("successfully finds a row", async () => { - await expectQuery({ fuzzy: { name: "oo" } }).toContainExactly([ - { name: "foo" }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ fuzzy: { name: "none" } }).toFindNothing() - }) - }) - - describe("string", () => { - it("successfully finds a row", async () => { - await expectQuery({ string: { name: "fo" } }).toContainExactly([ - { name: "foo" }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ string: { name: "none" } }).toFindNothing() - }) - - it("is case-insensitive", async () => { - await expectQuery({ string: { name: "FO" } }).toContainExactly([ - { name: "foo" }, - ]) - }) - }) - - describe("range", () => { - it("successfully finds multiple rows", async () => { - await expectQuery({ - range: { name: { low: "a", high: "z" } }, - }).toContainExactly([{ name: "bar" }, { name: "foo" }]) - }) - - it("successfully finds a row with a high bound", async () => { - await expectQuery({ - range: { name: { low: "a", high: "c" } }, - }).toContainExactly([{ name: "bar" }]) - }) - - it("successfully finds a row with a low bound", async () => { - await expectQuery({ - range: { name: { low: "f", high: "z" } }, - }).toContainExactly([{ name: "foo" }]) - }) - - it("successfully finds no rows", async () => { - await expectQuery({ - range: { name: { low: "g", high: "h" } }, - }).toFindNothing() - }) - - it("ignores low if it's an empty object", async () => { - await expectQuery({ - // @ts-ignore - range: { name: { low: {}, high: "z" } }, - }).toContainExactly([{ name: "foo" }, { name: "bar" }]) - }) - - it("ignores high if it's an empty object", async () => { - await expectQuery({ - // @ts-ignore - range: { name: { low: "a", high: {} } }, - }).toContainExactly([{ name: "foo" }, { name: "bar" }]) - }) - }) - - describe("empty", () => { - it("finds no empty rows", async () => { - await expectQuery({ empty: { name: null } }).toFindNothing() - }) - - it("should not be affected by when filter empty behaviour", async () => { - await expectQuery({ - empty: { name: null }, - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - }).toFindNothing() - }) - }) - - describe("notEmpty", () => { - it("finds all non-empty rows", async () => { - await expectQuery({ notEmpty: { name: null } }).toContainExactly([ - { name: "foo" }, - { name: "bar" }, - ]) - }) - - it("should not be affected by when filter empty behaviour", async () => { - await expectQuery({ - notEmpty: { name: null }, - onEmptyFilter: EmptyFilterOption.RETURN_NONE, - }).toContainExactly([{ name: "foo" }, { name: "bar" }]) - }) - }) - - describe("sort", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "name", - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([{ name: "bar" }, { name: "foo" }]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "name", - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([{ name: "foo" }, { name: "bar" }]) - }) - - describe("sortType STRING", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "name", - sortType: SortType.STRING, - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([{ name: "bar" }, { name: "foo" }]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "name", - sortType: SortType.STRING, - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([{ name: "foo" }, { name: "bar" }]) - }) - }) - - !isInternal && - !isInMemory && - // This test was added because we automatically add in a sort by the - // primary key, and we used to do this unconditionally which caused - // problems because it was possible for the primary key to appear twice - // in the resulting SQL ORDER BY clause, resulting in an SQL error. - // We now check first to make sure that the primary key isn't already - // in the sort before adding it. - describe("sort on primary key", () => { - beforeAll(async () => { - const tableName = structures.uuid().substring(0, 10) - await client!.schema.createTable(tableName, t => { - t.string("name").primary() - }) - const resp = await config.api.datasource.fetchSchema({ - datasourceId: datasource!._id!, - }) - - tableOrViewId = resp.datasource.entities![tableName]._id! - - await createRows([{ name: "foo" }, { name: "bar" }]) + describe("equal", () => { + it("successfully finds true row", async () => { + await expectQuery({ equal: { isTrue: true } }).toMatchExactly( + [{ isTrue: true }] + ) }) - it("should be able to sort by a primary key column ascending", async () => - expectSearch({ - query: {}, - sort: "name", - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([{ name: "bar" }, { name: "foo" }])) - - it("should be able to sort by a primary key column descending", async () => - expectSearch({ - query: {}, - sort: "name", - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([{ name: "foo" }, { name: "bar" }])) - }) - }) - }) - - describe("numbers", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - age: { name: "age", type: FieldType.NUMBER }, - }) - await createRows([{ age: 1 }, { age: 10 }]) - }) - - describe("equal", () => { - it("successfully finds a row", async () => { - await expectQuery({ equal: { age: 1 } }).toContainExactly([ - { age: 1 }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ equal: { age: 2 } }).toFindNothing() - }) - }) - - describe("notEqual", () => { - it("successfully finds a row", async () => { - await expectQuery({ notEqual: { age: 1 } }).toContainExactly([ - { age: 10 }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ notEqual: { age: 10 } }).toContainExactly([ - { age: 1 }, - ]) - }) - }) - - describe("oneOf", () => { - it("successfully finds a row", async () => { - await expectQuery({ oneOf: { age: [1] } }).toContainExactly([ - { age: 1 }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ oneOf: { age: [2] } }).toFindNothing() - }) - - it("can convert from a string", async () => { - await expectQuery({ - oneOf: { - // @ts-ignore - age: "1", - }, - }).toContainExactly([{ age: 1 }]) - }) - - it("can find multiple values for same column", async () => { - await expectQuery({ - oneOf: { - // @ts-ignore - age: "1,10", - }, - }).toContainExactly([{ age: 1 }, { age: 10 }]) - }) - }) - - describe("range", () => { - it("successfully finds a row", async () => { - await expectQuery({ - range: { age: { low: 1, high: 5 } }, - }).toContainExactly([{ age: 1 }]) - }) - - it("successfully finds multiple rows", async () => { - await expectQuery({ - range: { age: { low: 1, high: 10 } }, - }).toContainExactly([{ age: 1 }, { age: 10 }]) - }) - - it("successfully finds a row with a high bound", async () => { - await expectQuery({ - range: { age: { low: 5, high: 10 } }, - }).toContainExactly([{ age: 10 }]) - }) - - it("successfully finds no rows", async () => { - await expectQuery({ - range: { age: { low: 5, high: 9 } }, - }).toFindNothing() - }) - - it("greater than equal to", async () => { - await expectQuery({ - range: { - age: { low: 10, high: Number.MAX_SAFE_INTEGER }, - }, - }).toContainExactly([{ age: 10 }]) - }) - - it("greater than", async () => { - await expectQuery({ - range: { - age: { low: 5, high: Number.MAX_SAFE_INTEGER }, - }, - }).toContainExactly([{ age: 10 }]) - }) - - it("less than equal to", async () => { - await expectQuery({ - range: { - age: { high: 1, low: Number.MIN_SAFE_INTEGER }, - }, - }).toContainExactly([{ age: 1 }]) - }) - - it("less than", async () => { - await expectQuery({ - range: { - age: { high: 5, low: Number.MIN_SAFE_INTEGER }, - }, - }).toContainExactly([{ age: 1 }]) - }) - }) - - describe("sort", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "age", - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([{ age: 1 }, { age: 10 }]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "age", - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([{ age: 10 }, { age: 1 }]) - }) - }) - - describe("sortType NUMBER", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "age", - sortType: SortType.NUMBER, - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([{ age: 1 }, { age: 10 }]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "age", - sortType: SortType.NUMBER, - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([{ age: 10 }, { age: 1 }]) - }) - }) - }) - - describe("dates", () => { - const JAN_1ST = "2020-01-01T00:00:00.000Z" - const JAN_2ND = "2020-01-02T00:00:00.000Z" - const JAN_5TH = "2020-01-05T00:00:00.000Z" - const JAN_9TH = "2020-01-09T00:00:00.000Z" - const JAN_10TH = "2020-01-10T00:00:00.000Z" - - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - dob: { name: "dob", type: FieldType.DATETIME }, - }) - - await createRows([{ dob: JAN_1ST }, { dob: JAN_10TH }]) - }) - - describe("equal", () => { - it("successfully finds a row", async () => { - await expectQuery({ equal: { dob: JAN_1ST } }).toContainExactly([ - { dob: JAN_1ST }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ equal: { dob: JAN_2ND } }).toFindNothing() - }) - }) - - describe("notEqual", () => { - it("successfully finds a row", async () => { - await expectQuery({ - notEqual: { dob: JAN_1ST }, - }).toContainExactly([{ dob: JAN_10TH }]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - notEqual: { dob: JAN_10TH }, - }).toContainExactly([{ dob: JAN_1ST }]) - }) - }) - - describe("oneOf", () => { - it("successfully finds a row", async () => { - await expectQuery({ oneOf: { dob: [JAN_1ST] } }).toContainExactly( - [{ dob: JAN_1ST }] - ) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ oneOf: { dob: [JAN_2ND] } }).toFindNothing() - }) - }) - - describe("range", () => { - it("successfully finds a row", async () => { - await expectQuery({ - range: { dob: { low: JAN_1ST, high: JAN_5TH } }, - }).toContainExactly([{ dob: JAN_1ST }]) - }) - - it("successfully finds multiple rows", async () => { - await expectQuery({ - range: { dob: { low: JAN_1ST, high: JAN_10TH } }, - }).toContainExactly([{ dob: JAN_1ST }, { dob: JAN_10TH }]) - }) - - it("successfully finds a row with a high bound", async () => { - await expectQuery({ - range: { dob: { low: JAN_5TH, high: JAN_10TH } }, - }).toContainExactly([{ dob: JAN_10TH }]) - }) - - it("successfully finds no rows", async () => { - await expectQuery({ - range: { dob: { low: JAN_5TH, high: JAN_9TH } }, - }).toFindNothing() - }) - - it("greater than equal to", async () => { - await expectQuery({ - range: { - dob: { low: JAN_10TH, high: MAX_VALID_DATE.toISOString() }, - }, - }).toContainExactly([{ dob: JAN_10TH }]) - }) - - it("greater than", async () => { - await expectQuery({ - range: { - dob: { low: JAN_5TH, high: MAX_VALID_DATE.toISOString() }, - }, - }).toContainExactly([{ dob: JAN_10TH }]) - }) - - it("less than equal to", async () => { - await expectQuery({ - range: { - dob: { high: JAN_1ST, low: MIN_VALID_DATE.toISOString() }, - }, - }).toContainExactly([{ dob: JAN_1ST }]) - }) - - it("less than", async () => { - await expectQuery({ - range: { - dob: { high: JAN_5TH, low: MIN_VALID_DATE.toISOString() }, - }, - }).toContainExactly([{ dob: JAN_1ST }]) - }) - }) - - describe("sort", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "dob", - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([{ dob: JAN_1ST }, { dob: JAN_10TH }]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "dob", - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([{ dob: JAN_10TH }, { dob: JAN_1ST }]) - }) - - describe("sortType STRING", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "dob", - sortType: SortType.STRING, - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([{ dob: JAN_1ST }, { dob: JAN_10TH }]) + it("successfully finds false row", async () => { + await expectQuery({ + equal: { isTrue: false }, + }).toMatchExactly([{ isTrue: false }]) + }) }) - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "dob", - sortType: SortType.STRING, - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([{ dob: JAN_10TH }, { dob: JAN_1ST }]) - }) - }) - }) - }) + describe("notEqual", () => { + it("successfully finds false row", async () => { + await expectQuery({ + notEqual: { isTrue: true }, + }).toContainExactly([{ isTrue: false }]) + }) - !isInternal && - describe("datetime - time only", () => { - const T_1000 = "10:00:00" - const T_1045 = "10:45:00" - const T_1200 = "12:00:00" - const T_1530 = "15:30:00" - const T_0000 = "00:00:00" - - const UNEXISTING_TIME = "10:01:00" - - const NULL_TIME__ID = `null_time__id` - - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - timeid: { name: "timeid", type: FieldType.STRING }, - time: { - name: "time", - type: FieldType.DATETIME, - timeOnly: true, - }, + it("successfully finds true row", async () => { + await expectQuery({ + notEqual: { isTrue: false }, + }).toContainExactly([{ isTrue: true }]) + }) }) - await createRows([ - { timeid: NULL_TIME__ID, time: null }, - { time: T_1000 }, - { time: T_1045 }, - { time: T_1200 }, - { time: T_1530 }, - { time: T_0000 }, - ]) - }) + describe("oneOf", () => { + it("successfully finds true row", async () => { + await expectQuery({ + oneOf: { isTrue: [true] }, + }).toContainExactly([{ isTrue: true }]) + }) - describe("equal", () => { - it("successfully finds a row", async () => { - await expectQuery({ equal: { time: T_1000 } }).toContainExactly( - [{ time: "10:00:00" }] - ) + it("successfully finds false row", async () => { + await expectQuery({ + oneOf: { isTrue: [false] }, + }).toContainExactly([{ isTrue: false }]) + }) }) - it("fails to find nonexistent row", async () => { - await expectQuery({ - equal: { time: UNEXISTING_TIME }, - }).toFindNothing() - }) - }) - - describe("notEqual", () => { - it("successfully finds a row", async () => { - await expectQuery({ - notEqual: { time: T_1000 }, - }).toContainExactly([ - { timeid: NULL_TIME__ID }, - { time: "10:45:00" }, - { time: "12:00:00" }, - { time: "15:30:00" }, - { time: "00:00:00" }, - ]) - }) - - it("return all when requesting non-existing", async () => { - await expectQuery({ - notEqual: { time: UNEXISTING_TIME }, - }).toContainExactly([ - { timeid: NULL_TIME__ID }, - { time: "10:00:00" }, - { time: "10:45:00" }, - { time: "12:00:00" }, - { time: "15:30:00" }, - { time: "00:00:00" }, - ]) - }) - }) - - describe("oneOf", () => { - it("successfully finds a row", async () => { - await expectQuery({ - oneOf: { time: [T_1000] }, - }).toContainExactly([{ time: "10:00:00" }]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - oneOf: { time: [UNEXISTING_TIME] }, - }).toFindNothing() - }) - }) - - describe("range", () => { - it("successfully finds a row", async () => { - await expectQuery({ - range: { time: { low: T_1045, high: T_1045 } }, - }).toContainExactly([{ time: "10:45:00" }]) - }) - - it("successfully finds multiple rows", async () => { - await expectQuery({ - range: { time: { low: T_1045, high: T_1530 } }, - }).toContainExactly([ - { time: "10:45:00" }, - { time: "12:00:00" }, - { time: "15:30:00" }, - ]) - }) - - it("successfully finds no rows", async () => { - await expectQuery({ - range: { - time: { low: UNEXISTING_TIME, high: UNEXISTING_TIME }, - }, - }).toFindNothing() - }) - }) - - describe("sort", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "time", - sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([ - { timeid: NULL_TIME__ID }, - { time: "00:00:00" }, - { time: "10:00:00" }, - { time: "10:45:00" }, - { time: "12:00:00" }, - { time: "15:30:00" }, - ]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "time", - sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([ - { time: "15:30:00" }, - { time: "12:00:00" }, - { time: "10:45:00" }, - { time: "10:00:00" }, - { time: "00:00:00" }, - { timeid: NULL_TIME__ID }, - ]) - }) - - describe("sortType STRING", () => { + describe("sort", () => { it("sorts ascending", async () => { await expectSearch({ query: {}, - sort: "time", - sortType: SortType.STRING, + sort: "isTrue", sortOrder: SortOrder.ASCENDING, - }).toMatchExactly([ - { timeid: NULL_TIME__ID }, - { time: "00:00:00" }, - { time: "10:00:00" }, - { time: "10:45:00" }, - { time: "12:00:00" }, - { time: "15:30:00" }, - ]) + }).toMatchExactly([{ isTrue: false }, { isTrue: true }]) }) it("sorts descending", async () => { await expectSearch({ query: {}, - sort: "time", - sortType: SortType.STRING, + sort: "isTrue", sortOrder: SortOrder.DESCENDING, - }).toMatchExactly([ - { time: "15:30:00" }, - { time: "12:00:00" }, - { time: "10:45:00" }, - { time: "10:00:00" }, - { time: "00:00:00" }, - { timeid: NULL_TIME__ID }, - ]) + }).toMatchExactly([{ isTrue: true }, { isTrue: false }]) }) }) }) - }) - isInternal && - !isInMemory && - describe("AI Column", () => { - const UNEXISTING_AI_COLUMN = "Real LLM Response" + !isInMemory && + describe("bindings", () => { + let globalUsers: any = [] - beforeAll(async () => { - mocks.licenses.useBudibaseAI() - mocks.licenses.useAICustomConfigs() + const serverTime = new Date() - tableOrViewId = await createTableOrView({ - product: { name: "product", type: FieldType.STRING }, - ai: { - name: "AI", - type: FieldType.AI, - operation: AIOperationEnum.PROMPT, - prompt: "Translate '{{ product }}' into German", - }, - }) + // In MariaDB and MySQL we only store dates to second precision, so we need + // to remove milliseconds from the server time to ensure searches work as + // expected. + serverTime.setMilliseconds(0) - await createRows([ - { product: "Big Mac" }, - { product: "McCrispy" }, - ]) - }) - - describe("equal", () => { - it("successfully finds rows based on AI column", async () => { - await expectQuery({ - equal: { ai: "Mock LLM Response" }, - }).toContainExactly([ - { product: "Big Mac" }, - { product: "McCrispy" }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - equal: { ai: UNEXISTING_AI_COLUMN }, - }).toFindNothing() - }) - }) - - describe("notEqual", () => { - it("Returns nothing when searching notEqual on the mock AI response", async () => { - await expectQuery({ - notEqual: { ai: "Mock LLM Response" }, - }).toContainExactly([]) - }) - - it("return all when requesting non-existing response", async () => { - await expectQuery({ - notEqual: { ai: "Real LLM Response" }, - }).toContainExactly([ - { product: "Big Mac" }, - { product: "McCrispy" }, - ]) - }) - }) - - describe("oneOf", () => { - it("successfully finds a row", async () => { - await expectQuery({ - oneOf: { ai: ["Mock LLM Response", "Other LLM Response"] }, - }).toContainExactly([ - { product: "Big Mac" }, - { product: "McCrispy" }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - oneOf: { ai: ["Whopper"] }, - }).toFindNothing() - }) - }) - }) - - describe("arrays", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - numbers: { - name: "numbers", - type: FieldType.ARRAY, - constraints: { - type: JsonFieldSubType.ARRAY, - inclusion: ["one", "two", "three"], - }, - }, - }) - await createRows([ - { numbers: ["one", "two"] }, - { numbers: ["three"] }, - ]) - }) - - describe("contains", () => { - it("successfully finds a row", async () => { - await expectQuery({ - contains: { numbers: ["one"] }, - }).toContainExactly([{ numbers: ["one", "two"] }]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - contains: { numbers: ["none"] }, - }).toFindNothing() - }) - - it("fails to find row containing all", async () => { - await expectQuery({ - contains: { numbers: ["one", "two", "three"] }, - }).toFindNothing() - }) - - it("finds all with empty list", async () => { - await expectQuery({ contains: { numbers: [] } }).toContainExactly( - [{ numbers: ["one", "two"] }, { numbers: ["three"] }] - ) - }) - }) - - describe("notContains", () => { - it("successfully finds a row", async () => { - await expectQuery({ - notContains: { numbers: ["one"] }, - }).toContainExactly([{ numbers: ["three"] }]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - notContains: { numbers: ["one", "two", "three"] }, - }).toContainExactly([ - { numbers: ["one", "two"] }, - { numbers: ["three"] }, - ]) - }) - - // Not sure if this is correct behaviour but changing it would be a - // breaking change. - it("finds all with empty list", async () => { - await expectQuery({ - notContains: { numbers: [] }, - }).toContainExactly([ - { numbers: ["one", "two"] }, - { numbers: ["three"] }, - ]) - }) - }) - - describe("containsAny", () => { - it("successfully finds rows", async () => { - await expectQuery({ - containsAny: { numbers: ["one", "two", "three"] }, - }).toContainExactly([ - { numbers: ["one", "two"] }, - { numbers: ["three"] }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - containsAny: { numbers: ["none"] }, - }).toFindNothing() - }) - - it("finds all with empty list", async () => { - await expectQuery({ - containsAny: { numbers: [] }, - }).toContainExactly([ - { numbers: ["one", "two"] }, - { numbers: ["three"] }, - ]) - }) - }) - }) - - describe("bigints", () => { - const SMALL = "1" - const MEDIUM = "10000000" - - // Our bigints are int64s in most datasources. - let BIG = "9223372036854775807" - - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - num: { name: "num", type: FieldType.BIGINT }, - }) - await createRows([{ num: SMALL }, { num: MEDIUM }, { num: BIG }]) - }) - - describe("equal", () => { - it("successfully finds a row", async () => { - await expectQuery({ equal: { num: SMALL } }).toContainExactly([ - { num: SMALL }, - ]) - }) - - it("successfully finds a big value", async () => { - await expectQuery({ equal: { num: BIG } }).toContainExactly([ - { num: BIG }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ equal: { num: "2" } }).toFindNothing() - }) - }) - - describe("notEqual", () => { - it("successfully finds a row", async () => { - await expectQuery({ notEqual: { num: SMALL } }).toContainExactly([ - { num: MEDIUM }, - { num: BIG }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ notEqual: { num: 10 } }).toContainExactly([ - { num: SMALL }, - { num: MEDIUM }, - { num: BIG }, - ]) - }) - }) - - describe("oneOf", () => { - it("successfully finds a row", async () => { - await expectQuery({ oneOf: { num: [SMALL] } }).toContainExactly([ - { num: SMALL }, - ]) - }) - - it("successfully finds all rows", async () => { - await expectQuery({ - oneOf: { num: [SMALL, MEDIUM, BIG] }, - }).toContainExactly([ - { num: SMALL }, - { num: MEDIUM }, - { num: BIG }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ oneOf: { num: [2] } }).toFindNothing() - }) - }) - - describe("range", () => { - it("successfully finds a row", async () => { - await expectQuery({ - range: { num: { low: SMALL, high: "5" } }, - }).toContainExactly([{ num: SMALL }]) - }) - - it("successfully finds multiple rows", async () => { - await expectQuery({ - range: { num: { low: SMALL, high: MEDIUM } }, - }).toContainExactly([{ num: SMALL }, { num: MEDIUM }]) - }) - - it("successfully finds a row with a high bound", async () => { - await expectQuery({ - range: { num: { low: MEDIUM, high: BIG } }, - }).toContainExactly([{ num: MEDIUM }, { num: BIG }]) - }) - - it("successfully finds no rows", async () => { - await expectQuery({ - range: { num: { low: "5", high: "5" } }, - }).toFindNothing() - }) - - it("can search using just a low value", async () => { - await expectQuery({ - range: { num: { low: MEDIUM } }, - }).toContainExactly([{ num: MEDIUM }, { num: BIG }]) - }) - - it("can search using just a high value", async () => { - await expectQuery({ - range: { num: { high: MEDIUM } }, - }).toContainExactly([{ num: SMALL }, { num: MEDIUM }]) - }) - }) - }) - - isInternal && - describe("auto", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - auto: { - name: "auto", - type: FieldType.AUTO, - autocolumn: true, - subtype: AutoFieldSubType.AUTO_ID, - }, - }) - await createRows(new Array(10).fill({})) - }) - - describe("equal", () => { - it("successfully finds a row", async () => { - await expectQuery({ equal: { auto: 1 } }).toContainExactly([ - { auto: 1 }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ equal: { auto: 0 } }).toFindNothing() - }) - }) - - describe("not equal", () => { - it("successfully finds a row", async () => { - await expectQuery({ notEqual: { auto: 1 } }).toContainExactly([ - { auto: 2 }, - { auto: 3 }, - { auto: 4 }, - { auto: 5 }, - { auto: 6 }, - { auto: 7 }, - { auto: 8 }, - { auto: 9 }, - { auto: 10 }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ notEqual: { auto: 0 } }).toContainExactly([ - { auto: 1 }, - { auto: 2 }, - { auto: 3 }, - { auto: 4 }, - { auto: 5 }, - { auto: 6 }, - { auto: 7 }, - { auto: 8 }, - { auto: 9 }, - { auto: 10 }, - ]) - }) - }) - - describe("oneOf", () => { - it("successfully finds a row", async () => { - await expectQuery({ oneOf: { auto: [1] } }).toContainExactly([ - { auto: 1 }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ oneOf: { auto: [0] } }).toFindNothing() - }) - }) - - describe("range", () => { - it("successfully finds a row", async () => { - await expectQuery({ - range: { auto: { low: 1, high: 1 } }, - }).toContainExactly([{ auto: 1 }]) - }) - - it("successfully finds multiple rows", async () => { - await expectQuery({ - range: { auto: { low: 1, high: 2 } }, - }).toContainExactly([{ auto: 1 }, { auto: 2 }]) - }) - - it("successfully finds a row with a high bound", async () => { - await expectQuery({ - range: { auto: { low: 2, high: 2 } }, - }).toContainExactly([{ auto: 2 }]) - }) - - it("successfully finds no rows", async () => { - await expectQuery({ - range: { auto: { low: 0, high: 0 } }, - }).toFindNothing() - }) - - it("can search using just a low value", async () => { - await expectQuery({ - range: { auto: { low: 9 } }, - }).toContainExactly([{ auto: 9 }, { auto: 10 }]) - }) - - it("can search using just a high value", async () => { - await expectQuery({ - range: { auto: { high: 2 } }, - }).toContainExactly([{ auto: 1 }, { auto: 2 }]) - }) - }) - - describe("sort", () => { - it("sorts ascending", async () => { - await expectSearch({ - query: {}, - sort: "auto", - sortOrder: SortOrder.ASCENDING, - sortType: SortType.NUMBER, - }).toMatchExactly([ - { auto: 1 }, - { auto: 2 }, - { auto: 3 }, - { auto: 4 }, - { auto: 5 }, - { auto: 6 }, - { auto: 7 }, - { auto: 8 }, - { auto: 9 }, - { auto: 10 }, - ]) - }) - - it("sorts descending", async () => { - await expectSearch({ - query: {}, - sort: "auto", - sortOrder: SortOrder.DESCENDING, - sortType: SortType.NUMBER, - }).toMatchExactly([ - { auto: 10 }, - { auto: 9 }, - { auto: 8 }, - { auto: 7 }, - { auto: 6 }, - { auto: 5 }, - { auto: 4 }, - { auto: 3 }, - { auto: 2 }, - { auto: 1 }, - ]) - }) - - // This is important for pagination. The order of results must always - // be stable or pagination will break. We don't want the user to need - // to specify an order for pagination to work. - it("is stable without a sort specified", async () => { - let { rows: fullRowList } = await config.api.row.search( - tableOrViewId, - { - tableId: tableOrViewId, - query: {}, - } + const future = new Date( + serverTime.getTime() + 1000 * 60 * 60 * 24 * 30 ) - // repeat the search many times to check the first row is always the same - let bookmark: string | number | undefined, - hasNextPage: boolean | undefined = true, - rowCount: number = 0 - do { - const response = await config.api.row.search(tableOrViewId, { - tableId: tableOrViewId, + const rows = (currentUser: User) => { + return [ + { name: "foo", appointment: "1982-01-05T00:00:00.000Z" }, + { name: "bar", appointment: "1995-05-06T00:00:00.000Z" }, + { + name: currentUser.firstName, + appointment: future.toISOString(), + }, + { + name: "serverDate", + appointment: serverTime.toISOString(), + }, + { + name: "single user, session user", + single_user: currentUser, + }, + { + name: "single user", + single_user: globalUsers[0], + }, + { + name: "deprecated single user, session user", + deprecated_single_user: [currentUser], + }, + { + name: "deprecated single user", + deprecated_single_user: [globalUsers[0]], + }, + { + name: "multi user", + multi_user: globalUsers, + }, + { + name: "multi user with session user", + multi_user: [...globalUsers, currentUser], + }, + { + name: "deprecated multi user", + deprecated_multi_user: globalUsers, + }, + { + name: "deprecated multi user with session user", + deprecated_multi_user: [...globalUsers, currentUser], + }, + ] + } + + beforeAll(async () => { + // Set up some global users + globalUsers = await Promise.all( + Array(2) + .fill(0) + .map(async () => { + const globalUser = await config.globalUser() + const userMedataId = globalUser._id + ? dbCore.generateUserMetadataID(globalUser._id) + : null + return { + _id: globalUser._id, + _meta: userMedataId, + } + }) + ) + + tableOrViewId = await createTableOrView({ + name: { name: "name", type: FieldType.STRING }, + appointment: { + name: "appointment", + type: FieldType.DATETIME, + }, + single_user: { + name: "single_user", + type: FieldType.BB_REFERENCE_SINGLE, + subtype: BBReferenceFieldSubType.USER, + }, + deprecated_single_user: { + name: "deprecated_single_user", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + }, + multi_user: { + name: "multi_user", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + constraints: { + type: "array", + }, + }, + deprecated_multi_user: { + name: "deprecated_multi_user", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USERS, + constraints: { + type: "array", + }, + }, + }) + await createRows(rows(config.getUser())) + }) + + // !! Current User is auto generated per run + it("should return all rows matching the session user firstname", async () => { + await expectQuery({ + equal: { name: "{{ [user].firstName }}" }, + }).toContainExactly([ + { + name: config.getUser().firstName, + appointment: future.toISOString(), + }, + ]) + }) + + it("should return all rows matching the session user firstname when logical operator used", async () => { + await expectQuery({ + $and: { + conditions: [ + { equal: { name: "{{ [user].firstName }}" } }, + ], + }, + }).toContainExactly([ + { + name: config.getUser().firstName, + appointment: future.toISOString(), + }, + ]) + }) + + it("should parse the date binding and return all rows after the resolved value", async () => { + await tk.withFreeze(serverTime, async () => { + await expectQuery({ + range: { + appointment: { + low: "{{ [now] }}", + high: "9999-00-00T00:00:00.000Z", + }, + }, + }).toContainExactly([ + { + name: config.getUser().firstName, + appointment: future.toISOString(), + }, + { + name: "serverDate", + appointment: serverTime.toISOString(), + }, + ]) + }) + }) + + it("should parse the date binding and return all rows before the resolved value", async () => { + await expectQuery({ + range: { + appointment: { + low: "0000-00-00T00:00:00.000Z", + high: "{{ [now] }}", + }, + }, + }).toContainExactly([ + { name: "foo", appointment: "1982-01-05T00:00:00.000Z" }, + { name: "bar", appointment: "1995-05-06T00:00:00.000Z" }, + { + name: "serverDate", + appointment: serverTime.toISOString(), + }, + ]) + }) + + it("should parse the encoded js snippet. Return rows with appointments up to 1 week in the past", async () => { + const jsBinding = "return snippets.WeeksAgo();" + const encodedBinding = encodeJSBinding(jsBinding) + + await expectQuery({ + range: { + appointment: { + low: "0000-00-00T00:00:00.000Z", + high: encodedBinding, + }, + }, + }).toContainExactly([ + { name: "foo", appointment: "1982-01-05T00:00:00.000Z" }, + { name: "bar", appointment: "1995-05-06T00:00:00.000Z" }, + ]) + }) + + it("should parse the encoded js binding. Return rows with appointments 2 weeks in the past", async () => { + const jsBinding = `const currentTime = new Date(${Date.now()})\ncurrentTime.setDate(currentTime.getDate()-14);\nreturn currentTime.toISOString();` + const encodedBinding = encodeJSBinding(jsBinding) + + await expectQuery({ + range: { + appointment: { + low: "0000-00-00T00:00:00.000Z", + high: encodedBinding, + }, + }, + }).toContainExactly([ + { name: "foo", appointment: "1982-01-05T00:00:00.000Z" }, + { name: "bar", appointment: "1995-05-06T00:00:00.000Z" }, + ]) + }) + + it("should match a single user row by the session user id", async () => { + await expectQuery({ + equal: { single_user: "{{ [user]._id }}" }, + }).toContainExactly([ + { + name: "single user, session user", + single_user: { _id: config.getUser()._id }, + }, + ]) + }) + + it("should match a deprecated single user row by the session user id", async () => { + await expectQuery({ + equal: { deprecated_single_user: "{{ [user]._id }}" }, + }).toContainExactly([ + { + name: "deprecated single user, session user", + deprecated_single_user: [{ _id: config.getUser()._id }], + }, + ]) + }) + + it("should match the session user id in a multi user field", async () => { + const allUsers = [...globalUsers, config.getUser()].map( + (user: any) => { + return { _id: user._id } + } + ) + + await expectQuery({ + contains: { multi_user: ["{{ [user]._id }}"] }, + }).toContainExactly([ + { + name: "multi user with session user", + multi_user: allUsers, + }, + ]) + }) + + it("should match the session user id in a deprecated multi user field", async () => { + const allUsers = [...globalUsers, config.getUser()].map( + (user: any) => { + return { _id: user._id } + } + ) + + await expectQuery({ + contains: { deprecated_multi_user: ["{{ [user]._id }}"] }, + }).toContainExactly([ + { + name: "deprecated multi user with session user", + deprecated_multi_user: allUsers, + }, + ]) + }) + + it("should not match the session user id in a multi user field", async () => { + await expectQuery({ + notContains: { multi_user: ["{{ [user]._id }}"] }, + notEmpty: { multi_user: true }, + }).toContainExactly([ + { + name: "multi user", + multi_user: globalUsers.map((user: any) => { + return { _id: user._id } + }), + }, + ]) + }) + + it("should not match the session user id in a deprecated multi user field", async () => { + await expectQuery({ + notContains: { + deprecated_multi_user: ["{{ [user]._id }}"], + }, + notEmpty: { deprecated_multi_user: true }, + }).toContainExactly([ + { + name: "deprecated multi user", + deprecated_multi_user: globalUsers.map((user: any) => { + return { _id: user._id } + }), + }, + ]) + }) + + it("should match the session user id and a user table row id using helpers, user binding and a static user id.", async () => { + await expectQuery({ + oneOf: { + single_user: [ + "{{ default [user]._id '_empty_' }}", + globalUsers[0]._id, + ], + }, + }).toContainExactly([ + { + name: "single user, session user", + single_user: { _id: config.getUser()._id }, + }, + { + name: "single user", + single_user: { _id: globalUsers[0]._id }, + }, + ]) + }) + + it("should match the session user id and a user table row id using helpers, user binding and a static user id. (deprecated single user)", async () => { + await expectQuery({ + oneOf: { + deprecated_single_user: [ + "{{ default [user]._id '_empty_' }}", + globalUsers[0]._id, + ], + }, + }).toContainExactly([ + { + name: "deprecated single user, session user", + deprecated_single_user: [{ _id: config.getUser()._id }], + }, + { + name: "deprecated single user", + deprecated_single_user: [{ _id: globalUsers[0]._id }], + }, + ]) + }) + + it("should resolve 'default' helper to '_empty_' when binding resolves to nothing", async () => { + await expectQuery({ + oneOf: { + single_user: [ + "{{ default [user]._idx '_empty_' }}", + globalUsers[0]._id, + ], + }, + }).toContainExactly([ + { + name: "single user", + single_user: { _id: globalUsers[0]._id }, + }, + ]) + }) + + it("should resolve 'default' helper to '_empty_' when binding resolves to nothing (deprecated single user)", async () => { + await expectQuery({ + oneOf: { + deprecated_single_user: [ + "{{ default [user]._idx '_empty_' }}", + globalUsers[0]._id, + ], + }, + }).toContainExactly([ + { + name: "deprecated single user", + deprecated_single_user: [{ _id: globalUsers[0]._id }], + }, + ]) + }) + }) + + const stringTypes = [FieldType.STRING, FieldType.LONGFORM] as const + describe.each(stringTypes)("%s", type => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + name: { name: "name", type }, + }) + await createRows([{ name: "foo" }, { name: "bar" }]) + }) + + describe("misc", () => { + it("should return all if no query is passed", async () => { + await expectSearch({} as RowSearchParams).toContainExactly([ + { name: "foo" }, + { name: "bar" }, + ]) + }) + + it("should return all if empty query is passed", async () => { + await expectQuery({}).toContainExactly([ + { name: "foo" }, + { name: "bar" }, + ]) + }) + + it("should return all if onEmptyFilter is RETURN_ALL", async () => { + await expectQuery({ + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + + // onEmptyFilter cannot be sent to view searches + !isView && + it("should return nothing if onEmptyFilter is RETURN_NONE", async () => { + await expectQuery({ + onEmptyFilter: EmptyFilterOption.RETURN_NONE, + }).toFindNothing() + }) + + it("should respect limit", async () => { + await expectSearch({ limit: 1, paginate: true, query: {}, - bookmark, - }) - bookmark = response.bookmark - hasNextPage = response.hasNextPage - expect(response.rows.length).toEqual(1) - const foundRow = response.rows[0] - expect(foundRow).toEqual(fullRowList[rowCount++]) - } while (hasNextPage) + }).toHaveLength(1) + }) }) - }) - describe("pagination", () => { - it("should paginate through all rows", async () => { - // @ts-ignore - let bookmark: string | number = undefined - let rows: Row[] = [] + describe("equal", () => { + it("successfully finds a row", async () => { + await expectQuery({ + equal: { name: "foo" }, + }).toContainExactly([{ name: "foo" }]) + }) - // eslint-disable-next-line no-constant-condition - while (true) { - const response = await config.api.row.search(tableOrViewId, { - tableId: tableOrViewId, - limit: 3, + it("fails to find nonexistent row", async () => { + await expectQuery({ equal: { name: "none" } }).toFindNothing() + }) + + it("works as an or condition", async () => { + await expectQuery({ + allOr: true, + equal: { name: "foo" }, + oneOf: { name: ["bar"] }, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + + it("can have multiple values for same column", async () => { + await expectQuery({ + allOr: true, + equal: { "1:name": "foo", "2:name": "bar" }, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + }) + + describe("notEqual", () => { + it("successfully finds a row", async () => { + await expectQuery({ + notEqual: { name: "foo" }, + }).toContainExactly([{ name: "bar" }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + notEqual: { name: "bar" }, + }).toContainExactly([{ name: "foo" }]) + }) + }) + + describe("oneOf", () => { + it("successfully finds a row", async () => { + await expectQuery({ + oneOf: { name: ["foo"] }, + }).toContainExactly([{ name: "foo" }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + oneOf: { name: ["none"] }, + }).toFindNothing() + }) + + it("can have multiple values for same column", async () => { + await expectQuery({ + oneOf: { + name: ["foo", "bar"], + }, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + + it("splits comma separated strings", async () => { + await expectQuery({ + oneOf: { + // @ts-ignore + name: "foo,bar", + }, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + + it("trims whitespace", async () => { + await expectQuery({ + oneOf: { + // @ts-ignore + name: "foo, bar", + }, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + + it("empty arrays returns all when onEmptyFilter is set to return 'all'", async () => { + await expectQuery({ + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + oneOf: { name: [] }, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + + // onEmptyFilter cannot be sent to view searches + !isView && + it("empty arrays returns all when onEmptyFilter is set to return 'none'", async () => { + await expectQuery({ + onEmptyFilter: EmptyFilterOption.RETURN_NONE, + oneOf: { name: [] }, + }).toContainExactly([]) + }) + }) + + describe("fuzzy", () => { + it("successfully finds a row", async () => { + await expectQuery({ fuzzy: { name: "oo" } }).toContainExactly( + [{ name: "foo" }] + ) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ fuzzy: { name: "none" } }).toFindNothing() + }) + }) + + describe("string", () => { + it("successfully finds a row", async () => { + await expectQuery({ + string: { name: "fo" }, + }).toContainExactly([{ name: "foo" }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + string: { name: "none" }, + }).toFindNothing() + }) + + it("is case-insensitive", async () => { + await expectQuery({ + string: { name: "FO" }, + }).toContainExactly([{ name: "foo" }]) + }) + }) + + describe("range", () => { + it("successfully finds multiple rows", async () => { + await expectQuery({ + range: { name: { low: "a", high: "z" } }, + }).toContainExactly([{ name: "bar" }, { name: "foo" }]) + }) + + it("successfully finds a row with a high bound", async () => { + await expectQuery({ + range: { name: { low: "a", high: "c" } }, + }).toContainExactly([{ name: "bar" }]) + }) + + it("successfully finds a row with a low bound", async () => { + await expectQuery({ + range: { name: { low: "f", high: "z" } }, + }).toContainExactly([{ name: "foo" }]) + }) + + it("successfully finds no rows", async () => { + await expectQuery({ + range: { name: { low: "g", high: "h" } }, + }).toFindNothing() + }) + + it("ignores low if it's an empty object", async () => { + await expectQuery({ + // @ts-ignore + range: { name: { low: {}, high: "z" } }, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + + it("ignores high if it's an empty object", async () => { + await expectQuery({ + // @ts-ignore + range: { name: { low: "a", high: {} } }, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + }) + + describe("empty", () => { + it("finds no empty rows", async () => { + await expectQuery({ empty: { name: null } }).toFindNothing() + }) + + it("should not be affected by when filter empty behaviour", async () => { + await expectQuery({ + empty: { name: null }, + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + }).toFindNothing() + }) + }) + + describe("notEmpty", () => { + it("finds all non-empty rows", async () => { + await expectQuery({ + notEmpty: { name: null }, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + + it("should not be affected by when filter empty behaviour", async () => { + await expectQuery({ + notEmpty: { name: null }, + onEmptyFilter: EmptyFilterOption.RETURN_NONE, + }).toContainExactly([{ name: "foo" }, { name: "bar" }]) + }) + }) + + describe("sort", () => { + it("sorts ascending", async () => { + await expectSearch({ query: {}, - bookmark, - paginate: true, + sort: "name", + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([{ name: "bar" }, { name: "foo" }]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "name", + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([{ name: "foo" }, { name: "bar" }]) + }) + + describe("sortType STRING", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "name", + sortType: SortType.STRING, + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([{ name: "bar" }, { name: "foo" }]) }) - rows.push(...response.rows) + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "name", + sortType: SortType.STRING, + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([{ name: "foo" }, { name: "bar" }]) + }) + }) - if (!response.bookmark || !response.hasNextPage) { - break - } - bookmark = response.bookmark - } + !isInternal && + !isInMemory && + // This test was added because we automatically add in a sort by the + // primary key, and we used to do this unconditionally which caused + // problems because it was possible for the primary key to appear twice + // in the resulting SQL ORDER BY clause, resulting in an SQL error. + // We now check first to make sure that the primary key isn't already + // in the sort before adding it. + describe("sort on primary key", () => { + beforeAll(async () => { + const tableName = structures.uuid().substring(0, 10) + await client!.schema.createTable(tableName, t => { + t.string("name").primary() + }) + const resp = await config.api.datasource.fetchSchema({ + datasourceId: datasource!._id!, + }) - const autoValues = rows - .map(row => row.auto) - .sort((a, b) => a - b) - expect(autoValues).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + tableOrViewId = resp.datasource.entities![tableName]._id! + + await createRows([{ name: "foo" }, { name: "bar" }]) + }) + + it("should be able to sort by a primary key column ascending", async () => + expectSearch({ + query: {}, + sort: "name", + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([{ name: "bar" }, { name: "foo" }])) + + it("should be able to sort by a primary key column descending", async () => + expectSearch({ + query: {}, + sort: "name", + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([{ name: "foo" }, { name: "bar" }])) + }) }) }) - }) - describe("field name 1:name", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - "1:name": { name: "1:name", type: FieldType.STRING }, - }) - await createRows([{ "1:name": "bar" }, { "1:name": "foo" }]) - }) - - it("successfully finds a row", async () => { - await expectQuery({ - equal: { "1:1:name": "bar" }, - }).toContainExactly([{ "1:name": "bar" }]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ equal: { "1:1:name": "none" } }).toFindNothing() - }) - }) - - isSql && - describe("related formulas", () => { - beforeAll(async () => { - const arrayTable = await createTable({ - name: { name: "name", type: FieldType.STRING }, - array: { - name: "array", - type: FieldType.ARRAY, - constraints: { - type: JsonFieldSubType.ARRAY, - inclusion: ["option 1", "option 2"], - }, - }, + describe("numbers", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + age: { name: "age", type: FieldType.NUMBER }, + }) + await createRows([{ age: 1 }, { age: 10 }]) }) - tableOrViewId = await createTableOrView({ - relationship: { - type: FieldType.LINK, - relationshipType: RelationshipType.MANY_TO_ONE, - name: "relationship", - fieldName: "relate", - tableId: arrayTable, - constraints: { - type: "array", - }, - }, - formula: { - type: FieldType.FORMULA, - name: "formula", - formula: encodeJSBinding( - `let array = [];$("relationship").forEach(rel => array = array.concat(rel.array));return array.sort().join(",")` - ), - }, - }) - const arrayRows = await Promise.all([ - config.api.row.save(arrayTable, { - name: "foo", - array: ["option 1"], - }), - config.api.row.save(arrayTable, { - name: "bar", - array: ["option 2"], - }), - ]) - await Promise.all([ - config.api.row.save(tableOrViewId, { - relationship: [arrayRows[0]._id, arrayRows[1]._id], - }), - ]) - }) - it("formula is correct with relationship arrays", async () => { - await expectQuery({}).toContain([ - { formula: "option 1,option 2" }, - ]) - }) - }) - - describe("user", () => { - let user1: User - let user2: User - - beforeAll(async () => { - user1 = await config.createUser({ _id: `us_${utils.newid()}` }) - user2 = await config.createUser({ _id: `us_${utils.newid()}` }) - - tableOrViewId = await createTableOrView({ - user: { - name: "user", - type: FieldType.BB_REFERENCE_SINGLE, - subtype: BBReferenceFieldSubType.USER, - }, - }) - - await createRows([{ user: user1 }, { user: user2 }, { user: null }]) - }) - - describe("equal", () => { - it("successfully finds a row", async () => { - await expectQuery({ - equal: { user: user1._id }, - }).toContainExactly([{ user: { _id: user1._id } }]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ equal: { user: "us_none" } }).toFindNothing() - }) - }) - - describe("notEqual", () => { - it("successfully finds a row", async () => { - await expectQuery({ - notEqual: { user: user1._id }, - }).toContainExactly([{ user: { _id: user2._id } }, {}]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - notEqual: { user: "us_none" }, - }).toContainExactly([ - { user: { _id: user1._id } }, - { user: { _id: user2._id } }, - {}, - ]) - }) - }) - - describe("oneOf", () => { - it("successfully finds a row", async () => { - await expectQuery({ - oneOf: { user: [user1._id] }, - }).toContainExactly([{ user: { _id: user1._id } }]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - oneOf: { user: ["us_none"] }, - }).toFindNothing() - }) - }) - - describe("empty", () => { - it("finds empty rows", async () => { - await expectQuery({ empty: { user: null } }).toContainExactly([ - {}, - ]) - }) - }) - - describe("notEmpty", () => { - it("finds non-empty rows", async () => { - await expectQuery({ notEmpty: { user: null } }).toContainExactly([ - { user: { _id: user1._id } }, - { user: { _id: user2._id } }, - ]) - }) - }) - }) - - describe("multi user", () => { - let user1: User - let user2: User - - beforeAll(async () => { - user1 = await config.createUser({ _id: `us_${utils.newid()}` }) - user2 = await config.createUser({ _id: `us_${utils.newid()}` }) - - tableOrViewId = await createTableOrView({ - users: { - name: "users", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - constraints: { type: "array" }, - }, - number: { - name: "number", - type: FieldType.NUMBER, - }, - }) - - await createRows([ - { number: 1, users: [user1] }, - { number: 2, users: [user2] }, - { number: 3, users: [user1, user2] }, - { number: 4, users: [] }, - ]) - }) - - describe("contains", () => { - it("successfully finds a row", async () => { - await expectQuery({ - contains: { users: [user1._id] }, - }).toContainExactly([ - { users: [{ _id: user1._id }] }, - { users: [{ _id: user1._id }, { _id: user2._id }] }, - ]) - }) - - it("successfully finds a row searching with a string", async () => { - await expectQuery({ - // @ts-expect-error this test specifically goes against the type to - // test that we coerce the string to an array. - contains: { "1:users": user1._id }, - }).toContainExactly([ - { users: [{ _id: user1._id }] }, - { users: [{ _id: user1._id }, { _id: user2._id }] }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - contains: { users: ["us_none"] }, - }).toFindNothing() - }) - }) - - describe("notContains", () => { - it("successfully finds a row", async () => { - await expectQuery({ - notContains: { users: [user1._id] }, - }).toContainExactly([{ users: [{ _id: user2._id }] }, {}]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - notContains: { users: ["us_none"] }, - }).toContainExactly([ - { users: [{ _id: user1._id }] }, - { users: [{ _id: user2._id }] }, - { users: [{ _id: user1._id }, { _id: user2._id }] }, - {}, - ]) - }) - }) - - describe("containsAny", () => { - it("successfully finds rows", async () => { - await expectQuery({ - containsAny: { users: [user1._id, user2._id] }, - }).toContainExactly([ - { users: [{ _id: user1._id }] }, - { users: [{ _id: user2._id }] }, - { users: [{ _id: user1._id }, { _id: user2._id }] }, - ]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - containsAny: { users: ["us_none"] }, - }).toFindNothing() - }) - }) - - describe("multi-column equals", () => { - it("successfully finds a row", async () => { - await expectQuery({ - equal: { number: 1 }, - contains: { users: [user1._id] }, - }).toContainExactly([{ users: [{ _id: user1._id }], number: 1 }]) - }) - - it("fails to find nonexistent row", async () => { - await expectQuery({ - equal: { number: 2 }, - contains: { users: [user1._id] }, - }).toFindNothing() - }) - }) - }) - - // It also can't work for in-memory searching because the related table name - // isn't available. - !isInMemory && - describe.each([ - RelationshipType.ONE_TO_MANY, - RelationshipType.MANY_TO_ONE, - RelationshipType.MANY_TO_MANY, - ])("relations (%s)", relationshipType => { - let productCategoryTable: Table, productCatRows: Row[] - - beforeAll(async () => { - const { relatedTable, tableId } = await basicRelationshipTables( - relationshipType - ) - tableOrViewId = tableId - productCategoryTable = relatedTable - - productCatRows = await Promise.all([ - config.api.row.save(productCategoryTable._id!, { name: "foo" }), - config.api.row.save(productCategoryTable._id!, { name: "bar" }), - ]) - - await Promise.all([ - config.api.row.save(tableOrViewId, { - name: "foo", - productCat: [productCatRows[0]._id], - }), - config.api.row.save(tableOrViewId, { - name: "bar", - productCat: [productCatRows[1]._id], - }), - config.api.row.save(tableOrViewId, { - name: "baz", - productCat: [], - }), - ]) - }) - - it("should be able to filter by relationship using column name", async () => { - await expectQuery({ - equal: { ["productCat.name"]: "foo" }, - }).toContainExactly([ - { name: "foo", productCat: [{ _id: productCatRows[0]._id }] }, - ]) - }) - - it("should be able to filter by relationship using table name", async () => { - await expectQuery({ - equal: { [`${productCategoryTable.name}.name`]: "foo" }, - }).toContainExactly([ - { name: "foo", productCat: [{ _id: productCatRows[0]._id }] }, - ]) - }) - - it("shouldn't return any relationship for last row", async () => { - await expectQuery({ - equal: { ["name"]: "baz" }, - }).toContainExactly([{ name: "baz", productCat: undefined }]) - }) - - describe("logical filters", () => { - const logicalOperators = [LogicalOperator.AND, LogicalOperator.OR] - - describe("$and", () => { - it("should allow single conditions", async () => { - await expectQuery({ - $and: { - conditions: [ - { - equal: { ["productCat.name"]: "foo" }, - }, - ], - }, - }).toContainExactly([ - { - name: "foo", - productCat: [{ _id: productCatRows[0]._id }], - }, + describe("equal", () => { + it("successfully finds a row", async () => { + await expectQuery({ equal: { age: 1 } }).toContainExactly([ + { age: 1 }, ]) }) - it("should allow exclusive conditions", async () => { - await expectQuery({ - $and: { - conditions: [ - { - equal: { ["productCat.name"]: "foo" }, - notEqual: { ["productCat.name"]: "foo" }, - }, - ], - }, - }).toContainExactly([]) + it("fails to find nonexistent row", async () => { + await expectQuery({ equal: { age: 2 } }).toFindNothing() + }) + }) + + describe("notEqual", () => { + it("successfully finds a row", async () => { + await expectQuery({ notEqual: { age: 1 } }).toContainExactly([ + { age: 10 }, + ]) }) - it.each([logicalOperators])( - "should allow nested ands with single conditions (with %s as root)", - async rootOperator => { + it("fails to find nonexistent row", async () => { + await expectQuery({ notEqual: { age: 10 } }).toContainExactly( + [{ age: 1 }] + ) + }) + }) + + describe("oneOf", () => { + it("successfully finds a row", async () => { + await expectQuery({ oneOf: { age: [1] } }).toContainExactly([ + { age: 1 }, + ]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ oneOf: { age: [2] } }).toFindNothing() + }) + + it("can convert from a string", async () => { + await expectQuery({ + oneOf: { + // @ts-ignore + age: "1", + }, + }).toContainExactly([{ age: 1 }]) + }) + + it("can find multiple values for same column", async () => { + await expectQuery({ + oneOf: { + // @ts-ignore + age: "1,10", + }, + }).toContainExactly([{ age: 1 }, { age: 10 }]) + }) + }) + + describe("range", () => { + it("successfully finds a row", async () => { + await expectQuery({ + range: { age: { low: 1, high: 5 } }, + }).toContainExactly([{ age: 1 }]) + }) + + it("successfully finds multiple rows", async () => { + await expectQuery({ + range: { age: { low: 1, high: 10 } }, + }).toContainExactly([{ age: 1 }, { age: 10 }]) + }) + + it("successfully finds a row with a high bound", async () => { + await expectQuery({ + range: { age: { low: 5, high: 10 } }, + }).toContainExactly([{ age: 10 }]) + }) + + it("successfully finds no rows", async () => { + await expectQuery({ + range: { age: { low: 5, high: 9 } }, + }).toFindNothing() + }) + + it("greater than equal to", async () => { + await expectQuery({ + range: { + age: { low: 10, high: Number.MAX_SAFE_INTEGER }, + }, + }).toContainExactly([{ age: 10 }]) + }) + + it("greater than", async () => { + await expectQuery({ + range: { + age: { low: 5, high: Number.MAX_SAFE_INTEGER }, + }, + }).toContainExactly([{ age: 10 }]) + }) + + it("less than equal to", async () => { + await expectQuery({ + range: { + age: { high: 1, low: Number.MIN_SAFE_INTEGER }, + }, + }).toContainExactly([{ age: 1 }]) + }) + + it("less than", async () => { + await expectQuery({ + range: { + age: { high: 5, low: Number.MIN_SAFE_INTEGER }, + }, + }).toContainExactly([{ age: 1 }]) + }) + }) + + describe("sort", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "age", + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([{ age: 1 }, { age: 10 }]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "age", + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([{ age: 10 }, { age: 1 }]) + }) + }) + + describe("sortType NUMBER", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "age", + sortType: SortType.NUMBER, + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([{ age: 1 }, { age: 10 }]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "age", + sortType: SortType.NUMBER, + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([{ age: 10 }, { age: 1 }]) + }) + }) + }) + + describe("dates", () => { + const JAN_1ST = "2020-01-01T00:00:00.000Z" + const JAN_2ND = "2020-01-02T00:00:00.000Z" + const JAN_5TH = "2020-01-05T00:00:00.000Z" + const JAN_9TH = "2020-01-09T00:00:00.000Z" + const JAN_10TH = "2020-01-10T00:00:00.000Z" + + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + dob: { name: "dob", type: FieldType.DATETIME }, + }) + + await createRows([{ dob: JAN_1ST }, { dob: JAN_10TH }]) + }) + + describe("equal", () => { + it("successfully finds a row", async () => { + await expectQuery({ + equal: { dob: JAN_1ST }, + }).toContainExactly([{ dob: JAN_1ST }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ equal: { dob: JAN_2ND } }).toFindNothing() + }) + }) + + describe("notEqual", () => { + it("successfully finds a row", async () => { + await expectQuery({ + notEqual: { dob: JAN_1ST }, + }).toContainExactly([{ dob: JAN_10TH }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + notEqual: { dob: JAN_10TH }, + }).toContainExactly([{ dob: JAN_1ST }]) + }) + }) + + describe("oneOf", () => { + it("successfully finds a row", async () => { + await expectQuery({ + oneOf: { dob: [JAN_1ST] }, + }).toContainExactly([{ dob: JAN_1ST }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + oneOf: { dob: [JAN_2ND] }, + }).toFindNothing() + }) + }) + + describe("range", () => { + it("successfully finds a row", async () => { + await expectQuery({ + range: { dob: { low: JAN_1ST, high: JAN_5TH } }, + }).toContainExactly([{ dob: JAN_1ST }]) + }) + + it("successfully finds multiple rows", async () => { + await expectQuery({ + range: { dob: { low: JAN_1ST, high: JAN_10TH } }, + }).toContainExactly([{ dob: JAN_1ST }, { dob: JAN_10TH }]) + }) + + it("successfully finds a row with a high bound", async () => { + await expectQuery({ + range: { dob: { low: JAN_5TH, high: JAN_10TH } }, + }).toContainExactly([{ dob: JAN_10TH }]) + }) + + it("successfully finds no rows", async () => { + await expectQuery({ + range: { dob: { low: JAN_5TH, high: JAN_9TH } }, + }).toFindNothing() + }) + + it("greater than equal to", async () => { + await expectQuery({ + range: { + dob: { + low: JAN_10TH, + high: MAX_VALID_DATE.toISOString(), + }, + }, + }).toContainExactly([{ dob: JAN_10TH }]) + }) + + it("greater than", async () => { + await expectQuery({ + range: { + dob: { low: JAN_5TH, high: MAX_VALID_DATE.toISOString() }, + }, + }).toContainExactly([{ dob: JAN_10TH }]) + }) + + it("less than equal to", async () => { + await expectQuery({ + range: { + dob: { high: JAN_1ST, low: MIN_VALID_DATE.toISOString() }, + }, + }).toContainExactly([{ dob: JAN_1ST }]) + }) + + it("less than", async () => { + await expectQuery({ + range: { + dob: { high: JAN_5TH, low: MIN_VALID_DATE.toISOString() }, + }, + }).toContainExactly([{ dob: JAN_1ST }]) + }) + }) + + describe("sort", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "dob", + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([{ dob: JAN_1ST }, { dob: JAN_10TH }]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "dob", + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([{ dob: JAN_10TH }, { dob: JAN_1ST }]) + }) + + describe("sortType STRING", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "dob", + sortType: SortType.STRING, + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([{ dob: JAN_1ST }, { dob: JAN_10TH }]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "dob", + sortType: SortType.STRING, + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([{ dob: JAN_10TH }, { dob: JAN_1ST }]) + }) + }) + }) + }) + + !isInternal && + describe("datetime - time only", () => { + const T_1000 = "10:00:00" + const T_1045 = "10:45:00" + const T_1200 = "12:00:00" + const T_1530 = "15:30:00" + const T_0000 = "00:00:00" + + const UNEXISTING_TIME = "10:01:00" + + const NULL_TIME__ID = `null_time__id` + + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + timeid: { name: "timeid", type: FieldType.STRING }, + time: { + name: "time", + type: FieldType.DATETIME, + timeOnly: true, + }, + }) + + await createRows([ + { timeid: NULL_TIME__ID, time: null }, + { time: T_1000 }, + { time: T_1045 }, + { time: T_1200 }, + { time: T_1530 }, + { time: T_0000 }, + ]) + }) + + describe("equal", () => { + it("successfully finds a row", async () => { await expectQuery({ - [rootOperator]: { - conditions: [ - { - $and: { - conditions: [ - { - equal: { ["productCat.name"]: "foo" }, - }, - ], - }, - }, - ], + equal: { time: T_1000 }, + }).toContainExactly([{ time: "10:00:00" }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + equal: { time: UNEXISTING_TIME }, + }).toFindNothing() + }) + }) + + describe("notEqual", () => { + it("successfully finds a row", async () => { + await expectQuery({ + notEqual: { time: T_1000 }, + }).toContainExactly([ + { timeid: NULL_TIME__ID }, + { time: "10:45:00" }, + { time: "12:00:00" }, + { time: "15:30:00" }, + { time: "00:00:00" }, + ]) + }) + + it("return all when requesting non-existing", async () => { + await expectQuery({ + notEqual: { time: UNEXISTING_TIME }, + }).toContainExactly([ + { timeid: NULL_TIME__ID }, + { time: "10:00:00" }, + { time: "10:45:00" }, + { time: "12:00:00" }, + { time: "15:30:00" }, + { time: "00:00:00" }, + ]) + }) + }) + + describe("oneOf", () => { + it("successfully finds a row", async () => { + await expectQuery({ + oneOf: { time: [T_1000] }, + }).toContainExactly([{ time: "10:00:00" }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + oneOf: { time: [UNEXISTING_TIME] }, + }).toFindNothing() + }) + }) + + describe("range", () => { + it("successfully finds a row", async () => { + await expectQuery({ + range: { time: { low: T_1045, high: T_1045 } }, + }).toContainExactly([{ time: "10:45:00" }]) + }) + + it("successfully finds multiple rows", async () => { + await expectQuery({ + range: { time: { low: T_1045, high: T_1530 } }, + }).toContainExactly([ + { time: "10:45:00" }, + { time: "12:00:00" }, + { time: "15:30:00" }, + ]) + }) + + it("successfully finds no rows", async () => { + await expectQuery({ + range: { + time: { low: UNEXISTING_TIME, high: UNEXISTING_TIME }, + }, + }).toFindNothing() + }) + }) + + describe("sort", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "time", + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([ + { timeid: NULL_TIME__ID }, + { time: "00:00:00" }, + { time: "10:00:00" }, + { time: "10:45:00" }, + { time: "12:00:00" }, + { time: "15:30:00" }, + ]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "time", + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([ + { time: "15:30:00" }, + { time: "12:00:00" }, + { time: "10:45:00" }, + { time: "10:00:00" }, + { time: "00:00:00" }, + { timeid: NULL_TIME__ID }, + ]) + }) + + describe("sortType STRING", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "time", + sortType: SortType.STRING, + sortOrder: SortOrder.ASCENDING, + }).toMatchExactly([ + { timeid: NULL_TIME__ID }, + { time: "00:00:00" }, + { time: "10:00:00" }, + { time: "10:45:00" }, + { time: "12:00:00" }, + { time: "15:30:00" }, + ]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "time", + sortType: SortType.STRING, + sortOrder: SortOrder.DESCENDING, + }).toMatchExactly([ + { time: "15:30:00" }, + { time: "12:00:00" }, + { time: "10:45:00" }, + { time: "10:00:00" }, + { time: "00:00:00" }, + { timeid: NULL_TIME__ID }, + ]) + }) + }) + }) + }) + + isInternal && + !isInMemory && + describe("AI Column", () => { + const UNEXISTING_AI_COLUMN = "Real LLM Response" + + beforeAll(async () => { + mocks.licenses.useBudibaseAI() + mocks.licenses.useAICustomConfigs() + + tableOrViewId = await createTableOrView({ + product: { name: "product", type: FieldType.STRING }, + ai: { + name: "AI", + type: FieldType.AI, + operation: AIOperationEnum.PROMPT, + prompt: "Translate '{{ product }}' into German", + }, + }) + + await createRows([ + { product: "Big Mac" }, + { product: "McCrispy" }, + ]) + }) + + describe("equal", () => { + it("successfully finds rows based on AI column", async () => { + await expectQuery({ + equal: { ai: "Mock LLM Response" }, + }).toContainExactly([ + { product: "Big Mac" }, + { product: "McCrispy" }, + ]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + equal: { ai: UNEXISTING_AI_COLUMN }, + }).toFindNothing() + }) + }) + + describe("notEqual", () => { + it("Returns nothing when searching notEqual on the mock AI response", async () => { + await expectQuery({ + notEqual: { ai: "Mock LLM Response" }, + }).toContainExactly([]) + }) + + it("return all when requesting non-existing response", async () => { + await expectQuery({ + notEqual: { ai: "Real LLM Response" }, + }).toContainExactly([ + { product: "Big Mac" }, + { product: "McCrispy" }, + ]) + }) + }) + + describe("oneOf", () => { + it("successfully finds a row", async () => { + await expectQuery({ + oneOf: { + ai: ["Mock LLM Response", "Other LLM Response"], }, }).toContainExactly([ - { - name: "foo", - productCat: [{ _id: productCatRows[0]._id }], - }, + { product: "Big Mac" }, + { product: "McCrispy" }, ]) - } - ) + }) - it.each([logicalOperators])( - "should allow nested ands with exclusive conditions (with %s as root)", - async rootOperator => { + it("fails to find nonexistent row", async () => { await expectQuery({ - [rootOperator]: { - conditions: [ - { - $and: { - conditions: [ - { - equal: { ["productCat.name"]: "foo" }, - notEqual: { ["productCat.name"]: "foo" }, - }, - ], - }, - }, - ], - }, - }).toContainExactly([]) - } - ) - - it.each([logicalOperators])( - "should allow nested ands with multiple conditions (with %s as root)", - async rootOperator => { - await expectQuery({ - [rootOperator]: { - conditions: [ - { - $and: { - conditions: [ - { - equal: { ["productCat.name"]: "foo" }, - }, - ], - }, - notEqual: { ["productCat.name"]: "foo" }, - }, - ], - }, - }).toContainExactly([]) - } - ) + oneOf: { ai: ["Whopper"] }, + }).toFindNothing() + }) + }) }) - describe("$ors", () => { - it("should allow single conditions", async () => { + describe("arrays", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + numbers: { + name: "numbers", + type: FieldType.ARRAY, + constraints: { + type: JsonFieldSubType.ARRAY, + inclusion: ["one", "two", "three"], + }, + }, + }) + await createRows([ + { numbers: ["one", "two"] }, + { numbers: ["three"] }, + ]) + }) + + describe("contains", () => { + it("successfully finds a row", async () => { await expectQuery({ - $or: { - conditions: [ - { - equal: { ["productCat.name"]: "foo" }, - }, - ], - }, + contains: { numbers: ["one"] }, + }).toContainExactly([{ numbers: ["one", "two"] }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + contains: { numbers: ["none"] }, + }).toFindNothing() + }) + + it("fails to find row containing all", async () => { + await expectQuery({ + contains: { numbers: ["one", "two", "three"] }, + }).toFindNothing() + }) + + it("finds all with empty list", async () => { + await expectQuery({ + contains: { numbers: [] }, }).toContainExactly([ - { - name: "foo", - productCat: [{ _id: productCatRows[0]._id }], - }, + { numbers: ["one", "two"] }, + { numbers: ["three"] }, + ]) + }) + }) + + describe("notContains", () => { + it("successfully finds a row", async () => { + await expectQuery({ + notContains: { numbers: ["one"] }, + }).toContainExactly([{ numbers: ["three"] }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + notContains: { numbers: ["one", "two", "three"] }, + }).toContainExactly([ + { numbers: ["one", "two"] }, + { numbers: ["three"] }, ]) }) - it("should allow exclusive conditions", async () => { + // Not sure if this is correct behaviour but changing it would be a + // breaking change. + it("finds all with empty list", async () => { await expectQuery({ - $or: { - conditions: [ - { - equal: { ["productCat.name"]: "foo" }, - notEqual: { ["productCat.name"]: "foo" }, - }, - ], - }, + notContains: { numbers: [] }, }).toContainExactly([ - { - name: "foo", - productCat: [{ _id: productCatRows[0]._id }], + { numbers: ["one", "two"] }, + { numbers: ["three"] }, + ]) + }) + }) + + describe("containsAny", () => { + it("successfully finds rows", async () => { + await expectQuery({ + containsAny: { numbers: ["one", "two", "three"] }, + }).toContainExactly([ + { numbers: ["one", "two"] }, + { numbers: ["three"] }, + ]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + containsAny: { numbers: ["none"] }, + }).toFindNothing() + }) + + it("finds all with empty list", async () => { + await expectQuery({ + containsAny: { numbers: [] }, + }).toContainExactly([ + { numbers: ["one", "two"] }, + { numbers: ["three"] }, + ]) + }) + }) + }) + + describe("bigints", () => { + const SMALL = "1" + const MEDIUM = "10000000" + + // Our bigints are int64s in most datasources. + let BIG = "9223372036854775807" + + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + num: { name: "num", type: FieldType.BIGINT }, + }) + await createRows([ + { num: SMALL }, + { num: MEDIUM }, + { num: BIG }, + ]) + }) + + describe("equal", () => { + it("successfully finds a row", async () => { + await expectQuery({ equal: { num: SMALL } }).toContainExactly( + [{ num: SMALL }] + ) + }) + + it("successfully finds a big value", async () => { + await expectQuery({ equal: { num: BIG } }).toContainExactly([ + { num: BIG }, + ]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ equal: { num: "2" } }).toFindNothing() + }) + }) + + describe("notEqual", () => { + it("successfully finds a row", async () => { + await expectQuery({ + notEqual: { num: SMALL }, + }).toContainExactly([{ num: MEDIUM }, { num: BIG }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ notEqual: { num: 10 } }).toContainExactly( + [{ num: SMALL }, { num: MEDIUM }, { num: BIG }] + ) + }) + }) + + describe("oneOf", () => { + it("successfully finds a row", async () => { + await expectQuery({ + oneOf: { num: [SMALL] }, + }).toContainExactly([{ num: SMALL }]) + }) + + it("successfully finds all rows", async () => { + await expectQuery({ + oneOf: { num: [SMALL, MEDIUM, BIG] }, + }).toContainExactly([ + { num: SMALL }, + { num: MEDIUM }, + { num: BIG }, + ]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ oneOf: { num: [2] } }).toFindNothing() + }) + }) + + describe("range", () => { + it("successfully finds a row", async () => { + await expectQuery({ + range: { num: { low: SMALL, high: "5" } }, + }).toContainExactly([{ num: SMALL }]) + }) + + it("successfully finds multiple rows", async () => { + await expectQuery({ + range: { num: { low: SMALL, high: MEDIUM } }, + }).toContainExactly([{ num: SMALL }, { num: MEDIUM }]) + }) + + it("successfully finds a row with a high bound", async () => { + await expectQuery({ + range: { num: { low: MEDIUM, high: BIG } }, + }).toContainExactly([{ num: MEDIUM }, { num: BIG }]) + }) + + it("successfully finds no rows", async () => { + await expectQuery({ + range: { num: { low: "5", high: "5" } }, + }).toFindNothing() + }) + + it("can search using just a low value", async () => { + await expectQuery({ + range: { num: { low: MEDIUM } }, + }).toContainExactly([{ num: MEDIUM }, { num: BIG }]) + }) + + it("can search using just a high value", async () => { + await expectQuery({ + range: { num: { high: MEDIUM } }, + }).toContainExactly([{ num: SMALL }, { num: MEDIUM }]) + }) + }) + }) + + isInternal && + describe("auto", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + auto: { + name: "auto", + type: FieldType.AUTO, + autocolumn: true, + subtype: AutoFieldSubType.AUTO_ID, }, - { + }) + await createRows(new Array(10).fill({})) + }) + + describe("equal", () => { + it("successfully finds a row", async () => { + await expectQuery({ equal: { auto: 1 } }).toContainExactly([ + { auto: 1 }, + ]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ equal: { auto: 0 } }).toFindNothing() + }) + }) + + describe("not equal", () => { + it("successfully finds a row", async () => { + await expectQuery({ + notEqual: { auto: 1 }, + }).toContainExactly([ + { auto: 2 }, + { auto: 3 }, + { auto: 4 }, + { auto: 5 }, + { auto: 6 }, + { auto: 7 }, + { auto: 8 }, + { auto: 9 }, + { auto: 10 }, + ]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + notEqual: { auto: 0 }, + }).toContainExactly([ + { auto: 1 }, + { auto: 2 }, + { auto: 3 }, + { auto: 4 }, + { auto: 5 }, + { auto: 6 }, + { auto: 7 }, + { auto: 8 }, + { auto: 9 }, + { auto: 10 }, + ]) + }) + }) + + describe("oneOf", () => { + it("successfully finds a row", async () => { + await expectQuery({ + oneOf: { auto: [1] }, + }).toContainExactly([{ auto: 1 }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ oneOf: { auto: [0] } }).toFindNothing() + }) + }) + + describe("range", () => { + it("successfully finds a row", async () => { + await expectQuery({ + range: { auto: { low: 1, high: 1 } }, + }).toContainExactly([{ auto: 1 }]) + }) + + it("successfully finds multiple rows", async () => { + await expectQuery({ + range: { auto: { low: 1, high: 2 } }, + }).toContainExactly([{ auto: 1 }, { auto: 2 }]) + }) + + it("successfully finds a row with a high bound", async () => { + await expectQuery({ + range: { auto: { low: 2, high: 2 } }, + }).toContainExactly([{ auto: 2 }]) + }) + + it("successfully finds no rows", async () => { + await expectQuery({ + range: { auto: { low: 0, high: 0 } }, + }).toFindNothing() + }) + + it("can search using just a low value", async () => { + await expectQuery({ + range: { auto: { low: 9 } }, + }).toContainExactly([{ auto: 9 }, { auto: 10 }]) + }) + + it("can search using just a high value", async () => { + await expectQuery({ + range: { auto: { high: 2 } }, + }).toContainExactly([{ auto: 1 }, { auto: 2 }]) + }) + }) + + describe("sort", () => { + it("sorts ascending", async () => { + await expectSearch({ + query: {}, + sort: "auto", + sortOrder: SortOrder.ASCENDING, + sortType: SortType.NUMBER, + }).toMatchExactly([ + { auto: 1 }, + { auto: 2 }, + { auto: 3 }, + { auto: 4 }, + { auto: 5 }, + { auto: 6 }, + { auto: 7 }, + { auto: 8 }, + { auto: 9 }, + { auto: 10 }, + ]) + }) + + it("sorts descending", async () => { + await expectSearch({ + query: {}, + sort: "auto", + sortOrder: SortOrder.DESCENDING, + sortType: SortType.NUMBER, + }).toMatchExactly([ + { auto: 10 }, + { auto: 9 }, + { auto: 8 }, + { auto: 7 }, + { auto: 6 }, + { auto: 5 }, + { auto: 4 }, + { auto: 3 }, + { auto: 2 }, + { auto: 1 }, + ]) + }) + + // This is important for pagination. The order of results must always + // be stable or pagination will break. We don't want the user to need + // to specify an order for pagination to work. + it("is stable without a sort specified", async () => { + let { rows: fullRowList } = await config.api.row.search( + tableOrViewId, + { + tableId: tableOrViewId, + query: {}, + } + ) + + // repeat the search many times to check the first row is always the same + let bookmark: string | number | undefined, + hasNextPage: boolean | undefined = true, + rowCount: number = 0 + do { + const response = await config.api.row.search( + tableOrViewId, + { + tableId: tableOrViewId, + limit: 1, + paginate: true, + query: {}, + bookmark, + } + ) + bookmark = response.bookmark + hasNextPage = response.hasNextPage + expect(response.rows.length).toEqual(1) + const foundRow = response.rows[0] + expect(foundRow).toEqual(fullRowList[rowCount++]) + } while (hasNextPage) + }) + }) + + describe("pagination", () => { + it("should paginate through all rows", async () => { + // @ts-ignore + let bookmark: string | number = undefined + let rows: Row[] = [] + + // eslint-disable-next-line no-constant-condition + while (true) { + const response = await config.api.row.search( + tableOrViewId, + { + tableId: tableOrViewId, + limit: 3, + query: {}, + bookmark, + paginate: true, + } + ) + + rows.push(...response.rows) + + if (!response.bookmark || !response.hasNextPage) { + break + } + bookmark = response.bookmark + } + + const autoValues = rows + .map(row => row.auto) + .sort((a, b) => a - b) + expect(autoValues).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) + }) + }) + }) + + describe("field name 1:name", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + "1:name": { name: "1:name", type: FieldType.STRING }, + }) + await createRows([{ "1:name": "bar" }, { "1:name": "foo" }]) + }) + + it("successfully finds a row", async () => { + await expectQuery({ + equal: { "1:1:name": "bar" }, + }).toContainExactly([{ "1:name": "bar" }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + equal: { "1:1:name": "none" }, + }).toFindNothing() + }) + }) + + isSql && + describe("related formulas", () => { + beforeAll(async () => { + const arrayTable = await createTable({ + name: { name: "name", type: FieldType.STRING }, + array: { + name: "array", + type: FieldType.ARRAY, + constraints: { + type: JsonFieldSubType.ARRAY, + inclusion: ["option 1", "option 2"], + }, + }, + }) + tableOrViewId = await createTableOrView({ + relationship: { + type: FieldType.LINK, + relationshipType: RelationshipType.MANY_TO_ONE, + name: "relationship", + fieldName: "relate", + tableId: arrayTable, + constraints: { + type: "array", + }, + }, + formula: { + type: FieldType.FORMULA, + name: "formula", + formula: encodeJSBinding( + `let array = [];$("relationship").forEach(rel => array = array.concat(rel.array));return array.sort().join(",")` + ), + }, + }) + const arrayRows = await Promise.all([ + config.api.row.save(arrayTable, { + name: "foo", + array: ["option 1"], + }), + config.api.row.save(arrayTable, { name: "bar", - productCat: [{ _id: productCatRows[1]._id }], - }, - { name: "baz", productCat: undefined }, + array: ["option 2"], + }), + ]) + await Promise.all([ + config.api.row.save(tableOrViewId, { + relationship: [arrayRows[0]._id, arrayRows[1]._id], + }), ]) }) - it.each([logicalOperators])( - "should allow nested ors with single conditions (with %s as root)", - async rootOperator => { - await expectQuery({ - [rootOperator]: { - conditions: [ - { - $or: { - conditions: [ - { - equal: { ["productCat.name"]: "foo" }, - }, - ], - }, - }, - ], - }, - }).toContainExactly([ - { - name: "foo", - productCat: [{ _id: productCatRows[0]._id }], - }, - ]) - } - ) + it("formula is correct with relationship arrays", async () => { + await expectQuery({}).toContain([ + { formula: "option 1,option 2" }, + ]) + }) + }) - it.each([logicalOperators])( - "should allow nested ors with exclusive conditions (with %s as root)", - async rootOperator => { - await expectQuery({ - [rootOperator]: { - conditions: [ - { - $or: { - conditions: [ - { - equal: { ["productCat.name"]: "foo" }, - notEqual: { ["productCat.name"]: "foo" }, - }, - ], - }, - }, - ], - }, - }).toContainExactly([ - { - name: "foo", - productCat: [{ _id: productCatRows[0]._id }], - }, - { - name: "bar", - productCat: [{ _id: productCatRows[1]._id }], - }, - { name: "baz", productCat: undefined }, - ]) - } - ) + describe("user", () => { + let user1: User + let user2: User - it("should allow nested ors with multiple conditions", async () => { + beforeAll(async () => { + user1 = await config.createUser({ _id: `us_${utils.newid()}` }) + user2 = await config.createUser({ _id: `us_${utils.newid()}` }) + + tableOrViewId = await createTableOrView({ + user: { + name: "user", + type: FieldType.BB_REFERENCE_SINGLE, + subtype: BBReferenceFieldSubType.USER, + }, + }) + + await createRows([ + { user: user1 }, + { user: user2 }, + { user: null }, + ]) + }) + + describe("equal", () => { + it("successfully finds a row", async () => { await expectQuery({ - $or: { - conditions: [ + equal: { user: user1._id }, + }).toContainExactly([{ user: { _id: user1._id } }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + equal: { user: "us_none" }, + }).toFindNothing() + }) + }) + + describe("notEqual", () => { + it("successfully finds a row", async () => { + await expectQuery({ + notEqual: { user: user1._id }, + }).toContainExactly([{ user: { _id: user2._id } }, {}]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + notEqual: { user: "us_none" }, + }).toContainExactly([ + { user: { _id: user1._id } }, + { user: { _id: user2._id } }, + {}, + ]) + }) + }) + + describe("oneOf", () => { + it("successfully finds a row", async () => { + await expectQuery({ + oneOf: { user: [user1._id] }, + }).toContainExactly([{ user: { _id: user1._id } }]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + oneOf: { user: ["us_none"] }, + }).toFindNothing() + }) + }) + + describe("empty", () => { + it("finds empty rows", async () => { + await expectQuery({ empty: { user: null } }).toContainExactly( + [{}] + ) + }) + }) + + describe("notEmpty", () => { + it("finds non-empty rows", async () => { + await expectQuery({ + notEmpty: { user: null }, + }).toContainExactly([ + { user: { _id: user1._id } }, + { user: { _id: user2._id } }, + ]) + }) + }) + }) + + describe("multi user", () => { + let user1: User + let user2: User + + beforeAll(async () => { + user1 = await config.createUser({ _id: `us_${utils.newid()}` }) + user2 = await config.createUser({ _id: `us_${utils.newid()}` }) + + tableOrViewId = await createTableOrView({ + users: { + name: "users", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + constraints: { type: "array" }, + }, + number: { + name: "number", + type: FieldType.NUMBER, + }, + }) + + await createRows([ + { number: 1, users: [user1] }, + { number: 2, users: [user2] }, + { number: 3, users: [user1, user2] }, + { number: 4, users: [] }, + ]) + }) + + describe("contains", () => { + it("successfully finds a row", async () => { + await expectQuery({ + contains: { users: [user1._id] }, + }).toContainExactly([ + { users: [{ _id: user1._id }] }, + { users: [{ _id: user1._id }, { _id: user2._id }] }, + ]) + }) + + it("successfully finds a row searching with a string", async () => { + await expectQuery({ + // @ts-expect-error this test specifically goes against the type to + // test that we coerce the string to an array. + contains: { "1:users": user1._id }, + }).toContainExactly([ + { users: [{ _id: user1._id }] }, + { users: [{ _id: user1._id }, { _id: user2._id }] }, + ]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + contains: { users: ["us_none"] }, + }).toFindNothing() + }) + }) + + describe("notContains", () => { + it("successfully finds a row", async () => { + await expectQuery({ + notContains: { users: [user1._id] }, + }).toContainExactly([{ users: [{ _id: user2._id }] }, {}]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + notContains: { users: ["us_none"] }, + }).toContainExactly([ + { users: [{ _id: user1._id }] }, + { users: [{ _id: user2._id }] }, + { users: [{ _id: user1._id }, { _id: user2._id }] }, + {}, + ]) + }) + }) + + describe("containsAny", () => { + it("successfully finds rows", async () => { + await expectQuery({ + containsAny: { users: [user1._id, user2._id] }, + }).toContainExactly([ + { users: [{ _id: user1._id }] }, + { users: [{ _id: user2._id }] }, + { users: [{ _id: user1._id }, { _id: user2._id }] }, + ]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + containsAny: { users: ["us_none"] }, + }).toFindNothing() + }) + }) + + describe("multi-column equals", () => { + it("successfully finds a row", async () => { + await expectQuery({ + equal: { number: 1 }, + contains: { users: [user1._id] }, + }).toContainExactly([ + { users: [{ _id: user1._id }], number: 1 }, + ]) + }) + + it("fails to find nonexistent row", async () => { + await expectQuery({ + equal: { number: 2 }, + contains: { users: [user1._id] }, + }).toFindNothing() + }) + }) + }) + + // It also can't work for in-memory searching because the related table name + // isn't available. + !isInMemory && + describe.each([ + RelationshipType.ONE_TO_MANY, + RelationshipType.MANY_TO_ONE, + RelationshipType.MANY_TO_MANY, + ])("relations (%s)", relationshipType => { + let productCategoryTable: Table, productCatRows: Row[] + + beforeAll(async () => { + const { relatedTable, tableId } = + await basicRelationshipTables(relationshipType) + tableOrViewId = tableId + productCategoryTable = relatedTable + + productCatRows = await Promise.all([ + config.api.row.save(productCategoryTable._id!, { + name: "foo", + }), + config.api.row.save(productCategoryTable._id!, { + name: "bar", + }), + ]) + + await Promise.all([ + config.api.row.save(tableOrViewId, { + name: "foo", + productCat: [productCatRows[0]._id], + }), + config.api.row.save(tableOrViewId, { + name: "bar", + productCat: [productCatRows[1]._id], + }), + config.api.row.save(tableOrViewId, { + name: "baz", + productCat: [], + }), + ]) + }) + + it("should be able to filter by relationship using column name", async () => { + await expectQuery({ + equal: { ["productCat.name"]: "foo" }, + }).toContainExactly([ + { + name: "foo", + productCat: [{ _id: productCatRows[0]._id }], + }, + ]) + }) + + it("should be able to filter by relationship using table name", async () => { + await expectQuery({ + equal: { [`${productCategoryTable.name}.name`]: "foo" }, + }).toContainExactly([ + { + name: "foo", + productCat: [{ _id: productCatRows[0]._id }], + }, + ]) + }) + + it("shouldn't return any relationship for last row", async () => { + await expectQuery({ + equal: { ["name"]: "baz" }, + }).toContainExactly([{ name: "baz", productCat: undefined }]) + }) + + describe("logical filters", () => { + const logicalOperators = [ + LogicalOperator.AND, + LogicalOperator.OR, + ] + + describe("$and", () => { + it("should allow single conditions", async () => { + await expectQuery({ + $and: { + conditions: [ + { + equal: { ["productCat.name"]: "foo" }, + }, + ], + }, + }).toContainExactly([ { - $or: { + name: "foo", + productCat: [{ _id: productCatRows[0]._id }], + }, + ]) + }) + + it("should allow exclusive conditions", async () => { + await expectQuery({ + $and: { + conditions: [ + { + equal: { ["productCat.name"]: "foo" }, + notEqual: { ["productCat.name"]: "foo" }, + }, + ], + }, + }).toContainExactly([]) + }) + + it.each([logicalOperators])( + "should allow nested ands with single conditions (with %s as root)", + async rootOperator => { + await expectQuery({ + [rootOperator]: { conditions: [ { - equal: { ["productCat.name"]: "foo" }, + $and: { + conditions: [ + { + equal: { ["productCat.name"]: "foo" }, + }, + ], + }, }, ], }, - notEqual: { ["productCat.name"]: "foo" }, + }).toContainExactly([ + { + name: "foo", + productCat: [{ _id: productCatRows[0]._id }], + }, + ]) + } + ) + + it.each([logicalOperators])( + "should allow nested ands with exclusive conditions (with %s as root)", + async rootOperator => { + await expectQuery({ + [rootOperator]: { + conditions: [ + { + $and: { + conditions: [ + { + equal: { ["productCat.name"]: "foo" }, + notEqual: { ["productCat.name"]: "foo" }, + }, + ], + }, + }, + ], + }, + }).toContainExactly([]) + } + ) + + it.each([logicalOperators])( + "should allow nested ands with multiple conditions (with %s as root)", + async rootOperator => { + await expectQuery({ + [rootOperator]: { + conditions: [ + { + $and: { + conditions: [ + { + equal: { ["productCat.name"]: "foo" }, + }, + ], + }, + notEqual: { ["productCat.name"]: "foo" }, + }, + ], + }, + }).toContainExactly([]) + } + ) + }) + + describe("$ors", () => { + it("should allow single conditions", async () => { + await expectQuery({ + $or: { + conditions: [ + { + equal: { ["productCat.name"]: "foo" }, + }, + ], }, - ], + }).toContainExactly([ + { + name: "foo", + productCat: [{ _id: productCatRows[0]._id }], + }, + ]) + }) + + it("should allow exclusive conditions", async () => { + await expectQuery({ + $or: { + conditions: [ + { + equal: { ["productCat.name"]: "foo" }, + notEqual: { ["productCat.name"]: "foo" }, + }, + ], + }, + }).toContainExactly([ + { + name: "foo", + productCat: [{ _id: productCatRows[0]._id }], + }, + { + name: "bar", + productCat: [{ _id: productCatRows[1]._id }], + }, + { name: "baz", productCat: undefined }, + ]) + }) + + it.each([logicalOperators])( + "should allow nested ors with single conditions (with %s as root)", + async rootOperator => { + await expectQuery({ + [rootOperator]: { + conditions: [ + { + $or: { + conditions: [ + { + equal: { ["productCat.name"]: "foo" }, + }, + ], + }, + }, + ], + }, + }).toContainExactly([ + { + name: "foo", + productCat: [{ _id: productCatRows[0]._id }], + }, + ]) + } + ) + + it.each([logicalOperators])( + "should allow nested ors with exclusive conditions (with %s as root)", + async rootOperator => { + await expectQuery({ + [rootOperator]: { + conditions: [ + { + $or: { + conditions: [ + { + equal: { ["productCat.name"]: "foo" }, + notEqual: { ["productCat.name"]: "foo" }, + }, + ], + }, + }, + ], + }, + }).toContainExactly([ + { + name: "foo", + productCat: [{ _id: productCatRows[0]._id }], + }, + { + name: "bar", + productCat: [{ _id: productCatRows[1]._id }], + }, + { name: "baz", productCat: undefined }, + ]) + } + ) + + it("should allow nested ors with multiple conditions", async () => { + await expectQuery({ + $or: { + conditions: [ + { + $or: { + conditions: [ + { + equal: { ["productCat.name"]: "foo" }, + }, + ], + }, + notEqual: { ["productCat.name"]: "foo" }, + }, + ], + }, + }).toContainExactly([ + { + name: "foo", + productCat: [{ _id: productCatRows[0]._id }], + }, + { + name: "bar", + productCat: [{ _id: productCatRows[1]._id }], + }, + { name: "baz", productCat: undefined }, + ]) + }) + }) + }) + }) + + isSql && + describe.each([ + RelationshipType.MANY_TO_ONE, + RelationshipType.MANY_TO_MANY, + ])("big relations (%s)", relationshipType => { + beforeAll(async () => { + const { relatedTable, tableId } = + await basicRelationshipTables(relationshipType) + tableOrViewId = tableId + const mainRow = await config.api.row.save(tableOrViewId, { + name: "foo", + }) + for (let i = 0; i < 11; i++) { + await config.api.row.save(relatedTable._id!, { + name: i, + product: [mainRow._id!], + }) + } + }) + + it("can only pull 10 related rows", async () => { + await withCoreEnv( + { SQL_MAX_RELATED_ROWS: "10" }, + async () => { + const response = await expectQuery({}).toContain([ + { name: "foo" }, + ]) + expect(response.rows[0].productCat).toBeArrayOfSize(10) + } + ) + }) + + it("can pull max rows when env not set (defaults to 500)", async () => { + const response = await expectQuery({}).toContain([ + { name: "foo" }, + ]) + expect(response.rows[0].productCat).toBeArrayOfSize(11) + }) + }) + + isSql && + describe("relations to same table", () => { + let relatedTable: string, relatedRows: Row[] + + beforeAll(async () => { + relatedTable = await createTable({ + name: { name: "name", type: FieldType.STRING }, + }) + tableOrViewId = await createTableOrView({ + name: { name: "name", type: FieldType.STRING }, + related1: { + type: FieldType.LINK, + name: "related1", + fieldName: "main1", + tableId: relatedTable, + relationshipType: RelationshipType.MANY_TO_MANY, + }, + related2: { + type: FieldType.LINK, + name: "related2", + fieldName: "main2", + tableId: relatedTable, + relationshipType: RelationshipType.MANY_TO_MANY, + }, + }) + relatedRows = await Promise.all([ + config.api.row.save(relatedTable, { name: "foo" }), + config.api.row.save(relatedTable, { name: "bar" }), + config.api.row.save(relatedTable, { name: "baz" }), + config.api.row.save(relatedTable, { name: "boo" }), + ]) + await Promise.all([ + config.api.row.save(tableOrViewId, { + name: "test", + related1: [relatedRows[0]._id!], + related2: [relatedRows[1]._id!], + }), + config.api.row.save(tableOrViewId, { + name: "test2", + related1: [relatedRows[2]._id!], + related2: [relatedRows[3]._id!], + }), + config.api.row.save(tableOrViewId, { + name: "test3", + related1: [relatedRows[1]._id], + related2: [relatedRows[2]._id!], + }), + ]) + }) + + it("should be able to relate to same table", async () => { + await expectSearch({ + query: {}, + }).toContainExactly([ + { + name: "test", + related1: [{ _id: relatedRows[0]._id }], + related2: [{ _id: relatedRows[1]._id }], + }, + { + name: "test2", + related1: [{ _id: relatedRows[2]._id }], + related2: [{ _id: relatedRows[3]._id }], + }, + { + name: "test3", + related1: [{ _id: relatedRows[1]._id }], + related2: [{ _id: relatedRows[2]._id }], + }, + ]) + }) + + it("should be able to filter via the first relation field with equal", async () => { + await expectSearch({ + query: { + equal: { + ["related1.name"]: "baz", + }, }, }).toContainExactly([ { - name: "foo", - productCat: [{ _id: productCatRows[0]._id }], + name: "test2", + related1: [{ _id: relatedRows[2]._id }], }, + ]) + }) + + it("should be able to filter via the second relation field with not equal", async () => { + await expectSearch({ + query: { + notEqual: { + ["1:related2.name"]: "foo", + ["2:related2.name"]: "baz", + ["3:related2.name"]: "boo", + }, + }, + }).toContainExactly([ { - name: "bar", - productCat: [{ _id: productCatRows[1]._id }], + name: "test", + }, + ]) + }) + + it("should be able to filter on both fields", async () => { + await expectSearch({ + query: { + notEqual: { + ["related1.name"]: "foo", + ["related2.name"]: "baz", + }, + }, + }).toContainExactly([ + { + name: "test2", }, - { name: "baz", productCat: undefined }, ]) }) }) - }) - }) - isSql && - describe.each([ - RelationshipType.MANY_TO_ONE, - RelationshipType.MANY_TO_MANY, - ])("big relations (%s)", relationshipType => { - beforeAll(async () => { - const { relatedTable, tableId } = await basicRelationshipTables( - relationshipType - ) - tableOrViewId = tableId - const mainRow = await config.api.row.save(tableOrViewId, { - name: "foo", - }) - for (let i = 0; i < 11; i++) { - await config.api.row.save(relatedTable._id!, { - name: i, - product: [mainRow._id!], - }) - } - }) - - it("can only pull 10 related rows", async () => { - await withCoreEnv({ SQL_MAX_RELATED_ROWS: "10" }, async () => { - const response = await expectQuery({}).toContain([ - { name: "foo" }, - ]) - expect(response.rows[0].productCat).toBeArrayOfSize(10) - }) - }) - - it("can pull max rows when env not set (defaults to 500)", async () => { - const response = await expectQuery({}).toContain([ - { name: "foo" }, - ]) - expect(response.rows[0].productCat).toBeArrayOfSize(11) - }) - }) - - isSql && - describe("relations to same table", () => { - let relatedTable: string, relatedRows: Row[] - - beforeAll(async () => { - relatedTable = await createTable({ - name: { name: "name", type: FieldType.STRING }, - }) - tableOrViewId = await createTableOrView({ - name: { name: "name", type: FieldType.STRING }, - related1: { - type: FieldType.LINK, - name: "related1", - fieldName: "main1", - tableId: relatedTable, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - related2: { - type: FieldType.LINK, - name: "related2", - fieldName: "main2", - tableId: relatedTable, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - }) - relatedRows = await Promise.all([ - config.api.row.save(relatedTable, { name: "foo" }), - config.api.row.save(relatedTable, { name: "bar" }), - config.api.row.save(relatedTable, { name: "baz" }), - config.api.row.save(relatedTable, { name: "boo" }), - ]) - await Promise.all([ - config.api.row.save(tableOrViewId, { - name: "test", - related1: [relatedRows[0]._id!], - related2: [relatedRows[1]._id!], - }), - config.api.row.save(tableOrViewId, { - name: "test2", - related1: [relatedRows[2]._id!], - related2: [relatedRows[3]._id!], - }), - config.api.row.save(tableOrViewId, { - name: "test3", - related1: [relatedRows[1]._id], - related2: [relatedRows[2]._id!], - }), - ]) - }) - - it("should be able to relate to same table", async () => { - await expectSearch({ - query: {}, - }).toContainExactly([ - { - name: "test", - related1: [{ _id: relatedRows[0]._id }], - related2: [{ _id: relatedRows[1]._id }], - }, - { - name: "test2", - related1: [{ _id: relatedRows[2]._id }], - related2: [{ _id: relatedRows[3]._id }], - }, - { - name: "test3", - related1: [{ _id: relatedRows[1]._id }], - related2: [{ _id: relatedRows[2]._id }], - }, - ]) - }) - - it("should be able to filter via the first relation field with equal", async () => { - await expectSearch({ - query: { - equal: { - ["related1.name"]: "baz", - }, - }, - }).toContainExactly([ - { - name: "test2", - related1: [{ _id: relatedRows[2]._id }], - }, - ]) - }) - - it("should be able to filter via the second relation field with not equal", async () => { - await expectSearch({ - query: { - notEqual: { - ["1:related2.name"]: "foo", - ["2:related2.name"]: "baz", - ["3:related2.name"]: "boo", - }, - }, - }).toContainExactly([ - { - name: "test", - }, - ]) - }) - - it("should be able to filter on both fields", async () => { - await expectSearch({ - query: { - notEqual: { - ["related1.name"]: "foo", - ["related2.name"]: "baz", - }, - }, - }).toContainExactly([ - { - name: "test2", - }, - ]) - }) - }) - - isInternal && - describe("no column error backwards compat", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - name: { - name: "name", - type: FieldType.STRING, - }, - }) - }) - - it("shouldn't error when column doesn't exist", async () => { - await expectSearch({ - query: { - string: { - "1:something": "a", - }, - }, - }).toMatch({ rows: [] }) - }) - }) - - describe("row counting", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - name: { - name: "name", - type: FieldType.STRING, - }, - }) - await createRows([{ name: "a" }, { name: "b" }]) - }) - - it("should be able to count rows when option set", async () => { - await expectSearch({ - countRows: true, - query: { - notEmpty: { - name: true, - }, - }, - }).toMatch({ totalRows: 2, rows: expect.any(Array) }) - }) - - it("shouldn't count rows when option is not set", async () => { - await expectSearch({ - countRows: false, - query: { - notEmpty: { - name: true, - }, - }, - }).toNotHaveProperty(["totalRows"]) - }) - }) - - describe("Invalid column definitions", () => { - beforeAll(async () => { - // need to create an invalid table - means ignoring typescript - tableOrViewId = await createTableOrView({ - // @ts-ignore - invalid: { - type: FieldType.STRING, - }, - name: { - name: "name", - type: FieldType.STRING, - }, - }) - await createRows([ - { name: "foo", invalid: "id1" }, - { name: "bar", invalid: "id2" }, - ]) - }) - - it("can get rows with all table data", async () => { - await expectSearch({ - query: {}, - }).toContain([ - { name: "foo", invalid: "id1" }, - { name: "bar", invalid: "id2" }, - ]) - }) - }) - - describe.each(["data_name_test", "name_data_test", "name_test_data_"])( - "special (%s) case", - column => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - [column]: { - name: column, - type: FieldType.STRING, - }, - }) - await createRows([{ [column]: "a" }, { [column]: "b" }]) - }) - - it("should be able to query a column with data_ in it", async () => { - await expectSearch({ - query: { - equal: { - [`1:${column}`]: "a", - }, - }, - }).toContainExactly([{ [column]: "a" }]) - }) - } - ) - - isInternal && - describe("sample data", () => { - beforeAll(async () => { - await config.api.application.addSampleData(config.appId!) - tableOrViewId = DEFAULT_EMPLOYEE_TABLE_SCHEMA._id! - rows = await config.api.row.fetch(tableOrViewId) - }) - - it("should be able to search sample data", async () => { - await expectSearch({ - query: {}, - }).toContain([ - { - "First Name": "Mandy", - }, - ]) - }) - }) - - describe.each([ - { low: "2024-07-03T00:00:00.000Z", high: "9999-00-00T00:00:00.000Z" }, - { low: "2024-07-03T00:00:00.000Z", high: "9998-00-00T00:00:00.000Z" }, - { low: "0000-00-00T00:00:00.000Z", high: "2024-07-04T00:00:00.000Z" }, - { low: "0001-00-00T00:00:00.000Z", high: "2024-07-04T00:00:00.000Z" }, - ])("date special cases", ({ low, high }) => { - const earlyDate = "2024-07-03T10:00:00.000Z", - laterDate = "2024-07-03T11:00:00.000Z" - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - date: { - name: "date", - type: FieldType.DATETIME, - }, - }) - await createRows([{ date: earlyDate }, { date: laterDate }]) - }) - - it("should be able to handle a date search", async () => { - await expectSearch({ - query: { - range: { - "1:date": { low, high }, - }, - }, - }).toContainExactly([{ date: earlyDate }, { date: laterDate }]) - }) - }) - - describe.each([ - "名前", // Japanese for "name" - "Benutzer-ID", // German for "user ID", includes a hyphen - "numéro", // French for "number", includes an accent - "år", // Swedish for "year", includes a ring above - "naïve", // English word borrowed from French, includes an umlaut - "الاسم", // Arabic for "name" - "оплата", // Russian for "payment" - "पता", // Hindi for "address" - "用戶名", // Chinese for "username" - "çalışma_zamanı", // Turkish for "runtime", includes an underscore and a cedilla - "preço", // Portuguese for "price", includes a cedilla - "사용자명", // Korean for "username" - "usuario_ñoño", // Spanish, uses an underscore and includes "ñ" - "файл", // Bulgarian for "file" - "δεδομένα", // Greek for "data" - "geändert_am", // German for "modified on", includes an umlaut - "ব্যবহারকারীর_নাম", // Bengali for "user name", includes an underscore - "São_Paulo", // Portuguese, includes an underscore and a tilde - "età", // Italian for "age", includes an accent - "ชื่อผู้ใช้", // Thai for "username" - ])("non-ascii column name: %s", name => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - [name]: { - name, - type: FieldType.STRING, - }, - }) - await createRows([{ [name]: "a" }, { [name]: "b" }]) - }) - - it("should be able to query a column with non-ascii characters", async () => { - await expectSearch({ - query: { - equal: { - [`1:${name}`]: "a", - }, - }, - }).toContainExactly([{ [name]: "a" }]) - }) - }) - - // This is currently not supported in external datasources, it produces SQL - // errors at time of writing. We supported it (potentially by accident) in - // Lucene, though, so we need to make sure it's supported in SQS as well. We - // found real cases in production of column names ending in a space. - isInternal && - describe("space at end of column name", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - "name ": { - name: "name ", - type: FieldType.STRING, - }, - }) - await createRows([{ ["name "]: "foo" }, { ["name "]: "bar" }]) - }) - - it("should be able to query a column that ends with a space", async () => { - await expectSearch({ - query: { - string: { - "name ": "foo", - }, - }, - }).toContainExactly([{ ["name "]: "foo" }]) - }) - - it("should be able to query a column that ends with a space using numeric notation", async () => { - await expectSearch({ - query: { - string: { - "1:name ": "foo", - }, - }, - }).toContainExactly([{ ["name "]: "foo" }]) - }) - }) - - isInternal && - describe("space at start of column name", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - " name": { - name: " name", - type: FieldType.STRING, - }, - }) - await createRows([{ [" name"]: "foo" }, { [" name"]: "bar" }]) - }) - - it("should be able to query a column that starts with a space", async () => { - await expectSearch({ - query: { - string: { - " name": "foo", - }, - }, - }).toContainExactly([{ [" name"]: "foo" }]) - }) - - it("should be able to query a column that starts with a space using numeric notation", async () => { - await expectSearch({ - query: { - string: { - "1: name": "foo", - }, - }, - }).toContainExactly([{ [" name"]: "foo" }]) - }) - }) - - isInternal && - !isView && - describe("duplicate columns", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - name: { - name: "name", - type: FieldType.STRING, - }, - }) - await context.doInAppContext(config.getAppId(), async () => { - const db = context.getAppDB() - const tableDoc = await db.get
(tableOrViewId) - tableDoc.schema.Name = { - name: "Name", - type: FieldType.STRING, - } - try { - // remove the SQLite definitions so that they can be rebuilt as part of the search - const sqliteDoc = await db.get(SQLITE_DESIGN_DOC_ID) - await db.remove(sqliteDoc) - } catch (err) { - // no-op - } - }) - await createRows([{ name: "foo", Name: "bar" }]) - }) - - it("should handle invalid duplicate column names", async () => { - await expectSearch({ - query: {}, - }).toContainExactly([{ name: "foo" }]) - }) - }) - - !isInMemory && - describe("search by _id", () => { - let row: Row - - beforeAll(async () => { - const toRelateTable = await createTable({ - name: { - name: "name", - type: FieldType.STRING, - }, - }) - tableOrViewId = await createTableOrView({ - name: { - name: "name", - type: FieldType.STRING, - }, - rel: { - name: "rel", - type: FieldType.LINK, - relationshipType: RelationshipType.MANY_TO_MANY, - tableId: toRelateTable, - fieldName: "rel", - }, - }) - const [row1, row2] = await Promise.all([ - config.api.row.save(toRelateTable, { name: "tag 1" }), - config.api.row.save(toRelateTable, { name: "tag 2" }), - ]) - row = await config.api.row.save(tableOrViewId, { - name: "product 1", - rel: [row1._id, row2._id], - }) - }) - - it("can filter by the row ID with limit 1", async () => { - await expectSearch({ - query: { - equal: { _id: row._id }, - }, - limit: 1, - }).toContainExactly([row]) - }) - }) - - !isInternal && - describe("search by composite key", () => { - beforeAll(async () => { - const table = await config.api.table.save( - tableForDatasource(datasource, { - schema: { - idColumn1: { - name: "idColumn1", - type: FieldType.NUMBER, - }, - idColumn2: { - name: "idColumn2", - type: FieldType.NUMBER, - }, - }, - primary: ["idColumn1", "idColumn2"], - }) - ) - tableOrViewId = table._id! - await createRows([{ idColumn1: 1, idColumn2: 2 }]) - }) - - it("can filter by the row ID with limit 1", async () => { - await expectSearch({ - query: { - equal: { _id: generateRowIdField([1, 2]) }, - }, - limit: 1, - }).toContain([ - { - idColumn1: 1, - idColumn2: 2, - }, - ]) - }) - }) - - isSql && - describe("primaryDisplay", () => { - beforeAll(async () => { - let toRelateTableId = await createTable({ - name: { - name: "name", - type: FieldType.STRING, - }, - }) - tableOrViewId = await createTableOrView({ - name: { - name: "name", - type: FieldType.STRING, - }, - link: { - name: "link", - type: FieldType.LINK, - relationshipType: RelationshipType.MANY_TO_ONE, - tableId: toRelateTableId, - fieldName: "link", - }, - }) - - const toRelateTable = await config.api.table.get(toRelateTableId) - await config.api.table.save({ - ...toRelateTable, - primaryDisplay: "link", - }) - const relatedRows = await Promise.all([ - config.api.row.save(toRelateTable._id!, { name: "related" }), - ]) - await config.api.row.save(tableOrViewId, { - name: "test", - link: relatedRows.map(row => row._id), - }) - }) - - it("should be able to query, primary display on related table shouldn't be used", async () => { - // this test makes sure that if a relationship has been specified as the primary display on a table - // it is ignored and another column is used instead - await expectQuery({}).toContain([ - { name: "test", link: [{ primaryDisplay: "related" }] }, - ]) - }) - }) - - describe("$and", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - age: { name: "age", type: FieldType.NUMBER }, - name: { name: "name", type: FieldType.STRING }, - }) - await createRows([ - { age: 1, name: "Jane" }, - { age: 10, name: "Jack" }, - { age: 7, name: "Hanna" }, - { age: 8, name: "Jan" }, - ]) - }) - - it("successfully finds a row for one level condition", async () => { - await expectQuery({ - $and: { - conditions: [ - { equal: { age: 10 } }, - { equal: { name: "Jack" } }, - ], - }, - }).toContainExactly([{ age: 10, name: "Jack" }]) - }) - - it("successfully finds a row for one level with multiple conditions", async () => { - await expectQuery({ - $and: { - conditions: [ - { equal: { age: 10 } }, - { equal: { name: "Jack" } }, - ], - }, - }).toContainExactly([{ age: 10, name: "Jack" }]) - }) - - it("successfully finds multiple rows for one level with multiple conditions", async () => { - await expectQuery({ - $and: { - conditions: [ - { range: { age: { low: 1, high: 9 } } }, - { string: { name: "Ja" } }, - ], - }, - }).toContainExactly([ - { age: 1, name: "Jane" }, - { age: 8, name: "Jan" }, - ]) - }) - - it("successfully finds rows for nested filters", async () => { - await expectQuery({ - $and: { - conditions: [ - { - $and: { - conditions: [ - { - range: { age: { low: 1, high: 10 } }, - }, - { string: { name: "Ja" } }, - ], - }, - equal: { name: "Jane" }, - }, - ], - }, - }).toContainExactly([{ age: 1, name: "Jane" }]) - }) - - it("returns nothing when filtering out all data", async () => { - await expectQuery({ - $and: { - conditions: [ - { equal: { age: 7 } }, - { equal: { name: "Jack" } }, - ], - }, - }).toFindNothing() - }) - - !isInMemory && - it("validates conditions that are not objects", async () => { - await expect( - expectQuery({ - $and: { - conditions: [ - { equal: { age: 10 } }, - "invalidCondition" as any, - ], - }, - }).toFindNothing() - ).rejects.toThrow( - 'Invalid body - "query.$and.conditions[1]" must be of type object' - ) - }) - - !isInMemory && - it("validates $and without conditions", async () => { - await expect( - expectQuery({ - $and: { - conditions: [ - { equal: { age: 10 } }, - { - $and: { - conditions: undefined as any, - }, - }, - ], - }, - }).toFindNothing() - ).rejects.toThrow( - 'Invalid body - "query.$and.conditions[1].$and.conditions" is required' - ) - }) - - // onEmptyFilter cannot be sent to view searches - !isView && - it("returns no rows when onEmptyFilter set to none", async () => { - await expectSearch({ - query: { - onEmptyFilter: EmptyFilterOption.RETURN_NONE, - $and: { - conditions: [{ equal: { name: "" } }], - }, - }, - }).toFindNothing() - }) - - it("returns all rows when onEmptyFilter set to all", async () => { - await expectSearch({ - query: { - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - $and: { - conditions: [{ equal: { name: "" } }], - }, - }, - }).toHaveLength(4) - }) - }) - - describe("$or", () => { - beforeAll(async () => { - tableOrViewId = await createTableOrView({ - age: { name: "age", type: FieldType.NUMBER }, - name: { name: "name", type: FieldType.STRING }, - }) - await createRows([ - { age: 1, name: "Jane" }, - { age: 10, name: "Jack" }, - { age: 7, name: "Hanna" }, - { age: 8, name: "Jan" }, - ]) - }) - - it("successfully finds a row for one level condition", async () => { - await expectQuery({ - $or: { - conditions: [ - { equal: { age: 7 } }, - { equal: { name: "Jack" } }, - ], - }, - }).toContainExactly([ - { age: 10, name: "Jack" }, - { age: 7, name: "Hanna" }, - ]) - }) - - it("successfully finds a row for one level with multiple conditions", async () => { - await expectQuery({ - $or: { - conditions: [ - { equal: { age: 7 } }, - { equal: { name: "Jack" } }, - ], - }, - }).toContainExactly([ - { age: 10, name: "Jack" }, - { age: 7, name: "Hanna" }, - ]) - }) - - it("successfully finds multiple rows for one level with multiple conditions", async () => { - await expectQuery({ - $or: { - conditions: [ - { range: { age: { low: 1, high: 9 } } }, - { string: { name: "Jan" } }, - ], - }, - }).toContainExactly([ - { age: 1, name: "Jane" }, - { age: 7, name: "Hanna" }, - { age: 8, name: "Jan" }, - ]) - }) - - it("successfully finds rows for nested filters", async () => { - await expectQuery({ - $or: { - conditions: [ - { - $or: { - conditions: [ - { - range: { age: { low: 1, high: 7 } }, - }, - { string: { name: "Jan" } }, - ], - }, - equal: { name: "Jane" }, - }, - ], - }, - }).toContainExactly([ - { age: 1, name: "Jane" }, - { age: 7, name: "Hanna" }, - { age: 8, name: "Jan" }, - ]) - }) - - it("returns nothing when filtering out all data", async () => { - await expectQuery({ - $or: { - conditions: [ - { equal: { age: 6 } }, - { equal: { name: "John" } }, - ], - }, - }).toFindNothing() - }) - - it("can nest $and under $or filters", async () => { - await expectQuery({ - $or: { - conditions: [ - { - $and: { - conditions: [ - { - range: { age: { low: 1, high: 8 } }, - }, - { equal: { name: "Jan" } }, - ], - }, - equal: { name: "Jane" }, - }, - ], - }, - }).toContainExactly([ - { age: 1, name: "Jane" }, - { age: 8, name: "Jan" }, - ]) - }) - - it("can nest $or under $and filters", async () => { - await expectQuery({ - $and: { - conditions: [ - { - $or: { - conditions: [ - { - range: { age: { low: 1, high: 8 } }, - }, - { equal: { name: "Jan" } }, - ], - }, - equal: { name: "Jane" }, - }, - ], - }, - }).toContainExactly([{ age: 1, name: "Jane" }]) - }) - - // onEmptyFilter cannot be sent to view searches - !isView && - it("returns no rows when onEmptyFilter set to none", async () => { - await expectSearch({ - query: { - onEmptyFilter: EmptyFilterOption.RETURN_NONE, - $or: { - conditions: [{ equal: { name: "" } }], - }, - }, - }).toFindNothing() - }) - - it("returns all rows when onEmptyFilter set to all", async () => { - await expectSearch({ - query: { - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - $or: { - conditions: [{ equal: { name: "" } }], - }, - }, - }).toHaveLength(4) - }) - }) - - isSql && - describe("max related columns", () => { - let relatedRows: Row[] - - beforeAll(async () => { - const relatedSchema: TableSchema = {} - const row: Row = {} - for (let i = 0; i < 100; i++) { - const name = `column${i}` - relatedSchema[name] = { name, type: FieldType.NUMBER } - row[name] = i - } - const relatedTable = await createTable(relatedSchema) - tableOrViewId = await createTableOrView({ - name: { name: "name", type: FieldType.STRING }, - related1: { - type: FieldType.LINK, - name: "related1", - fieldName: "main1", - tableId: relatedTable, - relationshipType: RelationshipType.MANY_TO_MANY, - }, - }) - relatedRows = await Promise.all([ - config.api.row.save(relatedTable, row), - ]) - await config.api.row.save(tableOrViewId, { - name: "foo", - related1: [relatedRows[0]._id], - }) - }) - - it("retrieve the row with relationships", async () => { - await expectQuery({}).toContainExactly([ - { - name: "foo", - related1: [{ _id: relatedRows[0]._id }], - }, - ]) - }) - }) - - !isInternal && - describe("SQL injection", () => { - const badStrings = [ - "1; DROP TABLE %table_name%;", - "1; DELETE FROM %table_name%;", - "1; UPDATE %table_name% SET name = 'foo';", - "1; INSERT INTO %table_name% (name) VALUES ('foo');", - "' OR '1'='1' --", - "'; DROP TABLE %table_name%; --", - "' OR 1=1 --", - "' UNION SELECT null, null, null; --", - "' AND (SELECT COUNT(*) FROM %table_name%) > 0 --", - "\"; EXEC xp_cmdshell('dir'); --", - "\"' OR 'a'='a", - "OR 1=1;", - "'; SHUTDOWN --", - ] - - describe.each(badStrings)("bad string: %s", badStringTemplate => { - // The SQL that knex generates when you try to use a double quote in a - // field name is always invalid and never works, so we skip it for these - // tests. - const skipFieldNameCheck = - isOracle && badStringTemplate.includes('"') - - !skipFieldNameCheck && - it("should not allow SQL injection as a field name", async () => { - const tableOrViewId = await createTableOrView() - const table = await getTable(tableOrViewId) - const badString = badStringTemplate.replace( - /%table_name%/g, - table.name - ) - - await config.api.table.save({ - ...table, - schema: { - ...table.schema, - [badString]: { name: badString, type: FieldType.STRING }, + isInternal && + describe("no column error backwards compat", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + name: { + name: "name", + type: FieldType.STRING, }, }) - - if (docIds.isViewId(tableOrViewId)) { - const view = await config.api.viewV2.get(tableOrViewId) - await config.api.viewV2.update({ - ...view, - schema: { - [badString]: { visible: true }, - }, - }) - } - - await config.api.row.save(tableOrViewId, { - [badString]: "foo", - }) - - await assertTableExists(table) - await assertTableNumRows(table, 1) - - const { rows } = await config.api.row.search( - tableOrViewId, - { query: {} }, - { status: 200 } - ) - - expect(rows).toHaveLength(1) - - await assertTableExists(table) - await assertTableNumRows(table, 1) }) - it("should not allow SQL injection as a field value", async () => { - const tableOrViewId = await createTableOrView({ - foo: { - name: "foo", + it("shouldn't error when column doesn't exist", async () => { + await expectSearch({ + query: { + string: { + "1:something": "a", + }, + }, + }).toMatch({ rows: [] }) + }) + }) + + describe("row counting", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + name: { + name: "name", type: FieldType.STRING, }, }) - const table = await getTable(tableOrViewId) - const badString = badStringTemplate.replace( - /%table_name%/g, - table.name - ) + await createRows([{ name: "a" }, { name: "b" }]) + }) - await config.api.row.save(tableOrViewId, { foo: "foo" }) + it("should be able to count rows when option set", async () => { + await expectSearch({ + countRows: true, + query: { + notEmpty: { + name: true, + }, + }, + }).toMatch({ totalRows: 2, rows: expect.any(Array) }) + }) - await assertTableExists(table) - await assertTableNumRows(table, 1) - - const { rows } = await config.api.row.search( - tableOrViewId, - { query: { equal: { foo: badString } } }, - { status: 200 } - ) - - expect(rows).toBeEmpty() - await assertTableExists(table) - await assertTableNumRows(table, 1) + it("shouldn't count rows when option is not set", async () => { + await expectSearch({ + countRows: false, + query: { + notEmpty: { + name: true, + }, + }, + }).toNotHaveProperty(["totalRows"]) }) }) - }) + + describe("Invalid column definitions", () => { + beforeAll(async () => { + // need to create an invalid table - means ignoring typescript + tableOrViewId = await createTableOrView({ + // @ts-ignore + invalid: { + type: FieldType.STRING, + }, + name: { + name: "name", + type: FieldType.STRING, + }, + }) + await createRows([ + { name: "foo", invalid: "id1" }, + { name: "bar", invalid: "id2" }, + ]) + }) + + it("can get rows with all table data", async () => { + await expectSearch({ + query: {}, + }).toContain([ + { name: "foo", invalid: "id1" }, + { name: "bar", invalid: "id2" }, + ]) + }) + }) + + describe.each([ + "data_name_test", + "name_data_test", + "name_test_data_", + ])("special (%s) case", column => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + [column]: { + name: column, + type: FieldType.STRING, + }, + }) + await createRows([{ [column]: "a" }, { [column]: "b" }]) + }) + + it("should be able to query a column with data_ in it", async () => { + await expectSearch({ + query: { + equal: { + [`1:${column}`]: "a", + }, + }, + }).toContainExactly([{ [column]: "a" }]) + }) + }) + + isInternal && + describe("sample data", () => { + beforeAll(async () => { + await config.api.application.addSampleData(config.appId!) + tableOrViewId = DEFAULT_EMPLOYEE_TABLE_SCHEMA._id! + rows = await config.api.row.fetch(tableOrViewId) + }) + + it("should be able to search sample data", async () => { + await expectSearch({ + query: {}, + }).toContain([ + { + "First Name": "Mandy", + }, + ]) + }) + }) + + describe.each([ + { + low: "2024-07-03T00:00:00.000Z", + high: "9999-00-00T00:00:00.000Z", + }, + { + low: "2024-07-03T00:00:00.000Z", + high: "9998-00-00T00:00:00.000Z", + }, + { + low: "0000-00-00T00:00:00.000Z", + high: "2024-07-04T00:00:00.000Z", + }, + { + low: "0001-00-00T00:00:00.000Z", + high: "2024-07-04T00:00:00.000Z", + }, + ])("date special cases", ({ low, high }) => { + const earlyDate = "2024-07-03T10:00:00.000Z", + laterDate = "2024-07-03T11:00:00.000Z" + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + date: { + name: "date", + type: FieldType.DATETIME, + }, + }) + await createRows([{ date: earlyDate }, { date: laterDate }]) + }) + + it("should be able to handle a date search", async () => { + await expectSearch({ + query: { + range: { + "1:date": { low, high }, + }, + }, + }).toContainExactly([{ date: earlyDate }, { date: laterDate }]) + }) + }) + + describe.each([ + "名前", // Japanese for "name" + "Benutzer-ID", // German for "user ID", includes a hyphen + "numéro", // French for "number", includes an accent + "år", // Swedish for "year", includes a ring above + "naïve", // English word borrowed from French, includes an umlaut + "الاسم", // Arabic for "name" + "оплата", // Russian for "payment" + "पता", // Hindi for "address" + "用戶名", // Chinese for "username" + "çalışma_zamanı", // Turkish for "runtime", includes an underscore and a cedilla + "preço", // Portuguese for "price", includes a cedilla + "사용자명", // Korean for "username" + "usuario_ñoño", // Spanish, uses an underscore and includes "ñ" + "файл", // Bulgarian for "file" + "δεδομένα", // Greek for "data" + "geändert_am", // German for "modified on", includes an umlaut + "ব্যবহারকারীর_নাম", // Bengali for "user name", includes an underscore + "São_Paulo", // Portuguese, includes an underscore and a tilde + "età", // Italian for "age", includes an accent + "ชื่อผู้ใช้", // Thai for "username" + ])("non-ascii column name: %s", name => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + [name]: { + name, + type: FieldType.STRING, + }, + }) + await createRows([{ [name]: "a" }, { [name]: "b" }]) + }) + + it("should be able to query a column with non-ascii characters", async () => { + await expectSearch({ + query: { + equal: { + [`1:${name}`]: "a", + }, + }, + }).toContainExactly([{ [name]: "a" }]) + }) + }) + + // This is currently not supported in external datasources, it produces SQL + // errors at time of writing. We supported it (potentially by accident) in + // Lucene, though, so we need to make sure it's supported in SQS as well. We + // found real cases in production of column names ending in a space. + isInternal && + describe("space at end of column name", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + "name ": { + name: "name ", + type: FieldType.STRING, + }, + }) + await createRows([{ ["name "]: "foo" }, { ["name "]: "bar" }]) + }) + + it("should be able to query a column that ends with a space", async () => { + await expectSearch({ + query: { + string: { + "name ": "foo", + }, + }, + }).toContainExactly([{ ["name "]: "foo" }]) + }) + + it("should be able to query a column that ends with a space using numeric notation", async () => { + await expectSearch({ + query: { + string: { + "1:name ": "foo", + }, + }, + }).toContainExactly([{ ["name "]: "foo" }]) + }) + }) + + isInternal && + describe("space at start of column name", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + " name": { + name: " name", + type: FieldType.STRING, + }, + }) + await createRows([{ [" name"]: "foo" }, { [" name"]: "bar" }]) + }) + + it("should be able to query a column that starts with a space", async () => { + await expectSearch({ + query: { + string: { + " name": "foo", + }, + }, + }).toContainExactly([{ [" name"]: "foo" }]) + }) + + it("should be able to query a column that starts with a space using numeric notation", async () => { + await expectSearch({ + query: { + string: { + "1: name": "foo", + }, + }, + }).toContainExactly([{ [" name"]: "foo" }]) + }) + }) + + isInternal && + !isView && + describe("duplicate columns", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + name: { + name: "name", + type: FieldType.STRING, + }, + }) + await context.doInAppContext(config.getAppId(), async () => { + const db = context.getAppDB() + const tableDoc = await db.get
(tableOrViewId) + tableDoc.schema.Name = { + name: "Name", + type: FieldType.STRING, + } + try { + // remove the SQLite definitions so that they can be rebuilt as part of the search + const sqliteDoc = await db.get(SQLITE_DESIGN_DOC_ID) + await db.remove(sqliteDoc) + } catch (err) { + // no-op + } + }) + await createRows([{ name: "foo", Name: "bar" }]) + }) + + it("should handle invalid duplicate column names", async () => { + await expectSearch({ + query: {}, + }).toContainExactly([{ name: "foo" }]) + }) + }) + + !isInMemory && + describe("search by _id", () => { + let row: Row + + beforeAll(async () => { + const toRelateTable = await createTable({ + name: { + name: "name", + type: FieldType.STRING, + }, + }) + tableOrViewId = await createTableOrView({ + name: { + name: "name", + type: FieldType.STRING, + }, + rel: { + name: "rel", + type: FieldType.LINK, + relationshipType: RelationshipType.MANY_TO_MANY, + tableId: toRelateTable, + fieldName: "rel", + }, + }) + const [row1, row2] = await Promise.all([ + config.api.row.save(toRelateTable, { name: "tag 1" }), + config.api.row.save(toRelateTable, { name: "tag 2" }), + ]) + row = await config.api.row.save(tableOrViewId, { + name: "product 1", + rel: [row1._id, row2._id], + }) + }) + + it("can filter by the row ID with limit 1", async () => { + await expectSearch({ + query: { + equal: { _id: row._id }, + }, + limit: 1, + }).toContainExactly([row]) + }) + }) + + !isInternal && + describe("search by composite key", () => { + beforeAll(async () => { + const table = await config.api.table.save( + tableForDatasource(datasource, { + schema: { + idColumn1: { + name: "idColumn1", + type: FieldType.NUMBER, + }, + idColumn2: { + name: "idColumn2", + type: FieldType.NUMBER, + }, + }, + primary: ["idColumn1", "idColumn2"], + }) + ) + tableOrViewId = table._id! + await createRows([{ idColumn1: 1, idColumn2: 2 }]) + }) + + it("can filter by the row ID with limit 1", async () => { + await expectSearch({ + query: { + equal: { _id: generateRowIdField([1, 2]) }, + }, + limit: 1, + }).toContain([ + { + idColumn1: 1, + idColumn2: 2, + }, + ]) + }) + }) + + isSql && + describe("primaryDisplay", () => { + beforeAll(async () => { + let toRelateTableId = await createTable({ + name: { + name: "name", + type: FieldType.STRING, + }, + }) + tableOrViewId = await createTableOrView({ + name: { + name: "name", + type: FieldType.STRING, + }, + link: { + name: "link", + type: FieldType.LINK, + relationshipType: RelationshipType.MANY_TO_ONE, + tableId: toRelateTableId, + fieldName: "link", + }, + }) + + const toRelateTable = await config.api.table.get( + toRelateTableId + ) + await config.api.table.save({ + ...toRelateTable, + primaryDisplay: "link", + }) + const relatedRows = await Promise.all([ + config.api.row.save(toRelateTable._id!, { + name: "related", + }), + ]) + await config.api.row.save(tableOrViewId, { + name: "test", + link: relatedRows.map(row => row._id), + }) + }) + + it("should be able to query, primary display on related table shouldn't be used", async () => { + // this test makes sure that if a relationship has been specified as the primary display on a table + // it is ignored and another column is used instead + await expectQuery({}).toContain([ + { name: "test", link: [{ primaryDisplay: "related" }] }, + ]) + }) + }) + + describe("$and", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + age: { name: "age", type: FieldType.NUMBER }, + name: { name: "name", type: FieldType.STRING }, + }) + await createRows([ + { age: 1, name: "Jane" }, + { age: 10, name: "Jack" }, + { age: 7, name: "Hanna" }, + { age: 8, name: "Jan" }, + ]) + }) + + it("successfully finds a row for one level condition", async () => { + await expectQuery({ + $and: { + conditions: [ + { equal: { age: 10 } }, + { equal: { name: "Jack" } }, + ], + }, + }).toContainExactly([{ age: 10, name: "Jack" }]) + }) + + it("successfully finds a row for one level with multiple conditions", async () => { + await expectQuery({ + $and: { + conditions: [ + { equal: { age: 10 } }, + { equal: { name: "Jack" } }, + ], + }, + }).toContainExactly([{ age: 10, name: "Jack" }]) + }) + + it("successfully finds multiple rows for one level with multiple conditions", async () => { + await expectQuery({ + $and: { + conditions: [ + { range: { age: { low: 1, high: 9 } } }, + { string: { name: "Ja" } }, + ], + }, + }).toContainExactly([ + { age: 1, name: "Jane" }, + { age: 8, name: "Jan" }, + ]) + }) + + it("successfully finds rows for nested filters", async () => { + await expectQuery({ + $and: { + conditions: [ + { + $and: { + conditions: [ + { + range: { age: { low: 1, high: 10 } }, + }, + { string: { name: "Ja" } }, + ], + }, + equal: { name: "Jane" }, + }, + ], + }, + }).toContainExactly([{ age: 1, name: "Jane" }]) + }) + + it("returns nothing when filtering out all data", async () => { + await expectQuery({ + $and: { + conditions: [ + { equal: { age: 7 } }, + { equal: { name: "Jack" } }, + ], + }, + }).toFindNothing() + }) + + !isInMemory && + it("validates conditions that are not objects", async () => { + await expect( + expectQuery({ + $and: { + conditions: [ + { equal: { age: 10 } }, + "invalidCondition" as any, + ], + }, + }).toFindNothing() + ).rejects.toThrow( + 'Invalid body - "query.$and.conditions[1]" must be of type object' + ) + }) + + !isInMemory && + it("validates $and without conditions", async () => { + await expect( + expectQuery({ + $and: { + conditions: [ + { equal: { age: 10 } }, + { + $and: { + conditions: undefined as any, + }, + }, + ], + }, + }).toFindNothing() + ).rejects.toThrow( + 'Invalid body - "query.$and.conditions[1].$and.conditions" is required' + ) + }) + + // onEmptyFilter cannot be sent to view searches + !isView && + it("returns no rows when onEmptyFilter set to none", async () => { + await expectSearch({ + query: { + onEmptyFilter: EmptyFilterOption.RETURN_NONE, + $and: { + conditions: [{ equal: { name: "" } }], + }, + }, + }).toFindNothing() + }) + + it("returns all rows when onEmptyFilter set to all", async () => { + await expectSearch({ + query: { + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + $and: { + conditions: [{ equal: { name: "" } }], + }, + }, + }).toHaveLength(4) + }) + }) + + describe("$or", () => { + beforeAll(async () => { + tableOrViewId = await createTableOrView({ + age: { name: "age", type: FieldType.NUMBER }, + name: { name: "name", type: FieldType.STRING }, + }) + await createRows([ + { age: 1, name: "Jane" }, + { age: 10, name: "Jack" }, + { age: 7, name: "Hanna" }, + { age: 8, name: "Jan" }, + ]) + }) + + it("successfully finds a row for one level condition", async () => { + await expectQuery({ + $or: { + conditions: [ + { equal: { age: 7 } }, + { equal: { name: "Jack" } }, + ], + }, + }).toContainExactly([ + { age: 10, name: "Jack" }, + { age: 7, name: "Hanna" }, + ]) + }) + + it("successfully finds a row for one level with multiple conditions", async () => { + await expectQuery({ + $or: { + conditions: [ + { equal: { age: 7 } }, + { equal: { name: "Jack" } }, + ], + }, + }).toContainExactly([ + { age: 10, name: "Jack" }, + { age: 7, name: "Hanna" }, + ]) + }) + + it("successfully finds multiple rows for one level with multiple conditions", async () => { + await expectQuery({ + $or: { + conditions: [ + { range: { age: { low: 1, high: 9 } } }, + { string: { name: "Jan" } }, + ], + }, + }).toContainExactly([ + { age: 1, name: "Jane" }, + { age: 7, name: "Hanna" }, + { age: 8, name: "Jan" }, + ]) + }) + + it("successfully finds rows for nested filters", async () => { + await expectQuery({ + $or: { + conditions: [ + { + $or: { + conditions: [ + { + range: { age: { low: 1, high: 7 } }, + }, + { string: { name: "Jan" } }, + ], + }, + equal: { name: "Jane" }, + }, + ], + }, + }).toContainExactly([ + { age: 1, name: "Jane" }, + { age: 7, name: "Hanna" }, + { age: 8, name: "Jan" }, + ]) + }) + + it("returns nothing when filtering out all data", async () => { + await expectQuery({ + $or: { + conditions: [ + { equal: { age: 6 } }, + { equal: { name: "John" } }, + ], + }, + }).toFindNothing() + }) + + it("can nest $and under $or filters", async () => { + await expectQuery({ + $or: { + conditions: [ + { + $and: { + conditions: [ + { + range: { age: { low: 1, high: 8 } }, + }, + { equal: { name: "Jan" } }, + ], + }, + equal: { name: "Jane" }, + }, + ], + }, + }).toContainExactly([ + { age: 1, name: "Jane" }, + { age: 8, name: "Jan" }, + ]) + }) + + it("can nest $or under $and filters", async () => { + await expectQuery({ + $and: { + conditions: [ + { + $or: { + conditions: [ + { + range: { age: { low: 1, high: 8 } }, + }, + { equal: { name: "Jan" } }, + ], + }, + equal: { name: "Jane" }, + }, + ], + }, + }).toContainExactly([{ age: 1, name: "Jane" }]) + }) + + // onEmptyFilter cannot be sent to view searches + !isView && + it("returns no rows when onEmptyFilter set to none", async () => { + await expectSearch({ + query: { + onEmptyFilter: EmptyFilterOption.RETURN_NONE, + $or: { + conditions: [{ equal: { name: "" } }], + }, + }, + }).toFindNothing() + }) + + it("returns all rows when onEmptyFilter set to all", async () => { + await expectSearch({ + query: { + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + $or: { + conditions: [{ equal: { name: "" } }], + }, + }, + }).toHaveLength(4) + }) + }) + + isSql && + describe("max related columns", () => { + let relatedRows: Row[] + + beforeAll(async () => { + const relatedSchema: TableSchema = {} + const row: Row = {} + for (let i = 0; i < 100; i++) { + const name = `column${i}` + relatedSchema[name] = { name, type: FieldType.NUMBER } + row[name] = i + } + const relatedTable = await createTable(relatedSchema) + tableOrViewId = await createTableOrView({ + name: { name: "name", type: FieldType.STRING }, + related1: { + type: FieldType.LINK, + name: "related1", + fieldName: "main1", + tableId: relatedTable, + relationshipType: RelationshipType.MANY_TO_MANY, + }, + }) + relatedRows = await Promise.all([ + config.api.row.save(relatedTable, row), + ]) + await config.api.row.save(tableOrViewId, { + name: "foo", + related1: [relatedRows[0]._id], + }) + }) + + it("retrieve the row with relationships", async () => { + await expectQuery({}).toContainExactly([ + { + name: "foo", + related1: [{ _id: relatedRows[0]._id }], + }, + ]) + }) + }) + + !isInternal && + describe("SQL injection", () => { + const badStrings = [ + "1; DROP TABLE %table_name%;", + "1; DELETE FROM %table_name%;", + "1; UPDATE %table_name% SET name = 'foo';", + "1; INSERT INTO %table_name% (name) VALUES ('foo');", + "' OR '1'='1' --", + "'; DROP TABLE %table_name%; --", + "' OR 1=1 --", + "' UNION SELECT null, null, null; --", + "' AND (SELECT COUNT(*) FROM %table_name%) > 0 --", + "\"; EXEC xp_cmdshell('dir'); --", + "\"' OR 'a'='a", + "OR 1=1;", + "'; SHUTDOWN --", + ] + + describe.each(badStrings)( + "bad string: %s", + badStringTemplate => { + // The SQL that knex generates when you try to use a double quote in a + // field name is always invalid and never works, so we skip it for these + // tests. + const skipFieldNameCheck = + isOracle && badStringTemplate.includes('"') + + !skipFieldNameCheck && + it("should not allow SQL injection as a field name", async () => { + const tableOrViewId = await createTableOrView() + const table = await getTable(tableOrViewId) + const badString = badStringTemplate.replace( + /%table_name%/g, + table.name + ) + + await config.api.table.save({ + ...table, + schema: { + ...table.schema, + [badString]: { + name: badString, + type: FieldType.STRING, + }, + }, + }) + + if (docIds.isViewId(tableOrViewId)) { + const view = await config.api.viewV2.get( + tableOrViewId + ) + await config.api.viewV2.update({ + ...view, + schema: { + [badString]: { visible: true }, + }, + }) + } + + await config.api.row.save(tableOrViewId, { + [badString]: "foo", + }) + + await assertTableExists(table) + await assertTableNumRows(table, 1) + + const { rows } = await config.api.row.search( + tableOrViewId, + { query: {} }, + { status: 200 } + ) + + expect(rows).toHaveLength(1) + + await assertTableExists(table) + await assertTableNumRows(table, 1) + }) + + it("should not allow SQL injection as a field value", async () => { + const tableOrViewId = await createTableOrView({ + foo: { + name: "foo", + type: FieldType.STRING, + }, + }) + const table = await getTable(tableOrViewId) + const badString = badStringTemplate.replace( + /%table_name%/g, + table.name + ) + + await config.api.row.save(tableOrViewId, { foo: "foo" }) + + await assertTableExists(table) + await assertTableNumRows(table, 1) + + const { rows } = await config.api.row.search( + tableOrViewId, + { query: { equal: { foo: badString } } }, + { status: 200 } + ) + + expect(rows).toBeEmpty() + await assertTableExists(table) + await assertTableNumRows(table, 1) + }) + } + ) + }) + } + ) }) - }) - } -) + } + ) +} diff --git a/packages/server/src/api/routes/tests/table.spec.ts b/packages/server/src/api/routes/tests/table.spec.ts index b9d8696714..8556a598c6 100644 --- a/packages/server/src/api/routes/tests/table.spec.ts +++ b/packages/server/src/api/routes/tests/table.spec.ts @@ -38,203 +38,758 @@ import timekeeper from "timekeeper" const { basicTable } = setup.structures const ISO_REGEX_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/ -datasourceDescribe( - { name: "/tables (%s)", exclude: [DatabaseName.MONGODB] }, - ({ config, dsProvider, isInternal, isOracle }) => { - let datasource: Datasource | undefined +const descriptions = datasourceDescribe({ exclude: [DatabaseName.MONGODB] }) - beforeAll(async () => { - const ds = await dsProvider() - datasource = ds.datasource - }) +if (descriptions.length) { + describe.each(descriptions)( + "/tables ($dbName)", + ({ config, dsProvider, isInternal, isOracle }) => { + let datasource: Datasource | undefined - describe("create", () => { - beforeEach(() => { - jest.clearAllMocks() + beforeAll(async () => { + const ds = await dsProvider() + datasource = ds.datasource }) - let names = [ - "alphanum", - "with spaces", - "with-dashes", - "with_underscores", - "with `backticks`", - ] - - if (!isOracle) { - names.push(`with "double quotes"`) - names.push(`with 'single quotes'`) - } - - it.each(names)("creates a table with name: %s", async name => { - const table = await config.api.table.save( - tableForDatasource(datasource, { name }) - ) - expect(table.name).toEqual(name) - expect(events.table.created).toHaveBeenCalledTimes(1) - expect(events.table.created).toHaveBeenCalledWith(table) - - const res = await config.api.table.get(table._id!) - expect(res.name).toEqual(name) - }) - - it("creates a table via data import", async () => { - const table: SaveTableRequest = basicTable() - table.rows = [{ name: "test-name", description: "test-desc" }] - - const res = await config.api.table.save(table) - - expect(events.table.created).toHaveBeenCalledTimes(1) - expect(events.table.created).toHaveBeenCalledWith(res) - expect(events.table.imported).toHaveBeenCalledTimes(1) - expect(events.table.imported).toHaveBeenCalledWith(res) - expect(events.rows.imported).toHaveBeenCalledTimes(1) - expect(events.rows.imported).toHaveBeenCalledWith(res, 1) - }) - - it("should not allow a column to have a default value and be required", async () => { - await config.api.table.save( - tableForDatasource(datasource, { - schema: { - name: { - name: "name", - type: FieldType.STRING, - default: "default", - constraints: { - presence: true, - }, - }, - }, - }), - { - status: 400, - body: { - message: - 'Cannot make field "name" required, it has a default value.', - }, - } - ) - }) - - it("should apply authorization to endpoint", async () => { - await checkBuilderEndpoint({ - config, - method: "POST", - url: `/api/tables`, - body: basicTable(), + describe("create", () => { + beforeEach(() => { + jest.clearAllMocks() }) - }) - it("does not persist the row fields that are not on the table schema", async () => { - const table: SaveTableRequest = basicTable() - table.rows = [ - { - name: "test-name", - description: "test-desc", - nonValid: "test-non-valid", - }, + let names = [ + "alphanum", + "with spaces", + "with-dashes", + "with_underscores", + "with `backticks`", ] - const res = await config.api.table.save(table) + if (!isOracle) { + names.push(`with "double quotes"`) + names.push(`with 'single quotes'`) + } - const persistedRows = await config.api.row.search(res._id!) + it.each(names)("creates a table with name: %s", async name => { + const table = await config.api.table.save( + tableForDatasource(datasource, { name }) + ) + expect(table.name).toEqual(name) + expect(events.table.created).toHaveBeenCalledTimes(1) + expect(events.table.created).toHaveBeenCalledWith(table) - expect(persistedRows.rows).toEqual([ - expect.objectContaining({ - name: "test-name", - description: "test-desc", - }), - ]) - expect(persistedRows.rows[0].nonValid).toBeUndefined() - }) + const res = await config.api.table.get(table._id!) + expect(res.name).toEqual(name) + }) - it.each( - isInternal ? PROTECTED_INTERNAL_COLUMNS : PROTECTED_EXTERNAL_COLUMNS - )( - "cannot use protected column names (%s) while importing a table", - async columnName => { + it("creates a table via data import", async () => { + const table: SaveTableRequest = basicTable() + table.rows = [{ name: "test-name", description: "test-desc" }] + + const res = await config.api.table.save(table) + + expect(events.table.created).toHaveBeenCalledTimes(1) + expect(events.table.created).toHaveBeenCalledWith(res) + expect(events.table.imported).toHaveBeenCalledTimes(1) + expect(events.table.imported).toHaveBeenCalledWith(res) + expect(events.rows.imported).toHaveBeenCalledTimes(1) + expect(events.rows.imported).toHaveBeenCalledWith(res, 1) + }) + + it("should not allow a column to have a default value and be required", async () => { + await config.api.table.save( + tableForDatasource(datasource, { + schema: { + name: { + name: "name", + type: FieldType.STRING, + default: "default", + constraints: { + presence: true, + }, + }, + }, + }), + { + status: 400, + body: { + message: + 'Cannot make field "name" required, it has a default value.', + }, + } + ) + }) + + it("should apply authorization to endpoint", async () => { + await checkBuilderEndpoint({ + config, + method: "POST", + url: `/api/tables`, + body: basicTable(), + }) + }) + + it("does not persist the row fields that are not on the table schema", async () => { const table: SaveTableRequest = basicTable() table.rows = [ { name: "test-name", description: "test-desc", + nonValid: "test-non-valid", }, ] - await config.api.table.save( - { - ...table, - schema: { - ...table.schema, - [columnName]: { - name: columnName, - type: FieldType.STRING, + const res = await config.api.table.save(table) + + const persistedRows = await config.api.row.search(res._id!) + + expect(persistedRows.rows).toEqual([ + expect.objectContaining({ + name: "test-name", + description: "test-desc", + }), + ]) + expect(persistedRows.rows[0].nonValid).toBeUndefined() + }) + + it.each( + isInternal ? PROTECTED_INTERNAL_COLUMNS : PROTECTED_EXTERNAL_COLUMNS + )( + "cannot use protected column names (%s) while importing a table", + async columnName => { + const table: SaveTableRequest = basicTable() + table.rows = [ + { + name: "test-name", + description: "test-desc", + }, + ] + + await config.api.table.save( + { + ...table, + schema: { + ...table.schema, + [columnName]: { + name: columnName, + type: FieldType.STRING, + }, }, }, - }, - { - status: 400, - body: { - message: `Column(s) "${columnName}" are duplicated - check for other columns with these name (case in-sensitive)`, + { status: 400, - }, - } - ) - } - ) - }) - - describe("permissions", () => { - it("get the base permissions for the table", async () => { - const table = await config.api.table.save( - tableForDatasource(datasource, { - schema: { - name: { - type: FieldType.STRING, - name: "name", - }, - }, - }) + body: { + message: `Column(s) "${columnName}" are duplicated - check for other columns with these name (case in-sensitive)`, + status: 400, + }, + } + ) + } ) + }) - // get the explicit permissions - const { permissions } = await config.api.permission.get(table._id!, { - status: 200, - }) - const explicitPermissions = { - role: "ADMIN", - permissionType: "EXPLICIT", - } - expect(permissions.write).toEqual(explicitPermissions) - expect(permissions.read).toEqual(explicitPermissions) - - // revoke the explicit permissions - for (let level of [PermissionLevel.WRITE, PermissionLevel.READ]) { - await config.api.permission.revoke( - { - roleId: permissions[level].role, - resourceId: table._id!, - level, - }, - { status: 200 } + describe("permissions", () => { + it("get the base permissions for the table", async () => { + const table = await config.api.table.save( + tableForDatasource(datasource, { + schema: { + name: { + type: FieldType.STRING, + name: "name", + }, + }, + }) ) - } - // check base permissions - const { permissions: basePermissions } = - await config.api.permission.get(table._id!, { + // get the explicit permissions + const { permissions } = await config.api.permission.get(table._id!, { status: 200, }) - const basePerms = { role: "BASIC", permissionType: "BASE" } - expect(basePermissions.write).toEqual(basePerms) - expect(basePermissions.read).toEqual(basePerms) - }) - }) + const explicitPermissions = { + role: "ADMIN", + permissionType: "EXPLICIT", + } + expect(permissions.write).toEqual(explicitPermissions) + expect(permissions.read).toEqual(explicitPermissions) - describe("update", () => { - it("updates a table", async () => { - const table = await config.api.table.save( - tableForDatasource(datasource, { + // revoke the explicit permissions + for (let level of [PermissionLevel.WRITE, PermissionLevel.READ]) { + await config.api.permission.revoke( + { + roleId: permissions[level].role, + resourceId: table._id!, + level, + }, + { status: 200 } + ) + } + + // check base permissions + const { permissions: basePermissions } = + await config.api.permission.get(table._id!, { + status: 200, + }) + const basePerms = { role: "BASIC", permissionType: "BASE" } + expect(basePermissions.write).toEqual(basePerms) + expect(basePermissions.read).toEqual(basePerms) + }) + }) + + describe("update", () => { + it("updates a table", async () => { + const table = await config.api.table.save( + tableForDatasource(datasource, { + schema: { + name: { + type: FieldType.STRING, + name: "name", + constraints: { + type: "string", + }, + }, + }, + }) + ) + + const updatedTable = await config.api.table.save({ + ...table, + name: generator.guid(), + }) + + expect(events.table.updated).toHaveBeenCalledTimes(1) + expect(events.table.updated).toHaveBeenCalledWith(updatedTable) + }) + + it("updates all the row fields for a table when a schema key is renamed", async () => { + const testTable = await config.api.table.save(basicTable(datasource)) + await config.createLegacyView({ + name: "TestView", + field: "Price", + calculation: ViewCalculation.STATISTICS, + tableId: testTable._id!, + schema: {}, + filters: [], + }) + + const testRow = await config.api.row.save(testTable._id!, { + name: "test", + }) + + const { name, ...otherColumns } = testTable.schema + const updatedTable = await config.api.table.save({ + ...testTable, + _rename: { + old: "name", + updated: "updatedName", + }, + schema: { + ...otherColumns, + updatedName: { + ...name, + name: "updatedName", + }, + }, + }) + + expect(updatedTable.name).toEqual(testTable.name) + + const res = await config.api.row.get(testTable._id!, testRow._id!) + expect(res.updatedName).toEqual("test") + expect(res.name).toBeUndefined() + }) + + isInternal && + it("updates only the passed fields", async () => { + await timekeeper.withFreeze(new Date(2021, 1, 1), async () => { + const table = await config.api.table.save( + tableForDatasource(datasource, { + schema: { + autoId: { + name: "id", + type: FieldType.NUMBER, + subtype: AutoFieldSubType.AUTO_ID, + autocolumn: true, + constraints: { + type: "number", + presence: false, + }, + }, + }, + }) + ) + + const newName = generator.guid() + + const updatedTable = await config.api.table.save({ + ...table, + name: newName, + }) + + let expected: Table = { + ...table, + name: newName, + _id: expect.any(String), + } + if (isInternal) { + expected._rev = expect.stringMatching(/^2-.+/) + } + + expect(updatedTable).toEqual(expect.objectContaining(expected)) + + const persistedTable = await config.api.table.get( + updatedTable._id! + ) + expected = { + ...table, + name: newName, + _id: updatedTable._id, + } + if (datasource?.isSQL) { + expected.sql = true + } + if (isInternal) { + expected._rev = expect.stringMatching(/^2-.+/) + } + expect(persistedTable).toEqual(expect.objectContaining(expected)) + }) + }) + + describe("user table", () => { + isInternal && + it("should add roleId and email field when adjusting user table schema", async () => { + const table = await config.api.table.save({ + ...basicTable(datasource), + _id: "ta_users", + }) + expect(table.schema.email).toBeDefined() + expect(table.schema.roleId).toBeDefined() + }) + }) + + describe("default field validation", () => { + it("should error if an existing column is set to required and has a default value", async () => { + const table = await config.api.table.save( + tableForDatasource(datasource, { + schema: { + name: { + name: "name", + type: FieldType.STRING, + default: "default", + }, + }, + }) + ) + + await config.api.table.save( + { + ...table, + schema: { + ...table.schema, + name: { + name: "name", + type: FieldType.STRING, + default: "default", + constraints: { + presence: true, + }, + }, + }, + }, + { + status: 400, + body: { + message: + 'Cannot make field "name" required, it has a default value.', + }, + } + ) + }) + + it("should error if an existing column is given a default value and is required", async () => { + const table = await config.api.table.save( + tableForDatasource(datasource, { + schema: { + name: { + name: "name", + type: FieldType.STRING, + constraints: { + presence: true, + }, + }, + }, + }) + ) + + await config.api.table.save( + { + ...table, + schema: { + ...table.schema, + name: { + name: "name", + type: FieldType.STRING, + default: "default", + constraints: { + presence: true, + }, + }, + }, + }, + { + status: 400, + body: { + message: + 'Cannot make field "name" required, it has a default value.', + }, + } + ) + }) + + it("should be able to set an existing column to have a default value if it's not required", async () => { + const table = await config.api.table.save( + tableForDatasource(datasource, { + schema: { + name: { + name: "name", + type: FieldType.STRING, + }, + }, + }) + ) + + await config.api.table.save( + { + ...table, + schema: { + ...table.schema, + name: { + name: "name", + type: FieldType.STRING, + default: "default", + }, + }, + }, + { status: 200 } + ) + }) + + it("should be able to remove a default value if the column is not required", async () => { + const table = await config.api.table.save( + tableForDatasource(datasource, { + schema: { + name: { + name: "name", + type: FieldType.STRING, + default: "default", + }, + }, + }) + ) + + await config.api.table.save( + { + ...table, + schema: { + ...table.schema, + name: { + name: "name", + type: FieldType.STRING, + }, + }, + }, + { status: 200 } + ) + }) + }) + + describe("external table validation", () => { + !isInternal && + it("should error if column is of type auto", async () => { + const table = basicTable(datasource) + await config.api.table.save( + { + ...table, + schema: { + ...table.schema, + auto: { + name: "auto", + autocolumn: true, + type: FieldType.AUTO, + subtype: AutoFieldSubType.AUTO_ID, + }, + }, + }, + { + status: 400, + body: { + message: `Column "auto" has type "${FieldType.AUTO}" - this is not supported.`, + }, + } + ) + }) + + !isInternal && + it("should error if column has auto subtype", async () => { + const table = basicTable(datasource) + await config.api.table.save( + { + ...table, + schema: { + ...table.schema, + auto: { + name: "auto", + autocolumn: true, + type: FieldType.NUMBER, + subtype: AutoFieldSubType.AUTO_ID, + }, + }, + }, + { + status: 400, + body: { + message: `Column "auto" has subtype "${AutoFieldSubType.AUTO_ID}" - this is not supported.`, + }, + } + ) + }) + }) + + isInternal && + it("shouldn't allow duplicate column names", async () => { + const saveTableRequest: SaveTableRequest = { + ...basicTable(), + } + saveTableRequest.schema["Type"] = { + type: FieldType.STRING, + name: "Type", + } + // allow the "Type" column - internal columns aren't case sensitive + await config.api.table.save(saveTableRequest, { + status: 200, + }) + saveTableRequest.schema.foo = { + type: FieldType.STRING, + name: "foo", + } + saveTableRequest.schema.FOO = { + type: FieldType.STRING, + name: "FOO", + } + + await config.api.table.save(saveTableRequest, { + status: 400, + body: { + message: + 'Column(s) "foo" are duplicated - check for other columns with these name (case in-sensitive)', + }, + }) + }) + + it("should add a new column for an internal DB table", async () => { + const saveTableRequest: SaveTableRequest = { + ...basicTable(), + } + + const response = await config.api.table.save(saveTableRequest) + + const expectedResponse = { + ...saveTableRequest, + _rev: expect.stringMatching(/^\d-.+/), + _id: expect.stringMatching(/^ta_.+/), + createdAt: expect.stringMatching(ISO_REGEX_PATTERN), + updatedAt: expect.stringMatching(ISO_REGEX_PATTERN), + views: {}, + } + expect(response).toEqual(expectedResponse) + }) + }) + + describe("import", () => { + it("imports rows successfully", async () => { + const name = generator.guid() + const table = await config.api.table.save( + basicTable(datasource, { name }) + ) + const importRequest = { + schema: table.schema, + rows: [{ name: "test-name", description: "test-desc" }], + } + + jest.clearAllMocks() + + await config.api.table.import(table._id!, importRequest) + + expect(events.table.created).not.toHaveBeenCalled() + expect(events.rows.imported).toHaveBeenCalledTimes(1) + expect(events.rows.imported).toHaveBeenCalledWith( + expect.objectContaining({ + name, + _id: table._id, + }), + 1 + ) + }) + }) + + describe("fetch", () => { + let testTable: Table + + beforeEach(async () => { + testTable = await config.api.table.save( + basicTable(datasource, { name: generator.guid() }) + ) + }) + + it("returns all tables", async () => { + const res = await config.api.table.fetch() + const table = res.find(t => t._id === testTable._id) + expect(table).toBeDefined() + expect(table!.name).toEqual(testTable.name) + expect(table!.type).toEqual("table") + expect(table!.sourceType).toEqual(testTable.sourceType) + }) + + it("should apply authorization to endpoint", async () => { + await checkBuilderEndpoint({ + config, + method: "GET", + url: `/api/tables`, + }) + }) + + it("should enrich the view schemas", async () => { + const viewV2 = await config.api.viewV2.create({ + tableId: testTable._id!, + name: generator.guid(), + }) + const legacyView = await config.api.legacyView.save({ + tableId: testTable._id!, + name: generator.guid(), + filters: [], + schema: {}, + }) + + const res = await config.api.table.fetch() + + const table = res.find(t => t._id === testTable._id) + expect(table).toBeDefined() + expect(table!.views![viewV2.name]).toBeDefined() + + const expectedViewV2: ViewV2Enriched = { + ...viewV2, + schema: { + description: { + constraints: { + type: "string", + }, + name: "description", + type: FieldType.STRING, + visible: false, + }, + name: { + constraints: { + type: "string", + }, + name: "name", + type: FieldType.STRING, + visible: false, + }, + }, + } + + if (!isInternal) { + expectedViewV2.schema!.id = { + name: "id", + type: FieldType.NUMBER, + visible: false, + autocolumn: true, + } + } + + expect(table!.views![viewV2.name!]).toEqual(expectedViewV2) + + if (isInternal) { + expect(table!.views![legacyView.name!]).toBeDefined() + expect(table!.views![legacyView.name!]).toEqual({ + ...legacyView, + schema: { + description: { + constraints: { + type: "string", + }, + name: "description", + type: "string", + }, + name: { + constraints: { + type: "string", + }, + name: "name", + type: "string", + }, + }, + }) + } + }) + }) + + describe("get", () => { + it("returns a table", async () => { + const table = await config.api.table.save( + basicTable(datasource, { name: generator.guid() }) + ) + const res = await config.api.table.get(table._id!) + expect(res).toEqual(expect.objectContaining(table)) + }) + }) + + describe("indexing", () => { + it("should be able to create a table with indexes", async () => { + await context.doInAppContext(config.getAppId(), async () => { + const db = context.getAppDB() + const indexCount = (await db.getIndexes()).total_rows + const table = basicTable() + table.indexes = ["name"] + const res = await config.api.table.save(table) + expect(res._id).toBeDefined() + expect(res._rev).toBeDefined() + expect((await db.getIndexes()).total_rows).toEqual(indexCount + 1) + // update index to see what happens + table.indexes = ["name", "description"] + await config.api.table.save({ + ...table, + _id: res._id, + _rev: res._rev, + }) + // shouldn't have created a new index + expect((await db.getIndexes()).total_rows).toEqual(indexCount + 1) + }) + }) + }) + + describe("destroy", () => { + let testTable: Table + + beforeEach(async () => { + testTable = await config.createTable() + }) + + it("returns a success response when a table is deleted.", async () => { + await config.api.table.destroy(testTable._id!, testTable._rev!, { + body: { message: `Table ${testTable._id} deleted.` }, + }) + expect(events.table.deleted).toHaveBeenCalledTimes(1) + expect(events.table.deleted).toHaveBeenCalledWith( + expect.objectContaining({ + ...testTable, + tableId: testTable._id, + }) + ) + }) + + it("deletes linked references to the table after deletion", async () => { + const linkedTable = await config.createTable({ + name: "LinkedTable", + type: "table", schema: { name: { type: FieldType.STRING, @@ -243,68 +798,299 @@ datasourceDescribe( type: "string", }, }, + TestTable: { + type: FieldType.LINK, + relationshipType: RelationshipType.ONE_TO_MANY, + name: "TestTable", + fieldName: "TestTable", + tableId: testTable._id!, + constraints: { + type: "array", + }, + }, }, }) - ) - const updatedTable = await config.api.table.save({ - ...table, - name: generator.guid(), + await config.api.table.destroy(testTable._id!, testTable._rev!, { + body: { message: `Table ${testTable._id} deleted.` }, + }) + const dependentTable = await config.api.table.get(linkedTable._id!) + expect(dependentTable.schema.TestTable).not.toBeDefined() }) - expect(events.table.updated).toHaveBeenCalledTimes(1) - expect(events.table.updated).toHaveBeenCalledWith(updatedTable) + it("should apply authorization to endpoint", async () => { + await checkBuilderEndpoint({ + config, + method: "DELETE", + url: `/api/tables/${testTable._id}/${testTable._rev}`, + }) + }) }) - it("updates all the row fields for a table when a schema key is renamed", async () => { - const testTable = await config.api.table.save(basicTable(datasource)) - await config.createLegacyView({ - name: "TestView", - field: "Price", - calculation: ViewCalculation.STATISTICS, - tableId: testTable._id!, - schema: {}, - filters: [], + describe("migrate", () => { + let users: User[] + beforeAll(async () => { + users = await Promise.all([ + config.createUser({ email: `${uuid.v4()}@example.com` }), + config.createUser({ email: `${uuid.v4()}@example.com` }), + config.createUser({ email: `${uuid.v4()}@example.com` }), + ]) }) - const testRow = await config.api.row.save(testTable._id!, { - name: "test", - }) - - const { name, ...otherColumns } = testTable.schema - const updatedTable = await config.api.table.save({ - ...testTable, - _rename: { - old: "name", - updated: "updatedName", - }, - schema: { - ...otherColumns, - updatedName: { - ...name, - name: "updatedName", + it("should successfully migrate a one-to-many user relationship to a user column", async () => { + const table = await config.api.table.save({ + name: "table", + type: "table", + sourceId: INTERNAL_TABLE_SOURCE_ID, + sourceType: TableSourceType.INTERNAL, + schema: { + "user relationship": { + type: FieldType.LINK, + fieldName: "test", + name: "user relationship", + constraints: { + type: "array", + presence: false, + }, + relationshipType: RelationshipType.ONE_TO_MANY, + tableId: InternalTable.USER_METADATA, + }, }, - }, + }) + + const rows = await Promise.all( + users.map(u => + config.api.row.save(table._id!, { "user relationship": [u] }) + ) + ) + + await config.api.table.migrate(table._id!, { + oldColumn: "user relationship", + newColumn: "user column", + }) + + const migratedTable = await config.api.table.get(table._id!) + expect(migratedTable.schema["user column"]).toEqual({ + name: "user column", + type: FieldType.BB_REFERENCE_SINGLE, + subtype: BBReferenceFieldSubType.USER, + }) + expect(migratedTable.schema["user relationship"]).not.toBeDefined() + + const migratedRows = await config.api.row.fetch(table._id!) + + rows.sort((a, b) => a._id!.localeCompare(b._id!)) + migratedRows.sort((a, b) => a._id!.localeCompare(b._id!)) + + for (const [i, row] of rows.entries()) { + const migratedRow = migratedRows[i] + expect(migratedRow["user column"]).toBeDefined() + expect(migratedRow["user relationship"]).not.toBeDefined() + expect(row["user relationship"][0]._id).toEqual( + migratedRow["user column"]._id + ) + } }) - expect(updatedTable.name).toEqual(testTable.name) + it("should succeed when the row is created from the other side of the relationship", async () => { + // We found a bug just after releasing this feature where if the row was created from the + // users table, not the table linking to it, the migration would succeed but lose the data. + // This happened because the order of the documents in the link was reversed. + const table = await config.api.table.save({ + name: "table", + type: "table", + sourceId: INTERNAL_TABLE_SOURCE_ID, + sourceType: TableSourceType.INTERNAL, + schema: { + "user relationship": { + type: FieldType.LINK, + fieldName: "test", + name: "user relationship", + constraints: { + type: "array", + presence: false, + }, + relationshipType: RelationshipType.MANY_TO_ONE, + tableId: InternalTable.USER_METADATA, + }, + }, + }) - const res = await config.api.row.get(testTable._id!, testRow._id!) - expect(res.updatedName).toEqual("test") - expect(res.name).toBeUndefined() - }) + let testRow = await config.api.row.save(table._id!, {}) - isInternal && - it("updates only the passed fields", async () => { - await timekeeper.withFreeze(new Date(2021, 1, 1), async () => { - const table = await config.api.table.save( + await Promise.all( + users.map(u => + config.api.row.patch(InternalTable.USER_METADATA, { + tableId: InternalTable.USER_METADATA, + _rev: u._rev!, + _id: u._id!, + test: [testRow], + }) + ) + ) + + await config.api.table.migrate(table._id!, { + oldColumn: "user relationship", + newColumn: "user column", + }) + + const migratedTable = await config.api.table.get(table._id!) + expect(migratedTable.schema["user column"]).toEqual({ + name: "user column", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + constraints: { + type: "array", + }, + }) + expect(migratedTable.schema["user relationship"]).not.toBeDefined() + + const migratedRow = await config.api.row.get(table._id!, testRow._id!) + + expect(migratedRow["user column"]).toBeDefined() + expect(migratedRow["user relationship"]).not.toBeDefined() + expect(migratedRow["user column"]).toHaveLength(3) + expect(migratedRow["user column"].map((u: Row) => u._id)).toEqual( + expect.arrayContaining(users.map(u => u._id)) + ) + }) + + it("should successfully migrate a many-to-many user relationship to a users column", async () => { + const table = await config.api.table.save({ + name: "table", + type: "table", + sourceId: INTERNAL_TABLE_SOURCE_ID, + sourceType: TableSourceType.INTERNAL, + schema: { + "user relationship": { + type: FieldType.LINK, + fieldName: "test", + name: "user relationship", + constraints: { + type: "array", + presence: false, + }, + relationshipType: RelationshipType.MANY_TO_MANY, + tableId: InternalTable.USER_METADATA, + }, + }, + }) + + const row1 = await config.api.row.save(table._id!, { + "user relationship": [users[0], users[1]], + }) + + const row2 = await config.api.row.save(table._id!, { + "user relationship": [users[1], users[2]], + }) + + await config.api.table.migrate(table._id!, { + oldColumn: "user relationship", + newColumn: "user column", + }) + + const migratedTable = await config.api.table.get(table._id!) + expect(migratedTable.schema["user column"]).toEqual({ + name: "user column", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + constraints: { + type: "array", + }, + }) + expect(migratedTable.schema["user relationship"]).not.toBeDefined() + + const row1Migrated = await config.api.row.get(table._id!, row1._id!) + expect(row1Migrated["user relationship"]).not.toBeDefined() + expect(row1Migrated["user column"].map((r: Row) => r._id)).toEqual( + expect.arrayContaining([users[0]._id, users[1]._id]) + ) + + const row2Migrated = await config.api.row.get(table._id!, row2._id!) + expect(row2Migrated["user relationship"]).not.toBeDefined() + expect(row2Migrated["user column"].map((r: Row) => r._id)).toEqual( + expect.arrayContaining([users[1]._id, users[2]._id]) + ) + }) + + it("should successfully migrate a many-to-one user relationship to a users column", async () => { + const table = await config.api.table.save({ + name: "table", + type: "table", + sourceId: INTERNAL_TABLE_SOURCE_ID, + sourceType: TableSourceType.INTERNAL, + schema: { + "user relationship": { + type: FieldType.LINK, + fieldName: "test", + name: "user relationship", + constraints: { + type: "array", + presence: false, + }, + relationshipType: RelationshipType.MANY_TO_ONE, + tableId: InternalTable.USER_METADATA, + }, + }, + }) + + const row1 = await config.api.row.save(table._id!, { + "user relationship": [users[0], users[1]], + }) + + const row2 = await config.api.row.save(table._id!, { + "user relationship": [users[2]], + }) + + await config.api.table.migrate(table._id!, { + oldColumn: "user relationship", + newColumn: "user column", + }) + + const migratedTable = await config.api.table.get(table._id!) + expect(migratedTable.schema["user column"]).toEqual({ + name: "user column", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + constraints: { + type: "array", + }, + }) + expect(migratedTable.schema["user relationship"]).not.toBeDefined() + + const row1Migrated = await config.api.row.get(table._id!, row1._id!) + expect(row1Migrated["user relationship"]).not.toBeDefined() + expect(row1Migrated["user column"].map((r: Row) => r._id)).toEqual( + expect.arrayContaining([users[0]._id, users[1]._id]) + ) + + const row2Migrated = await config.api.row.get(table._id!, row2._id!) + expect(row2Migrated["user relationship"]).not.toBeDefined() + expect(row2Migrated["user column"].map((r: Row) => r._id)).toEqual([ + users[2]._id, + ]) + }) + + describe("unhappy paths", () => { + let table: Table + beforeAll(async () => { + table = await config.api.table.save( tableForDatasource(datasource, { schema: { - autoId: { - name: "id", + "user relationship": { + type: FieldType.LINK, + fieldName: "test", + name: "user relationship", + constraints: { + type: "array", + presence: false, + }, + relationshipType: RelationshipType.MANY_TO_ONE, + tableId: InternalTable.USER_METADATA, + }, + num: { type: FieldType.NUMBER, - subtype: AutoFieldSubType.AUTO_ID, - autocolumn: true, + name: "num", constraints: { type: "number", presence: false, @@ -313,1077 +1099,238 @@ datasourceDescribe( }, }) ) - - const newName = generator.guid() - - const updatedTable = await config.api.table.save({ - ...table, - name: newName, - }) - - let expected: Table = { - ...table, - name: newName, - _id: expect.any(String), - } - if (isInternal) { - expected._rev = expect.stringMatching(/^2-.+/) - } - - expect(updatedTable).toEqual(expect.objectContaining(expected)) - - const persistedTable = await config.api.table.get(updatedTable._id!) - expected = { - ...table, - name: newName, - _id: updatedTable._id, - } - if (datasource?.isSQL) { - expected.sql = true - } - if (isInternal) { - expected._rev = expect.stringMatching(/^2-.+/) - } - expect(persistedTable).toEqual(expect.objectContaining(expected)) }) - }) - describe("user table", () => { - isInternal && - it("should add roleId and email field when adjusting user table schema", async () => { - const table = await config.api.table.save({ - ...basicTable(datasource), - _id: "ta_users", - }) - expect(table.schema.email).toBeDefined() - expect(table.schema.roleId).toBeDefined() - }) - }) - - describe("default field validation", () => { - it("should error if an existing column is set to required and has a default value", async () => { - const table = await config.api.table.save( - tableForDatasource(datasource, { - schema: { - name: { - name: "name", - type: FieldType.STRING, - default: "default", - }, - }, - }) - ) - - await config.api.table.save( - { - ...table, - schema: { - ...table.schema, - name: { - name: "name", - type: FieldType.STRING, - default: "default", - constraints: { - presence: true, - }, - }, - }, - }, - { - status: 400, - body: { - message: - 'Cannot make field "name" required, it has a default value.', - }, - } - ) - }) - - it("should error if an existing column is given a default value and is required", async () => { - const table = await config.api.table.save( - tableForDatasource(datasource, { - schema: { - name: { - name: "name", - type: FieldType.STRING, - constraints: { - presence: true, - }, - }, - }, - }) - ) - - await config.api.table.save( - { - ...table, - schema: { - ...table.schema, - name: { - name: "name", - type: FieldType.STRING, - default: "default", - constraints: { - presence: true, - }, - }, - }, - }, - { - status: 400, - body: { - message: - 'Cannot make field "name" required, it has a default value.', - }, - } - ) - }) - - it("should be able to set an existing column to have a default value if it's not required", async () => { - const table = await config.api.table.save( - tableForDatasource(datasource, { - schema: { - name: { - name: "name", - type: FieldType.STRING, - }, - }, - }) - ) - - await config.api.table.save( - { - ...table, - schema: { - ...table.schema, - name: { - name: "name", - type: FieldType.STRING, - default: "default", - }, - }, - }, - { status: 200 } - ) - }) - - it("should be able to remove a default value if the column is not required", async () => { - const table = await config.api.table.save( - tableForDatasource(datasource, { - schema: { - name: { - name: "name", - type: FieldType.STRING, - default: "default", - }, - }, - }) - ) - - await config.api.table.save( - { - ...table, - schema: { - ...table.schema, - name: { - name: "name", - type: FieldType.STRING, - }, - }, - }, - { status: 200 } - ) - }) - }) - - describe("external table validation", () => { - !isInternal && - it("should error if column is of type auto", async () => { - const table = basicTable(datasource) - await config.api.table.save( + it("should fail if the new column name is blank", async () => { + await config.api.table.migrate( + table._id!, { - ...table, - schema: { - ...table.schema, - auto: { - name: "auto", - autocolumn: true, - type: FieldType.AUTO, - subtype: AutoFieldSubType.AUTO_ID, - }, - }, + oldColumn: "user relationship", + newColumn: "", }, - { - status: 400, - body: { - message: `Column "auto" has type "${FieldType.AUTO}" - this is not supported.`, - }, - } + { status: 400 } ) }) - !isInternal && - it("should error if column has auto subtype", async () => { - const table = basicTable(datasource) - await config.api.table.save( + it("should fail if the new column name is a reserved name", async () => { + await config.api.table.migrate( + table._id!, { - ...table, - schema: { - ...table.schema, - auto: { - name: "auto", - autocolumn: true, - type: FieldType.NUMBER, - subtype: AutoFieldSubType.AUTO_ID, - }, - }, + oldColumn: "user relationship", + newColumn: "_id", }, - { - status: 400, - body: { - message: `Column "auto" has subtype "${AutoFieldSubType.AUTO_ID}" - this is not supported.`, - }, - } + { status: 400 } ) }) - }) - isInternal && - it("shouldn't allow duplicate column names", async () => { - const saveTableRequest: SaveTableRequest = { - ...basicTable(), - } - saveTableRequest.schema["Type"] = { - type: FieldType.STRING, - name: "Type", - } - // allow the "Type" column - internal columns aren't case sensitive - await config.api.table.save(saveTableRequest, { - status: 200, + it("should fail if the new column name is the same as an existing column", async () => { + await config.api.table.migrate( + table._id!, + { + oldColumn: "user relationship", + newColumn: "num", + }, + { status: 400 } + ) }) - saveTableRequest.schema.foo = { type: FieldType.STRING, name: "foo" } - saveTableRequest.schema.FOO = { type: FieldType.STRING, name: "FOO" } - await config.api.table.save(saveTableRequest, { - status: 400, - body: { - message: - 'Column(s) "foo" are duplicated - check for other columns with these name (case in-sensitive)', - }, + it("should fail if the old column name isn't a column in the table", async () => { + await config.api.table.migrate( + table._id!, + { + oldColumn: "not a column", + newColumn: "new column", + }, + { status: 400 } + ) }) }) - - it("should add a new column for an internal DB table", async () => { - const saveTableRequest: SaveTableRequest = { - ...basicTable(), - } - - const response = await config.api.table.save(saveTableRequest) - - const expectedResponse = { - ...saveTableRequest, - _rev: expect.stringMatching(/^\d-.+/), - _id: expect.stringMatching(/^ta_.+/), - createdAt: expect.stringMatching(ISO_REGEX_PATTERN), - updatedAt: expect.stringMatching(ISO_REGEX_PATTERN), - views: {}, - } - expect(response).toEqual(expectedResponse) - }) - }) - - describe("import", () => { - it("imports rows successfully", async () => { - const name = generator.guid() - const table = await config.api.table.save( - basicTable(datasource, { name }) - ) - const importRequest = { - schema: table.schema, - rows: [{ name: "test-name", description: "test-desc" }], - } - - jest.clearAllMocks() - - await config.api.table.import(table._id!, importRequest) - - expect(events.table.created).not.toHaveBeenCalled() - expect(events.rows.imported).toHaveBeenCalledTimes(1) - expect(events.rows.imported).toHaveBeenCalledWith( - expect.objectContaining({ - name, - _id: table._id, - }), - 1 - ) - }) - }) - - describe("fetch", () => { - let testTable: Table - - beforeEach(async () => { - testTable = await config.api.table.save( - basicTable(datasource, { name: generator.guid() }) - ) }) - it("returns all tables", async () => { - const res = await config.api.table.fetch() - const table = res.find(t => t._id === testTable._id) - expect(table).toBeDefined() - expect(table!.name).toEqual(testTable.name) - expect(table!.type).toEqual("table") - expect(table!.sourceType).toEqual(testTable.sourceType) - }) - - it("should apply authorization to endpoint", async () => { - await checkBuilderEndpoint({ - config, - method: "GET", - url: `/api/tables`, - }) - }) - - it("should enrich the view schemas", async () => { - const viewV2 = await config.api.viewV2.create({ - tableId: testTable._id!, - name: generator.guid(), - }) - const legacyView = await config.api.legacyView.save({ - tableId: testTable._id!, - name: generator.guid(), - filters: [], - schema: {}, - }) - - const res = await config.api.table.fetch() - - const table = res.find(t => t._id === testTable._id) - expect(table).toBeDefined() - expect(table!.views![viewV2.name]).toBeDefined() - - const expectedViewV2: ViewV2Enriched = { - ...viewV2, - schema: { - description: { - constraints: { - type: "string", - }, - name: "description", - type: FieldType.STRING, - visible: false, - }, - name: { - constraints: { - type: "string", - }, - name: "name", - type: FieldType.STRING, - visible: false, - }, - }, - } - - if (!isInternal) { - expectedViewV2.schema!.id = { - name: "id", - type: FieldType.NUMBER, - visible: false, - autocolumn: true, - } - } - - expect(table!.views![viewV2.name!]).toEqual(expectedViewV2) - - if (isInternal) { - expect(table!.views![legacyView.name!]).toBeDefined() - expect(table!.views![legacyView.name!]).toEqual({ - ...legacyView, - schema: { - description: { - constraints: { - type: "string", - }, - name: "description", - type: "string", - }, - name: { - constraints: { - type: "string", - }, - name: "name", - type: "string", - }, - }, - }) - } - }) - }) - - describe("get", () => { - it("returns a table", async () => { - const table = await config.api.table.save( - basicTable(datasource, { name: generator.guid() }) - ) - const res = await config.api.table.get(table._id!) - expect(res).toEqual(expect.objectContaining(table)) - }) - }) - - describe("indexing", () => { - it("should be able to create a table with indexes", async () => { - await context.doInAppContext(config.getAppId(), async () => { - const db = context.getAppDB() - const indexCount = (await db.getIndexes()).total_rows - const table = basicTable() - table.indexes = ["name"] - const res = await config.api.table.save(table) - expect(res._id).toBeDefined() - expect(res._rev).toBeDefined() - expect((await db.getIndexes()).total_rows).toEqual(indexCount + 1) - // update index to see what happens - table.indexes = ["name", "description"] - await config.api.table.save({ - ...table, - _id: res._id, - _rev: res._rev, - }) - // shouldn't have created a new index - expect((await db.getIndexes()).total_rows).toEqual(indexCount + 1) - }) - }) - }) - - describe("destroy", () => { - let testTable: Table - - beforeEach(async () => { - testTable = await config.createTable() - }) - - it("returns a success response when a table is deleted.", async () => { - await config.api.table.destroy(testTable._id!, testTable._rev!, { - body: { message: `Table ${testTable._id} deleted.` }, - }) - expect(events.table.deleted).toHaveBeenCalledTimes(1) - expect(events.table.deleted).toHaveBeenCalledWith( - expect.objectContaining({ - ...testTable, - tableId: testTable._id, - }) - ) - }) - - it("deletes linked references to the table after deletion", async () => { - const linkedTable = await config.createTable({ - name: "LinkedTable", - type: "table", - schema: { - name: { - type: FieldType.STRING, - name: "name", - constraints: { - type: "string", - }, - }, - TestTable: { - type: FieldType.LINK, - relationshipType: RelationshipType.ONE_TO_MANY, - name: "TestTable", - fieldName: "TestTable", - tableId: testTable._id!, - constraints: { - type: "array", - }, - }, - }, - }) - - await config.api.table.destroy(testTable._id!, testTable._rev!, { - body: { message: `Table ${testTable._id} deleted.` }, - }) - const dependentTable = await config.api.table.get(linkedTable._id!) - expect(dependentTable.schema.TestTable).not.toBeDefined() - }) - - it("should apply authorization to endpoint", async () => { - await checkBuilderEndpoint({ - config, - method: "DELETE", - url: `/api/tables/${testTable._id}/${testTable._rev}`, - }) - }) - }) - - describe("migrate", () => { - let users: User[] - beforeAll(async () => { - users = await Promise.all([ - config.createUser({ email: `${uuid.v4()}@example.com` }), - config.createUser({ email: `${uuid.v4()}@example.com` }), - config.createUser({ email: `${uuid.v4()}@example.com` }), - ]) - }) - - it("should successfully migrate a one-to-many user relationship to a user column", async () => { - const table = await config.api.table.save({ - name: "table", - type: "table", - sourceId: INTERNAL_TABLE_SOURCE_ID, - sourceType: TableSourceType.INTERNAL, - schema: { - "user relationship": { - type: FieldType.LINK, - fieldName: "test", - name: "user relationship", - constraints: { - type: "array", - presence: false, - }, - relationshipType: RelationshipType.ONE_TO_MANY, - tableId: InternalTable.USER_METADATA, - }, - }, - }) - - const rows = await Promise.all( - users.map(u => - config.api.row.save(table._id!, { "user relationship": [u] }) - ) - ) - - await config.api.table.migrate(table._id!, { - oldColumn: "user relationship", - newColumn: "user column", - }) - - const migratedTable = await config.api.table.get(table._id!) - expect(migratedTable.schema["user column"]).toEqual({ - name: "user column", - type: FieldType.BB_REFERENCE_SINGLE, - subtype: BBReferenceFieldSubType.USER, - }) - expect(migratedTable.schema["user relationship"]).not.toBeDefined() - - const migratedRows = await config.api.row.fetch(table._id!) - - rows.sort((a, b) => a._id!.localeCompare(b._id!)) - migratedRows.sort((a, b) => a._id!.localeCompare(b._id!)) - - for (const [i, row] of rows.entries()) { - const migratedRow = migratedRows[i] - expect(migratedRow["user column"]).toBeDefined() - expect(migratedRow["user relationship"]).not.toBeDefined() - expect(row["user relationship"][0]._id).toEqual( - migratedRow["user column"]._id - ) - } - }) - - it("should succeed when the row is created from the other side of the relationship", async () => { - // We found a bug just after releasing this feature where if the row was created from the - // users table, not the table linking to it, the migration would succeed but lose the data. - // This happened because the order of the documents in the link was reversed. - const table = await config.api.table.save({ - name: "table", - type: "table", - sourceId: INTERNAL_TABLE_SOURCE_ID, - sourceType: TableSourceType.INTERNAL, - schema: { - "user relationship": { - type: FieldType.LINK, - fieldName: "test", - name: "user relationship", - constraints: { - type: "array", - presence: false, - }, - relationshipType: RelationshipType.MANY_TO_ONE, - tableId: InternalTable.USER_METADATA, - }, - }, - }) - - let testRow = await config.api.row.save(table._id!, {}) - - await Promise.all( - users.map(u => - config.api.row.patch(InternalTable.USER_METADATA, { - tableId: InternalTable.USER_METADATA, - _rev: u._rev!, - _id: u._id!, - test: [testRow], - }) - ) - ) - - await config.api.table.migrate(table._id!, { - oldColumn: "user relationship", - newColumn: "user column", - }) - - const migratedTable = await config.api.table.get(table._id!) - expect(migratedTable.schema["user column"]).toEqual({ - name: "user column", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - constraints: { - type: "array", - }, - }) - expect(migratedTable.schema["user relationship"]).not.toBeDefined() - - const migratedRow = await config.api.row.get(table._id!, testRow._id!) - - expect(migratedRow["user column"]).toBeDefined() - expect(migratedRow["user relationship"]).not.toBeDefined() - expect(migratedRow["user column"]).toHaveLength(3) - expect(migratedRow["user column"].map((u: Row) => u._id)).toEqual( - expect.arrayContaining(users.map(u => u._id)) - ) - }) - - it("should successfully migrate a many-to-many user relationship to a users column", async () => { - const table = await config.api.table.save({ - name: "table", - type: "table", - sourceId: INTERNAL_TABLE_SOURCE_ID, - sourceType: TableSourceType.INTERNAL, - schema: { - "user relationship": { - type: FieldType.LINK, - fieldName: "test", - name: "user relationship", - constraints: { - type: "array", - presence: false, - }, - relationshipType: RelationshipType.MANY_TO_MANY, - tableId: InternalTable.USER_METADATA, - }, - }, - }) - - const row1 = await config.api.row.save(table._id!, { - "user relationship": [users[0], users[1]], - }) - - const row2 = await config.api.row.save(table._id!, { - "user relationship": [users[1], users[2]], - }) - - await config.api.table.migrate(table._id!, { - oldColumn: "user relationship", - newColumn: "user column", - }) - - const migratedTable = await config.api.table.get(table._id!) - expect(migratedTable.schema["user column"]).toEqual({ - name: "user column", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - constraints: { - type: "array", - }, - }) - expect(migratedTable.schema["user relationship"]).not.toBeDefined() - - const row1Migrated = await config.api.row.get(table._id!, row1._id!) - expect(row1Migrated["user relationship"]).not.toBeDefined() - expect(row1Migrated["user column"].map((r: Row) => r._id)).toEqual( - expect.arrayContaining([users[0]._id, users[1]._id]) - ) - - const row2Migrated = await config.api.row.get(table._id!, row2._id!) - expect(row2Migrated["user relationship"]).not.toBeDefined() - expect(row2Migrated["user column"].map((r: Row) => r._id)).toEqual( - expect.arrayContaining([users[1]._id, users[2]._id]) - ) - }) - - it("should successfully migrate a many-to-one user relationship to a users column", async () => { - const table = await config.api.table.save({ - name: "table", - type: "table", - sourceId: INTERNAL_TABLE_SOURCE_ID, - sourceType: TableSourceType.INTERNAL, - schema: { - "user relationship": { - type: FieldType.LINK, - fieldName: "test", - name: "user relationship", - constraints: { - type: "array", - presence: false, - }, - relationshipType: RelationshipType.MANY_TO_ONE, - tableId: InternalTable.USER_METADATA, - }, - }, - }) - - const row1 = await config.api.row.save(table._id!, { - "user relationship": [users[0], users[1]], - }) - - const row2 = await config.api.row.save(table._id!, { - "user relationship": [users[2]], - }) - - await config.api.table.migrate(table._id!, { - oldColumn: "user relationship", - newColumn: "user column", - }) - - const migratedTable = await config.api.table.get(table._id!) - expect(migratedTable.schema["user column"]).toEqual({ - name: "user column", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - constraints: { - type: "array", - }, - }) - expect(migratedTable.schema["user relationship"]).not.toBeDefined() - - const row1Migrated = await config.api.row.get(table._id!, row1._id!) - expect(row1Migrated["user relationship"]).not.toBeDefined() - expect(row1Migrated["user column"].map((r: Row) => r._id)).toEqual( - expect.arrayContaining([users[0]._id, users[1]._id]) - ) - - const row2Migrated = await config.api.row.get(table._id!, row2._id!) - expect(row2Migrated["user relationship"]).not.toBeDefined() - expect(row2Migrated["user column"].map((r: Row) => r._id)).toEqual([ - users[2]._id, - ]) - }) - - describe("unhappy paths", () => { - let table: Table - beforeAll(async () => { - table = await config.api.table.save( - tableForDatasource(datasource, { - schema: { - "user relationship": { - type: FieldType.LINK, - fieldName: "test", - name: "user relationship", - constraints: { - type: "array", - presence: false, - }, - relationshipType: RelationshipType.MANY_TO_ONE, - tableId: InternalTable.USER_METADATA, - }, - num: { - type: FieldType.NUMBER, - name: "num", - constraints: { - type: "number", - presence: false, - }, - }, - }, - }) - ) - }) - - it("should fail if the new column name is blank", async () => { - await config.api.table.migrate( - table._id!, - { - oldColumn: "user relationship", - newColumn: "", - }, - { status: 400 } - ) - }) - - it("should fail if the new column name is a reserved name", async () => { - await config.api.table.migrate( - table._id!, - { - oldColumn: "user relationship", - newColumn: "_id", - }, - { status: 400 } - ) - }) - - it("should fail if the new column name is the same as an existing column", async () => { - await config.api.table.migrate( - table._id!, - { - oldColumn: "user relationship", - newColumn: "num", - }, - { status: 400 } - ) - }) - - it("should fail if the old column name isn't a column in the table", async () => { - await config.api.table.migrate( - table._id!, - { - oldColumn: "not a column", - newColumn: "new column", - }, - { status: 400 } - ) - }) - }) - }) - - describe.each([ - [ - RowExportFormat.CSV, - (val: any) => JSON.stringify(val).replace(/"/g, "'"), - ], - [RowExportFormat.JSON, (val: any) => val], - ])("import validation (%s)", (_, userParser) => { - const basicSchema: TableSchema = { - id: { - type: FieldType.NUMBER, - name: "id", - }, - name: { - type: FieldType.STRING, - name: "name", - }, - } - - const importCases: [ - string, - ( - rows: Row[], - schema: TableSchema - ) => Promise - ][] = [ + describe.each([ [ - "validateNewTableImport", - async (rows: Row[], schema: TableSchema) => { - const result = await config.api.table.validateNewTableImport({ - rows, - schema, - }) - return result - }, + RowExportFormat.CSV, + (val: any) => JSON.stringify(val).replace(/"/g, "'"), ], - [ - "validateExistingTableImport", - async (rows: Row[], schema: TableSchema) => { - const table = await config.api.table.save( - tableForDatasource(datasource, { - primary: ["id"], + [RowExportFormat.JSON, (val: any) => val], + ])("import validation (%s)", (_, userParser) => { + const basicSchema: TableSchema = { + id: { + type: FieldType.NUMBER, + name: "id", + }, + name: { + type: FieldType.STRING, + name: "name", + }, + } + + const importCases: [ + string, + ( + rows: Row[], + schema: TableSchema + ) => Promise + ][] = [ + [ + "validateNewTableImport", + async (rows: Row[], schema: TableSchema) => { + const result = await config.api.table.validateNewTableImport({ + rows, schema, }) + return result + }, + ], + [ + "validateExistingTableImport", + async (rows: Row[], schema: TableSchema) => { + const table = await config.api.table.save( + tableForDatasource(datasource, { + primary: ["id"], + schema, + }) + ) + const result = await config.api.table.validateExistingTableImport( + { + tableId: table._id, + rows, + } + ) + return result + }, + ], + ] + + describe.each(importCases)("%s", (_, testDelegate) => { + it("validates basic imports", async () => { + const result = await testDelegate( + [{ id: generator.natural(), name: generator.first() }], + basicSchema ) - const result = await config.api.table.validateExistingTableImport({ - tableId: table._id, - rows, - }) - return result - }, - ], - ] - describe.each(importCases)("%s", (_, testDelegate) => { - it("validates basic imports", async () => { - const result = await testDelegate( - [{ id: generator.natural(), name: generator.first() }], - basicSchema - ) - - expect(result).toEqual({ - allValid: true, - errors: {}, - invalidColumns: [], - schemaValidation: { - id: true, - name: true, - }, - }) - }) - - it.each( - isInternal ? PROTECTED_INTERNAL_COLUMNS : PROTECTED_EXTERNAL_COLUMNS - )("don't allow protected names in schema (%s)", async columnName => { - const result = await config.api.table.validateNewTableImport({ - rows: [ - { - id: generator.natural(), - name: generator.first(), - [columnName]: generator.word(), + expect(result).toEqual({ + allValid: true, + errors: {}, + invalidColumns: [], + schemaValidation: { + id: true, + name: true, }, - ], - schema: { - ...basicSchema, - }, + }) }) - expect(result).toEqual({ - allValid: false, - errors: { - [columnName]: `${columnName} is a protected column name`, - }, - invalidColumns: [], - schemaValidation: { - id: true, - name: true, - [columnName]: false, - }, - }) - }) - - it("does not allow imports without rows", async () => { - const result = await testDelegate([], basicSchema) - - expect(result).toEqual({ - allValid: false, - errors: {}, - invalidColumns: [], - schemaValidation: {}, - }) - }) - - it("validates imports with some empty rows", async () => { - const result = await testDelegate( - [{}, { id: generator.natural(), name: generator.first() }, {}], - basicSchema - ) - - expect(result).toEqual({ - allValid: true, - errors: {}, - invalidColumns: [], - schemaValidation: { - id: true, - name: true, - }, - }) - }) - - isInternal && it.each( isInternal ? PROTECTED_INTERNAL_COLUMNS : PROTECTED_EXTERNAL_COLUMNS - )( - "don't allow protected names in the rows (%s)", - async columnName => { - const result = await config.api.table.validateNewTableImport({ - rows: [ - { - id: generator.natural(), - name: generator.first(), + )("don't allow protected names in schema (%s)", async columnName => { + const result = await config.api.table.validateNewTableImport({ + rows: [ + { + id: generator.natural(), + name: generator.first(), + [columnName]: generator.word(), + }, + ], + schema: { + ...basicSchema, + }, + }) + + expect(result).toEqual({ + allValid: false, + errors: { + [columnName]: `${columnName} is a protected column name`, + }, + invalidColumns: [], + schemaValidation: { + id: true, + name: true, + [columnName]: false, + }, + }) + }) + + it("does not allow imports without rows", async () => { + const result = await testDelegate([], basicSchema) + + expect(result).toEqual({ + allValid: false, + errors: {}, + invalidColumns: [], + schemaValidation: {}, + }) + }) + + it("validates imports with some empty rows", async () => { + const result = await testDelegate( + [{}, { id: generator.natural(), name: generator.first() }, {}], + basicSchema + ) + + expect(result).toEqual({ + allValid: true, + errors: {}, + invalidColumns: [], + schemaValidation: { + id: true, + name: true, + }, + }) + }) + + isInternal && + it.each( + isInternal + ? PROTECTED_INTERNAL_COLUMNS + : PROTECTED_EXTERNAL_COLUMNS + )( + "don't allow protected names in the rows (%s)", + async columnName => { + const result = await config.api.table.validateNewTableImport({ + rows: [ + { + id: generator.natural(), + name: generator.first(), + }, + ], + schema: { + ...basicSchema, + [columnName]: { + name: columnName, + type: FieldType.STRING, + }, }, - ], - schema: { - ...basicSchema, - [columnName]: { - name: columnName, - type: FieldType.STRING, + }) + + expect(result).toEqual({ + allValid: false, + errors: { + [columnName]: `${columnName} is a protected column name`, }, - }, - }) + invalidColumns: [], + schemaValidation: { + id: true, + name: true, + [columnName]: false, + }, + }) + } + ) - expect(result).toEqual({ - allValid: false, - errors: { - [columnName]: `${columnName} is a protected column name`, - }, - invalidColumns: [], - schemaValidation: { - id: true, - name: true, - [columnName]: false, - }, - }) - } - ) - - it("validates required fields and valid rows", async () => { - const schema: TableSchema = { - ...basicSchema, - name: { - type: FieldType.STRING, - name: "name", - constraints: { presence: true }, - }, - } - - const result = await testDelegate( - [ - { id: generator.natural(), name: generator.first() }, - { id: generator.natural(), name: generator.first() }, - ], - schema - ) - - expect(result).toEqual({ - allValid: true, - errors: {}, - invalidColumns: [], - schemaValidation: { - id: true, - name: true, - }, - }) - }) - - it("validates required fields and non-valid rows", async () => { - const schema: TableSchema = { - ...basicSchema, - name: { - type: FieldType.STRING, - name: "name", - constraints: { presence: true }, - }, - } - - const result = await testDelegate( - [ - { id: generator.natural(), name: generator.first() }, - { id: generator.natural(), name: "" }, - ], - schema - ) - - expect(result).toEqual({ - allValid: false, - errors: {}, - invalidColumns: [], - schemaValidation: { - id: true, - name: false, - }, - }) - }) - - describe("bb references", () => { - const getUserValues = () => ({ - _id: docIds.generateGlobalUserID(), - primaryDisplay: generator.first(), - email: generator.email({}), - }) - - it("can validate user column imports", async () => { + it("validates required fields and valid rows", async () => { const schema: TableSchema = { ...basicSchema, - user: { - type: FieldType.BB_REFERENCE_SINGLE, - subtype: BBReferenceFieldSubType.USER, - name: "user", + name: { + type: FieldType.STRING, + name: "name", + constraints: { presence: true }, }, } const result = await testDelegate( [ - { - id: generator.natural(), - name: generator.first(), - user: userParser(getUserValues()), - }, + { id: generator.natural(), name: generator.first() }, + { id: generator.natural(), name: generator.first() }, ], schema ) @@ -1395,33 +1342,24 @@ datasourceDescribe( schemaValidation: { id: true, name: true, - user: true, }, }) }) - it("can validate user column imports with invalid data", async () => { + it("validates required fields and non-valid rows", async () => { const schema: TableSchema = { ...basicSchema, - user: { - type: FieldType.BB_REFERENCE_SINGLE, - subtype: BBReferenceFieldSubType.USER, - name: "user", + name: { + type: FieldType.STRING, + name: "name", + constraints: { presence: true }, }, } const result = await testDelegate( [ - { - id: generator.natural(), - name: generator.first(), - user: userParser(getUserValues()), - }, - { - id: generator.natural(), - name: generator.first(), - user: "no valid user data", - }, + { id: generator.natural(), name: generator.first() }, + { id: generator.natural(), name: "" }, ], schema ) @@ -1432,84 +1370,164 @@ datasourceDescribe( invalidColumns: [], schemaValidation: { id: true, - name: true, - user: false, + name: false, }, }) }) - it("can validate users column imports", async () => { - const schema: TableSchema = { - ...basicSchema, - user: { - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - name: "user", - externalType: "array", - }, - } + describe("bb references", () => { + const getUserValues = () => ({ + _id: docIds.generateGlobalUserID(), + primaryDisplay: generator.first(), + email: generator.email({}), + }) - const result = await testDelegate( - [ - { - id: generator.natural(), - name: generator.first(), - user: userParser([ - getUserValues(), - getUserValues(), - getUserValues(), - ]), + it("can validate user column imports", async () => { + const schema: TableSchema = { + ...basicSchema, + user: { + type: FieldType.BB_REFERENCE_SINGLE, + subtype: BBReferenceFieldSubType.USER, + name: "user", }, - ], - schema - ) + } - expect(result).toEqual({ - allValid: true, - errors: {}, - invalidColumns: [], - schemaValidation: { - id: true, - name: true, - user: true, - }, + const result = await testDelegate( + [ + { + id: generator.natural(), + name: generator.first(), + user: userParser(getUserValues()), + }, + ], + schema + ) + + expect(result).toEqual({ + allValid: true, + errors: {}, + invalidColumns: [], + schemaValidation: { + id: true, + name: true, + user: true, + }, + }) + }) + + it("can validate user column imports with invalid data", async () => { + const schema: TableSchema = { + ...basicSchema, + user: { + type: FieldType.BB_REFERENCE_SINGLE, + subtype: BBReferenceFieldSubType.USER, + name: "user", + }, + } + + const result = await testDelegate( + [ + { + id: generator.natural(), + name: generator.first(), + user: userParser(getUserValues()), + }, + { + id: generator.natural(), + name: generator.first(), + user: "no valid user data", + }, + ], + schema + ) + + expect(result).toEqual({ + allValid: false, + errors: {}, + invalidColumns: [], + schemaValidation: { + id: true, + name: true, + user: false, + }, + }) + }) + + it("can validate users column imports", async () => { + const schema: TableSchema = { + ...basicSchema, + user: { + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + name: "user", + externalType: "array", + }, + } + + const result = await testDelegate( + [ + { + id: generator.natural(), + name: generator.first(), + user: userParser([ + getUserValues(), + getUserValues(), + getUserValues(), + ]), + }, + ], + schema + ) + + expect(result).toEqual({ + allValid: true, + errors: {}, + invalidColumns: [], + schemaValidation: { + id: true, + name: true, + user: true, + }, + }) }) }) }) - }) - describe("validateExistingTableImport", () => { - isInternal && - it("can reimport _id fields for internal tables", async () => { - const table = await config.api.table.save( - tableForDatasource(datasource, { - primary: ["id"], - schema: basicSchema, - }) - ) - const result = await config.api.table.validateExistingTableImport({ - tableId: table._id, - rows: [ + describe("validateExistingTableImport", () => { + isInternal && + it("can reimport _id fields for internal tables", async () => { + const table = await config.api.table.save( + tableForDatasource(datasource, { + primary: ["id"], + schema: basicSchema, + }) + ) + const result = await config.api.table.validateExistingTableImport( { - _id: docIds.generateRowID(table._id!), - id: generator.natural(), - name: generator.first(), - }, - ], - }) + tableId: table._id, + rows: [ + { + _id: docIds.generateRowID(table._id!), + id: generator.natural(), + name: generator.first(), + }, + ], + } + ) - expect(result).toEqual({ - allValid: true, - errors: {}, - invalidColumns: [], - schemaValidation: { - _id: true, - id: true, - name: true, - }, + expect(result).toEqual({ + allValid: true, + errors: {}, + invalidColumns: [], + schemaValidation: { + _id: true, + id: true, + name: true, + }, + }) }) - }) + }) }) - }) - } -) + } + ) +} diff --git a/packages/server/src/api/routes/tests/viewV2.spec.ts b/packages/server/src/api/routes/tests/viewV2.spec.ts index 63d315cea9..6e82395e19 100644 --- a/packages/server/src/api/routes/tests/viewV2.spec.ts +++ b/packages/server/src/api/routes/tests/viewV2.spec.ts @@ -44,158 +44,163 @@ import merge from "lodash/merge" import { quotas } from "@budibase/pro" import { db, roles, context } from "@budibase/backend-core" -datasourceDescribe( - { name: "/v2/views (%s)", exclude: [DatabaseName.MONGODB] }, - ({ config, isInternal, dsProvider }) => { - let table: Table - let rawDatasource: Datasource | undefined - let datasource: Datasource | undefined +const descriptions = datasourceDescribe({ exclude: [DatabaseName.MONGODB] }) - function saveTableRequest( - ...overrides: Partial>[] - ): SaveTableRequest { - const req: SaveTableRequest = { - name: generator.guid().replaceAll("-", "").substring(0, 16), - type: "table", - sourceType: datasource - ? TableSourceType.EXTERNAL - : TableSourceType.INTERNAL, - sourceId: datasource ? datasource._id! : INTERNAL_TABLE_SOURCE_ID, - primary: ["id"], - schema: { - id: { - type: FieldType.NUMBER, - name: "id", - autocolumn: true, - constraints: { - presence: true, +if (descriptions.length) { + describe.each(descriptions)( + "/v2/views ($dbName)", + ({ config, isInternal, dsProvider }) => { + let table: Table + let rawDatasource: Datasource | undefined + let datasource: Datasource | undefined + + function saveTableRequest( + ...overrides: Partial>[] + ): SaveTableRequest { + const req: SaveTableRequest = { + name: generator.guid().replaceAll("-", "").substring(0, 16), + type: "table", + sourceType: datasource + ? TableSourceType.EXTERNAL + : TableSourceType.INTERNAL, + sourceId: datasource ? datasource._id! : INTERNAL_TABLE_SOURCE_ID, + primary: ["id"], + schema: { + id: { + type: FieldType.NUMBER, + name: "id", + autocolumn: true, + constraints: { + presence: true, + }, }, }, - }, + } + return merge(req, ...overrides) } - return merge(req, ...overrides) - } - function priceTable(): SaveTableRequest { - return saveTableRequest({ - schema: { - Price: { - type: FieldType.NUMBER, - name: "Price", - constraints: {}, - }, - Category: { - type: FieldType.STRING, - name: "Category", - constraints: { - type: "string", + function priceTable(): SaveTableRequest { + return saveTableRequest({ + schema: { + Price: { + type: FieldType.NUMBER, + name: "Price", + constraints: {}, + }, + Category: { + type: FieldType.STRING, + name: "Category", + constraints: { + type: "string", + }, }, }, - }, - }) - } - - beforeAll(async () => { - await config.init() - - const ds = await dsProvider() - rawDatasource = ds.rawDatasource - datasource = ds.datasource - table = await config.api.table.save(priceTable()) - }) - - beforeEach(() => { - jest.clearAllMocks() - mocks.licenses.useCloudFree() - }) - - describe("view crud", () => { - describe("create", () => { - it("persist the view when the view is successfully created", async () => { - const newView: CreateViewRequest = { - name: generator.name(), - tableId: table._id!, - schema: { - id: { visible: true }, - }, - } - const res = await config.api.viewV2.create(newView) - - expect(res).toEqual({ - ...newView, - id: expect.stringMatching(new RegExp(`${table._id!}_`)), - version: 2, - }) }) + } - it("can persist views with all fields", async () => { - const newView: Required> = { - name: generator.name(), - tableId: table._id!, - primaryDisplay: "id", - queryUI: { - groups: [ - { - filters: [ + beforeAll(async () => { + await config.init() + + const ds = await dsProvider() + rawDatasource = ds.rawDatasource + datasource = ds.datasource + table = await config.api.table.save(priceTable()) + }) + + beforeEach(() => { + jest.clearAllMocks() + mocks.licenses.useCloudFree() + }) + + describe("view crud", () => { + describe("create", () => { + it("persist the view when the view is successfully created", async () => { + const newView: CreateViewRequest = { + name: generator.name(), + tableId: table._id!, + schema: { + id: { visible: true }, + }, + } + const res = await config.api.viewV2.create(newView) + + expect(res).toEqual({ + ...newView, + id: expect.stringMatching(new RegExp(`${table._id!}_`)), + version: 2, + }) + }) + + it("can persist views with all fields", async () => { + const newView: Required> = + { + name: generator.name(), + tableId: table._id!, + primaryDisplay: "id", + queryUI: { + groups: [ { - operator: BasicOperator.EQUAL, - field: "field", - value: "value", - }, - ], - }, - ], - }, - sort: { - field: "fieldToSort", - order: SortOrder.DESCENDING, - type: SortType.STRING, - }, - schema: { - id: { visible: true }, - Price: { - visible: true, - }, - }, - } - const res = await config.api.viewV2.create(newView) - - const expected: ViewV2 = { - ...newView, - schema: { - id: { visible: true }, - Price: { - visible: true, - }, - }, - query: { - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - $and: { - conditions: [ - { - $and: { - conditions: [ + filters: [ { - equal: { - field: "value", - }, + operator: BasicOperator.EQUAL, + field: "field", + value: "value", }, ], }, + ], + }, + sort: { + field: "fieldToSort", + order: SortOrder.DESCENDING, + type: SortType.STRING, + }, + schema: { + id: { visible: true }, + Price: { + visible: true, }, - ], + }, + } + const res = await config.api.viewV2.create(newView) + + const expected: ViewV2 = { + ...newView, + schema: { + id: { visible: true }, + Price: { + visible: true, + }, }, - }, - id: expect.any(String), - version: 2, - } + query: { + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + $and: { + conditions: [ + { + $and: { + conditions: [ + { + equal: { + field: "value", + }, + }, + ], + }, + }, + ], + }, + }, + id: expect.any(String), + version: 2, + } - expect(res).toEqual(expected) - }) + expect(res).toEqual(expected) + }) - it("can create a view with just a query field, no queryUI, for backwards compatibility", async () => { - const newView: Required> = - { + it("can create a view with just a query field, no queryUI, for backwards compatibility", async () => { + const newView: Required< + Omit + > = { name: generator.name(), tableId: table._id!, primaryDisplay: "id", @@ -218,180 +223,194 @@ datasourceDescribe( }, }, } - const res = await config.api.viewV2.create(newView) + const res = await config.api.viewV2.create(newView) - const expected: ViewV2 = { - ...newView, - schema: { - id: { visible: true }, - Price: { - visible: true, - }, - }, - queryUI: { - logicalOperator: UILogicalOperator.ALL, - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - groups: [ - { - logicalOperator: UILogicalOperator.ALL, - filters: [ - { - operator: BasicOperator.EQUAL, - field: "field", - value: "value", - }, - ], + const expected: ViewV2 = { + ...newView, + schema: { + id: { visible: true }, + Price: { + visible: true, }, - ], - }, - id: expect.any(String), - version: 2, - } - - expect(res).toEqual(expected) - }) - - it("persist only UI schema overrides", async () => { - const newView: CreateViewRequest = { - name: generator.name(), - tableId: table._id!, - schema: { - id: { - name: "id", - type: FieldType.NUMBER, - visible: true, }, - Price: { - name: "Price", - type: FieldType.NUMBER, - visible: true, - order: 1, - width: 100, - }, - Category: { - name: "Category", - type: FieldType.STRING, - visible: false, - icon: "ic", - }, - } as ViewV2Schema, - } - - const createdView = await config.api.viewV2.create(newView) - - expect(createdView).toEqual({ - ...newView, - schema: { - id: { visible: true }, - Price: { - visible: true, - order: 1, - width: 100, - }, - Category: { - visible: false, - icon: "ic", - }, - }, - id: createdView.id, - version: 2, - }) - }) - - it("will not throw an exception if the schema is 'deleting' non UI fields", async () => { - const newView: CreateViewRequest = { - name: generator.name(), - tableId: table._id!, - schema: { - id: { - name: "id", - type: FieldType.NUMBER, - autocolumn: true, - visible: true, - }, - Price: { - name: "Price", - type: FieldType.NUMBER, - visible: true, - }, - Category: { - name: "Category", - type: FieldType.STRING, - }, - } as ViewV2Schema, - } - - await config.api.viewV2.create(newView, { - status: 201, - }) - }) - - it("does not persist non-visible fields", async () => { - const newView: CreateViewRequest = { - name: generator.name(), - tableId: table._id!, - primaryDisplay: "id", - schema: { - id: { visible: true }, - Price: { visible: true }, - Category: { visible: false }, - }, - } - const res = await config.api.viewV2.create(newView) - - expect(res).toEqual({ - ...newView, - schema: { - id: { visible: true }, - Price: { visible: true }, - Category: { visible: false }, - }, - id: expect.any(String), - version: 2, - }) - }) - - it("throws bad request when the schema fields are not valid", async () => { - const newView: CreateViewRequest = { - name: generator.name(), - tableId: table._id!, - schema: { - id: { visible: true }, - nonExisting: { - visible: true, - }, - }, - } - await config.api.viewV2.create(newView, { - status: 400, - body: { - message: - 'Field "nonExisting" is not valid for the requested table', - }, - }) - }) - - describe("readonly fields", () => { - it("readonly fields are persisted", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - name: "name", - type: FieldType.STRING, + queryUI: { + logicalOperator: UILogicalOperator.ALL, + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + groups: [ + { + logicalOperator: UILogicalOperator.ALL, + filters: [ + { + operator: BasicOperator.EQUAL, + field: "field", + value: "value", + }, + ], }, - description: { - name: "description", - type: FieldType.STRING, - }, - }, - }) - ) + ], + }, + id: expect.any(String), + version: 2, + } + expect(res).toEqual(expected) + }) + + it("persist only UI schema overrides", async () => { const newView: CreateViewRequest = { name: generator.name(), tableId: table._id!, schema: { + id: { + name: "id", + type: FieldType.NUMBER, + visible: true, + }, + Price: { + name: "Price", + type: FieldType.NUMBER, + visible: true, + order: 1, + width: 100, + }, + Category: { + name: "Category", + type: FieldType.STRING, + visible: false, + icon: "ic", + }, + } as ViewV2Schema, + } + + const createdView = await config.api.viewV2.create(newView) + + expect(createdView).toEqual({ + ...newView, + schema: { + id: { visible: true }, + Price: { + visible: true, + order: 1, + width: 100, + }, + Category: { + visible: false, + icon: "ic", + }, + }, + id: createdView.id, + version: 2, + }) + }) + + it("will not throw an exception if the schema is 'deleting' non UI fields", async () => { + const newView: CreateViewRequest = { + name: generator.name(), + tableId: table._id!, + schema: { + id: { + name: "id", + type: FieldType.NUMBER, + autocolumn: true, + visible: true, + }, + Price: { + name: "Price", + type: FieldType.NUMBER, + visible: true, + }, + Category: { + name: "Category", + type: FieldType.STRING, + }, + } as ViewV2Schema, + } + + await config.api.viewV2.create(newView, { + status: 201, + }) + }) + + it("does not persist non-visible fields", async () => { + const newView: CreateViewRequest = { + name: generator.name(), + tableId: table._id!, + primaryDisplay: "id", + schema: { + id: { visible: true }, + Price: { visible: true }, + Category: { visible: false }, + }, + } + const res = await config.api.viewV2.create(newView) + + expect(res).toEqual({ + ...newView, + schema: { + id: { visible: true }, + Price: { visible: true }, + Category: { visible: false }, + }, + id: expect.any(String), + version: 2, + }) + }) + + it("throws bad request when the schema fields are not valid", async () => { + const newView: CreateViewRequest = { + name: generator.name(), + tableId: table._id!, + schema: { + id: { visible: true }, + nonExisting: { + visible: true, + }, + }, + } + await config.api.viewV2.create(newView, { + status: 400, + body: { + message: + 'Field "nonExisting" is not valid for the requested table', + }, + }) + }) + + describe("readonly fields", () => { + it("readonly fields are persisted", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + name: "name", + type: FieldType.STRING, + }, + description: { + name: "description", + type: FieldType.STRING, + }, + }, + }) + ) + + const newView: CreateViewRequest = { + name: generator.name(), + tableId: table._id!, + schema: { + id: { visible: true }, + name: { + visible: true, + readonly: true, + }, + description: { + visible: true, + readonly: true, + }, + }, + } + + const res = await config.api.viewV2.create(newView) + expect(res.schema).toEqual({ id: { visible: true }, name: { visible: true, @@ -401,63 +420,122 @@ datasourceDescribe( visible: true, readonly: true, }, - }, - } - - const res = await config.api.viewV2.create(newView) - expect(res.schema).toEqual({ - id: { visible: true }, - name: { - visible: true, - readonly: true, - }, - description: { - visible: true, - readonly: true, - }, - }) - }) - - it("required fields cannot be marked as readonly", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - name: "name", - type: FieldType.STRING, - constraints: { presence: true }, - }, - description: { - name: "description", - type: FieldType.STRING, - }, - }, }) - ) + }) - const newView: CreateViewRequest = { - name: generator.name(), - tableId: table._id!, - schema: { - id: { visible: true }, - name: { - visible: true, - readonly: true, + it("required fields cannot be marked as readonly", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + name: "name", + type: FieldType.STRING, + constraints: { presence: true }, + }, + description: { + name: "description", + type: FieldType.STRING, + }, + }, + }) + ) + + const newView: CreateViewRequest = { + name: generator.name(), + tableId: table._id!, + schema: { + id: { visible: true }, + name: { + visible: true, + readonly: true, + }, }, - }, - } + } - await config.api.viewV2.create(newView, { - status: 400, - body: { - message: - 'You can\'t make "name" readonly because it is a required field.', + await config.api.viewV2.create(newView, { status: 400, - }, + body: { + message: + 'You can\'t make "name" readonly because it is a required field.', + status: 400, + }, + }) + }) + + it("readonly fields must be visible", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + name: "name", + type: FieldType.STRING, + }, + description: { + name: "description", + type: FieldType.STRING, + }, + }, + }) + ) + + const newView: CreateViewRequest = { + name: generator.name(), + tableId: table._id!, + schema: { + id: { visible: true }, + name: { + visible: false, + readonly: true, + }, + }, + } + + await config.api.viewV2.create(newView, { + status: 400, + body: { + message: + 'Field "name" must be visible if you want to make it readonly', + status: 400, + }, + }) + }) + + it("readonly fields can be used on free license", async () => { + mocks.licenses.useCloudFree() + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + name: "name", + type: FieldType.STRING, + }, + description: { + name: "description", + type: FieldType.STRING, + }, + }, + }) + ) + + const newView: CreateViewRequest = { + name: generator.name(), + tableId: table._id!, + schema: { + id: { visible: true }, + name: { + visible: true, + readonly: true, + }, + }, + } + + await config.api.viewV2.create(newView, { + status: 201, + }) }) }) - it("readonly fields must be visible", async () => { + it("display fields must be visible", async () => { const table = await config.api.table.save( saveTableRequest({ schema: { @@ -476,11 +554,11 @@ datasourceDescribe( const newView: CreateViewRequest = { name: generator.name(), tableId: table._id!, + primaryDisplay: "name", schema: { id: { visible: true }, name: { visible: false, - readonly: true, }, }, } @@ -489,14 +567,13 @@ datasourceDescribe( status: 400, body: { message: - 'Field "name" must be visible if you want to make it readonly', + 'You can\'t hide "name" because it is the display column.', status: 400, }, }) }) - it("readonly fields can be used on free license", async () => { - mocks.licenses.useCloudFree() + it("display fields can be readonly", async () => { const table = await config.api.table.save( saveTableRequest({ schema: { @@ -515,6 +592,7 @@ datasourceDescribe( const newView: CreateViewRequest = { name: generator.name(), tableId: table._id!, + primaryDisplay: "name", schema: { id: { visible: true }, name: { @@ -528,134 +606,9 @@ datasourceDescribe( status: 201, }) }) - }) - it("display fields must be visible", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - name: "name", - type: FieldType.STRING, - }, - description: { - name: "description", - type: FieldType.STRING, - }, - }, - }) - ) - - const newView: CreateViewRequest = { - name: generator.name(), - tableId: table._id!, - primaryDisplay: "name", - schema: { - id: { visible: true }, - name: { - visible: false, - }, - }, - } - - await config.api.viewV2.create(newView, { - status: 400, - body: { - message: - 'You can\'t hide "name" because it is the display column.', - status: 400, - }, - }) - }) - - it("display fields can be readonly", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - name: "name", - type: FieldType.STRING, - }, - description: { - name: "description", - type: FieldType.STRING, - }, - }, - }) - ) - - const newView: CreateViewRequest = { - name: generator.name(), - tableId: table._id!, - primaryDisplay: "name", - schema: { - id: { visible: true }, - name: { - visible: true, - readonly: true, - }, - }, - } - - await config.api.viewV2.create(newView, { - status: 201, - }) - }) - - it("can create a view with calculation fields", async () => { - let view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - sum: { - visible: true, - calculationType: CalculationType.SUM, - field: "Price", - }, - }, - }) - - expect(Object.keys(view.schema!)).toHaveLength(1) - - let sum = view.schema!.sum as NumericCalculationFieldMetadata - expect(sum).toBeDefined() - expect(sum.calculationType).toEqual(CalculationType.SUM) - expect(sum.field).toEqual("Price") - - view = await config.api.viewV2.get(view.id) - sum = view.schema!.sum as NumericCalculationFieldMetadata - expect(sum).toBeDefined() - expect(sum.calculationType).toEqual(CalculationType.SUM) - expect(sum.field).toEqual("Price") - }) - - it("cannot create a view with calculation fields unless it has the right type", async () => { - await config.api.viewV2.create( - { - tableId: table._id!, - name: generator.guid(), - schema: { - sum: { - visible: true, - calculationType: CalculationType.SUM, - field: "Price", - }, - }, - }, - { - status: 400, - body: { - message: - "Calculation fields are not allowed in non-calculation views", - }, - } - ) - }) - - it("cannot create a calculation view with more than 5 aggregations", async () => { - await config.api.viewV2.create( - { + it("can create a view with calculation fields", async () => { + let view = await config.api.viewV2.create({ tableId: table._id!, name: generator.guid(), type: ViewV2Type.CALCULATION, @@ -665,622 +618,33 @@ datasourceDescribe( calculationType: CalculationType.SUM, field: "Price", }, - count: { - visible: true, - calculationType: CalculationType.COUNT, - field: "Price", - }, - countDistinct: { - visible: true, - calculationType: CalculationType.COUNT, - distinct: true, - field: "Price", - }, - min: { - visible: true, - calculationType: CalculationType.MIN, - field: "Price", - }, - max: { - visible: true, - calculationType: CalculationType.MAX, - field: "Price", - }, - avg: { - visible: true, - calculationType: CalculationType.AVG, - field: "Price", - }, - }, - }, - { - status: 400, - body: { - message: - "Calculation views can only have a maximum of 5 fields", - }, - } - ) - }) - - it("cannot create a calculation view with duplicate calculations", async () => { - await config.api.viewV2.create( - { - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - sum: { - visible: true, - calculationType: CalculationType.SUM, - field: "Price", - }, - sum2: { - visible: true, - calculationType: CalculationType.SUM, - field: "Price", - }, - }, - }, - { - status: 400, - body: { - message: - 'Duplicate calculation on field "Price", calculation type "sum"', - }, - } - ) - }) - - it("finds duplicate counts", async () => { - await config.api.viewV2.create( - { - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - count: { - visible: true, - calculationType: CalculationType.COUNT, - field: "Price", - }, - count2: { - visible: true, - calculationType: CalculationType.COUNT, - field: "Price", - }, - }, - }, - { - status: 400, - body: { - message: - 'Duplicate calculation on field "Price", calculation type "count"', - }, - } - ) - }) - - it("finds duplicate count distincts", async () => { - await config.api.viewV2.create( - { - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - count: { - visible: true, - calculationType: CalculationType.COUNT, - distinct: true, - field: "Price", - }, - count2: { - visible: true, - calculationType: CalculationType.COUNT, - distinct: true, - field: "Price", - }, - }, - }, - { - status: 400, - body: { - message: - 'Duplicate calculation on field "Price", calculation type "count distinct"', - }, - } - ) - }) - - it("does not confuse counts and count distincts in the duplicate check", async () => { - await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - count: { - visible: true, - calculationType: CalculationType.COUNT, - field: "Price", - }, - count2: { - visible: true, - calculationType: CalculationType.COUNT, - distinct: true, - field: "Price", - }, - }, - }) - }) - - it("does not confuse counts on different fields in the duplicate check", async () => { - await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - count: { - visible: true, - calculationType: CalculationType.COUNT, - field: "Price", - }, - count2: { - visible: true, - calculationType: CalculationType.COUNT, - field: "Category", - }, - }, - }) - }) - - it("does not get confused when a calculation field shadows a basic one", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - age: { - name: "age", - type: FieldType.NUMBER, - }, }, }) - ) - await config.api.row.bulkImport(table._id!, { - rows: [{ age: 1 }, { age: 2 }, { age: 3 }], + expect(Object.keys(view.schema!)).toHaveLength(1) + + let sum = view.schema!.sum as NumericCalculationFieldMetadata + expect(sum).toBeDefined() + expect(sum.calculationType).toEqual(CalculationType.SUM) + expect(sum.field).toEqual("Price") + + view = await config.api.viewV2.get(view.id) + sum = view.schema!.sum as NumericCalculationFieldMetadata + expect(sum).toBeDefined() + expect(sum.calculationType).toEqual(CalculationType.SUM) + expect(sum.field).toEqual("Price") }) - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - age: { - visible: true, - calculationType: CalculationType.SUM, - field: "age", - }, - }, - }) - - const { rows } = await config.api.row.search(view.id) - expect(rows).toHaveLength(1) - expect(rows[0].age).toEqual(6) - }) - - // We don't allow the creation of tables with most JsonTypes when using - // external datasources. - isInternal && - it("cannot use complex types as group-by fields", async () => { - for (const type of JsonTypes) { - const field = { name: "field", type } as FieldSchema - const table = await config.api.table.save( - saveTableRequest({ schema: { field } }) - ) - await config.api.viewV2.create( - { - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - field: { visible: true }, - }, - }, - { - status: 400, - body: { - message: `Grouping by fields of type "${type}" is not supported`, - }, - } - ) - } - }) - - isInternal && - it("shouldn't trigger a complex type check on a group by field if field is invisible", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - field: { - name: "field", - type: FieldType.JSON, - }, - }, - }) - ) - + it("cannot create a view with calculation fields unless it has the right type", async () => { await config.api.viewV2.create( { tableId: table._id!, name: generator.guid(), - type: ViewV2Type.CALCULATION, schema: { - field: { visible: false }, - }, - }, - { - status: 201, - } - ) - }) - }) - - describe("update", () => { - let view: ViewV2 - let table: Table - - beforeEach(async () => { - table = await config.api.table.save(priceTable()) - - view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - id: { visible: true }, - }, - }) - }) - - it("can update an existing view data", async () => { - const tableId = table._id! - await config.api.viewV2.update({ - ...view, - query: [ - { - operator: BasicOperator.EQUAL, - field: "newField", - value: "thatValue", - }, - ], - }) - - const expected: ViewV2 = { - ...view, - query: [ - { - operator: BasicOperator.EQUAL, - field: "newField", - value: "thatValue", - }, - ], - // Should also update queryUI because query was not previously set. - queryUI: { - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - logicalOperator: UILogicalOperator.ALL, - groups: [ - { - logicalOperator: UILogicalOperator.ALL, - filters: [ - { - operator: BasicOperator.EQUAL, - field: "newField", - value: "thatValue", - }, - ], - }, - ], - }, - schema: expect.anything(), - } - - expect((await config.api.table.get(tableId)).views).toEqual({ - [view.name]: expected, - }) - }) - - it("can update all fields", async () => { - const tableId = table._id! - - const updatedData: Required< - Omit - > = { - version: view.version, - id: view.id, - tableId, - name: view.name, - primaryDisplay: "Price", - query: [ - { - operator: BasicOperator.EQUAL, - field: "newField", - value: "newValue", - }, - ], - sort: { - field: generator.word(), - order: SortOrder.DESCENDING, - type: SortType.STRING, - }, - schema: { - id: { visible: true }, - Category: { - visible: false, - }, - Price: { - visible: true, - readonly: true, - }, - }, - } - await config.api.viewV2.update(updatedData) - - const expected: ViewV2 = { - ...updatedData, - // queryUI gets generated from query - queryUI: { - logicalOperator: UILogicalOperator.ALL, - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - groups: [ - { - logicalOperator: UILogicalOperator.ALL, - filters: [ - { - operator: BasicOperator.EQUAL, - field: "newField", - value: "newValue", - }, - ], - }, - ], - }, - schema: { - ...table.schema, - id: expect.objectContaining({ - visible: true, - }), - Category: expect.objectContaining({ - visible: false, - }), - Price: expect.objectContaining({ - visible: true, - readonly: true, - }), - }, - } - - expect((await config.api.table.get(tableId)).views).toEqual({ - [view.name]: expected, - }) - }) - - it("can update an existing view name", async () => { - const tableId = table._id! - const newName = generator.guid() - await config.api.viewV2.update({ ...view, name: newName }) - - expect(await config.api.table.get(tableId)).toEqual( - expect.objectContaining({ - views: { - [newName]: { - ...view, - name: newName, - schema: expect.anything(), - }, - }, - }) - ) - }) - - it("cannot update an unexisting views nor edit ids", async () => { - const tableId = table._id! - await config.api.viewV2.update( - { ...view, id: generator.guid() }, - { status: 404 } - ) - - expect(await config.api.table.get(tableId)).toEqual( - expect.objectContaining({ - views: { - [view.name]: { - ...view, - schema: expect.anything(), - }, - }, - }) - ) - }) - - it("cannot update views with the wrong tableId", async () => { - const tableId = table._id! - await config.api.viewV2.update( - { - ...view, - tableId: generator.guid(), - query: [ - { - operator: BasicOperator.EQUAL, - field: "newField", - value: "thatValue", - }, - ], - }, - { status: 404 } - ) - - expect(await config.api.table.get(tableId)).toEqual( - expect.objectContaining({ - views: { - [view.name]: { - ...view, - schema: expect.anything(), - }, - }, - }) - ) - }) - - isInternal && - it("cannot update views v1", async () => { - const viewV1 = await config.api.legacyView.save({ - tableId: table._id!, - name: generator.guid(), - filters: [], - schema: {}, - }) - - await config.api.viewV2.update(viewV1 as unknown as ViewV2, { - status: 400, - body: { - message: "Only views V2 can be updated", - status: 400, - }, - }) - }) - - it("cannot update the a view with unmatching ids between url and body", async () => { - const anotherView = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - id: { visible: true }, - }, - }) - const result = await config - .request!.put(`/api/v2/views/${anotherView.id}`) - .send(view) - .set(config.defaultHeaders()) - .expect("Content-Type", /json/) - .expect(400) - - expect(result.body).toEqual({ - message: "View id does not match between the body and the uri path", - status: 400, - }) - }) - - it("updates only UI schema overrides", async () => { - const updatedView = await config.api.viewV2.update({ - ...view, - schema: { - ...view.schema, - Price: { - name: "Price", - type: FieldType.NUMBER, - visible: true, - order: 1, - width: 100, - }, - Category: { - name: "Category", - type: FieldType.STRING, - visible: false, - icon: "ic", - }, - } as ViewV2Schema, - }) - - expect(updatedView).toEqual({ - ...view, - schema: { - id: { visible: true }, - Price: { - visible: true, - order: 1, - width: 100, - }, - Category: { visible: false, icon: "ic" }, - }, - id: view.id, - version: 2, - }) - }) - - it("will not throw an exception if the schema is 'deleting' non UI fields", async () => { - await config.api.viewV2.update( - { - ...view, - schema: { - ...view.schema, - Price: { - name: "Price", - type: FieldType.NUMBER, - visible: true, - }, - Category: { - name: "Category", - type: FieldType.STRING, - }, - } as ViewV2Schema, - }, - { - status: 200, - } - ) - }) - - it("cannot update view type after creation", async () => { - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - id: { visible: true }, - Price: { - visible: true, - }, - }, - }) - - await config.api.viewV2.update( - { - ...view, - type: ViewV2Type.CALCULATION, - }, - { - status: 400, - body: { - message: "Cannot update view type after creation", - }, - } - ) - }) - - isInternal && - it("updating schema will only validate modified field", async () => { - let view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - id: { visible: true }, - Price: { - visible: true, - }, - Category: { visible: true }, - }, - }) - - // Update the view to an invalid state - const tableToUpdate = await config.api.table.get(table._id!) - ;(tableToUpdate.views![view.name] as ViewV2).schema!.id.visible = - false - await db.getDB(config.appId!).put(tableToUpdate) - - view = await config.api.viewV2.get(view.id) - await config.api.viewV2.update( - { - ...view, - schema: { - ...view.schema, - Price: { - visible: false, + sum: { + visible: true, + calculationType: CalculationType.SUM, + field: "Price", }, }, }, @@ -1288,172 +652,196 @@ datasourceDescribe( status: 400, body: { message: - 'You can\'t hide "id" because it is a required field.', - status: 400, + "Calculation fields are not allowed in non-calculation views", }, } ) }) - it("can update queryUI field and query gets regenerated", async () => { - await config.api.viewV2.update({ - ...view, - queryUI: { - groups: [ - { - filters: [ - { - operator: BasicOperator.EQUAL, - field: "field", - value: "value", - }, - ], - }, - ], - }, - }) - - let updatedView = await config.api.viewV2.get(view.id) - let expected: SearchFilters = { - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - $and: { - conditions: [ - { - $and: { - conditions: [ - { - equal: { field: "value" }, - }, - ], - }, - }, - ], - }, - } - expect(updatedView.query).toEqual(expected) - - await config.api.viewV2.update({ - ...updatedView, - queryUI: { - groups: [ - { - filters: [ - { - operator: BasicOperator.EQUAL, - field: "newField", - value: "newValue", - }, - ], - }, - ], - }, - }) - - updatedView = await config.api.viewV2.get(view.id) - expected = { - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - $and: { - conditions: [ - { - $and: { - conditions: [ - { - equal: { newField: "newValue" }, - }, - ], - }, - }, - ], - }, - } - expect(updatedView.query).toEqual(expected) - }) - - it("can delete either query and it will get regenerated from queryUI", async () => { - await config.api.viewV2.update({ - ...view, - query: [ + it("cannot create a calculation view with more than 5 aggregations", async () => { + await config.api.viewV2.create( { - operator: BasicOperator.EQUAL, - field: "field", - value: "value", - }, - ], - }) - - let updatedView = await config.api.viewV2.get(view.id) - expect(updatedView.queryUI).toBeDefined() - - await config.api.viewV2.update({ - ...updatedView, - query: undefined, - }) - - updatedView = await config.api.viewV2.get(view.id) - expect(updatedView.query).toBeDefined() - }) - - // This is because the conversion from queryUI -> query loses data, so you - // can't accurately reproduce the original queryUI from the query. If - // query is a LegacyFilter[] we allow it, because for Budibase v3 - // everything in the db had query set to a LegacyFilter[], and there's no - // loss of information converting from a LegacyFilter[] to a - // UISearchFilter. But we convert to a SearchFilters and that can't be - // accurately converted to a UISearchFilter. - it("can't regenerate queryUI from a query once it has been generated from a queryUI", async () => { - await config.api.viewV2.update({ - ...view, - queryUI: { - groups: [ - { - filters: [ - { - operator: BasicOperator.EQUAL, - field: "field", - value: "value", - }, - ], + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + sum: { + visible: true, + calculationType: CalculationType.SUM, + field: "Price", + }, + count: { + visible: true, + calculationType: CalculationType.COUNT, + field: "Price", + }, + countDistinct: { + visible: true, + calculationType: CalculationType.COUNT, + distinct: true, + field: "Price", + }, + min: { + visible: true, + calculationType: CalculationType.MIN, + field: "Price", + }, + max: { + visible: true, + calculationType: CalculationType.MAX, + field: "Price", + }, + avg: { + visible: true, + calculationType: CalculationType.AVG, + field: "Price", + }, }, - ], - }, + }, + { + status: 400, + body: { + message: + "Calculation views can only have a maximum of 5 fields", + }, + } + ) }) - let updatedView = await config.api.viewV2.get(view.id) - expect(updatedView.query).toBeDefined() - - await config.api.viewV2.update( - { - ...updatedView, - queryUI: undefined, - }, - { - status: 400, - body: { - message: "view is missing queryUI field", + it("cannot create a calculation view with duplicate calculations", async () => { + await config.api.viewV2.create( + { + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + sum: { + visible: true, + calculationType: CalculationType.SUM, + field: "Price", + }, + sum2: { + visible: true, + calculationType: CalculationType.SUM, + field: "Price", + }, + }, }, - } - ) - }) + { + status: 400, + body: { + message: + 'Duplicate calculation on field "Price", calculation type "sum"', + }, + } + ) + }) - describe("calculation views", () => { - let table: Table - let view: ViewV2 + it("finds duplicate counts", async () => { + await config.api.viewV2.create( + { + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + count: { + visible: true, + calculationType: CalculationType.COUNT, + field: "Price", + }, + count2: { + visible: true, + calculationType: CalculationType.COUNT, + field: "Price", + }, + }, + }, + { + status: 400, + body: { + message: + 'Duplicate calculation on field "Price", calculation type "count"', + }, + } + ) + }) - beforeEach(async () => { - table = await config.api.table.save( + it("finds duplicate count distincts", async () => { + await config.api.viewV2.create( + { + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + count: { + visible: true, + calculationType: CalculationType.COUNT, + distinct: true, + field: "Price", + }, + count2: { + visible: true, + calculationType: CalculationType.COUNT, + distinct: true, + field: "Price", + }, + }, + }, + { + status: 400, + body: { + message: + 'Duplicate calculation on field "Price", calculation type "count distinct"', + }, + } + ) + }) + + it("does not confuse counts and count distincts in the duplicate check", async () => { + await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + count: { + visible: true, + calculationType: CalculationType.COUNT, + field: "Price", + }, + count2: { + visible: true, + calculationType: CalculationType.COUNT, + distinct: true, + field: "Price", + }, + }, + }) + }) + + it("does not confuse counts on different fields in the duplicate check", async () => { + await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + count: { + visible: true, + calculationType: CalculationType.COUNT, + field: "Price", + }, + count2: { + visible: true, + calculationType: CalculationType.COUNT, + field: "Category", + }, + }, + }) + }) + + it("does not get confused when a calculation field shadows a basic one", async () => { + const table = await config.api.table.save( saveTableRequest({ schema: { - name: { - name: "name", - type: FieldType.STRING, - constraints: { - presence: true, - }, - }, - country: { - name: "country", - type: FieldType.STRING, - }, age: { name: "age", type: FieldType.NUMBER, @@ -1462,14 +850,15 @@ datasourceDescribe( }) ) - view = await config.api.viewV2.create({ + await config.api.row.bulkImport(table._id!, { + rows: [{ age: 1 }, { age: 2 }, { age: 3 }], + }) + + const view = await config.api.viewV2.create({ tableId: table._id!, name: generator.guid(), type: ViewV2Type.CALCULATION, schema: { - country: { - visible: true, - }, age: { visible: true, calculationType: CalculationType.SUM, @@ -1478,774 +867,1200 @@ datasourceDescribe( }, }) - await config.api.row.bulkImport(table._id!, { - rows: [ + const { rows } = await config.api.row.search(view.id) + expect(rows).toHaveLength(1) + expect(rows[0].age).toEqual(6) + }) + + // We don't allow the creation of tables with most JsonTypes when using + // external datasources. + isInternal && + it("cannot use complex types as group-by fields", async () => { + for (const type of JsonTypes) { + const field = { name: "field", type } as FieldSchema + const table = await config.api.table.save( + saveTableRequest({ schema: { field } }) + ) + await config.api.viewV2.create( + { + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + field: { visible: true }, + }, + }, + { + status: 400, + body: { + message: `Grouping by fields of type "${type}" is not supported`, + }, + } + ) + } + }) + + isInternal && + it("shouldn't trigger a complex type check on a group by field if field is invisible", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + field: { + name: "field", + type: FieldType.JSON, + }, + }, + }) + ) + + await config.api.viewV2.create( { - name: "Steve", - age: 30, - country: "UK", + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + field: { visible: false }, + }, }, { - name: "Jane", - age: 31, - country: "UK", - }, + status: 201, + } + ) + }) + }) + + describe("update", () => { + let view: ViewV2 + let table: Table + + beforeEach(async () => { + table = await config.api.table.save(priceTable()) + + view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + schema: { + id: { visible: true }, + }, + }) + }) + + it("can update an existing view data", async () => { + const tableId = table._id! + await config.api.viewV2.update({ + ...view, + query: [ { - name: "Ruari", - age: 32, - country: "USA", - }, - { - name: "Alice", - age: 33, - country: "USA", + operator: BasicOperator.EQUAL, + field: "newField", + value: "thatValue", }, ], }) - }) - it("returns the expected rows prior to modification", async () => { - const { rows } = await config.api.row.search(view.id) - expect(rows).toHaveLength(2) - expect(rows).toEqual( - expect.arrayContaining([ + const expected: ViewV2 = { + ...view, + query: [ { - country: "USA", - age: 65, + operator: BasicOperator.EQUAL, + field: "newField", + value: "thatValue", }, - { - country: "UK", - age: 61, - }, - ]) - ) - }) - - it("can remove a group by field", async () => { - delete view.schema!.country - await config.api.viewV2.update(view) - - const { rows } = await config.api.row.search(view.id) - expect(rows).toHaveLength(1) - expect(rows).toEqual( - expect.arrayContaining([ - { - age: 126, - }, - ]) - ) - }) - - it("can remove a calculation field", async () => { - delete view.schema!.age - await config.api.viewV2.update(view) - - const { rows } = await config.api.row.search(view.id) - expect(rows).toHaveLength(4) - - // Because the removal of the calculation field actually makes this - // no longer a calculation view, these rows will now have _id and - // _rev fields. - expect(rows).toEqual( - expect.arrayContaining([ - expect.objectContaining({ country: "UK" }), - expect.objectContaining({ country: "UK" }), - expect.objectContaining({ country: "USA" }), - expect.objectContaining({ country: "USA" }), - ]) - ) - }) - - it("can add a new group by field", async () => { - view.schema!.name = { visible: true } - await config.api.viewV2.update(view) - - const { rows } = await config.api.row.search(view.id) - expect(rows).toHaveLength(4) - expect(rows).toEqual( - expect.arrayContaining([ - { - name: "Steve", - age: 30, - country: "UK", - }, - { - name: "Jane", - age: 31, - country: "UK", - }, - { - name: "Ruari", - age: 32, - country: "USA", - }, - { - name: "Alice", - age: 33, - country: "USA", - }, - ]) - ) - }) - - it("can add a new group by field that is invisible, even if required on the table", async () => { - view.schema!.name = { visible: false } - await config.api.viewV2.update(view) - - const { rows } = await config.api.row.search(view.id) - expect(rows).toHaveLength(2) - expect(rows).toEqual( - expect.arrayContaining([ - { - country: "USA", - age: 65, - }, - { - country: "UK", - age: 61, - }, - ]) - ) - }) - - it("can add a new calculation field", async () => { - view.schema!.count = { - visible: true, - calculationType: CalculationType.COUNT, - field: "age", - } - await config.api.viewV2.update(view) - - const { rows } = await config.api.row.search(view.id) - expect(rows).toHaveLength(2) - expect(rows).toEqual( - expect.arrayContaining([ - { - country: "USA", - age: 65, - count: 2, - }, - { - country: "UK", - age: 61, - count: 2, - }, - ]) - ) - }) - }) - }) - - describe("delete", () => { - let view: ViewV2 - - beforeAll(async () => { - view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - id: { visible: true }, - }, - }) - }) - - it("can delete an existing view", async () => { - const tableId = table._id! - const getPersistedView = async () => - (await config.api.table.get(tableId)).views![view.name] - - expect(await getPersistedView()).toBeDefined() - - await config.api.viewV2.delete(view.id) - - expect(await getPersistedView()).toBeUndefined() - }) - }) - - describe.each([ - ["from view api", (view: ViewV2) => config.api.viewV2.get(view.id)], - [ - "from table", - async (view: ViewV2) => { - const table = await config.api.table.get(view.tableId) - return table.views![view.name] as ViewV2 - }, - ], - ])("read (%s)", (_, getDelegate) => { - let table: Table - let tableId: string - - beforeEach(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - one: { - type: FieldType.STRING, - name: "one", - }, - two: { - type: FieldType.STRING, - name: "two", - }, - three: { - type: FieldType.STRING, - name: "three", - }, - }, - }) - ) - tableId = table._id! - }) - - it("retrieves the view data with the enriched schema", async () => { - const view = await config.api.viewV2.create({ - tableId, - name: generator.guid(), - schema: { - id: { visible: true }, - one: { visible: true }, - two: { visible: true }, - }, - }) - - expect(await getDelegate(view)).toEqual({ - ...view, - schema: { - id: { ...table.schema["id"], visible: true }, - one: { ...table.schema["one"], visible: true }, - two: { ...table.schema["two"], visible: true }, - three: { ...table.schema["three"], visible: false }, - }, - }) - }) - - it("does not include columns removed from the table", async () => { - const view = await config.api.viewV2.create({ - tableId, - name: generator.guid(), - schema: { - id: { visible: true }, - one: { visible: true }, - two: { visible: true }, - }, - }) - const table = await config.api.table.get(tableId) - const { one: _, ...newSchema } = table.schema - await config.api.table.save({ ...table, schema: newSchema }) - - expect(await getDelegate(view)).toEqual({ - ...view, - schema: { - id: { ...table.schema["id"], visible: true }, - two: { ...table.schema["two"], visible: true }, - three: { ...table.schema["three"], visible: false }, - }, - }) - }) - - it("does not include columns hidden from the table", async () => { - const view = await config.api.viewV2.create({ - tableId, - name: generator.guid(), - schema: { - id: { visible: true }, - one: { visible: true }, - two: { visible: true }, - }, - }) - const table = await config.api.table.get(tableId) - await config.api.table.save({ - ...table, - schema: { - ...table.schema, - two: { ...table.schema["two"], visible: false }, - }, - }) - - expect(await getDelegate(view)).toEqual({ - ...view, - schema: { - id: { ...table.schema["id"], visible: true }, - one: { ...table.schema["one"], visible: true }, - three: { ...table.schema["three"], visible: false }, - }, - }) - }) - - it("should be able to fetch readonly config after downgrades", async () => { - const res = await config.api.viewV2.create({ - name: generator.name(), - tableId: table._id!, - schema: { - id: { visible: true }, - one: { visible: true, readonly: true }, - }, - }) - - mocks.licenses.useCloudFree() - const view = await getDelegate(res) - expect(view.schema?.one).toEqual( - expect.objectContaining({ visible: true, readonly: true }) - ) - }) - - it("should fill in the queryUI field if it's missing", async () => { - const res = await config.api.viewV2.create({ - name: generator.name(), - tableId: tableId, - query: [ - { - operator: BasicOperator.EQUAL, - field: "one", - value: "1", - }, - ], - schema: { - id: { visible: true }, - one: { visible: true }, - }, - }) - - const table = await config.api.table.get(tableId) - const rawView = table.views![res.name] as ViewV2 - delete rawView.queryUI - - await context.doInAppContext(config.getAppId(), async () => { - const db = context.getAppDB() - - if (!rawDatasource) { - await db.put(table) - } else { - const ds = await config.api.datasource.get(datasource!._id!) - ds.entities![table.name] = table - const updatedDs = { - ...rawDatasource, - _id: ds._id, - _rev: ds._rev, - entities: ds.entities, - } - await db.put(updatedDs) - } - }) - - const view = await getDelegate(res) - const expected: UISearchFilter = { - onEmptyFilter: EmptyFilterOption.RETURN_ALL, - logicalOperator: UILogicalOperator.ALL, - groups: [ - { + ], + // Should also update queryUI because query was not previously set. + queryUI: { + onEmptyFilter: EmptyFilterOption.RETURN_ALL, logicalOperator: UILogicalOperator.ALL, - filters: [ + groups: [ { - operator: BasicOperator.EQUAL, - field: "one", - value: "1", + logicalOperator: UILogicalOperator.ALL, + filters: [ + { + operator: BasicOperator.EQUAL, + field: "newField", + value: "thatValue", + }, + ], }, ], }, - ], - } - expect(view.queryUI).toEqual(expected) - }) - }) + schema: expect.anything(), + } - describe("updating table schema", () => { - describe("existing columns changed to required", () => { - beforeEach(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - id: { - name: "id", - type: FieldType.NUMBER, - autocolumn: true, - }, - name: { - name: "name", - type: FieldType.STRING, - }, - }, - }) - ) - }) - - it("allows updating when no views constrains the field", async () => { - await config.api.viewV2.create({ - name: "view a", - tableId: table._id!, - schema: { - id: { visible: true }, - name: { visible: true }, - }, + expect((await config.api.table.get(tableId)).views).toEqual({ + [view.name]: expected, }) - - table = await config.api.table.get(table._id!) - await config.api.table.save( - { - ...table, - schema: { - ...table.schema, - name: { - name: "name", - type: FieldType.STRING, - constraints: { presence: { allowEmpty: false } }, - }, - }, - }, - { status: 200 } - ) }) - it("rejects if field is readonly in any view", async () => { - await config.api.viewV2.create({ - name: "view a", - tableId: table._id!, + it("can update all fields", async () => { + const tableId = table._id! + + const updatedData: Required< + Omit + > = { + version: view.version, + id: view.id, + tableId, + name: view.name, + primaryDisplay: "Price", + query: [ + { + operator: BasicOperator.EQUAL, + field: "newField", + value: "newValue", + }, + ], + sort: { + field: generator.word(), + order: SortOrder.DESCENDING, + type: SortType.STRING, + }, schema: { id: { visible: true }, - name: { + Category: { + visible: false, + }, + Price: { visible: true, readonly: true, }, }, - }) + } + await config.api.viewV2.update(updatedData) - table = await config.api.table.get(table._id!) - await config.api.table.save( - { - ...table, - schema: { - ...table.schema, - name: { - name: "name", - type: FieldType.STRING, - constraints: { presence: true }, + const expected: ViewV2 = { + ...updatedData, + // queryUI gets generated from query + queryUI: { + logicalOperator: UILogicalOperator.ALL, + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + groups: [ + { + logicalOperator: UILogicalOperator.ALL, + filters: [ + { + operator: BasicOperator.EQUAL, + field: "newField", + value: "newValue", + }, + ], + }, + ], + }, + schema: { + ...table.schema, + id: expect.objectContaining({ + visible: true, + }), + Category: expect.objectContaining({ + visible: false, + }), + Price: expect.objectContaining({ + visible: true, + readonly: true, + }), + }, + } + + expect((await config.api.table.get(tableId)).views).toEqual({ + [view.name]: expected, + }) + }) + + it("can update an existing view name", async () => { + const tableId = table._id! + const newName = generator.guid() + await config.api.viewV2.update({ ...view, name: newName }) + + expect(await config.api.table.get(tableId)).toEqual( + expect.objectContaining({ + views: { + [newName]: { + ...view, + name: newName, + schema: expect.anything(), }, }, + }) + ) + }) + + it("cannot update an unexisting views nor edit ids", async () => { + const tableId = table._id! + await config.api.viewV2.update( + { ...view, id: generator.guid() }, + { status: 404 } + ) + + expect(await config.api.table.get(tableId)).toEqual( + expect.objectContaining({ + views: { + [view.name]: { + ...view, + schema: expect.anything(), + }, + }, + }) + ) + }) + + it("cannot update views with the wrong tableId", async () => { + const tableId = table._id! + await config.api.viewV2.update( + { + ...view, + tableId: generator.guid(), + query: [ + { + operator: BasicOperator.EQUAL, + field: "newField", + value: "thatValue", + }, + ], + }, + { status: 404 } + ) + + expect(await config.api.table.get(tableId)).toEqual( + expect.objectContaining({ + views: { + [view.name]: { + ...view, + schema: expect.anything(), + }, + }, + }) + ) + }) + + isInternal && + it("cannot update views v1", async () => { + const viewV1 = await config.api.legacyView.save({ + tableId: table._id!, + name: generator.guid(), + filters: [], + schema: {}, + }) + + await config.api.viewV2.update(viewV1 as unknown as ViewV2, { + status: 400, + body: { + message: "Only views V2 can be updated", + status: 400, + }, + }) + }) + + it("cannot update the a view with unmatching ids between url and body", async () => { + const anotherView = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + schema: { + id: { visible: true }, + }, + }) + const result = await config + .request!.put(`/api/v2/views/${anotherView.id}`) + .send(view) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(400) + + expect(result.body).toEqual({ + message: + "View id does not match between the body and the uri path", + status: 400, + }) + }) + + it("updates only UI schema overrides", async () => { + const updatedView = await config.api.viewV2.update({ + ...view, + schema: { + ...view.schema, + Price: { + name: "Price", + type: FieldType.NUMBER, + visible: true, + order: 1, + width: 100, + }, + Category: { + name: "Category", + type: FieldType.STRING, + visible: false, + icon: "ic", + }, + } as ViewV2Schema, + }) + + expect(updatedView).toEqual({ + ...view, + schema: { + id: { visible: true }, + Price: { + visible: true, + order: 1, + width: 100, + }, + Category: { visible: false, icon: "ic" }, + }, + id: view.id, + version: 2, + }) + }) + + it("will not throw an exception if the schema is 'deleting' non UI fields", async () => { + await config.api.viewV2.update( + { + ...view, + schema: { + ...view.schema, + Price: { + name: "Price", + type: FieldType.NUMBER, + visible: true, + }, + Category: { + name: "Category", + type: FieldType.STRING, + }, + } as ViewV2Schema, + }, + { + status: 200, + } + ) + }) + + it("cannot update view type after creation", async () => { + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + schema: { + id: { visible: true }, + Price: { + visible: true, + }, + }, + }) + + await config.api.viewV2.update( + { + ...view, + type: ViewV2Type.CALCULATION, }, { status: 400, body: { - status: 400, - message: - 'To make field "name" required, this field must be present and writable in views: view a.', + message: "Cannot update view type after creation", }, } ) }) - it("rejects if field is hidden in any view", async () => { - await config.api.viewV2.create({ - name: "view a", - tableId: table._id!, - schema: { id: { visible: true } }, - }) - - table = await config.api.table.get(table._id!) - await config.api.table.save( - { - ...table, + isInternal && + it("updating schema will only validate modified field", async () => { + let view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), schema: { - ...table.schema, - name: { - name: "name", - type: FieldType.STRING, - constraints: { presence: true }, + id: { visible: true }, + Price: { + visible: true, + }, + Category: { visible: true }, + }, + }) + + // Update the view to an invalid state + const tableToUpdate = await config.api.table.get(table._id!) + ;(tableToUpdate.views![view.name] as ViewV2).schema!.id.visible = + false + await db.getDB(config.appId!).put(tableToUpdate) + + view = await config.api.viewV2.get(view.id) + await config.api.viewV2.update( + { + ...view, + schema: { + ...view.schema, + Price: { + visible: false, + }, }, }, + { + status: 400, + body: { + message: + 'You can\'t hide "id" because it is a required field.', + status: 400, + }, + } + ) + }) + + it("can update queryUI field and query gets regenerated", async () => { + await config.api.viewV2.update({ + ...view, + queryUI: { + groups: [ + { + filters: [ + { + operator: BasicOperator.EQUAL, + field: "field", + value: "value", + }, + ], + }, + ], + }, + }) + + let updatedView = await config.api.viewV2.get(view.id) + let expected: SearchFilters = { + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + $and: { + conditions: [ + { + $and: { + conditions: [ + { + equal: { field: "value" }, + }, + ], + }, + }, + ], + }, + } + expect(updatedView.query).toEqual(expected) + + await config.api.viewV2.update({ + ...updatedView, + queryUI: { + groups: [ + { + filters: [ + { + operator: BasicOperator.EQUAL, + field: "newField", + value: "newValue", + }, + ], + }, + ], + }, + }) + + updatedView = await config.api.viewV2.get(view.id) + expected = { + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + $and: { + conditions: [ + { + $and: { + conditions: [ + { + equal: { newField: "newValue" }, + }, + ], + }, + }, + ], + }, + } + expect(updatedView.query).toEqual(expected) + }) + + it("can delete either query and it will get regenerated from queryUI", async () => { + await config.api.viewV2.update({ + ...view, + query: [ + { + operator: BasicOperator.EQUAL, + field: "field", + value: "value", + }, + ], + }) + + let updatedView = await config.api.viewV2.get(view.id) + expect(updatedView.queryUI).toBeDefined() + + await config.api.viewV2.update({ + ...updatedView, + query: undefined, + }) + + updatedView = await config.api.viewV2.get(view.id) + expect(updatedView.query).toBeDefined() + }) + + // This is because the conversion from queryUI -> query loses data, so you + // can't accurately reproduce the original queryUI from the query. If + // query is a LegacyFilter[] we allow it, because for Budibase v3 + // everything in the db had query set to a LegacyFilter[], and there's no + // loss of information converting from a LegacyFilter[] to a + // UISearchFilter. But we convert to a SearchFilters and that can't be + // accurately converted to a UISearchFilter. + it("can't regenerate queryUI from a query once it has been generated from a queryUI", async () => { + await config.api.viewV2.update({ + ...view, + queryUI: { + groups: [ + { + filters: [ + { + operator: BasicOperator.EQUAL, + field: "field", + value: "value", + }, + ], + }, + ], + }, + }) + + let updatedView = await config.api.viewV2.get(view.id) + expect(updatedView.query).toBeDefined() + + await config.api.viewV2.update( + { + ...updatedView, + queryUI: undefined, }, { status: 400, body: { - status: 400, - message: - 'To make field "name" required, this field must be present and writable in views: view a.', + message: "view is missing queryUI field", }, } ) }) + + describe("calculation views", () => { + let table: Table + let view: ViewV2 + + beforeEach(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + name: "name", + type: FieldType.STRING, + constraints: { + presence: true, + }, + }, + country: { + name: "country", + type: FieldType.STRING, + }, + age: { + name: "age", + type: FieldType.NUMBER, + }, + }, + }) + ) + + view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + country: { + visible: true, + }, + age: { + visible: true, + calculationType: CalculationType.SUM, + field: "age", + }, + }, + }) + + await config.api.row.bulkImport(table._id!, { + rows: [ + { + name: "Steve", + age: 30, + country: "UK", + }, + { + name: "Jane", + age: 31, + country: "UK", + }, + { + name: "Ruari", + age: 32, + country: "USA", + }, + { + name: "Alice", + age: 33, + country: "USA", + }, + ], + }) + }) + + it("returns the expected rows prior to modification", async () => { + const { rows } = await config.api.row.search(view.id) + expect(rows).toHaveLength(2) + expect(rows).toEqual( + expect.arrayContaining([ + { + country: "USA", + age: 65, + }, + { + country: "UK", + age: 61, + }, + ]) + ) + }) + + it("can remove a group by field", async () => { + delete view.schema!.country + await config.api.viewV2.update(view) + + const { rows } = await config.api.row.search(view.id) + expect(rows).toHaveLength(1) + expect(rows).toEqual( + expect.arrayContaining([ + { + age: 126, + }, + ]) + ) + }) + + it("can remove a calculation field", async () => { + delete view.schema!.age + await config.api.viewV2.update(view) + + const { rows } = await config.api.row.search(view.id) + expect(rows).toHaveLength(4) + + // Because the removal of the calculation field actually makes this + // no longer a calculation view, these rows will now have _id and + // _rev fields. + expect(rows).toEqual( + expect.arrayContaining([ + expect.objectContaining({ country: "UK" }), + expect.objectContaining({ country: "UK" }), + expect.objectContaining({ country: "USA" }), + expect.objectContaining({ country: "USA" }), + ]) + ) + }) + + it("can add a new group by field", async () => { + view.schema!.name = { visible: true } + await config.api.viewV2.update(view) + + const { rows } = await config.api.row.search(view.id) + expect(rows).toHaveLength(4) + expect(rows).toEqual( + expect.arrayContaining([ + { + name: "Steve", + age: 30, + country: "UK", + }, + { + name: "Jane", + age: 31, + country: "UK", + }, + { + name: "Ruari", + age: 32, + country: "USA", + }, + { + name: "Alice", + age: 33, + country: "USA", + }, + ]) + ) + }) + + it("can add a new group by field that is invisible, even if required on the table", async () => { + view.schema!.name = { visible: false } + await config.api.viewV2.update(view) + + const { rows } = await config.api.row.search(view.id) + expect(rows).toHaveLength(2) + expect(rows).toEqual( + expect.arrayContaining([ + { + country: "USA", + age: 65, + }, + { + country: "UK", + age: 61, + }, + ]) + ) + }) + + it("can add a new calculation field", async () => { + view.schema!.count = { + visible: true, + calculationType: CalculationType.COUNT, + field: "age", + } + await config.api.viewV2.update(view) + + const { rows } = await config.api.row.search(view.id) + expect(rows).toHaveLength(2) + expect(rows).toEqual( + expect.arrayContaining([ + { + country: "USA", + age: 65, + count: 2, + }, + { + country: "UK", + age: 61, + count: 2, + }, + ]) + ) + }) + }) }) - describe("foreign relationship columns", () => { - const createAuxTable = () => - config.api.table.save( + describe("delete", () => { + let view: ViewV2 + + beforeAll(async () => { + view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + schema: { + id: { visible: true }, + }, + }) + }) + + it("can delete an existing view", async () => { + const tableId = table._id! + const getPersistedView = async () => + (await config.api.table.get(tableId)).views![view.name] + + expect(await getPersistedView()).toBeDefined() + + await config.api.viewV2.delete(view.id) + + expect(await getPersistedView()).toBeUndefined() + }) + }) + + describe.each([ + ["from view api", (view: ViewV2) => config.api.viewV2.get(view.id)], + [ + "from table", + async (view: ViewV2) => { + const table = await config.api.table.get(view.tableId) + return table.views![view.name] as ViewV2 + }, + ], + ])("read (%s)", (_, getDelegate) => { + let table: Table + let tableId: string + + beforeEach(async () => { + table = await config.api.table.save( saveTableRequest({ - primaryDisplay: "name", schema: { - name: { name: "name", type: FieldType.STRING }, - age: { name: "age", type: FieldType.NUMBER }, + one: { + type: FieldType.STRING, + name: "one", + }, + two: { + type: FieldType.STRING, + name: "two", + }, + three: { + type: FieldType.STRING, + name: "three", + }, }, }) ) + tableId = table._id! + }) - const createMainTable = async ( - links: { - name: string - tableId: string - fk: string - }[] - ) => { - const table = await config.api.table.save( - saveTableRequest({ - schema: {}, - }) - ) + it("retrieves the view data with the enriched schema", async () => { + const view = await config.api.viewV2.create({ + tableId, + name: generator.guid(), + schema: { + id: { visible: true }, + one: { visible: true }, + two: { visible: true }, + }, + }) + + expect(await getDelegate(view)).toEqual({ + ...view, + schema: { + id: { ...table.schema["id"], visible: true }, + one: { ...table.schema["one"], visible: true }, + two: { ...table.schema["two"], visible: true }, + three: { ...table.schema["three"], visible: false }, + }, + }) + }) + + it("does not include columns removed from the table", async () => { + const view = await config.api.viewV2.create({ + tableId, + name: generator.guid(), + schema: { + id: { visible: true }, + one: { visible: true }, + two: { visible: true }, + }, + }) + const table = await config.api.table.get(tableId) + const { one: _, ...newSchema } = table.schema + await config.api.table.save({ ...table, schema: newSchema }) + + expect(await getDelegate(view)).toEqual({ + ...view, + schema: { + id: { ...table.schema["id"], visible: true }, + two: { ...table.schema["two"], visible: true }, + three: { ...table.schema["three"], visible: false }, + }, + }) + }) + + it("does not include columns hidden from the table", async () => { + const view = await config.api.viewV2.create({ + tableId, + name: generator.guid(), + schema: { + id: { visible: true }, + one: { visible: true }, + two: { visible: true }, + }, + }) + const table = await config.api.table.get(tableId) await config.api.table.save({ ...table, schema: { ...table.schema, - ...links.reduce((acc, c) => { - acc[c.name] = { - name: c.name, - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: c.tableId, - fieldName: c.fk, - constraints: { type: "array" }, - } - return acc - }, {}), + two: { ...table.schema["two"], visible: false }, }, }) - return table - } - const createView = async (tableId: string, schema: ViewV2Schema) => - await config.api.viewV2.create({ - name: generator.guid(), - tableId, - schema, + expect(await getDelegate(view)).toEqual({ + ...view, + schema: { + id: { ...table.schema["id"], visible: true }, + one: { ...table.schema["one"], visible: true }, + three: { ...table.schema["three"], visible: false }, + }, + }) + }) + + it("should be able to fetch readonly config after downgrades", async () => { + const res = await config.api.viewV2.create({ + name: generator.name(), + tableId: table._id!, + schema: { + id: { visible: true }, + one: { visible: true, readonly: true }, + }, }) - const renameColumn = async (table: Table, renaming: RenameColumn) => { - const newSchema = { ...table.schema } - newSchema[renaming.updated] = { - ...table.schema[renaming.old], - name: renaming.updated, + mocks.licenses.useCloudFree() + const view = await getDelegate(res) + expect(view.schema?.one).toEqual( + expect.objectContaining({ visible: true, readonly: true }) + ) + }) + + it("should fill in the queryUI field if it's missing", async () => { + const res = await config.api.viewV2.create({ + name: generator.name(), + tableId: tableId, + query: [ + { + operator: BasicOperator.EQUAL, + field: "one", + value: "1", + }, + ], + schema: { + id: { visible: true }, + one: { visible: true }, + }, + }) + + const table = await config.api.table.get(tableId) + const rawView = table.views![res.name] as ViewV2 + delete rawView.queryUI + + await context.doInAppContext(config.getAppId(), async () => { + const db = context.getAppDB() + + if (!rawDatasource) { + await db.put(table) + } else { + const ds = await config.api.datasource.get(datasource!._id!) + ds.entities![table.name] = table + const updatedDs = { + ...rawDatasource, + _id: ds._id, + _rev: ds._rev, + entities: ds.entities, + } + await db.put(updatedDs) + } + }) + + const view = await getDelegate(res) + const expected: UISearchFilter = { + onEmptyFilter: EmptyFilterOption.RETURN_ALL, + logicalOperator: UILogicalOperator.ALL, + groups: [ + { + logicalOperator: UILogicalOperator.ALL, + filters: [ + { + operator: BasicOperator.EQUAL, + field: "one", + value: "1", + }, + ], + }, + ], } - delete newSchema[renaming.old] + expect(view.queryUI).toEqual(expected) + }) + }) - await config.api.table.save({ - ...table, - schema: newSchema, - _rename: renaming, - }) - } - - it("updating a column will update link columns configuration", async () => { - let auxTable = await createAuxTable() - - const table = await createMainTable([ - { name: "aux", tableId: auxTable._id!, fk: "fk_aux" }, - ]) - // Refetch auxTable - auxTable = await config.api.table.get(auxTable._id!) - - const view = await createView(table._id!, { - aux: { - visible: true, - columns: { - name: { visible: true, readonly: true }, - age: { visible: true, readonly: true }, - }, - }, - }) - - await renameColumn(auxTable, { old: "age", updated: "dob" }) - - const updatedView = await config.api.viewV2.get(view.id) - expect(updatedView).toEqual( - expect.objectContaining({ - schema: expect.objectContaining({ - aux: expect.objectContaining({ - columns: { - id: expect.objectContaining({ - visible: false, - readonly: false, - }), - name: expect.objectContaining({ - visible: true, - readonly: true, - }), - dob: expect.objectContaining({ - visible: true, - readonly: true, - }), + describe("updating table schema", () => { + describe("existing columns changed to required", () => { + beforeEach(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + id: { + name: "id", + type: FieldType.NUMBER, + autocolumn: true, }, - }), - }), + name: { + name: "name", + type: FieldType.STRING, + }, + }, + }) + ) + }) + + it("allows updating when no views constrains the field", async () => { + await config.api.viewV2.create({ + name: "view a", + tableId: table._id!, + schema: { + id: { visible: true }, + name: { visible: true }, + }, }) - ) + + table = await config.api.table.get(table._id!) + await config.api.table.save( + { + ...table, + schema: { + ...table.schema, + name: { + name: "name", + type: FieldType.STRING, + constraints: { presence: { allowEmpty: false } }, + }, + }, + }, + { status: 200 } + ) + }) + + it("rejects if field is readonly in any view", async () => { + await config.api.viewV2.create({ + name: "view a", + tableId: table._id!, + schema: { + id: { visible: true }, + name: { + visible: true, + readonly: true, + }, + }, + }) + + table = await config.api.table.get(table._id!) + await config.api.table.save( + { + ...table, + schema: { + ...table.schema, + name: { + name: "name", + type: FieldType.STRING, + constraints: { presence: true }, + }, + }, + }, + { + status: 400, + body: { + status: 400, + message: + 'To make field "name" required, this field must be present and writable in views: view a.', + }, + } + ) + }) + + it("rejects if field is hidden in any view", async () => { + await config.api.viewV2.create({ + name: "view a", + tableId: table._id!, + schema: { id: { visible: true } }, + }) + + table = await config.api.table.get(table._id!) + await config.api.table.save( + { + ...table, + schema: { + ...table.schema, + name: { + name: "name", + type: FieldType.STRING, + constraints: { presence: true }, + }, + }, + }, + { + status: 400, + body: { + status: 400, + message: + 'To make field "name" required, this field must be present and writable in views: view a.', + }, + } + ) + }) }) - it("handles multiple fields using the same table", async () => { - let auxTable = await createAuxTable() + describe("foreign relationship columns", () => { + const createAuxTable = () => + config.api.table.save( + saveTableRequest({ + primaryDisplay: "name", + schema: { + name: { name: "name", type: FieldType.STRING }, + age: { name: "age", type: FieldType.NUMBER }, + }, + }) + ) - const table = await createMainTable([ - { name: "aux", tableId: auxTable._id!, fk: "fk_aux" }, - { name: "aux2", tableId: auxTable._id!, fk: "fk_aux2" }, - ]) - // Refetch auxTable - auxTable = await config.api.table.get(auxTable._id!) - - const view = await createView(table._id!, { - aux: { - visible: true, - columns: { - name: { visible: true, readonly: true }, - age: { visible: true, readonly: true }, + const createMainTable = async ( + links: { + name: string + tableId: string + fk: string + }[] + ) => { + const table = await config.api.table.save( + saveTableRequest({ + schema: {}, + }) + ) + await config.api.table.save({ + ...table, + schema: { + ...table.schema, + ...links.reduce((acc, c) => { + acc[c.name] = { + name: c.name, + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: c.tableId, + fieldName: c.fk, + constraints: { type: "array" }, + } + return acc + }, {}), }, - }, - aux2: { - visible: true, - columns: { - name: { visible: true, readonly: true }, - age: { visible: true, readonly: true }, - }, - }, - }) - - await renameColumn(auxTable, { old: "age", updated: "dob" }) - - const updatedView = await config.api.viewV2.get(view.id) - expect(updatedView).toEqual( - expect.objectContaining({ - schema: expect.objectContaining({ - aux: expect.objectContaining({ - columns: { - id: expect.objectContaining({ - visible: false, - readonly: false, - }), - name: expect.objectContaining({ - visible: true, - readonly: true, - }), - dob: expect.objectContaining({ - visible: true, - readonly: true, - }), - }, - }), - aux2: expect.objectContaining({ - columns: { - id: expect.objectContaining({ - visible: false, - readonly: false, - }), - name: expect.objectContaining({ - visible: true, - readonly: true, - }), - dob: expect.objectContaining({ - visible: true, - readonly: true, - }), - }, - }), - }), }) - ) - }) - - it("does not rename columns with the same name but from other tables", async () => { - let auxTable = await createAuxTable() - let aux2Table = await createAuxTable() - - const table = await createMainTable([ - { name: "aux", tableId: auxTable._id!, fk: "fk_aux" }, - { name: "aux2", tableId: aux2Table._id!, fk: "fk_aux2" }, - ]) - - // Refetch auxTable - auxTable = await config.api.table.get(auxTable._id!) - - const view = await createView(table._id!, { - aux: { - visible: true, - columns: { - name: { visible: true, readonly: true }, - }, - }, - aux2: { - visible: true, - columns: { - name: { visible: true, readonly: true }, - }, - }, - }) - - await renameColumn(auxTable, { old: "name", updated: "fullName" }) - - const updatedView = await config.api.viewV2.get(view.id) - expect(updatedView).toEqual( - expect.objectContaining({ - schema: expect.objectContaining({ - aux: expect.objectContaining({ - columns: { - id: expect.objectContaining({ - visible: false, - readonly: false, - }), - fullName: expect.objectContaining({ - visible: true, - readonly: true, - }), - age: expect.objectContaining({ - visible: false, - readonly: false, - }), - }, - }), - aux2: expect.objectContaining({ - columns: { - id: expect.objectContaining({ - visible: false, - readonly: false, - }), - name: expect.objectContaining({ - visible: true, - readonly: true, - }), - age: expect.objectContaining({ - visible: false, - readonly: false, - }), - }, - }), - }), - }) - ) - }) - - it("updates all views references", async () => { - let auxTable = await createAuxTable() - - const table1 = await createMainTable([ - { name: "aux", tableId: auxTable._id!, fk: "fk_aux_table1" }, - ]) - const table2 = await createMainTable([ - { name: "aux", tableId: auxTable._id!, fk: "fk_aux_table2" }, - ]) - - // Refetch auxTable - auxTable = await config.api.table.get(auxTable._id!) - - const viewSchema = { - aux: { - visible: true, - columns: { - name: { visible: true, readonly: true }, - age: { visible: true, readonly: true }, - }, - }, + return table } - const view1 = await createView(table1._id!, viewSchema) - const view2 = await createView(table1._id!, viewSchema) - const view3 = await createView(table2._id!, viewSchema) - await renameColumn(auxTable, { old: "age", updated: "dob" }) + const createView = async (tableId: string, schema: ViewV2Schema) => + await config.api.viewV2.create({ + name: generator.guid(), + tableId, + schema, + }) + + const renameColumn = async ( + table: Table, + renaming: RenameColumn + ) => { + const newSchema = { ...table.schema } + newSchema[renaming.updated] = { + ...table.schema[renaming.old], + name: renaming.updated, + } + delete newSchema[renaming.old] + + await config.api.table.save({ + ...table, + schema: newSchema, + _rename: renaming, + }) + } + + it("updating a column will update link columns configuration", async () => { + let auxTable = await createAuxTable() + + const table = await createMainTable([ + { name: "aux", tableId: auxTable._id!, fk: "fk_aux" }, + ]) + // Refetch auxTable + auxTable = await config.api.table.get(auxTable._id!) + + const view = await createView(table._id!, { + aux: { + visible: true, + columns: { + name: { visible: true, readonly: true }, + age: { visible: true, readonly: true }, + }, + }, + }) + + await renameColumn(auxTable, { old: "age", updated: "dob" }) - for (const view of [view1, view2, view3]) { const updatedView = await config.api.viewV2.get(view.id) expect(updatedView).toEqual( expect.objectContaining({ @@ -2269,74 +2084,605 @@ datasourceDescribe( }), }) ) - } + }) + + it("handles multiple fields using the same table", async () => { + let auxTable = await createAuxTable() + + const table = await createMainTable([ + { name: "aux", tableId: auxTable._id!, fk: "fk_aux" }, + { name: "aux2", tableId: auxTable._id!, fk: "fk_aux2" }, + ]) + // Refetch auxTable + auxTable = await config.api.table.get(auxTable._id!) + + const view = await createView(table._id!, { + aux: { + visible: true, + columns: { + name: { visible: true, readonly: true }, + age: { visible: true, readonly: true }, + }, + }, + aux2: { + visible: true, + columns: { + name: { visible: true, readonly: true }, + age: { visible: true, readonly: true }, + }, + }, + }) + + await renameColumn(auxTable, { old: "age", updated: "dob" }) + + const updatedView = await config.api.viewV2.get(view.id) + expect(updatedView).toEqual( + expect.objectContaining({ + schema: expect.objectContaining({ + aux: expect.objectContaining({ + columns: { + id: expect.objectContaining({ + visible: false, + readonly: false, + }), + name: expect.objectContaining({ + visible: true, + readonly: true, + }), + dob: expect.objectContaining({ + visible: true, + readonly: true, + }), + }, + }), + aux2: expect.objectContaining({ + columns: { + id: expect.objectContaining({ + visible: false, + readonly: false, + }), + name: expect.objectContaining({ + visible: true, + readonly: true, + }), + dob: expect.objectContaining({ + visible: true, + readonly: true, + }), + }, + }), + }), + }) + ) + }) + + it("does not rename columns with the same name but from other tables", async () => { + let auxTable = await createAuxTable() + let aux2Table = await createAuxTable() + + const table = await createMainTable([ + { name: "aux", tableId: auxTable._id!, fk: "fk_aux" }, + { name: "aux2", tableId: aux2Table._id!, fk: "fk_aux2" }, + ]) + + // Refetch auxTable + auxTable = await config.api.table.get(auxTable._id!) + + const view = await createView(table._id!, { + aux: { + visible: true, + columns: { + name: { visible: true, readonly: true }, + }, + }, + aux2: { + visible: true, + columns: { + name: { visible: true, readonly: true }, + }, + }, + }) + + await renameColumn(auxTable, { old: "name", updated: "fullName" }) + + const updatedView = await config.api.viewV2.get(view.id) + expect(updatedView).toEqual( + expect.objectContaining({ + schema: expect.objectContaining({ + aux: expect.objectContaining({ + columns: { + id: expect.objectContaining({ + visible: false, + readonly: false, + }), + fullName: expect.objectContaining({ + visible: true, + readonly: true, + }), + age: expect.objectContaining({ + visible: false, + readonly: false, + }), + }, + }), + aux2: expect.objectContaining({ + columns: { + id: expect.objectContaining({ + visible: false, + readonly: false, + }), + name: expect.objectContaining({ + visible: true, + readonly: true, + }), + age: expect.objectContaining({ + visible: false, + readonly: false, + }), + }, + }), + }), + }) + ) + }) + + it("updates all views references", async () => { + let auxTable = await createAuxTable() + + const table1 = await createMainTable([ + { name: "aux", tableId: auxTable._id!, fk: "fk_aux_table1" }, + ]) + const table2 = await createMainTable([ + { name: "aux", tableId: auxTable._id!, fk: "fk_aux_table2" }, + ]) + + // Refetch auxTable + auxTable = await config.api.table.get(auxTable._id!) + + const viewSchema = { + aux: { + visible: true, + columns: { + name: { visible: true, readonly: true }, + age: { visible: true, readonly: true }, + }, + }, + } + const view1 = await createView(table1._id!, viewSchema) + const view2 = await createView(table1._id!, viewSchema) + const view3 = await createView(table2._id!, viewSchema) + + await renameColumn(auxTable, { old: "age", updated: "dob" }) + + for (const view of [view1, view2, view3]) { + const updatedView = await config.api.viewV2.get(view.id) + expect(updatedView).toEqual( + expect.objectContaining({ + schema: expect.objectContaining({ + aux: expect.objectContaining({ + columns: { + id: expect.objectContaining({ + visible: false, + readonly: false, + }), + name: expect.objectContaining({ + visible: true, + readonly: true, + }), + dob: expect.objectContaining({ + visible: true, + readonly: true, + }), + }, + }), + }), + }) + ) + } + }) + }) + }) + + describe("calculation views", () => { + it("should not remove calculation columns when modifying table schema", async () => { + let table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + name: "name", + type: FieldType.STRING, + }, + age: { + name: "age", + type: FieldType.NUMBER, + }, + }, + }) + ) + + let view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + sum: { + visible: true, + calculationType: CalculationType.SUM, + field: "age", + }, + }, + }) + + table = await config.api.table.get(table._id!) + await config.api.table.save({ + ...table, + schema: { + ...table.schema, + name: { + name: "name", + type: FieldType.STRING, + constraints: { presence: true }, + }, + }, + }) + + view = await config.api.viewV2.get(view.id) + expect(Object.keys(view.schema!).sort()).toEqual([ + "age", + "id", + "name", + "sum", + ]) + }) + + describe("bigints", () => { + let table: Table + let view: ViewV2 + + beforeEach(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + bigint: { + name: "bigint", + type: FieldType.BIGINT, + }, + }, + }) + ) + + view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + sum: { + visible: true, + calculationType: CalculationType.SUM, + field: "bigint", + }, + }, + }) + }) + + it("should not lose precision handling ints larger than JSs int53", async () => { + // The sum of the following 3 numbers cannot be represented by + // JavaScripts default int53 datatype for numbers, so this is a test + // that makes sure we aren't losing precision between the DB and the + // user. + await config.api.row.bulkImport(table._id!, { + rows: [ + { bigint: "1000000000000000000" }, + { bigint: "123" }, + { bigint: "321" }, + ], + }) + + const { rows } = await config.api.row.search(view.id) + expect(rows).toHaveLength(1) + expect(rows[0].sum).toEqual("1000000000000000444") + }) + + it("should be able to handle up to 2**63 - 1 bigints", async () => { + await config.api.row.bulkImport(table._id!, { + rows: [{ bigint: "9223372036854775806" }, { bigint: "1" }], + }) + + const { rows } = await config.api.row.search(view.id) + expect(rows).toHaveLength(1) + expect(rows[0].sum).toEqual("9223372036854775807") + }) }) }) }) - describe("calculation views", () => { - it("should not remove calculation columns when modifying table schema", async () => { - let table = await config.api.table.save( + describe("row operations", () => { + let table: Table, view: ViewV2 + beforeEach(async () => { + table = await config.api.table.save( saveTableRequest({ schema: { - name: { - name: "name", + one: { type: FieldType.STRING, name: "one" }, + two: { type: FieldType.STRING, name: "two" }, + default: { type: FieldType.STRING, - }, - age: { - name: "age", - type: FieldType.NUMBER, + name: "default", + default: "default", }, }, }) ) - - let view = await config.api.viewV2.create({ + view = await config.api.viewV2.create({ tableId: table._id!, name: generator.guid(), - type: ViewV2Type.CALCULATION, schema: { - sum: { - visible: true, - calculationType: CalculationType.SUM, - field: "age", - }, + id: { visible: true }, + two: { visible: true }, }, }) - - table = await config.api.table.get(table._id!) - await config.api.table.save({ - ...table, - schema: { - ...table.schema, - name: { - name: "name", - type: FieldType.STRING, - constraints: { presence: true }, - }, - }, - }) - - view = await config.api.viewV2.get(view.id) - expect(Object.keys(view.schema!).sort()).toEqual([ - "age", - "id", - "name", - "sum", - ]) }) - describe("bigints", () => { - let table: Table - let view: ViewV2 + describe("create", () => { + it("should persist a new row with only the provided view fields", async () => { + const newRow = await config.api.row.save(view.id, { + tableId: table!._id, + _viewId: view.id, + one: "foo", + two: "bar", + default: "ohnoes", + }) - beforeEach(async () => { + const row = await config.api.row.get(table._id!, newRow._id!) + expect(row.one).toBeUndefined() + expect(row.two).toEqual("bar") + expect(row.default).toEqual("default") + }) + + it("can't persist readonly columns", async () => { + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + schema: { + id: { visible: true }, + one: { visible: true, readonly: true }, + two: { visible: true }, + }, + }) + const row = await config.api.row.save(view.id, { + tableId: table!._id, + _viewId: view.id, + one: "foo", + two: "bar", + }) + + expect(row.one).toBeUndefined() + expect(row.two).toEqual("bar") + }) + + it("should not return non-view view fields for a row", async () => { + const newRow = await config.api.row.save(view.id, { + one: "foo", + two: "bar", + }) + + expect(newRow.one).toBeUndefined() + expect(newRow.two).toEqual("bar") + }) + + it("should not be possible to create a row in a calculation view", async () => { + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + id: { visible: true }, + one: { visible: true }, + }, + }) + + await config.api.row.save( + view.id, + { one: "foo" }, + { + status: 400, + body: { + message: "Cannot insert rows through a calculation view", + status: 400, + }, + } + ) + }) + }) + + describe("patch", () => { + it("should not return non-view view fields for a row", async () => { + const newRow = await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + const row = await config.api.row.patch(view.id, { + tableId: table._id!, + _id: newRow._id!, + _rev: newRow._rev!, + one: "newFoo", + two: "newBar", + }) + + expect(row.one).toBeUndefined() + expect(row.two).toEqual("newBar") + }) + + it("should update only the view fields for a row", async () => { + const newRow = await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + await config.api.row.patch(view.id, { + tableId: table._id!, + _id: newRow._id!, + _rev: newRow._rev!, + one: "newFoo", + two: "newBar", + }) + + const row = await config.api.row.get(table._id!, newRow._id!) + expect(row.one).toEqual("foo") + expect(row.two).toEqual("newBar") + }) + + it("can't update readonly columns", async () => { + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + schema: { + id: { visible: true }, + one: { visible: true, readonly: true }, + two: { visible: true }, + }, + }) + const newRow = await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + await config.api.row.patch(view.id, { + tableId: table._id!, + _id: newRow._id!, + _rev: newRow._rev!, + one: "newFoo", + two: "newBar", + }) + + const row = await config.api.row.get(table._id!, newRow._id!) + expect(row.one).toEqual("foo") + expect(row.two).toEqual("newBar") + }) + + it("should not be possible to modify a row in a calculation view", async () => { + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + id: { visible: true }, + one: { visible: true }, + }, + }) + + const newRow = await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + + await config.api.row.patch( + view.id, + { + tableId: table._id!, + _id: newRow._id!, + _rev: newRow._rev!, + one: "newFoo", + two: "newBar", + }, + { + status: 400, + body: { + message: "Cannot update rows through a calculation view", + }, + } + ) + }) + }) + + describe("destroy", () => { + const getRowUsage = async () => { + const { total } = await config.doInContext(undefined, () => + quotas.getCurrentUsageValues( + QuotaUsageType.STATIC, + StaticQuotaName.ROWS + ) + ) + return total + } + + const assertRowUsage = async (expected: number) => { + const usage = await getRowUsage() + expect(usage).toBe(expected) + } + + it("should be able to delete a row", async () => { + const createdRow = await config.api.row.save(table._id!, {}) + const rowUsage = await getRowUsage() + await config.api.row.bulkDelete(view.id, { rows: [createdRow] }) + await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) + await config.api.row.get(table._id!, createdRow._id!, { + status: 404, + }) + }) + + it("should be able to delete multiple rows", async () => { + const rows = await Promise.all([ + config.api.row.save(table._id!, {}), + config.api.row.save(table._id!, {}), + config.api.row.save(table._id!, {}), + ]) + const rowUsage = await getRowUsage() + + await config.api.row.bulkDelete(view.id, { + rows: [rows[0], rows[2]], + }) + + await assertRowUsage(isInternal ? rowUsage - 2 : rowUsage) + + await config.api.row.get(table._id!, rows[0]._id!, { + status: 404, + }) + await config.api.row.get(table._id!, rows[2]._id!, { + status: 404, + }) + await config.api.row.get(table._id!, rows[1]._id!, { status: 200 }) + }) + + it("should not be possible to delete a row in a calculation view", async () => { + const row = await config.api.row.save(table._id!, {}) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + id: { visible: true }, + one: { visible: true }, + }, + }) + + await config.api.row.delete( + view.id, + { _id: row._id! }, + { + status: 400, + body: { + message: "Cannot delete rows through a calculation view", + status: 400, + }, + } + ) + }) + }) + + describe("read", () => { + let view: ViewV2 + let table: Table + + beforeAll(async () => { table = await config.api.table.save( saveTableRequest({ schema: { - bigint: { - name: "bigint", - type: FieldType.BIGINT, + Country: { + type: FieldType.STRING, + name: "Country", + }, + Story: { + type: FieldType.STRING, + name: "Story", }, }, }) @@ -2345,852 +2691,552 @@ datasourceDescribe( view = await config.api.viewV2.create({ tableId: table._id!, name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - sum: { - visible: true, - calculationType: CalculationType.SUM, - field: "bigint", - }, - }, - }) - }) - - it("should not lose precision handling ints larger than JSs int53", async () => { - // The sum of the following 3 numbers cannot be represented by - // JavaScripts default int53 datatype for numbers, so this is a test - // that makes sure we aren't losing precision between the DB and the - // user. - await config.api.row.bulkImport(table._id!, { - rows: [ - { bigint: "1000000000000000000" }, - { bigint: "123" }, - { bigint: "321" }, - ], - }) - - const { rows } = await config.api.row.search(view.id) - expect(rows).toHaveLength(1) - expect(rows[0].sum).toEqual("1000000000000000444") - }) - - it("should be able to handle up to 2**63 - 1 bigints", async () => { - await config.api.row.bulkImport(table._id!, { - rows: [{ bigint: "9223372036854775806" }, { bigint: "1" }], - }) - - const { rows } = await config.api.row.search(view.id) - expect(rows).toHaveLength(1) - expect(rows[0].sum).toEqual("9223372036854775807") - }) - }) - }) - }) - - describe("row operations", () => { - let table: Table, view: ViewV2 - beforeEach(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - one: { type: FieldType.STRING, name: "one" }, - two: { type: FieldType.STRING, name: "two" }, - default: { - type: FieldType.STRING, - name: "default", - default: "default", - }, - }, - }) - ) - view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - id: { visible: true }, - two: { visible: true }, - }, - }) - }) - - describe("create", () => { - it("should persist a new row with only the provided view fields", async () => { - const newRow = await config.api.row.save(view.id, { - tableId: table!._id, - _viewId: view.id, - one: "foo", - two: "bar", - default: "ohnoes", - }) - - const row = await config.api.row.get(table._id!, newRow._id!) - expect(row.one).toBeUndefined() - expect(row.two).toEqual("bar") - expect(row.default).toEqual("default") - }) - - it("can't persist readonly columns", async () => { - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - id: { visible: true }, - one: { visible: true, readonly: true }, - two: { visible: true }, - }, - }) - const row = await config.api.row.save(view.id, { - tableId: table!._id, - _viewId: view.id, - one: "foo", - two: "bar", - }) - - expect(row.one).toBeUndefined() - expect(row.two).toEqual("bar") - }) - - it("should not return non-view view fields for a row", async () => { - const newRow = await config.api.row.save(view.id, { - one: "foo", - two: "bar", - }) - - expect(newRow.one).toBeUndefined() - expect(newRow.two).toEqual("bar") - }) - - it("should not be possible to create a row in a calculation view", async () => { - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - id: { visible: true }, - one: { visible: true }, - }, - }) - - await config.api.row.save( - view.id, - { one: "foo" }, - { - status: 400, - body: { - message: "Cannot insert rows through a calculation view", - status: 400, - }, - } - ) - }) - }) - - describe("patch", () => { - it("should not return non-view view fields for a row", async () => { - const newRow = await config.api.row.save(table._id!, { - one: "foo", - two: "bar", - }) - const row = await config.api.row.patch(view.id, { - tableId: table._id!, - _id: newRow._id!, - _rev: newRow._rev!, - one: "newFoo", - two: "newBar", - }) - - expect(row.one).toBeUndefined() - expect(row.two).toEqual("newBar") - }) - - it("should update only the view fields for a row", async () => { - const newRow = await config.api.row.save(table._id!, { - one: "foo", - two: "bar", - }) - await config.api.row.patch(view.id, { - tableId: table._id!, - _id: newRow._id!, - _rev: newRow._rev!, - one: "newFoo", - two: "newBar", - }) - - const row = await config.api.row.get(table._id!, newRow._id!) - expect(row.one).toEqual("foo") - expect(row.two).toEqual("newBar") - }) - - it("can't update readonly columns", async () => { - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - id: { visible: true }, - one: { visible: true, readonly: true }, - two: { visible: true }, - }, - }) - const newRow = await config.api.row.save(table._id!, { - one: "foo", - two: "bar", - }) - await config.api.row.patch(view.id, { - tableId: table._id!, - _id: newRow._id!, - _rev: newRow._rev!, - one: "newFoo", - two: "newBar", - }) - - const row = await config.api.row.get(table._id!, newRow._id!) - expect(row.one).toEqual("foo") - expect(row.two).toEqual("newBar") - }) - - it("should not be possible to modify a row in a calculation view", async () => { - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - id: { visible: true }, - one: { visible: true }, - }, - }) - - const newRow = await config.api.row.save(table._id!, { - one: "foo", - two: "bar", - }) - - await config.api.row.patch( - view.id, - { - tableId: table._id!, - _id: newRow._id!, - _rev: newRow._rev!, - one: "newFoo", - two: "newBar", - }, - { - status: 400, - body: { - message: "Cannot update rows through a calculation view", - }, - } - ) - }) - }) - - describe("destroy", () => { - const getRowUsage = async () => { - const { total } = await config.doInContext(undefined, () => - quotas.getCurrentUsageValues( - QuotaUsageType.STATIC, - StaticQuotaName.ROWS - ) - ) - return total - } - - const assertRowUsage = async (expected: number) => { - const usage = await getRowUsage() - expect(usage).toBe(expected) - } - - it("should be able to delete a row", async () => { - const createdRow = await config.api.row.save(table._id!, {}) - const rowUsage = await getRowUsage() - await config.api.row.bulkDelete(view.id, { rows: [createdRow] }) - await assertRowUsage(isInternal ? rowUsage - 1 : rowUsage) - await config.api.row.get(table._id!, createdRow._id!, { - status: 404, - }) - }) - - it("should be able to delete multiple rows", async () => { - const rows = await Promise.all([ - config.api.row.save(table._id!, {}), - config.api.row.save(table._id!, {}), - config.api.row.save(table._id!, {}), - ]) - const rowUsage = await getRowUsage() - - await config.api.row.bulkDelete(view.id, { rows: [rows[0], rows[2]] }) - - await assertRowUsage(isInternal ? rowUsage - 2 : rowUsage) - - await config.api.row.get(table._id!, rows[0]._id!, { - status: 404, - }) - await config.api.row.get(table._id!, rows[2]._id!, { - status: 404, - }) - await config.api.row.get(table._id!, rows[1]._id!, { status: 200 }) - }) - - it("should not be possible to delete a row in a calculation view", async () => { - const row = await config.api.row.save(table._id!, {}) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - id: { visible: true }, - one: { visible: true }, - }, - }) - - await config.api.row.delete( - view.id, - { _id: row._id! }, - { - status: 400, - body: { - message: "Cannot delete rows through a calculation view", - status: 400, - }, - } - ) - }) - }) - - describe("read", () => { - let view: ViewV2 - let table: Table - - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ schema: { + id: { visible: true }, Country: { - type: FieldType.STRING, - name: "Country", - }, - Story: { - type: FieldType.STRING, - name: "Story", + visible: true, }, }, }) - ) + }) - view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - id: { visible: true }, - Country: { - visible: true, - }, - }, + it("views have extra data trimmed", async () => { + let row = await config.api.row.save(view.id, { + Country: "Aussy", + Story: "aaaaa", + }) + + row = await config.api.row.get(table._id!, row._id!) + expect(row.Story).toBeUndefined() + expect(row.Country).toEqual("Aussy") }) }) - it("views have extra data trimmed", async () => { - let row = await config.api.row.save(view.id, { - Country: "Aussy", - Story: "aaaaa", - }) - - row = await config.api.row.get(table._id!, row._id!) - expect(row.Story).toBeUndefined() - expect(row.Country).toEqual("Aussy") - }) - }) - - describe("search", () => { - it("returns empty rows from view when no schema is passed", async () => { - const rows = await Promise.all( - Array.from({ length: 10 }, () => - config.api.row.save(table._id!, {}) + describe("search", () => { + it("returns empty rows from view when no schema is passed", async () => { + const rows = await Promise.all( + Array.from({ length: 10 }, () => + config.api.row.save(table._id!, {}) + ) ) - ) - const response = await config.api.viewV2.search(view.id) - expect(response.rows).toHaveLength(10) - expect(response).toEqual({ - rows: expect.arrayContaining( - rows.map(r => ({ - _viewId: view.id, - tableId: table._id, - id: r.id, - _id: r._id, - _rev: r._rev, - ...(isInternal - ? { - type: "row", - updatedAt: expect.any(String), - createdAt: expect.any(String), - } - : {}), - })) - ), - ...(isInternal - ? {} - : { - hasNextPage: false, - }), - }) - }) - - it("searching respects the view filters", async () => { - await config.api.row.save(table._id!, { - one: "foo", - two: "bar", - }) - const two = await config.api.row.save(table._id!, { - one: "foo2", - two: "bar2", - }) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - queryUI: { - groups: [ - { - filters: [ - { - operator: BasicOperator.EQUAL, - field: "two", - value: "bar2", - }, - ], - }, - ], - }, - schema: { - id: { visible: true }, - one: { visible: false }, - two: { visible: true }, - }, - }) - - const response = await config.api.viewV2.search(view.id) - expect(response.rows).toHaveLength(1) - expect(response).toEqual({ - rows: expect.arrayContaining([ - { - _viewId: view.id, - tableId: table._id, - id: two.id, - two: two.two, - _id: two._id, - _rev: two._rev, - ...(isInternal - ? { - type: "row", - createdAt: expect.any(String), - updatedAt: expect.any(String), - } - : {}), - }, - ]), - ...(isInternal - ? {} - : { - hasNextPage: false, - }), - }) - }) - - it("views filters are respected even if the column is hidden", async () => { - await config.api.row.save(table._id!, { - one: "foo", - two: "bar", - }) - const two = await config.api.row.save(table._id!, { - one: "foo2", - two: "bar2", - }) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - queryUI: { - groups: [ - { - filters: [ - { - operator: BasicOperator.EQUAL, - field: "two", - value: "bar2", - }, - ], - }, - ], - }, - schema: { - id: { visible: true }, - one: { visible: false }, - two: { visible: false }, - }, - }) - - const response = await config.api.viewV2.search(view.id) - expect(response.rows).toHaveLength(1) - expect(response.rows).toEqual([ - expect.objectContaining({ _id: two._id }), - ]) - }) - - it("views without data can be returned", async () => { - const response = await config.api.viewV2.search(view.id) - expect(response.rows).toHaveLength(0) - }) - - it("respects the limit parameter", async () => { - await Promise.all( - Array.from({ length: 10 }, () => - config.api.row.save(table._id!, {}) - ) - ) - const limit = generator.integer({ min: 1, max: 8 }) - const response = await config.api.viewV2.search(view.id, { - limit, - query: {}, - }) - expect(response.rows).toHaveLength(limit) - }) - - it("can handle pagination", async () => { - await Promise.all( - Array.from({ length: 10 }, () => - config.api.row.save(table._id!, {}) - ) - ) - const rows = (await config.api.viewV2.search(view.id)).rows - - const page1 = await config.api.viewV2.search(view.id, { - paginate: true, - limit: 4, - query: {}, - countRows: true, - }) - expect(page1).toEqual({ - rows: expect.arrayContaining(rows.slice(0, 4)), - hasNextPage: true, - bookmark: expect.anything(), - totalRows: 10, - }) - - const page2 = await config.api.viewV2.search(view.id, { - paginate: true, - limit: 4, - bookmark: page1.bookmark, - query: {}, - countRows: true, - }) - expect(page2).toEqual({ - rows: expect.arrayContaining(rows.slice(4, 8)), - hasNextPage: true, - bookmark: expect.anything(), - totalRows: 10, - }) - - const page3 = await config.api.viewV2.search(view.id, { - paginate: true, - limit: 4, - bookmark: page2.bookmark, - query: {}, - countRows: true, - }) - const expectation: SearchResponse = { - rows: expect.arrayContaining(rows.slice(8)), - hasNextPage: false, - totalRows: 10, - } - expect(page3).toEqual(expectation) - }) - - const sortTestOptions: [ - { - field: string - order?: SortOrder - type?: SortType - }, - string[] - ][] = [ - [ - { - field: "name", - order: SortOrder.ASCENDING, - type: SortType.STRING, - }, - ["Alice", "Bob", "Charly", "Danny"], - ], - [ - { - field: "name", - }, - ["Alice", "Bob", "Charly", "Danny"], - ], - [ - { - field: "name", - order: SortOrder.DESCENDING, - }, - ["Danny", "Charly", "Bob", "Alice"], - ], - [ - { - field: "name", - order: SortOrder.DESCENDING, - type: SortType.STRING, - }, - ["Danny", "Charly", "Bob", "Alice"], - ], - [ - { - field: "age", - order: SortOrder.ASCENDING, - type: SortType.NUMBER, - }, - ["Danny", "Alice", "Charly", "Bob"], - ], - [ - { - field: "age", - order: SortOrder.ASCENDING, - }, - ["Danny", "Alice", "Charly", "Bob"], - ], - [ - { - field: "age", - order: SortOrder.DESCENDING, - }, - ["Bob", "Charly", "Alice", "Danny"], - ], - [ - { - field: "age", - order: SortOrder.DESCENDING, - type: SortType.NUMBER, - }, - ["Bob", "Charly", "Alice", "Danny"], - ], - ] - - describe("sorting", () => { - let table: Table - const viewSchema = { - id: { visible: true }, - age: { visible: true }, - name: { visible: true }, - } - - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - type: "table", - schema: { - name: { - type: FieldType.STRING, - name: "name", - }, - surname: { - type: FieldType.STRING, - name: "surname", - }, - age: { - type: FieldType.NUMBER, - name: "age", - }, - address: { - type: FieldType.STRING, - name: "address", - }, - jobTitle: { - type: FieldType.STRING, - name: "jobTitle", - }, - }, - }) - ) - - const users = [ - { name: "Alice", age: 25 }, - { name: "Bob", age: 30 }, - { name: "Charly", age: 27 }, - { name: "Danny", age: 15 }, - ] - await Promise.all( - users.map(u => - config.api.row.save(table._id!, { + const response = await config.api.viewV2.search(view.id) + expect(response.rows).toHaveLength(10) + expect(response).toEqual({ + rows: expect.arrayContaining( + rows.map(r => ({ + _viewId: view.id, tableId: table._id, - ...u, + id: r.id, + _id: r._id, + _rev: r._rev, + ...(isInternal + ? { + type: "row", + updatedAt: expect.any(String), + createdAt: expect.any(String), + } + : {}), + })) + ), + ...(isInternal + ? {} + : { + hasNextPage: false, + }), + }) + }) + + it("searching respects the view filters", async () => { + await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + const two = await config.api.row.save(table._id!, { + one: "foo2", + two: "bar2", + }) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + queryUI: { + groups: [ + { + filters: [ + { + operator: BasicOperator.EQUAL, + field: "two", + value: "bar2", + }, + ], + }, + ], + }, + schema: { + id: { visible: true }, + one: { visible: false }, + two: { visible: true }, + }, + }) + + const response = await config.api.viewV2.search(view.id) + expect(response.rows).toHaveLength(1) + expect(response).toEqual({ + rows: expect.arrayContaining([ + { + _viewId: view.id, + tableId: table._id, + id: two.id, + two: two.two, + _id: two._id, + _rev: two._rev, + ...(isInternal + ? { + type: "row", + createdAt: expect.any(String), + updatedAt: expect.any(String), + } + : {}), + }, + ]), + ...(isInternal + ? {} + : { + hasNextPage: false, + }), + }) + }) + + it("views filters are respected even if the column is hidden", async () => { + await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + const two = await config.api.row.save(table._id!, { + one: "foo2", + two: "bar2", + }) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + queryUI: { + groups: [ + { + filters: [ + { + operator: BasicOperator.EQUAL, + field: "two", + value: "bar2", + }, + ], + }, + ], + }, + schema: { + id: { visible: true }, + one: { visible: false }, + two: { visible: false }, + }, + }) + + const response = await config.api.viewV2.search(view.id) + expect(response.rows).toHaveLength(1) + expect(response.rows).toEqual([ + expect.objectContaining({ _id: two._id }), + ]) + }) + + it("views without data can be returned", async () => { + const response = await config.api.viewV2.search(view.id) + expect(response.rows).toHaveLength(0) + }) + + it("respects the limit parameter", async () => { + await Promise.all( + Array.from({ length: 10 }, () => + config.api.row.save(table._id!, {}) + ) + ) + const limit = generator.integer({ min: 1, max: 8 }) + const response = await config.api.viewV2.search(view.id, { + limit, + query: {}, + }) + expect(response.rows).toHaveLength(limit) + }) + + it("can handle pagination", async () => { + await Promise.all( + Array.from({ length: 10 }, () => + config.api.row.save(table._id!, {}) + ) + ) + const rows = (await config.api.viewV2.search(view.id)).rows + + const page1 = await config.api.viewV2.search(view.id, { + paginate: true, + limit: 4, + query: {}, + countRows: true, + }) + expect(page1).toEqual({ + rows: expect.arrayContaining(rows.slice(0, 4)), + hasNextPage: true, + bookmark: expect.anything(), + totalRows: 10, + }) + + const page2 = await config.api.viewV2.search(view.id, { + paginate: true, + limit: 4, + bookmark: page1.bookmark, + query: {}, + countRows: true, + }) + expect(page2).toEqual({ + rows: expect.arrayContaining(rows.slice(4, 8)), + hasNextPage: true, + bookmark: expect.anything(), + totalRows: 10, + }) + + const page3 = await config.api.viewV2.search(view.id, { + paginate: true, + limit: 4, + bookmark: page2.bookmark, + query: {}, + countRows: true, + }) + const expectation: SearchResponse = { + rows: expect.arrayContaining(rows.slice(8)), + hasNextPage: false, + totalRows: 10, + } + expect(page3).toEqual(expectation) + }) + + const sortTestOptions: [ + { + field: string + order?: SortOrder + type?: SortType + }, + string[] + ][] = [ + [ + { + field: "name", + order: SortOrder.ASCENDING, + type: SortType.STRING, + }, + ["Alice", "Bob", "Charly", "Danny"], + ], + [ + { + field: "name", + }, + ["Alice", "Bob", "Charly", "Danny"], + ], + [ + { + field: "name", + order: SortOrder.DESCENDING, + }, + ["Danny", "Charly", "Bob", "Alice"], + ], + [ + { + field: "name", + order: SortOrder.DESCENDING, + type: SortType.STRING, + }, + ["Danny", "Charly", "Bob", "Alice"], + ], + [ + { + field: "age", + order: SortOrder.ASCENDING, + type: SortType.NUMBER, + }, + ["Danny", "Alice", "Charly", "Bob"], + ], + [ + { + field: "age", + order: SortOrder.ASCENDING, + }, + ["Danny", "Alice", "Charly", "Bob"], + ], + [ + { + field: "age", + order: SortOrder.DESCENDING, + }, + ["Bob", "Charly", "Alice", "Danny"], + ], + [ + { + field: "age", + order: SortOrder.DESCENDING, + type: SortType.NUMBER, + }, + ["Bob", "Charly", "Alice", "Danny"], + ], + ] + + describe("sorting", () => { + let table: Table + const viewSchema = { + id: { visible: true }, + age: { visible: true }, + name: { visible: true }, + } + + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + type: "table", + schema: { + name: { + type: FieldType.STRING, + name: "name", + }, + surname: { + type: FieldType.STRING, + name: "surname", + }, + age: { + type: FieldType.NUMBER, + name: "age", + }, + address: { + type: FieldType.STRING, + name: "address", + }, + jobTitle: { + type: FieldType.STRING, + name: "jobTitle", + }, + }, }) ) + + const users = [ + { name: "Alice", age: 25 }, + { name: "Bob", age: 30 }, + { name: "Charly", age: 27 }, + { name: "Danny", age: 15 }, + ] + await Promise.all( + users.map(u => + config.api.row.save(table._id!, { + tableId: table._id, + ...u, + }) + ) + ) + }) + + it.each(sortTestOptions)( + "allow sorting (%s)", + async (sortParams, expected) => { + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + sort: sortParams, + schema: viewSchema, + }) + + const response = await config.api.viewV2.search(view.id) + + expect(response.rows).toHaveLength(4) + expect(response.rows).toEqual( + expected.map(name => expect.objectContaining({ name })) + ) + } + ) + + it.each(sortTestOptions)( + "allow override the default view sorting (%s)", + async (sortParams, expected) => { + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + sort: { + field: "name", + order: SortOrder.ASCENDING, + type: SortType.STRING, + }, + schema: viewSchema, + }) + + const response = await config.api.viewV2.search(view.id, { + sort: sortParams.field, + sortOrder: sortParams.order, + sortType: sortParams.type, + query: {}, + }) + + expect(response.rows).toHaveLength(4) + expect(response.rows).toEqual( + expected.map(name => expect.objectContaining({ name })) + ) + } ) }) - it.each(sortTestOptions)( - "allow sorting (%s)", - async (sortParams, expected) => { - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - sort: sortParams, - schema: viewSchema, + it("can query on top of the view filters", async () => { + await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + await config.api.row.save(table._id!, { + one: "foo2", + two: "bar2", + }) + const three = await config.api.row.save(table._id!, { + one: "foo3", + two: "bar3", + }) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + queryUI: { + groups: [ + { + filters: [ + { + operator: BasicOperator.NOT_EQUAL, + field: "one", + value: "foo2", + }, + ], + }, + ], + }, + schema: { + id: { visible: true }, + one: { visible: true }, + two: { visible: true }, + }, + }) + + const response = await config.api.viewV2.search(view.id, { + query: { + [BasicOperator.EQUAL]: { + two: "bar3", + }, + [BasicOperator.NOT_EMPTY]: { + two: null, + }, + }, + }) + expect(response.rows).toHaveLength(1) + expect(response.rows).toEqual( + expect.arrayContaining([ + expect.objectContaining({ _id: three._id }), + ]) + ) + }) + + it("can query on top of the view filters (using or filters)", async () => { + const one = await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + await config.api.row.save(table._id!, { + one: "foo2", + two: "bar2", + }) + const three = await config.api.row.save(table._id!, { + one: "foo3", + two: "bar3", + }) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + queryUI: { + groups: [ + { + filters: [ + { + operator: BasicOperator.NOT_EQUAL, + field: "one", + value: "foo2", + }, + ], + }, + ], + }, + schema: { + id: { visible: true }, + one: { visible: false }, + two: { visible: true }, + }, + }) + + const response = await config.api.viewV2.search(view.id, { + query: { + allOr: true, + [BasicOperator.NOT_EQUAL]: { + two: "bar", + }, + [BasicOperator.NOT_EMPTY]: { + two: null, + }, + }, + }) + expect(response.rows).toHaveLength(2) + expect(response.rows).toEqual( + expect.arrayContaining([ + expect.objectContaining({ _id: one._id }), + expect.objectContaining({ _id: three._id }), + ]) + ) + }) + + it.each([true, false])( + "can filter a view without a view filter", + async allOr => { + const one = await config.api.row.save(table._id!, { + one: "foo", + two: "bar", + }) + await config.api.row.save(table._id!, { + one: "foo2", + two: "bar2", }) - const response = await config.api.viewV2.search(view.id) - - expect(response.rows).toHaveLength(4) - expect(response.rows).toEqual( - expected.map(name => expect.objectContaining({ name })) - ) - } - ) - - it.each(sortTestOptions)( - "allow override the default view sorting (%s)", - async (sortParams, expected) => { const view = await config.api.viewV2.create({ tableId: table._id!, name: generator.guid(), - sort: { - field: "name", - order: SortOrder.ASCENDING, - type: SortType.STRING, + schema: { + id: { visible: true }, + one: { visible: false }, + two: { visible: true }, }, - schema: viewSchema, }) const response = await config.api.viewV2.search(view.id, { - sort: sortParams.field, - sortOrder: sortParams.order, - sortType: sortParams.type, - query: {}, + query: { + allOr, + equal: { + two: "bar", + }, + }, }) - - expect(response.rows).toHaveLength(4) - expect(response.rows).toEqual( - expected.map(name => expect.objectContaining({ name })) - ) + expect(response.rows).toHaveLength(1) + expect(response.rows).toEqual([ + expect.objectContaining({ _id: one._id }), + ]) } ) - }) - it("can query on top of the view filters", async () => { - await config.api.row.save(table._id!, { - one: "foo", - two: "bar", - }) - await config.api.row.save(table._id!, { - one: "foo2", - two: "bar2", - }) - const three = await config.api.row.save(table._id!, { - one: "foo3", - two: "bar3", - }) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - queryUI: { - groups: [ - { - filters: [ - { - operator: BasicOperator.NOT_EQUAL, - field: "one", - value: "foo2", - }, - ], - }, - ], - }, - schema: { - id: { visible: true }, - one: { visible: true }, - two: { visible: true }, - }, - }) - - const response = await config.api.viewV2.search(view.id, { - query: { - [BasicOperator.EQUAL]: { - two: "bar3", - }, - [BasicOperator.NOT_EMPTY]: { - two: null, - }, - }, - }) - expect(response.rows).toHaveLength(1) - expect(response.rows).toEqual( - expect.arrayContaining([ - expect.objectContaining({ _id: three._id }), - ]) - ) - }) - - it("can query on top of the view filters (using or filters)", async () => { - const one = await config.api.row.save(table._id!, { - one: "foo", - two: "bar", - }) - await config.api.row.save(table._id!, { - one: "foo2", - two: "bar2", - }) - const three = await config.api.row.save(table._id!, { - one: "foo3", - two: "bar3", - }) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - queryUI: { - groups: [ - { - filters: [ - { - operator: BasicOperator.NOT_EQUAL, - field: "one", - value: "foo2", - }, - ], - }, - ], - }, - schema: { - id: { visible: true }, - one: { visible: false }, - two: { visible: true }, - }, - }) - - const response = await config.api.viewV2.search(view.id, { - query: { - allOr: true, - [BasicOperator.NOT_EQUAL]: { - two: "bar", - }, - [BasicOperator.NOT_EMPTY]: { - two: null, - }, - }, - }) - expect(response.rows).toHaveLength(2) - expect(response.rows).toEqual( - expect.arrayContaining([ - expect.objectContaining({ _id: one._id }), - expect.objectContaining({ _id: three._id }), - ]) - ) - }) - - it.each([true, false])( - "can filter a view without a view filter", - async allOr => { - const one = await config.api.row.save(table._id!, { + it.each([true, false])("cannot bypass a view filter", async allOr => { + await config.api.row.save(table._id!, { one: "foo", two: "bar", }) @@ -3202,6 +3248,19 @@ datasourceDescribe( const view = await config.api.viewV2.create({ tableId: table._id!, name: generator.guid(), + queryUI: { + groups: [ + { + filters: [ + { + operator: BasicOperator.EQUAL, + field: "two", + value: "bar2", + }, + ], + }, + ], + }, schema: { id: { visible: true }, one: { visible: false }, @@ -3217,408 +3276,330 @@ datasourceDescribe( }, }, }) - expect(response.rows).toHaveLength(1) - expect(response.rows).toEqual([ - expect.objectContaining({ _id: one._id }), - ]) - } - ) - - it.each([true, false])("cannot bypass a view filter", async allOr => { - await config.api.row.save(table._id!, { - one: "foo", - two: "bar", - }) - await config.api.row.save(table._id!, { - one: "foo2", - two: "bar2", + expect(response.rows).toHaveLength(0) }) - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - queryUI: { - groups: [ - { - filters: [ - { - operator: BasicOperator.EQUAL, - field: "two", - value: "bar2", - }, - ], - }, - ], - }, - schema: { - id: { visible: true }, - one: { visible: false }, - two: { visible: true }, - }, - }) - - const response = await config.api.viewV2.search(view.id, { - query: { - allOr, - equal: { - two: "bar", - }, - }, - }) - expect(response.rows).toHaveLength(0) - }) - - describe("foreign relationship columns", () => { - const createMainTable = async ( - links: { - name: string - tableId: string - fk: string - }[] - ) => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { title: { name: "title", type: FieldType.STRING } }, - }) - ) - await config.api.table.save({ - ...table, - schema: { - ...table.schema, - ...links.reduce((acc, c) => { - acc[c.name] = { - name: c.name, - relationshipType: RelationshipType.ONE_TO_MANY, - type: FieldType.LINK, - tableId: c.tableId, - fieldName: c.fk, - constraints: { type: "array" }, - } - return acc - }, {}), - }, - }) - return table - } - const createAuxTable = (schema: TableSchema) => - config.api.table.save( - saveTableRequest({ - primaryDisplay: "name", - schema: { - ...schema, - name: { name: "name", type: FieldType.STRING }, - }, - }) - ) - - it("returns squashed fields respecting the view config", async () => { - const auxTable = await createAuxTable({ - age: { name: "age", type: FieldType.NUMBER }, - }) - const auxRow = await config.api.row.save(auxTable._id!, { - name: generator.name(), - age: generator.age(), - }) - - const table = await createMainTable([ - { name: "aux", tableId: auxTable._id!, fk: "fk_aux" }, - ]) - await config.api.row.save(table._id!, { - title: generator.word(), - aux: [auxRow], - }) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - title: { visible: true }, - aux: { - visible: true, - columns: { - name: { visible: false, readonly: false }, - age: { visible: true, readonly: true }, - }, - }, - }, - }) - - const response = await config.api.viewV2.search(view.id) - expect(response.rows).toEqual([ - expect.objectContaining({ - aux: [ - { - _id: auxRow._id, - primaryDisplay: auxRow.name, - age: auxRow.age, - }, - ], - }), - ]) - }) - - it("enriches squashed fields", async () => { - const auxTable = await createAuxTable({ - user: { - name: "user", - type: FieldType.BB_REFERENCE_SINGLE, - subtype: BBReferenceFieldSubType.USER, - constraints: { presence: true }, - }, - }) - const table = await createMainTable([ - { name: "aux", tableId: auxTable._id!, fk: "fk_aux" }, - ]) - - const user = config.getUser() - const auxRow = await config.api.row.save(auxTable._id!, { - name: generator.name(), - user: user._id, - }) - await config.api.row.save(table._id!, { - title: generator.word(), - aux: [auxRow], - }) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - schema: { - title: { visible: true }, - aux: { - visible: true, - columns: { - name: { visible: true, readonly: true }, - user: { visible: true, readonly: true }, - }, - }, - }, - }) - - const response = await config.api.viewV2.search(view.id) - - expect(response.rows).toEqual([ - expect.objectContaining({ - aux: [ - { - _id: auxRow._id, - primaryDisplay: auxRow.name, - name: auxRow.name, - user: { - _id: user._id, - email: user.email, - firstName: user.firstName, - lastName: user.lastName, - primaryDisplay: user.email, - }, - }, - ], - }), - ]) - }) - }) - - describe("calculations", () => { - let table: Table - let rows: Row[] - - beforeAll(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - quantity: { - type: FieldType.NUMBER, - name: "quantity", - }, - price: { - type: FieldType.NUMBER, - name: "price", - }, - }, - }) - ) - - rows = await Promise.all( - Array.from({ length: 10 }, () => - config.api.row.save(table._id!, { - quantity: generator.natural({ min: 1, max: 10 }), - price: generator.natural({ min: 1, max: 10 }), + describe("foreign relationship columns", () => { + const createMainTable = async ( + links: { + name: string + tableId: string + fk: string + }[] + ) => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { title: { name: "title", type: FieldType.STRING } }, }) ) - ) - }) - - it("should be able to search by calculations", async () => { - const view = await config.api.viewV2.create({ - tableId: table._id!, - type: ViewV2Type.CALCULATION, - name: generator.guid(), - schema: { - "Quantity Sum": { - visible: true, - calculationType: CalculationType.SUM, - field: "quantity", - }, - }, - }) - - const response = await config.api.viewV2.search(view.id, { - query: {}, - }) - - expect(response.rows).toHaveLength(1) - expect(response.rows).toEqual( - expect.arrayContaining([ - expect.objectContaining({ - "Quantity Sum": rows.reduce((acc, r) => acc + r.quantity, 0), - }), - ]) - ) - - // Calculation views do not return rows that can be linked back to - // the source table, and so should not have an _id field. - for (const row of response.rows) { - expect("_id" in row).toBe(false) - } - }) - - it("should be able to group by a basic field", async () => { - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - quantity: { - visible: true, - field: "quantity", - }, - "Total Price": { - visible: true, - calculationType: CalculationType.SUM, - field: "price", - }, - }, - }) - - const response = await config.api.viewV2.search(view.id, { - query: {}, - }) - - const priceByQuantity: Record = {} - for (const row of rows) { - priceByQuantity[row.quantity] ??= 0 - priceByQuantity[row.quantity] += row.price - } - - for (const row of response.rows) { - expect(row["Total Price"]).toEqual(priceByQuantity[row.quantity]) - } - }) - - it.each([ - CalculationType.COUNT, - CalculationType.SUM, - CalculationType.AVG, - CalculationType.MIN, - CalculationType.MAX, - ])("should be able to calculate $type", async type => { - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - aggregate: { - visible: true, - calculationType: type, - field: "price", - }, - }, - }) - - const response = await config.api.viewV2.search(view.id, { - query: {}, - }) - - function calculate( - type: CalculationType, - numbers: number[] - ): number { - switch (type) { - case CalculationType.COUNT: - return numbers.length - case CalculationType.SUM: - return numbers.reduce((a, b) => a + b, 0) - case CalculationType.AVG: - return numbers.reduce((a, b) => a + b, 0) / numbers.length - case CalculationType.MIN: - return Math.min(...numbers) - case CalculationType.MAX: - return Math.max(...numbers) - } - } - - const prices = rows.map(row => row.price) - const expected = calculate(type, prices) - const actual = response.rows[0].aggregate - - if (type === CalculationType.AVG) { - // The average calculation can introduce floating point rounding - // errors, so we need to compare to within a small margin of - // error. - expect(actual).toBeCloseTo(expected) - } else { - expect(actual).toEqual(expected) - } - }) - - it("should be able to do a COUNT(DISTINCT)", async () => { - const table = await config.api.table.save( - saveTableRequest({ + await config.api.table.save({ + ...table, schema: { - name: { - name: "name", - type: FieldType.STRING, + ...table.schema, + ...links.reduce((acc, c) => { + acc[c.name] = { + name: c.name, + relationshipType: RelationshipType.ONE_TO_MANY, + type: FieldType.LINK, + tableId: c.tableId, + fieldName: c.fk, + constraints: { type: "array" }, + } + return acc + }, {}), + }, + }) + return table + } + const createAuxTable = (schema: TableSchema) => + config.api.table.save( + saveTableRequest({ + primaryDisplay: "name", + schema: { + ...schema, + name: { name: "name", type: FieldType.STRING }, + }, + }) + ) + + it("returns squashed fields respecting the view config", async () => { + const auxTable = await createAuxTable({ + age: { name: "age", type: FieldType.NUMBER }, + }) + const auxRow = await config.api.row.save(auxTable._id!, { + name: generator.name(), + age: generator.age(), + }) + + const table = await createMainTable([ + { name: "aux", tableId: auxTable._id!, fk: "fk_aux" }, + ]) + await config.api.row.save(table._id!, { + title: generator.word(), + aux: [auxRow], + }) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + schema: { + title: { visible: true }, + aux: { + visible: true, + columns: { + name: { visible: false, readonly: false }, + age: { visible: true, readonly: true }, + }, }, }, }) - ) - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - count: { - visible: true, - calculationType: CalculationType.COUNT, - distinct: true, - field: "name", - }, - }, + const response = await config.api.viewV2.search(view.id) + expect(response.rows).toEqual([ + expect.objectContaining({ + aux: [ + { + _id: auxRow._id, + primaryDisplay: auxRow.name, + age: auxRow.age, + }, + ], + }), + ]) }) - await config.api.row.bulkImport(table._id!, { - rows: [ - { - name: "John", + it("enriches squashed fields", async () => { + const auxTable = await createAuxTable({ + user: { + name: "user", + type: FieldType.BB_REFERENCE_SINGLE, + subtype: BBReferenceFieldSubType.USER, + constraints: { presence: true }, }, - { - name: "John", - }, - { - name: "Sue", - }, - ], - }) + }) + const table = await createMainTable([ + { name: "aux", tableId: auxTable._id!, fk: "fk_aux" }, + ]) - const { rows } = await config.api.row.search(view.id) - expect(rows).toHaveLength(1) - expect(rows[0].count).toEqual(2) + const user = config.getUser() + const auxRow = await config.api.row.save(auxTable._id!, { + name: generator.name(), + user: user._id, + }) + await config.api.row.save(table._id!, { + title: generator.word(), + aux: [auxRow], + }) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + schema: { + title: { visible: true }, + aux: { + visible: true, + columns: { + name: { visible: true, readonly: true }, + user: { visible: true, readonly: true }, + }, + }, + }, + }) + + const response = await config.api.viewV2.search(view.id) + + expect(response.rows).toEqual([ + expect.objectContaining({ + aux: [ + { + _id: auxRow._id, + primaryDisplay: auxRow.name, + name: auxRow.name, + user: { + _id: user._id, + email: user.email, + firstName: user.firstName, + lastName: user.lastName, + primaryDisplay: user.email, + }, + }, + ], + }), + ]) + }) }) - it("should not be able to COUNT(DISTINCT ...) against a non-existent field", async () => { - await config.api.viewV2.create( - { + describe("calculations", () => { + let table: Table + let rows: Row[] + + beforeAll(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + quantity: { + type: FieldType.NUMBER, + name: "quantity", + }, + price: { + type: FieldType.NUMBER, + name: "price", + }, + }, + }) + ) + + rows = await Promise.all( + Array.from({ length: 10 }, () => + config.api.row.save(table._id!, { + quantity: generator.natural({ min: 1, max: 10 }), + price: generator.natural({ min: 1, max: 10 }), + }) + ) + ) + }) + + it("should be able to search by calculations", async () => { + const view = await config.api.viewV2.create({ + tableId: table._id!, + type: ViewV2Type.CALCULATION, + name: generator.guid(), + schema: { + "Quantity Sum": { + visible: true, + calculationType: CalculationType.SUM, + field: "quantity", + }, + }, + }) + + const response = await config.api.viewV2.search(view.id, { + query: {}, + }) + + expect(response.rows).toHaveLength(1) + expect(response.rows).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + "Quantity Sum": rows.reduce( + (acc, r) => acc + r.quantity, + 0 + ), + }), + ]) + ) + + // Calculation views do not return rows that can be linked back to + // the source table, and so should not have an _id field. + for (const row of response.rows) { + expect("_id" in row).toBe(false) + } + }) + + it("should be able to group by a basic field", async () => { + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + quantity: { + visible: true, + field: "quantity", + }, + "Total Price": { + visible: true, + calculationType: CalculationType.SUM, + field: "price", + }, + }, + }) + + const response = await config.api.viewV2.search(view.id, { + query: {}, + }) + + const priceByQuantity: Record = {} + for (const row of rows) { + priceByQuantity[row.quantity] ??= 0 + priceByQuantity[row.quantity] += row.price + } + + for (const row of response.rows) { + expect(row["Total Price"]).toEqual( + priceByQuantity[row.quantity] + ) + } + }) + + it.each([ + CalculationType.COUNT, + CalculationType.SUM, + CalculationType.AVG, + CalculationType.MIN, + CalculationType.MAX, + ])("should be able to calculate $type", async type => { + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + aggregate: { + visible: true, + calculationType: type, + field: "price", + }, + }, + }) + + const response = await config.api.viewV2.search(view.id, { + query: {}, + }) + + function calculate( + type: CalculationType, + numbers: number[] + ): number { + switch (type) { + case CalculationType.COUNT: + return numbers.length + case CalculationType.SUM: + return numbers.reduce((a, b) => a + b, 0) + case CalculationType.AVG: + return numbers.reduce((a, b) => a + b, 0) / numbers.length + case CalculationType.MIN: + return Math.min(...numbers) + case CalculationType.MAX: + return Math.max(...numbers) + } + } + + const prices = rows.map(row => row.price) + const expected = calculate(type, prices) + const actual = response.rows[0].aggregate + + if (type === CalculationType.AVG) { + // The average calculation can introduce floating point rounding + // errors, so we need to compare to within a small margin of + // error. + expect(actual).toBeCloseTo(expected) + } else { + expect(actual).toEqual(expected) + } + }) + + it("should be able to do a COUNT(DISTINCT)", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + name: "name", + type: FieldType.STRING, + }, + }, + }) + ) + + const view = await config.api.viewV2.create({ tableId: table._id!, name: generator.guid(), type: ViewV2Type.CALCULATION, @@ -3627,71 +3608,474 @@ datasourceDescribe( visible: true, calculationType: CalculationType.COUNT, distinct: true, - field: "does not exist oh no", - }, - }, - }, - { - status: 400, - body: { - message: - 'Calculation field "count" references field "does not exist oh no" which does not exist in the table schema', - }, - } - ) - }) - - it("should be able to filter on relationships", async () => { - const companies = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - name: "name", - type: FieldType.STRING, + field: "name", }, }, }) - ) - const employees = await config.api.table.save( - saveTableRequest({ - schema: { - age: { - type: FieldType.NUMBER, - name: "age", - }, - name: { - type: FieldType.STRING, - name: "name", - }, - company: { - type: FieldType.LINK, - name: "company", - tableId: companies._id!, - relationshipType: RelationshipType.ONE_TO_MANY, - fieldName: "company", - }, - }, - }) - ) - - const view = await config.api.viewV2.create({ - tableId: employees._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - queryUI: { - groups: [ + await config.api.row.bulkImport(table._id!, { + rows: [ { - filters: [ - { - operator: BasicOperator.EQUAL, - field: "company.name", - value: "Aperture Science Laboratories", - }, - ], + name: "John", + }, + { + name: "John", + }, + { + name: "Sue", }, ], - }, + }) + + const { rows } = await config.api.row.search(view.id) + expect(rows).toHaveLength(1) + expect(rows[0].count).toEqual(2) + }) + + it("should not be able to COUNT(DISTINCT ...) against a non-existent field", async () => { + await config.api.viewV2.create( + { + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + count: { + visible: true, + calculationType: CalculationType.COUNT, + distinct: true, + field: "does not exist oh no", + }, + }, + }, + { + status: 400, + body: { + message: + 'Calculation field "count" references field "does not exist oh no" which does not exist in the table schema', + }, + } + ) + }) + + it("should be able to filter on relationships", async () => { + const companies = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + name: "name", + type: FieldType.STRING, + }, + }, + }) + ) + + const employees = await config.api.table.save( + saveTableRequest({ + schema: { + age: { + type: FieldType.NUMBER, + name: "age", + }, + name: { + type: FieldType.STRING, + name: "name", + }, + company: { + type: FieldType.LINK, + name: "company", + tableId: companies._id!, + relationshipType: RelationshipType.ONE_TO_MANY, + fieldName: "company", + }, + }, + }) + ) + + const view = await config.api.viewV2.create({ + tableId: employees._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + queryUI: { + groups: [ + { + filters: [ + { + operator: BasicOperator.EQUAL, + field: "company.name", + value: "Aperture Science Laboratories", + }, + ], + }, + ], + }, + schema: { + sum: { + visible: true, + calculationType: CalculationType.SUM, + field: "age", + }, + }, + }) + + const apertureScience = await config.api.row.save( + companies._id!, + { + name: "Aperture Science Laboratories", + } + ) + + const blackMesa = await config.api.row.save(companies._id!, { + name: "Black Mesa", + }) + + await Promise.all([ + config.api.row.save(employees._id!, { + name: "Alice", + age: 25, + company: apertureScience._id, + }), + config.api.row.save(employees._id!, { + name: "Bob", + age: 30, + company: apertureScience._id, + }), + config.api.row.save(employees._id!, { + name: "Charly", + age: 27, + company: blackMesa._id, + }), + config.api.row.save(employees._id!, { + name: "Danny", + age: 15, + company: blackMesa._id, + }), + ]) + + const { rows } = await config.api.viewV2.search(view.id, { + query: {}, + }) + + expect(rows).toHaveLength(1) + expect(rows[0].sum).toEqual(55) + }) + + it("should be able to count non-numeric fields", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + firstName: { + type: FieldType.STRING, + name: "firstName", + }, + lastName: { + type: FieldType.STRING, + name: "lastName", + }, + }, + }) + ) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + count: { + visible: true, + calculationType: CalculationType.COUNT, + field: "firstName", + }, + }, + }) + + await config.api.row.bulkImport(table._id!, { + rows: [ + { firstName: "Jane", lastName: "Smith" }, + { firstName: "Jane", lastName: "Doe" }, + { firstName: "Alice", lastName: "Smith" }, + ], + }) + + const { rows } = await config.api.viewV2.search(view.id, { + query: {}, + }) + + expect(rows).toHaveLength(1) + expect(rows[0].count).toEqual(3) + }) + + it("should be able to filter rows on the view itself", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + quantity: { + type: FieldType.NUMBER, + name: "quantity", + }, + price: { + type: FieldType.NUMBER, + name: "price", + }, + }, + }) + ) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + queryUI: { + groups: [ + { + filters: [ + { + operator: BasicOperator.EQUAL, + field: "quantity", + value: 1, + }, + ], + }, + ], + }, + schema: { + sum: { + visible: true, + calculationType: CalculationType.SUM, + field: "price", + }, + }, + }) + + await config.api.row.bulkImport(table._id!, { + rows: [ + { + quantity: 1, + price: 1, + }, + { + quantity: 1, + price: 2, + }, + { + quantity: 2, + price: 10, + }, + ], + }) + + const { rows } = await config.api.viewV2.search(view.id, { + query: {}, + }) + expect(rows).toHaveLength(1) + expect(rows[0].sum).toEqual(3) + }) + + it("should be able to filter on group by fields", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + quantity: { + type: FieldType.NUMBER, + name: "quantity", + }, + price: { + type: FieldType.NUMBER, + name: "price", + }, + }, + }) + ) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + quantity: { visible: true }, + sum: { + visible: true, + calculationType: CalculationType.SUM, + field: "price", + }, + }, + }) + + await config.api.row.bulkImport(table._id!, { + rows: [ + { + quantity: 1, + price: 1, + }, + { + quantity: 1, + price: 2, + }, + { + quantity: 2, + price: 10, + }, + ], + }) + + const { rows } = await config.api.viewV2.search(view.id, { + query: { + equal: { + quantity: 1, + }, + }, + }) + + expect(rows).toHaveLength(1) + expect(rows[0].sum).toEqual(3) + }) + + it("should be able to sort by group by field", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + quantity: { + type: FieldType.NUMBER, + name: "quantity", + }, + price: { + type: FieldType.NUMBER, + name: "price", + }, + }, + }) + ) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + quantity: { visible: true }, + sum: { + visible: true, + calculationType: CalculationType.SUM, + field: "price", + }, + }, + }) + + await config.api.row.bulkImport(table._id!, { + rows: [ + { + quantity: 1, + price: 1, + }, + { + quantity: 1, + price: 2, + }, + { + quantity: 2, + price: 10, + }, + ], + }) + + const { rows } = await config.api.viewV2.search(view.id, { + query: {}, + sort: "quantity", + sortOrder: SortOrder.DESCENDING, + }) + + expect(rows).toEqual([ + expect.objectContaining({ quantity: 2, sum: 10 }), + expect.objectContaining({ quantity: 1, sum: 3 }), + ]) + }) + + it("should be able to sort by a calculation", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + quantity: { + type: FieldType.NUMBER, + name: "quantity", + }, + price: { + type: FieldType.NUMBER, + name: "price", + }, + }, + }) + ) + + await config.api.row.bulkImport(table._id!, { + rows: [ + { + quantity: 1, + price: 1, + }, + { + quantity: 1, + price: 2, + }, + { + quantity: 2, + price: 10, + }, + ], + }) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, + schema: { + quantity: { visible: true }, + sum: { + visible: true, + calculationType: CalculationType.SUM, + field: "price", + }, + }, + }) + + const { rows } = await config.api.viewV2.search(view.id, { + query: {}, + sort: "sum", + sortOrder: SortOrder.DESCENDING, + }) + + expect(rows).toEqual([ + expect.objectContaining({ quantity: 2, sum: 10 }), + expect.objectContaining({ quantity: 1, sum: 3 }), + ]) + }) + }) + + it("should not need required fields to be present", async () => { + const table = await config.api.table.save( + saveTableRequest({ + schema: { + name: { + name: "name", + type: FieldType.STRING, + constraints: { + presence: true, + }, + }, + age: { + name: "age", + type: FieldType.NUMBER, + }, + }, + }) + ) + + await Promise.all([ + config.api.row.save(table._id!, { name: "Steve", age: 30 }), + config.api.row.save(table._id!, { name: "Jane", age: 31 }), + ]) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + type: ViewV2Type.CALCULATION, schema: { sum: { visible: true, @@ -3701,934 +4085,572 @@ datasourceDescribe( }, }) - const apertureScience = await config.api.row.save(companies._id!, { - name: "Aperture Science Laboratories", - }) - - const blackMesa = await config.api.row.save(companies._id!, { - name: "Black Mesa", - }) - - await Promise.all([ - config.api.row.save(employees._id!, { - name: "Alice", - age: 25, - company: apertureScience._id, - }), - config.api.row.save(employees._id!, { - name: "Bob", - age: 30, - company: apertureScience._id, - }), - config.api.row.save(employees._id!, { - name: "Charly", - age: 27, - company: blackMesa._id, - }), - config.api.row.save(employees._id!, { - name: "Danny", - age: 15, - company: blackMesa._id, - }), - ]) - - const { rows } = await config.api.viewV2.search(view.id, { + const response = await config.api.viewV2.search(view.id, { query: {}, }) - expect(rows).toHaveLength(1) - expect(rows[0].sum).toEqual(55) + expect(response.rows).toHaveLength(1) + expect(response.rows[0].sum).toEqual(61) }) - it("should be able to count non-numeric fields", async () => { + it("should be able to filter on a single user field in both the view query and search query", async () => { const table = await config.api.table.save( saveTableRequest({ schema: { - firstName: { - type: FieldType.STRING, - name: "firstName", - }, - lastName: { - type: FieldType.STRING, - name: "lastName", + user: { + name: "user", + type: FieldType.BB_REFERENCE_SINGLE, + subtype: BBReferenceFieldSubType.USER, }, }, }) ) - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - count: { - visible: true, - calculationType: CalculationType.COUNT, - field: "firstName", - }, - }, + await config.api.row.save(table._id!, { + user: config.getUser()._id, }) - await config.api.row.bulkImport(table._id!, { - rows: [ - { firstName: "Jane", lastName: "Smith" }, - { firstName: "Jane", lastName: "Doe" }, - { firstName: "Alice", lastName: "Smith" }, - ], - }) - - const { rows } = await config.api.viewV2.search(view.id, { - query: {}, - }) - - expect(rows).toHaveLength(1) - expect(rows[0].count).toEqual(3) - }) - - it("should be able to filter rows on the view itself", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - quantity: { - type: FieldType.NUMBER, - name: "quantity", - }, - price: { - type: FieldType.NUMBER, - name: "price", - }, - }, - }) - ) - const view = await config.api.viewV2.create({ tableId: table._id!, name: generator.guid(), - type: ViewV2Type.CALCULATION, queryUI: { groups: [ { filters: [ { operator: BasicOperator.EQUAL, - field: "quantity", - value: 1, + field: "user", + value: "{{ [user].[_id] }}", }, ], }, ], }, schema: { - sum: { + user: { visible: true, - calculationType: CalculationType.SUM, - field: "price", }, }, }) - await config.api.row.bulkImport(table._id!, { - rows: [ - { - quantity: 1, - price: 1, - }, - { - quantity: 1, - price: 2, - }, - { - quantity: 2, - price: 10, - }, - ], - }) - - const { rows } = await config.api.viewV2.search(view.id, { - query: {}, - }) - expect(rows).toHaveLength(1) - expect(rows[0].sum).toEqual(3) - }) - - it("should be able to filter on group by fields", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - quantity: { - type: FieldType.NUMBER, - name: "quantity", - }, - price: { - type: FieldType.NUMBER, - name: "price", - }, - }, - }) - ) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - quantity: { visible: true }, - sum: { - visible: true, - calculationType: CalculationType.SUM, - field: "price", - }, - }, - }) - - await config.api.row.bulkImport(table._id!, { - rows: [ - { - quantity: 1, - price: 1, - }, - { - quantity: 1, - price: 2, - }, - { - quantity: 2, - price: 10, - }, - ], - }) - const { rows } = await config.api.viewV2.search(view.id, { query: { equal: { - quantity: 1, + user: "{{ [user].[_id] }}", }, }, }) expect(rows).toHaveLength(1) - expect(rows[0].sum).toEqual(3) + expect(rows[0].user._id).toEqual(config.getUser()._id) }) - it("should be able to sort by group by field", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - quantity: { - type: FieldType.NUMBER, - name: "quantity", - }, - price: { - type: FieldType.NUMBER, - name: "price", - }, - }, - }) - ) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - quantity: { visible: true }, - sum: { - visible: true, - calculationType: CalculationType.SUM, - field: "price", - }, - }, - }) - - await config.api.row.bulkImport(table._id!, { - rows: [ - { - quantity: 1, - price: 1, - }, - { - quantity: 1, - price: 2, - }, - { - quantity: 2, - price: 10, - }, - ], - }) - - const { rows } = await config.api.viewV2.search(view.id, { - query: {}, - sort: "quantity", - sortOrder: SortOrder.DESCENDING, - }) - - expect(rows).toEqual([ - expect.objectContaining({ quantity: 2, sum: 10 }), - expect.objectContaining({ quantity: 1, sum: 3 }), - ]) - }) - - it("should be able to sort by a calculation", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - quantity: { - type: FieldType.NUMBER, - name: "quantity", - }, - price: { - type: FieldType.NUMBER, - name: "price", - }, - }, - }) - ) - - await config.api.row.bulkImport(table._id!, { - rows: [ - { - quantity: 1, - price: 1, - }, - { - quantity: 1, - price: 2, - }, - { - quantity: 2, - price: 10, - }, - ], - }) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - quantity: { visible: true }, - sum: { - visible: true, - calculationType: CalculationType.SUM, - field: "price", - }, - }, - }) - - const { rows } = await config.api.viewV2.search(view.id, { - query: {}, - sort: "sum", - sortOrder: SortOrder.DESCENDING, - }) - - expect(rows).toEqual([ - expect.objectContaining({ quantity: 2, sum: 10 }), - expect.objectContaining({ quantity: 1, sum: 3 }), - ]) - }) - }) - - it("should not need required fields to be present", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - name: { - name: "name", - type: FieldType.STRING, - constraints: { - presence: true, - }, - }, - age: { - name: "age", - type: FieldType.NUMBER, - }, - }, - }) - ) - - await Promise.all([ - config.api.row.save(table._id!, { name: "Steve", age: 30 }), - config.api.row.save(table._id!, { name: "Jane", age: 31 }), - ]) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - type: ViewV2Type.CALCULATION, - schema: { - sum: { - visible: true, - calculationType: CalculationType.SUM, - field: "age", - }, - }, - }) - - const response = await config.api.viewV2.search(view.id, { - query: {}, - }) - - expect(response.rows).toHaveLength(1) - expect(response.rows[0].sum).toEqual(61) - }) - - it("should be able to filter on a single user field in both the view query and search query", async () => { - const table = await config.api.table.save( - saveTableRequest({ - schema: { - user: { - name: "user", - type: FieldType.BB_REFERENCE_SINGLE, - subtype: BBReferenceFieldSubType.USER, - }, - }, - }) - ) - - await config.api.row.save(table._id!, { - user: config.getUser()._id, - }) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - queryUI: { - groups: [ - { - filters: [ - { - operator: BasicOperator.EQUAL, - field: "user", - value: "{{ [user].[_id] }}", + describe("search operators", () => { + let table: Table + beforeEach(async () => { + table = await config.api.table.save( + saveTableRequest({ + schema: { + string: { name: "string", type: FieldType.STRING }, + longform: { name: "longform", type: FieldType.LONGFORM }, + options: { + name: "options", + type: FieldType.OPTIONS, + constraints: { inclusion: ["a", "b", "c"] }, }, - ], - }, - ], - }, - schema: { - user: { - visible: true, - }, - }, - }) - - const { rows } = await config.api.viewV2.search(view.id, { - query: { - equal: { - user: "{{ [user].[_id] }}", - }, - }, - }) - - expect(rows).toHaveLength(1) - expect(rows[0].user._id).toEqual(config.getUser()._id) - }) - - describe("search operators", () => { - let table: Table - beforeEach(async () => { - table = await config.api.table.save( - saveTableRequest({ - schema: { - string: { name: "string", type: FieldType.STRING }, - longform: { name: "longform", type: FieldType.LONGFORM }, - options: { - name: "options", - type: FieldType.OPTIONS, - constraints: { inclusion: ["a", "b", "c"] }, - }, - array: { - name: "array", - type: FieldType.ARRAY, - constraints: { - type: JsonFieldSubType.ARRAY, - inclusion: ["a", "b", "c"], - }, - }, - number: { name: "number", type: FieldType.NUMBER }, - bigint: { name: "bigint", type: FieldType.BIGINT }, - datetime: { name: "datetime", type: FieldType.DATETIME }, - boolean: { name: "boolean", type: FieldType.BOOLEAN }, - user: { - name: "user", - type: FieldType.BB_REFERENCE_SINGLE, - subtype: BBReferenceFieldSubType.USER, - }, - users: { - name: "users", - type: FieldType.BB_REFERENCE, - subtype: BBReferenceFieldSubType.USER, - constraints: { - type: JsonFieldSubType.ARRAY, + array: { + name: "array", + type: FieldType.ARRAY, + constraints: { + type: JsonFieldSubType.ARRAY, + inclusion: ["a", "b", "c"], + }, + }, + number: { name: "number", type: FieldType.NUMBER }, + bigint: { name: "bigint", type: FieldType.BIGINT }, + datetime: { name: "datetime", type: FieldType.DATETIME }, + boolean: { name: "boolean", type: FieldType.BOOLEAN }, + user: { + name: "user", + type: FieldType.BB_REFERENCE_SINGLE, + subtype: BBReferenceFieldSubType.USER, + }, + users: { + name: "users", + type: FieldType.BB_REFERENCE, + subtype: BBReferenceFieldSubType.USER, + constraints: { + type: JsonFieldSubType.ARRAY, + }, }, }, + }) + ) + }) + + interface TestCase { + name: string + query: UISearchFilter | (() => UISearchFilter) + insert: Row[] | (() => Row[]) + expected: Row[] | (() => Row[]) + searchOpts?: Partial + } + + function simpleQuery(...filters: LegacyFilter[]): UISearchFilter { + return { groups: [{ filters }] } + } + + const testCases: TestCase[] = [ + { + name: "empty query return all", + insert: [{ string: "foo" }], + query: { + onEmptyFilter: EmptyFilterOption.RETURN_ALL, }, - }) - ) - }) - - interface TestCase { - name: string - query: UISearchFilter | (() => UISearchFilter) - insert: Row[] | (() => Row[]) - expected: Row[] | (() => Row[]) - searchOpts?: Partial - } - - function simpleQuery(...filters: LegacyFilter[]): UISearchFilter { - return { groups: [{ filters }] } - } - - const testCases: TestCase[] = [ - { - name: "empty query return all", - insert: [{ string: "foo" }], - query: { - onEmptyFilter: EmptyFilterOption.RETURN_ALL, + expected: [{ string: "foo" }], }, - expected: [{ string: "foo" }], - }, - { - name: "empty query return none", - insert: [{ string: "foo" }], - query: { - onEmptyFilter: EmptyFilterOption.RETURN_NONE, + { + name: "empty query return none", + insert: [{ string: "foo" }], + query: { + onEmptyFilter: EmptyFilterOption.RETURN_NONE, + }, + expected: [], }, - expected: [], - }, - { - name: "simple string search", - insert: [{ string: "foo" }], - query: simpleQuery({ - operator: BasicOperator.EQUAL, - field: "string", - value: "foo", - }), - expected: [{ string: "foo" }], - }, - { - name: "non matching string search", - insert: [{ string: "foo" }], - query: simpleQuery({ - operator: BasicOperator.EQUAL, - field: "string", - value: "bar", - }), - expected: [], - }, - { - name: "allOr", - insert: [{ string: "bar" }, { string: "foo" }], - query: simpleQuery( - { + { + name: "simple string search", + insert: [{ string: "foo" }], + query: simpleQuery({ operator: BasicOperator.EQUAL, field: "string", value: "foo", - }, - { + }), + expected: [{ string: "foo" }], + }, + { + name: "non matching string search", + insert: [{ string: "foo" }], + query: simpleQuery({ operator: BasicOperator.EQUAL, field: "string", value: "bar", + }), + expected: [], + }, + { + name: "allOr", + insert: [{ string: "bar" }, { string: "foo" }], + query: simpleQuery( + { + operator: BasicOperator.EQUAL, + field: "string", + value: "foo", + }, + { + operator: BasicOperator.EQUAL, + field: "string", + value: "bar", + }, + { + operator: "allOr", + } + ), + searchOpts: { + sort: "string", + sortOrder: SortOrder.ASCENDING, }, - { - operator: "allOr", - } - ), - searchOpts: { - sort: "string", - sortOrder: SortOrder.ASCENDING, + expected: [{ string: "bar" }, { string: "foo" }], }, - expected: [{ string: "bar" }, { string: "foo" }], - }, - { - name: "can find rows with fuzzy search", - insert: [{ string: "foo" }, { string: "bar" }], - query: simpleQuery({ - operator: BasicOperator.FUZZY, - field: "string", - value: "fo", - }), - expected: [{ string: "foo" }], - }, - { - name: "can find nothing with fuzzy search", - insert: [{ string: "foo" }, { string: "bar" }], - query: simpleQuery({ - operator: BasicOperator.FUZZY, - field: "string", - value: "baz", - }), - expected: [], - }, - { - name: "can find numeric rows", - insert: [{ number: 1 }, { number: 2 }], - query: simpleQuery({ - operator: BasicOperator.EQUAL, - field: "number", - value: 1, - }), - expected: [{ number: 1 }], - }, - { - name: "can find numeric values with rangeHigh", - insert: [{ number: 1 }, { number: 2 }, { number: 3 }], - query: simpleQuery({ - operator: "rangeHigh", - field: "number", - value: 2, - }), - searchOpts: { - sort: "number", - sortOrder: SortOrder.ASCENDING, + { + name: "can find rows with fuzzy search", + insert: [{ string: "foo" }, { string: "bar" }], + query: simpleQuery({ + operator: BasicOperator.FUZZY, + field: "string", + value: "fo", + }), + expected: [{ string: "foo" }], }, - expected: [{ number: 1 }, { number: 2 }], - }, - { - name: "can find numeric values with rangeLow", - insert: [{ number: 1 }, { number: 2 }, { number: 3 }], - query: simpleQuery({ - operator: "rangeLow", - field: "number", - value: 2, - }), - searchOpts: { - sort: "number", - sortOrder: SortOrder.ASCENDING, + { + name: "can find nothing with fuzzy search", + insert: [{ string: "foo" }, { string: "bar" }], + query: simpleQuery({ + operator: BasicOperator.FUZZY, + field: "string", + value: "baz", + }), + expected: [], }, - expected: [{ number: 2 }, { number: 3 }], - }, - { - name: "can find numeric values with full range", - insert: [{ number: 1 }, { number: 2 }, { number: 3 }], - query: simpleQuery( - { + { + name: "can find numeric rows", + insert: [{ number: 1 }, { number: 2 }], + query: simpleQuery({ + operator: BasicOperator.EQUAL, + field: "number", + value: 1, + }), + expected: [{ number: 1 }], + }, + { + name: "can find numeric values with rangeHigh", + insert: [{ number: 1 }, { number: 2 }, { number: 3 }], + query: simpleQuery({ operator: "rangeHigh", field: "number", value: 2, + }), + searchOpts: { + sort: "number", + sortOrder: SortOrder.ASCENDING, }, - { + expected: [{ number: 1 }, { number: 2 }], + }, + { + name: "can find numeric values with rangeLow", + insert: [{ number: 1 }, { number: 2 }, { number: 3 }], + query: simpleQuery({ operator: "rangeLow", field: "number", value: 2, - } - ), - expected: [{ number: 2 }], - }, - { - name: "can find longform values", - insert: [{ longform: "foo" }, { longform: "bar" }], - query: simpleQuery({ - operator: BasicOperator.EQUAL, - field: "longform", - value: "foo", - }), - expected: [{ longform: "foo" }], - }, - { - name: "can find options values", - insert: [{ options: "a" }, { options: "b" }], - query: simpleQuery({ - operator: BasicOperator.EQUAL, - field: "options", - value: "a", - }), - expected: [{ options: "a" }], - }, - { - name: "can find array values", - insert: [ - // Number field here is just to guarantee order. - { number: 1, array: ["a"] }, - { number: 2, array: ["b"] }, - { number: 3, array: ["a", "c"] }, - ], - query: simpleQuery({ - operator: ArrayOperator.CONTAINS, - field: "array", - value: "a", - }), - searchOpts: { - sort: "number", - sortOrder: SortOrder.ASCENDING, - }, - expected: [{ array: ["a"] }, { array: ["a", "c"] }], - }, - { - name: "can find bigint values", - insert: [{ bigint: "1" }, { bigint: "2" }], - query: simpleQuery({ - operator: BasicOperator.EQUAL, - field: "bigint", - type: FieldType.BIGINT, - value: "1", - }), - expected: [{ bigint: "1" }], - }, - { - name: "can find datetime values", - insert: [ - { datetime: "2021-01-01T00:00:00.000Z" }, - { datetime: "2021-01-02T00:00:00.000Z" }, - ], - query: simpleQuery({ - operator: BasicOperator.EQUAL, - field: "datetime", - type: FieldType.DATETIME, - value: "2021-01-01", - }), - expected: [{ datetime: "2021-01-01T00:00:00.000Z" }], - }, - { - name: "can find boolean values", - insert: [{ boolean: true }, { boolean: false }], - query: simpleQuery({ - operator: BasicOperator.EQUAL, - field: "boolean", - value: true, - }), - expected: [{ boolean: true }], - }, - { - name: "can find user values", - insert: () => [{ user: config.getUser() }], - query: () => - simpleQuery({ - operator: BasicOperator.EQUAL, - field: "user", - value: config.getUser()._id, }), - expected: () => [ - { - user: expect.objectContaining({ _id: config.getUser()._id }), + searchOpts: { + sort: "number", + sortOrder: SortOrder.ASCENDING, }, - ], - }, - { - name: "can find users values", - insert: () => [{ users: [config.getUser()] }], - query: () => - simpleQuery({ - operator: ArrayOperator.CONTAINS, - field: "users", - value: [config.getUser()._id], + expected: [{ number: 2 }, { number: 3 }], + }, + { + name: "can find numeric values with full range", + insert: [{ number: 1 }, { number: 2 }, { number: 3 }], + query: simpleQuery( + { + operator: "rangeHigh", + field: "number", + value: 2, + }, + { + operator: "rangeLow", + field: "number", + value: 2, + } + ), + expected: [{ number: 2 }], + }, + { + name: "can find longform values", + insert: [{ longform: "foo" }, { longform: "bar" }], + query: simpleQuery({ + operator: BasicOperator.EQUAL, + field: "longform", + value: "foo", }), - expected: () => [ - { - users: [ - expect.objectContaining({ _id: config.getUser()._id }), + expected: [{ longform: "foo" }], + }, + { + name: "can find options values", + insert: [{ options: "a" }, { options: "b" }], + query: simpleQuery({ + operator: BasicOperator.EQUAL, + field: "options", + value: "a", + }), + expected: [{ options: "a" }], + }, + { + name: "can find array values", + insert: [ + // Number field here is just to guarantee order. + { number: 1, array: ["a"] }, + { number: 2, array: ["b"] }, + { number: 3, array: ["a", "c"] }, + ], + query: simpleQuery({ + operator: ArrayOperator.CONTAINS, + field: "array", + value: "a", + }), + searchOpts: { + sort: "number", + sortOrder: SortOrder.ASCENDING, + }, + expected: [{ array: ["a"] }, { array: ["a", "c"] }], + }, + { + name: "can find bigint values", + insert: [{ bigint: "1" }, { bigint: "2" }], + query: simpleQuery({ + operator: BasicOperator.EQUAL, + field: "bigint", + type: FieldType.BIGINT, + value: "1", + }), + expected: [{ bigint: "1" }], + }, + { + name: "can find datetime values", + insert: [ + { datetime: "2021-01-01T00:00:00.000Z" }, + { datetime: "2021-01-02T00:00:00.000Z" }, + ], + query: simpleQuery({ + operator: BasicOperator.EQUAL, + field: "datetime", + type: FieldType.DATETIME, + value: "2021-01-01", + }), + expected: [{ datetime: "2021-01-01T00:00:00.000Z" }], + }, + { + name: "can find boolean values", + insert: [{ boolean: true }, { boolean: false }], + query: simpleQuery({ + operator: BasicOperator.EQUAL, + field: "boolean", + value: true, + }), + expected: [{ boolean: true }], + }, + { + name: "can find user values", + insert: () => [{ user: config.getUser() }], + query: () => + simpleQuery({ + operator: BasicOperator.EQUAL, + field: "user", + value: config.getUser()._id, + }), + expected: () => [ + { + user: expect.objectContaining({ + _id: config.getUser()._id, + }), + }, + ], + }, + { + name: "can find users values", + insert: () => [{ users: [config.getUser()] }], + query: () => + simpleQuery({ + operator: ArrayOperator.CONTAINS, + field: "users", + value: [config.getUser()._id], + }), + expected: () => [ + { + users: [ + expect.objectContaining({ _id: config.getUser()._id }), + ], + }, + ], + }, + { + name: "can handle logical operator any", + insert: [{ string: "bar" }, { string: "foo" }], + query: { + groups: [ + { + logicalOperator: UILogicalOperator.ANY, + filters: [ + { + operator: BasicOperator.EQUAL, + field: "string", + value: "foo", + }, + { + operator: BasicOperator.EQUAL, + field: "string", + value: "bar", + }, + ], + }, ], }, - ], - }, - { - name: "can handle logical operator any", - insert: [{ string: "bar" }, { string: "foo" }], - query: { - groups: [ - { - logicalOperator: UILogicalOperator.ANY, - filters: [ - { - operator: BasicOperator.EQUAL, - field: "string", - value: "foo", - }, - { - operator: BasicOperator.EQUAL, - field: "string", - value: "bar", - }, - ], - }, - ], - }, - searchOpts: { - sort: "string", - sortOrder: SortOrder.ASCENDING, - }, - expected: [{ string: "bar" }, { string: "foo" }], - }, - { - name: "can handle logical operator all", - insert: [ - { string: "bar", number: 1 }, - { string: "foo", number: 2 }, - ], - query: { - groups: [ - { - logicalOperator: UILogicalOperator.ALL, - filters: [ - { - operator: BasicOperator.EQUAL, - field: "string", - value: "foo", - }, - { - operator: BasicOperator.EQUAL, - field: "number", - value: 2, - }, - ], - }, - ], - }, - searchOpts: { - sort: "string", - sortOrder: SortOrder.ASCENDING, - }, - expected: [{ string: "foo", number: 2 }], - }, - { - name: "overrides allOr with logical operators", - insert: [ - { string: "bar", number: 1 }, - { string: "foo", number: 1 }, - ], - query: { - groups: [ - { - logicalOperator: UILogicalOperator.ALL, - filters: [ - { operator: "allOr" }, - { - operator: BasicOperator.EQUAL, - field: "string", - value: "foo", - }, - { - operator: BasicOperator.EQUAL, - field: "number", - value: 1, - }, - ], - }, - ], - }, - searchOpts: { - sort: "string", - sortOrder: SortOrder.ASCENDING, - }, - expected: [{ string: "foo", number: 1 }], - }, - ] - - it.each(testCases)( - "$name", - async ({ query, insert, expected, searchOpts }) => { - // Some values can't be specified outside of a test (e.g. getting - // config.getUser(), it won't be initialised), so we use functions - // in those cases. - if (typeof insert === "function") { - insert = insert() - } - if (typeof expected === "function") { - expected = expected() - } - if (typeof query === "function") { - query = query() - } - - await config.api.row.bulkImport(table._id!, { rows: insert }) - - const view = await config.api.viewV2.create({ - tableId: table._id!, - name: generator.guid(), - queryUI: query, - schema: { - string: { visible: true }, - longform: { visible: true }, - options: { visible: true }, - array: { visible: true }, - number: { visible: true }, - bigint: { visible: true }, - datetime: { visible: true }, - boolean: { visible: true }, - user: { visible: true }, - users: { visible: true }, + searchOpts: { + sort: "string", + sortOrder: SortOrder.ASCENDING, }, - }) + expected: [{ string: "bar" }, { string: "foo" }], + }, + { + name: "can handle logical operator all", + insert: [ + { string: "bar", number: 1 }, + { string: "foo", number: 2 }, + ], + query: { + groups: [ + { + logicalOperator: UILogicalOperator.ALL, + filters: [ + { + operator: BasicOperator.EQUAL, + field: "string", + value: "foo", + }, + { + operator: BasicOperator.EQUAL, + field: "number", + value: 2, + }, + ], + }, + ], + }, + searchOpts: { + sort: "string", + sortOrder: SortOrder.ASCENDING, + }, + expected: [{ string: "foo", number: 2 }], + }, + { + name: "overrides allOr with logical operators", + insert: [ + { string: "bar", number: 1 }, + { string: "foo", number: 1 }, + ], + query: { + groups: [ + { + logicalOperator: UILogicalOperator.ALL, + filters: [ + { operator: "allOr" }, + { + operator: BasicOperator.EQUAL, + field: "string", + value: "foo", + }, + { + operator: BasicOperator.EQUAL, + field: "number", + value: 1, + }, + ], + }, + ], + }, + searchOpts: { + sort: "string", + sortOrder: SortOrder.ASCENDING, + }, + expected: [{ string: "foo", number: 1 }], + }, + ] - const { rows } = await config.api.viewV2.search(view.id, { - query: {}, - ...searchOpts, - }) - expect(rows).toEqual( - expected.map(r => expect.objectContaining(r)) - ) - } - ) - }) - }) + it.each(testCases)( + "$name", + async ({ query, insert, expected, searchOpts }) => { + // Some values can't be specified outside of a test (e.g. getting + // config.getUser(), it won't be initialised), so we use functions + // in those cases. + if (typeof insert === "function") { + insert = insert() + } + if (typeof expected === "function") { + expected = expected() + } + if (typeof query === "function") { + query = query() + } - describe("permissions", () => { - beforeEach(async () => { - await Promise.all( - Array.from({ length: 10 }, () => - config.api.row.save(table._id!, {}) + await config.api.row.bulkImport(table._id!, { rows: insert }) + + const view = await config.api.viewV2.create({ + tableId: table._id!, + name: generator.guid(), + queryUI: query, + schema: { + string: { visible: true }, + longform: { visible: true }, + options: { visible: true }, + array: { visible: true }, + number: { visible: true }, + bigint: { visible: true }, + datetime: { visible: true }, + boolean: { visible: true }, + user: { visible: true }, + users: { visible: true }, + }, + }) + + const { rows } = await config.api.viewV2.search(view.id, { + query: {}, + ...searchOpts, + }) + expect(rows).toEqual( + expected.map(r => expect.objectContaining(r)) + ) + } ) - ) - }) - - it("does not allow public users to fetch by default", async () => { - await config.publish() - await config.api.viewV2.publicSearch(view.id, undefined, { - status: 401, }) }) - it("allow public users to fetch when permissions are explicit", async () => { - await config.api.permission.add({ - roleId: roles.BUILTIN_ROLE_IDS.PUBLIC, - level: PermissionLevel.READ, - resourceId: view.id, + describe("permissions", () => { + beforeEach(async () => { + await Promise.all( + Array.from({ length: 10 }, () => + config.api.row.save(table._id!, {}) + ) + ) }) - await config.publish() - const response = await config.api.viewV2.publicSearch(view.id) - - expect(response.rows).toHaveLength(10) - }) - - it("allow public users to fetch when permissions are inherited", async () => { - await config.api.permission.add({ - roleId: roles.BUILTIN_ROLE_IDS.PUBLIC, - level: PermissionLevel.READ, - resourceId: table._id!, + it("does not allow public users to fetch by default", async () => { + await config.publish() + await config.api.viewV2.publicSearch(view.id, undefined, { + status: 401, + }) }) - await config.api.permission.revoke({ - roleId: roles.BUILTIN_ROLE_IDS.PUBLIC, // Don't think this matters since we are revoking the permission - level: PermissionLevel.READ, - resourceId: view.id, + + it("allow public users to fetch when permissions are explicit", async () => { + await config.api.permission.add({ + roleId: roles.BUILTIN_ROLE_IDS.PUBLIC, + level: PermissionLevel.READ, + resourceId: view.id, + }) + await config.publish() + + const response = await config.api.viewV2.publicSearch(view.id) + + expect(response.rows).toHaveLength(10) }) - await config.publish() - const response = await config.api.viewV2.publicSearch(view.id) + it("allow public users to fetch when permissions are inherited", async () => { + await config.api.permission.add({ + roleId: roles.BUILTIN_ROLE_IDS.PUBLIC, + level: PermissionLevel.READ, + resourceId: table._id!, + }) + await config.api.permission.revoke({ + roleId: roles.BUILTIN_ROLE_IDS.PUBLIC, // Don't think this matters since we are revoking the permission + level: PermissionLevel.READ, + resourceId: view.id, + }) + await config.publish() - expect(response.rows).toHaveLength(10) - }) + const response = await config.api.viewV2.publicSearch(view.id) - it("respects inherited permissions, not allowing not public views from public tables", async () => { - await config.api.permission.add({ - roleId: roles.BUILTIN_ROLE_IDS.PUBLIC, - level: PermissionLevel.READ, - resourceId: table._id!, + expect(response.rows).toHaveLength(10) }) - await config.api.permission.add({ - roleId: roles.BUILTIN_ROLE_IDS.POWER, - level: PermissionLevel.READ, - resourceId: view.id, - }) - await config.publish() - await config.api.viewV2.publicSearch(view.id, undefined, { - status: 401, + it("respects inherited permissions, not allowing not public views from public tables", async () => { + await config.api.permission.add({ + roleId: roles.BUILTIN_ROLE_IDS.PUBLIC, + level: PermissionLevel.READ, + resourceId: table._id!, + }) + await config.api.permission.add({ + roleId: roles.BUILTIN_ROLE_IDS.POWER, + level: PermissionLevel.READ, + resourceId: view.id, + }) + await config.publish() + + await config.api.viewV2.publicSearch(view.id, undefined, { + status: 401, + }) }) }) }) - }) - } -) + } + ) +} diff --git a/packages/server/src/automations/tests/executeQuery.spec.ts b/packages/server/src/automations/tests/executeQuery.spec.ts index 12bbe892a0..2d65be6e58 100644 --- a/packages/server/src/automations/tests/executeQuery.spec.ts +++ b/packages/server/src/automations/tests/executeQuery.spec.ts @@ -7,71 +7,74 @@ import { import { Knex } from "knex" import { generator } from "@budibase/backend-core/tests" -datasourceDescribe( - { - name: "execute query action", - exclude: [DatabaseName.MONGODB, DatabaseName.SQS], - }, - ({ config, dsProvider }) => { - let tableName: string - let client: Knex - let datasource: Datasource - let query: Query +const descriptions = datasourceDescribe({ + exclude: [DatabaseName.MONGODB, DatabaseName.SQS], +}) - beforeAll(async () => { - const ds = await dsProvider() - datasource = ds.datasource! - client = ds.client! - }) +if (descriptions.length) { + describe.each(descriptions)( + "execute query action ($dbName)", + ({ config, dsProvider }) => { + let tableName: string + let client: Knex + let datasource: Datasource + let query: Query - beforeEach(async () => { - tableName = generator.guid() - await client.schema.createTable(tableName, table => { - table.string("a") - table.integer("b") + beforeAll(async () => { + const ds = await dsProvider() + datasource = ds.datasource! + client = ds.client! }) - await client(tableName).insert({ a: "string", b: 1 }) - query = await setup.saveTestQuery(config, client, tableName, datasource) - }) - afterEach(async () => { - await client.schema.dropTable(tableName) - }) + beforeEach(async () => { + tableName = generator.guid() + await client.schema.createTable(tableName, table => { + table.string("a") + table.integer("b") + }) + await client(tableName).insert({ a: "string", b: 1 }) + query = await setup.saveTestQuery(config, client, tableName, datasource) + }) - it("should be able to execute a query", async () => { - let res = await setup.runStep( - config, - setup.actions.EXECUTE_QUERY.stepId, - { - query: { queryId: query._id }, - } - ) - expect(res.response).toEqual([{ a: "string", b: 1 }]) - expect(res.success).toEqual(true) - }) + afterEach(async () => { + await client.schema.dropTable(tableName) + }) - it("should handle a null query value", async () => { - let res = await setup.runStep( - config, - setup.actions.EXECUTE_QUERY.stepId, - { - query: null, - } - ) - expect(res.response.message).toEqual("Invalid inputs") - expect(res.success).toEqual(false) - }) + it("should be able to execute a query", async () => { + let res = await setup.runStep( + config, + setup.actions.EXECUTE_QUERY.stepId, + { + query: { queryId: query._id }, + } + ) + expect(res.response).toEqual([{ a: "string", b: 1 }]) + expect(res.success).toEqual(true) + }) - it("should handle an error executing a query", async () => { - let res = await setup.runStep( - config, - setup.actions.EXECUTE_QUERY.stepId, - { - query: { queryId: "wrong_id" }, - } - ) - expect(res.response).toBeDefined() - expect(res.success).toEqual(false) - }) - } -) + it("should handle a null query value", async () => { + let res = await setup.runStep( + config, + setup.actions.EXECUTE_QUERY.stepId, + { + query: null, + } + ) + expect(res.response.message).toEqual("Invalid inputs") + expect(res.success).toEqual(false) + }) + + it("should handle an error executing a query", async () => { + let res = await setup.runStep( + config, + setup.actions.EXECUTE_QUERY.stepId, + { + query: { queryId: "wrong_id" }, + } + ) + expect(res.response).toBeDefined() + expect(res.success).toEqual(false) + }) + } + ) +} diff --git a/packages/server/src/automations/tests/scenarios/scenarios.spec.ts b/packages/server/src/automations/tests/scenarios/scenarios.spec.ts index dcfd4a4341..45b251f4c1 100644 --- a/packages/server/src/automations/tests/scenarios/scenarios.spec.ts +++ b/packages/server/src/automations/tests/scenarios/scenarios.spec.ts @@ -433,9 +433,10 @@ describe("Automation Scenarios", () => { }) }) -datasourceDescribe( - { name: "", only: [DatabaseName.MYSQL] }, - ({ config, dsProvider }) => { +const descriptions = datasourceDescribe({ only: [DatabaseName.MYSQL] }) + +if (descriptions.length) { + describe.each(descriptions)("/rows ($dbName)", ({ config, dsProvider }) => { let datasource: Datasource let client: Knex @@ -531,5 +532,5 @@ datasourceDescribe( ) }) }) - } -) + }) +} diff --git a/packages/server/src/integration-test/mysql.spec.ts b/packages/server/src/integration-test/mysql.spec.ts index 8edf6a0190..9cf7242e24 100644 --- a/packages/server/src/integration-test/mysql.spec.ts +++ b/packages/server/src/integration-test/mysql.spec.ts @@ -10,119 +10,123 @@ function uniqueTableName(length?: number): string { .substring(0, length || 10) } -datasourceDescribe( - { - name: "Integration compatibility with mysql search_path", - only: [DatabaseName.MYSQL], - }, - ({ config, dsProvider }) => { - let rawDatasource: Datasource - let datasource: Datasource - let client: Knex +const mainDescriptions = datasourceDescribe({ only: [DatabaseName.MYSQL] }) - const database = generator.guid() - const database2 = generator.guid() +if (mainDescriptions.length) { + describe.each(mainDescriptions)( + "/Integration compatibility with mysql search_path ($dbName)", + ({ config, dsProvider }) => { + let rawDatasource: Datasource + let datasource: Datasource + let client: Knex - beforeAll(async () => { - const ds = await dsProvider() - rawDatasource = ds.rawDatasource! - datasource = ds.datasource! - client = ds.client! + const database = generator.guid() + const database2 = generator.guid() - await client.raw(`CREATE DATABASE \`${database}\`;`) - await client.raw(`CREATE DATABASE \`${database2}\`;`) + beforeAll(async () => { + const ds = await dsProvider() + rawDatasource = ds.rawDatasource! + datasource = ds.datasource! + client = ds.client! - rawDatasource.config!.database = database - datasource = await config.api.datasource.create(rawDatasource) - }) + await client.raw(`CREATE DATABASE \`${database}\`;`) + await client.raw(`CREATE DATABASE \`${database2}\`;`) - afterAll(async () => { - await client.raw(`DROP DATABASE \`${database}\`;`) - await client.raw(`DROP DATABASE \`${database2}\`;`) - }) - - it("discovers tables from any schema in search path", async () => { - await client.schema.createTable(`${database}.table1`, table => { - table.increments("id1").primary() + rawDatasource.config!.database = database + datasource = await config.api.datasource.create(rawDatasource) }) - const res = await config.api.datasource.info(datasource) - expect(res.tableNames).toBeDefined() - expect(res.tableNames).toEqual(expect.arrayContaining(["table1"])) - }) - it("does not mix columns from different tables", async () => { - const repeated_table_name = "table_same_name" - await client.schema.createTable( - `${database}.${repeated_table_name}`, - table => { - table.increments("id").primary() - table.string("val1") - } - ) - await client.schema.createTable( - `${database2}.${repeated_table_name}`, - table => { - table.increments("id2").primary() - table.string("val2") - } - ) - - const res = await config.api.datasource.fetchSchema({ - datasourceId: datasource._id!, - tablesFilter: [repeated_table_name], + afterAll(async () => { + await client.raw(`DROP DATABASE \`${database}\`;`) + await client.raw(`DROP DATABASE \`${database2}\`;`) }) - expect(res.datasource.entities![repeated_table_name].schema).toBeDefined() - const schema = res.datasource.entities![repeated_table_name].schema - expect(Object.keys(schema).sort()).toEqual(["id", "val1"]) - }) - } -) -datasourceDescribe( - { - name: "POST /api/datasources/:datasourceId/schema", - only: [DatabaseName.MYSQL], - }, - ({ config, dsProvider }) => { - let datasource: Datasource - let client: Knex + it("discovers tables from any schema in search path", async () => { + await client.schema.createTable(`${database}.table1`, table => { + table.increments("id1").primary() + }) + const res = await config.api.datasource.info(datasource) + expect(res.tableNames).toBeDefined() + expect(res.tableNames).toEqual(expect.arrayContaining(["table1"])) + }) - beforeAll(async () => { - const ds = await dsProvider() - datasource = ds.datasource! - client = ds.client! - }) - - let tableName: string - beforeEach(async () => { - tableName = uniqueTableName() - }) - - afterEach(async () => { - await client.schema.dropTableIfExists(tableName) - }) - - it("recognises enum columns as options", async () => { - const enumColumnName = "status" - - await client.schema.createTable(tableName, table => { - table.increments("order_id").primary() - table.string("customer_name", 100).notNullable() - table.enum( - enumColumnName, - ["pending", "processing", "shipped", "delivered", "cancelled"], - { useNative: true, enumName: `${tableName}_${enumColumnName}` } + it("does not mix columns from different tables", async () => { + const repeated_table_name = "table_same_name" + await client.schema.createTable( + `${database}.${repeated_table_name}`, + table => { + table.increments("id").primary() + table.string("val1") + } ) + await client.schema.createTable( + `${database2}.${repeated_table_name}`, + table => { + table.increments("id2").primary() + table.string("val2") + } + ) + + const res = await config.api.datasource.fetchSchema({ + datasourceId: datasource._id!, + tablesFilter: [repeated_table_name], + }) + expect( + res.datasource.entities![repeated_table_name].schema + ).toBeDefined() + const schema = res.datasource.entities![repeated_table_name].schema + expect(Object.keys(schema).sort()).toEqual(["id", "val1"]) }) + } + ) - const res = await config.api.datasource.fetchSchema({ - datasourceId: datasource._id!, - }) + const descriptions = datasourceDescribe({ only: [DatabaseName.MYSQL] }) - const table = res.datasource.entities![tableName] + if (descriptions.length) { + describe.each(descriptions)( + "POST /api/datasources/:datasourceId/schema ($dbName)", + ({ config, dsProvider }) => { + let datasource: Datasource + let client: Knex - expect(table).toBeDefined() - expect(table.schema[enumColumnName].type).toEqual(FieldType.OPTIONS) - }) + beforeAll(async () => { + const ds = await dsProvider() + datasource = ds.datasource! + client = ds.client! + }) + + let tableName: string + beforeEach(async () => { + tableName = uniqueTableName() + }) + + afterEach(async () => { + await client.schema.dropTableIfExists(tableName) + }) + + it("recognises enum columns as options", async () => { + const enumColumnName = "status" + + await client.schema.createTable(tableName, table => { + table.increments("order_id").primary() + table.string("customer_name", 100).notNullable() + table.enum( + enumColumnName, + ["pending", "processing", "shipped", "delivered", "cancelled"], + { useNative: true, enumName: `${tableName}_${enumColumnName}` } + ) + }) + + const res = await config.api.datasource.fetchSchema({ + datasourceId: datasource._id!, + }) + + const table = res.datasource.entities![tableName] + + expect(table).toBeDefined() + expect(table.schema[enumColumnName].type).toEqual(FieldType.OPTIONS) + }) + } + ) } -) +} diff --git a/packages/server/src/integration-test/postgres.spec.ts b/packages/server/src/integration-test/postgres.spec.ts index 7ef6b9a968..4f63579ba1 100644 --- a/packages/server/src/integration-test/postgres.spec.ts +++ b/packages/server/src/integration-test/postgres.spec.ts @@ -8,283 +8,292 @@ import { } from "../integrations/tests/utils" import { Knex } from "knex" -datasourceDescribe( - { name: "postgres integrations", only: [DatabaseName.POSTGRES] }, - ({ config, dsProvider }) => { - let datasource: Datasource - let client: Knex +const mainDescriptions = datasourceDescribe({ only: [DatabaseName.POSTGRES] }) - beforeAll(async () => { - const ds = await dsProvider() - datasource = ds.datasource! - client = ds.client! - }) +if (mainDescriptions.length) { + describe.each(mainDescriptions)( + "/postgres integrations", + ({ config, dsProvider }) => { + let datasource: Datasource + let client: Knex - afterAll(config.end) - - describe("POST /api/datasources/:datasourceId/schema", () => { - let tableName: string - - beforeEach(async () => { - tableName = generator.guid().replaceAll("-", "").substring(0, 10) + beforeAll(async () => { + const ds = await dsProvider() + datasource = ds.datasource! + client = ds.client! }) - afterEach(async () => { - await client.schema.dropTableIfExists(tableName) - }) + afterAll(config.end) - it("recognises when a table has no primary key", async () => { - await client.schema.createTable(tableName, table => { - table.increments("id", { primaryKey: false }) + describe("POST /api/datasources/:datasourceId/schema", () => { + let tableName: string + + beforeEach(async () => { + tableName = generator.guid().replaceAll("-", "").substring(0, 10) }) - const response = await config.api.datasource.fetchSchema({ - datasourceId: datasource._id!, + afterEach(async () => { + await client.schema.dropTableIfExists(tableName) }) - expect(response.errors).toEqual({ - [tableName]: "Table must have a primary key.", - }) - }) + it("recognises when a table has no primary key", async () => { + await client.schema.createTable(tableName, table => { + table.increments("id", { primaryKey: false }) + }) - it("recognises when a table is using a reserved column name", async () => { - await client.schema.createTable(tableName, table => { - table.increments("_id").primary() - }) + const response = await config.api.datasource.fetchSchema({ + datasourceId: datasource._id!, + }) - const response = await config.api.datasource.fetchSchema({ - datasourceId: datasource._id!, - }) - - expect(response.errors).toEqual({ - [tableName]: "Table contains invalid columns.", - }) - }) - - it("recognises enum columns as options", async () => { - const tableName = `orders_${generator - .guid() - .replaceAll("-", "") - .substring(0, 6)}` - - await client.schema.createTable(tableName, table => { - table.increments("order_id").primary() - table.string("customer_name").notNullable() - table.enum("status", ["pending", "processing", "shipped"], { - useNative: true, - enumName: `${tableName}_status`, + expect(response.errors).toEqual({ + [tableName]: "Table must have a primary key.", }) }) - const response = await config.api.datasource.fetchSchema({ - datasourceId: datasource._id!, + it("recognises when a table is using a reserved column name", async () => { + await client.schema.createTable(tableName, table => { + table.increments("_id").primary() + }) + + const response = await config.api.datasource.fetchSchema({ + datasourceId: datasource._id!, + }) + + expect(response.errors).toEqual({ + [tableName]: "Table contains invalid columns.", + }) }) - const table = response.datasource.entities?.[tableName] + it("recognises enum columns as options", async () => { + const tableName = `orders_${generator + .guid() + .replaceAll("-", "") + .substring(0, 6)}` - expect(table).toBeDefined() - expect(table?.schema["status"].type).toEqual(FieldType.OPTIONS) - }) - }) + await client.schema.createTable(tableName, table => { + table.increments("order_id").primary() + table.string("customer_name").notNullable() + table.enum("status", ["pending", "processing", "shipped"], { + useNative: true, + enumName: `${tableName}_status`, + }) + }) - describe("check custom column types", () => { - beforeAll(async () => { - await client.schema.createTable("binaryTable", table => { - table.binary("id").primary() - table.string("column1") - table.integer("column2") + const response = await config.api.datasource.fetchSchema({ + datasourceId: datasource._id!, + }) + + const table = response.datasource.entities?.[tableName] + + expect(table).toBeDefined() + expect(table?.schema["status"].type).toEqual(FieldType.OPTIONS) }) }) - it("should handle binary columns", async () => { - const response = await config.api.datasource.fetchSchema({ - datasourceId: datasource._id!, + describe("check custom column types", () => { + beforeAll(async () => { + await client.schema.createTable("binaryTable", table => { + table.binary("id").primary() + table.string("column1") + table.integer("column2") + }) }) - expect(response.datasource.entities).toBeDefined() - const table = response.datasource.entities?.["binaryTable"] - expect(table).toBeDefined() - expect(table?.schema.id.externalType).toBe("bytea") - const row = await config.api.row.save(table?._id!, { - id: "1111", - column1: "hello", - column2: 222, - }) - expect(row._id).toBeDefined() - const decoded = decodeURIComponent(row._id!).replace(/'/g, '"') - expect(JSON.parse(decoded)[0]).toBe("1111") - }) - }) - describe("check fetching null/not null table", () => { - beforeAll(async () => { - await client.schema.createTable("nullableTable", table => { - table.increments("order_id").primary() - table.integer("order_number").notNullable() + it("should handle binary columns", async () => { + const response = await config.api.datasource.fetchSchema({ + datasourceId: datasource._id!, + }) + expect(response.datasource.entities).toBeDefined() + const table = response.datasource.entities?.["binaryTable"] + expect(table).toBeDefined() + expect(table?.schema.id.externalType).toBe("bytea") + const row = await config.api.row.save(table?._id!, { + id: "1111", + column1: "hello", + column2: 222, + }) + expect(row._id).toBeDefined() + const decoded = decodeURIComponent(row._id!).replace(/'/g, '"') + expect(JSON.parse(decoded)[0]).toBe("1111") }) }) - it("should be able to change the table to allow nullable and refetch this", async () => { - const response = await config.api.datasource.fetchSchema({ - datasourceId: datasource._id!, - }) - const entities = response.datasource.entities - expect(entities).toBeDefined() - const nullableTable = entities?.["nullableTable"] - expect(nullableTable).toBeDefined() - expect( - nullableTable?.schema["order_number"].constraints?.presence - ).toEqual(true) - - // need to perform these calls raw to the DB so that the external state of the DB differs to what Budibase - // is aware of - therefore we can try to fetch and make sure BB updates correctly - await client.schema.alterTable("nullableTable", table => { - table.setNullable("order_number") + describe("check fetching null/not null table", () => { + beforeAll(async () => { + await client.schema.createTable("nullableTable", table => { + table.increments("order_id").primary() + table.integer("order_number").notNullable() + }) }) - const responseAfter = await config.api.datasource.fetchSchema({ - datasourceId: datasource._id!, + it("should be able to change the table to allow nullable and refetch this", async () => { + const response = await config.api.datasource.fetchSchema({ + datasourceId: datasource._id!, + }) + const entities = response.datasource.entities + expect(entities).toBeDefined() + const nullableTable = entities?.["nullableTable"] + expect(nullableTable).toBeDefined() + expect( + nullableTable?.schema["order_number"].constraints?.presence + ).toEqual(true) + + // need to perform these calls raw to the DB so that the external state of the DB differs to what Budibase + // is aware of - therefore we can try to fetch and make sure BB updates correctly + await client.schema.alterTable("nullableTable", table => { + table.setNullable("order_number") + }) + + const responseAfter = await config.api.datasource.fetchSchema({ + datasourceId: datasource._id!, + }) + const entitiesAfter = responseAfter.datasource.entities + expect(entitiesAfter).toBeDefined() + const nullableTableAfter = entitiesAfter?.["nullableTable"] + expect(nullableTableAfter).toBeDefined() + expect( + nullableTableAfter?.schema["order_number"].constraints?.presence + ).toBeUndefined() }) - const entitiesAfter = responseAfter.datasource.entities - expect(entitiesAfter).toBeDefined() - const nullableTableAfter = entitiesAfter?.["nullableTable"] - expect(nullableTableAfter).toBeDefined() - expect( - nullableTableAfter?.schema["order_number"].constraints?.presence - ).toBeUndefined() }) - }) - describe("money field 💰", () => { - const tableName = "moneytable" - let table: Table + describe("money field 💰", () => { + const tableName = "moneytable" + let table: Table - beforeAll(async () => { - await client.raw(` + beforeAll(async () => { + await client.raw(` CREATE TABLE ${tableName} ( id serial PRIMARY KEY, price money ) `) - const response = await config.api.datasource.fetchSchema({ - datasourceId: datasource._id!, - }) - table = response.datasource.entities![tableName] - }) - - it("should be able to import a money field", async () => { - expect(table).toBeDefined() - expect(table?.schema.price.type).toBe(FieldType.NUMBER) - }) - - it("should be able to search a money field", async () => { - await config.api.row.bulkImport(table._id!, { - rows: [{ price: 200 }, { price: 300 }], + const response = await config.api.datasource.fetchSchema({ + datasourceId: datasource._id!, + }) + table = response.datasource.entities![tableName] }) - const { rows } = await config.api.row.search(table._id!, { - query: { - equal: { - price: 200, + it("should be able to import a money field", async () => { + expect(table).toBeDefined() + expect(table?.schema.price.type).toBe(FieldType.NUMBER) + }) + + it("should be able to search a money field", async () => { + await config.api.row.bulkImport(table._id!, { + rows: [{ price: 200 }, { price: 300 }], + }) + + const { rows } = await config.api.row.search(table._id!, { + query: { + equal: { + price: 200, + }, }, - }, + }) + expect(rows).toHaveLength(1) + expect(rows[0].price).toBe("200.00") + }) + + it("should be able to update a money field", async () => { + let row = await config.api.row.save(table._id!, { price: 200 }) + expect(row.price).toBe("200.00") + + row = await config.api.row.save(table._id!, { ...row, price: 300 }) + expect(row.price).toBe("300.00") + + row = await config.api.row.save(table._id!, { + ...row, + price: "400.00", + }) + expect(row.price).toBe("400.00") }) - expect(rows).toHaveLength(1) - expect(rows[0].price).toBe("200.00") }) + } + ) - it("should be able to update a money field", async () => { - let row = await config.api.row.save(table._id!, { price: 200 }) - expect(row.price).toBe("200.00") + const descriptions = datasourceDescribe({ only: [DatabaseName.POSTGRES] }) - row = await config.api.row.save(table._id!, { ...row, price: 300 }) - expect(row.price).toBe("300.00") + if (descriptions.length) { + describe.each(descriptions)( + "Integration compatibility with postgres search_path", + ({ config, dsProvider }) => { + let datasource: Datasource + let client: Knex + let schema1: string + let schema2: string - row = await config.api.row.save(table._id!, { ...row, price: "400.00" }) - expect(row.price).toBe("400.00") - }) - }) + beforeEach(async () => { + const ds = await dsProvider() + datasource = ds.datasource! + const rawDatasource = ds.rawDatasource! + + schema1 = generator.guid().replaceAll("-", "") + schema2 = generator.guid().replaceAll("-", "") + + client = await knexClient(rawDatasource) + + await client.schema.createSchema(schema1) + await client.schema.createSchema(schema2) + + rawDatasource.config!.schema = `${schema1}, ${schema2}` + + client = await knexClient(rawDatasource) + datasource = await config.api.datasource.create(rawDatasource) + }) + + afterEach(async () => { + await client.schema.dropSchema(schema1, true) + await client.schema.dropSchema(schema2, true) + }) + + it("discovers tables from any schema in search path", async () => { + await client.schema.createTable(`${schema1}.table1`, table => { + table.increments("id1").primary() + }) + + await client.schema.createTable(`${schema2}.table2`, table => { + table.increments("id2").primary() + }) + + const response = await config.api.datasource.info(datasource) + expect(response.tableNames).toBeDefined() + expect(response.tableNames).toEqual( + expect.arrayContaining(["table1", "table2"]) + ) + }) + + it("does not mix columns from different tables", async () => { + const repeated_table_name = "table_same_name" + + await client.schema.createTable( + `${schema1}.${repeated_table_name}`, + table => { + table.increments("id").primary() + table.string("val1") + } + ) + + await client.schema.createTable( + `${schema2}.${repeated_table_name}`, + table => { + table.increments("id2").primary() + table.string("val2") + } + ) + + const response = await config.api.datasource.fetchSchema({ + datasourceId: datasource._id!, + tablesFilter: [repeated_table_name], + }) + expect( + response.datasource.entities?.[repeated_table_name].schema + ).toBeDefined() + const schema = + response.datasource.entities?.[repeated_table_name].schema + expect(Object.keys(schema || {}).sort()).toEqual(["id", "val1"]) + }) + } + ) } -) - -datasourceDescribe( - { - name: "Integration compatibility with postgres search_path", - only: [DatabaseName.POSTGRES], - }, - ({ config, dsProvider }) => { - let datasource: Datasource - let client: Knex - let schema1: string - let schema2: string - - beforeEach(async () => { - const ds = await dsProvider() - datasource = ds.datasource! - const rawDatasource = ds.rawDatasource! - - schema1 = generator.guid().replaceAll("-", "") - schema2 = generator.guid().replaceAll("-", "") - - client = await knexClient(rawDatasource) - - await client.schema.createSchema(schema1) - await client.schema.createSchema(schema2) - - rawDatasource.config!.schema = `${schema1}, ${schema2}` - - client = await knexClient(rawDatasource) - datasource = await config.api.datasource.create(rawDatasource) - }) - - afterEach(async () => { - await client.schema.dropSchema(schema1, true) - await client.schema.dropSchema(schema2, true) - }) - - it("discovers tables from any schema in search path", async () => { - await client.schema.createTable(`${schema1}.table1`, table => { - table.increments("id1").primary() - }) - - await client.schema.createTable(`${schema2}.table2`, table => { - table.increments("id2").primary() - }) - - const response = await config.api.datasource.info(datasource) - expect(response.tableNames).toBeDefined() - expect(response.tableNames).toEqual( - expect.arrayContaining(["table1", "table2"]) - ) - }) - - it("does not mix columns from different tables", async () => { - const repeated_table_name = "table_same_name" - - await client.schema.createTable( - `${schema1}.${repeated_table_name}`, - table => { - table.increments("id").primary() - table.string("val1") - } - ) - - await client.schema.createTable( - `${schema2}.${repeated_table_name}`, - table => { - table.increments("id2").primary() - table.string("val2") - } - ) - - const response = await config.api.datasource.fetchSchema({ - datasourceId: datasource._id!, - tablesFilter: [repeated_table_name], - }) - expect( - response.datasource.entities?.[repeated_table_name].schema - ).toBeDefined() - const schema = response.datasource.entities?.[repeated_table_name].schema - expect(Object.keys(schema || {}).sort()).toEqual(["id", "val1"]) - }) - } -) +} diff --git a/packages/server/src/sdk/app/rows/search/tests/search.spec.ts b/packages/server/src/sdk/app/rows/search/tests/search.spec.ts index 78e5ffa30b..b424c3707d 100644 --- a/packages/server/src/sdk/app/rows/search/tests/search.spec.ts +++ b/packages/server/src/sdk/app/rows/search/tests/search.spec.ts @@ -19,202 +19,206 @@ import { tableForDatasource } from "../../../../../tests/utilities/structures" // These test cases are only for things that cannot be tested through the API // (e.g. limiting searches to returning specific fields). If it's possible to // test through the API, it should be done there instead. -datasourceDescribe( - { name: "search sdk (%s)", exclude: [DatabaseName.MONGODB] }, - ({ config, dsProvider, isInternal }) => { - let datasource: Datasource | undefined - let table: Table +const descriptions = datasourceDescribe({ exclude: [DatabaseName.MONGODB] }) - beforeAll(async () => { - const ds = await dsProvider() - datasource = ds.datasource - }) +if (descriptions.length) { + describe.each(descriptions)( + "search sdk ($dbName)", + ({ config, dsProvider, isInternal }) => { + let datasource: Datasource | undefined + let table: Table - beforeEach(async () => { - const idFieldSchema: NumberFieldMetadata | AutoColumnFieldMetadata = - isInternal - ? { - name: "id", - type: FieldType.AUTO, - subtype: AutoFieldSubType.AUTO_ID, - autocolumn: true, - } - : { - name: "id", - type: FieldType.NUMBER, - autocolumn: true, - } - - table = await config.api.table.save( - tableForDatasource(datasource, { - primary: ["id"], - schema: { - id: idFieldSchema, - name: { - name: "name", - type: FieldType.STRING, - }, - surname: { - name: "surname", - type: FieldType.STRING, - }, - age: { - name: "age", - type: FieldType.NUMBER, - }, - address: { - name: "address", - type: FieldType.STRING, - }, - }, - }) - ) - - for (let i = 0; i < 10; i++) { - await config.api.row.save(table._id!, { - name: generator.first(), - surname: generator.last(), - age: generator.age(), - address: generator.address(), - }) - } - }) - - afterAll(async () => { - config.end() - }) - - it("querying by fields will always return data attribute columns", async () => { - await config.doInContext(config.appId, async () => { - const { rows } = await search({ - tableId: table._id!, - query: {}, - fields: ["name", "age"], - }) - - expect(rows).toHaveLength(10) - for (const row of rows) { - const keys = Object.keys(row) - expect(keys).toContain("name") - expect(keys).toContain("age") - expect(keys).not.toContain("surname") - expect(keys).not.toContain("address") - } + beforeAll(async () => { + const ds = await dsProvider() + datasource = ds.datasource }) - }) - !isInternal && - it("will decode _id in oneOf query", async () => { - await config.doInContext(config.appId, async () => { - const result = await search({ - tableId: table._id!, - query: { - oneOf: { - _id: ["%5B1%5D", "%5B4%5D", "%5B8%5D"], + beforeEach(async () => { + const idFieldSchema: NumberFieldMetadata | AutoColumnFieldMetadata = + isInternal + ? { + name: "id", + type: FieldType.AUTO, + subtype: AutoFieldSubType.AUTO_ID, + autocolumn: true, + } + : { + name: "id", + type: FieldType.NUMBER, + autocolumn: true, + } + + table = await config.api.table.save( + tableForDatasource(datasource, { + primary: ["id"], + schema: { + id: idFieldSchema, + name: { + name: "name", + type: FieldType.STRING, + }, + surname: { + name: "surname", + type: FieldType.STRING, + }, + age: { + name: "age", + type: FieldType.NUMBER, + }, + address: { + name: "address", + type: FieldType.STRING, }, }, }) + ) - expect(result.rows).toHaveLength(3) - expect(result.rows.map(row => row.id)).toEqual( - expect.arrayContaining([1, 4, 8]) - ) - }) - }) - - it("does not allow accessing hidden fields", async () => { - await config.doInContext(config.appId, async () => { - await config.api.table.save({ - ...table, - schema: { - ...table.schema, - name: { - ...table.schema.name, - visible: true, - }, - age: { - ...table.schema.age, - visible: false, - }, - }, - }) - const result = await search({ - tableId: table._id!, - query: {}, - }) - expect(result.rows).toHaveLength(10) - for (const row of result.rows) { - const keys = Object.keys(row) - expect(keys).toContain("name") - expect(keys).toContain("surname") - expect(keys).toContain("address") - expect(keys).not.toContain("age") + for (let i = 0; i < 10; i++) { + await config.api.row.save(table._id!, { + name: generator.first(), + surname: generator.last(), + age: generator.age(), + address: generator.address(), + }) } }) - }) - it("does not allow accessing hidden fields even if requested", async () => { - await config.doInContext(config.appId, async () => { - await config.api.table.save({ - ...table, - schema: { - ...table.schema, - name: { - ...table.schema.name, - visible: true, - }, - age: { - ...table.schema.age, - visible: false, - }, - }, - }) - const result = await search({ - tableId: table._id!, - query: {}, - fields: ["name", "age"], - }) - expect(result.rows).toHaveLength(10) - for (const row of result.rows) { - const keys = Object.keys(row) - expect(keys).toContain("name") - expect(keys).not.toContain("age") - expect(keys).not.toContain("surname") - expect(keys).not.toContain("address") - } + afterAll(async () => { + config.end() }) - }) - it.each([ - [["id", "name", "age"], 3], - [["name", "age"], 10], - ])( - "cannot query by non search fields (fields: %s)", - async (queryFields, expectedRows) => { + it("querying by fields will always return data attribute columns", async () => { await config.doInContext(config.appId, async () => { const { rows } = await search({ tableId: table._id!, - query: { - $or: { - conditions: [ - { - $and: { - conditions: [ - { range: { id: { low: 2, high: 4 } } }, - { range: { id: { low: 3, high: 5 } } }, - ], - }, - }, - { equal: { id: 7 } }, - ], - }, - }, - fields: queryFields, + query: {}, + fields: ["name", "age"], }) - expect(rows).toHaveLength(expectedRows) + expect(rows).toHaveLength(10) + for (const row of rows) { + const keys = Object.keys(row) + expect(keys).toContain("name") + expect(keys).toContain("age") + expect(keys).not.toContain("surname") + expect(keys).not.toContain("address") + } }) - } - ) - } -) + }) + + !isInternal && + it("will decode _id in oneOf query", async () => { + await config.doInContext(config.appId, async () => { + const result = await search({ + tableId: table._id!, + query: { + oneOf: { + _id: ["%5B1%5D", "%5B4%5D", "%5B8%5D"], + }, + }, + }) + + expect(result.rows).toHaveLength(3) + expect(result.rows.map(row => row.id)).toEqual( + expect.arrayContaining([1, 4, 8]) + ) + }) + }) + + it("does not allow accessing hidden fields", async () => { + await config.doInContext(config.appId, async () => { + await config.api.table.save({ + ...table, + schema: { + ...table.schema, + name: { + ...table.schema.name, + visible: true, + }, + age: { + ...table.schema.age, + visible: false, + }, + }, + }) + const result = await search({ + tableId: table._id!, + query: {}, + }) + expect(result.rows).toHaveLength(10) + for (const row of result.rows) { + const keys = Object.keys(row) + expect(keys).toContain("name") + expect(keys).toContain("surname") + expect(keys).toContain("address") + expect(keys).not.toContain("age") + } + }) + }) + + it("does not allow accessing hidden fields even if requested", async () => { + await config.doInContext(config.appId, async () => { + await config.api.table.save({ + ...table, + schema: { + ...table.schema, + name: { + ...table.schema.name, + visible: true, + }, + age: { + ...table.schema.age, + visible: false, + }, + }, + }) + const result = await search({ + tableId: table._id!, + query: {}, + fields: ["name", "age"], + }) + expect(result.rows).toHaveLength(10) + for (const row of result.rows) { + const keys = Object.keys(row) + expect(keys).toContain("name") + expect(keys).not.toContain("age") + expect(keys).not.toContain("surname") + expect(keys).not.toContain("address") + } + }) + }) + + it.each([ + [["id", "name", "age"], 3], + [["name", "age"], 10], + ])( + "cannot query by non search fields (fields: %s)", + async (queryFields, expectedRows) => { + await config.doInContext(config.appId, async () => { + const { rows } = await search({ + tableId: table._id!, + query: { + $or: { + conditions: [ + { + $and: { + conditions: [ + { range: { id: { low: 2, high: 4 } } }, + { range: { id: { low: 3, high: 5 } } }, + ], + }, + }, + { equal: { id: 7 } }, + ], + }, + }, + fields: queryFields, + }) + + expect(rows).toHaveLength(expectedRows) + }) + } + ) + } + ) +} From 28989bec6e74f11445efa3ad43a984b5cbe44033 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 19 Nov 2024 11:22:10 +0100 Subject: [PATCH 11/40] Update yarn.lock --- yarn.lock | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0fa0e00436..25009fa8b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19437,7 +19437,16 @@ string-similarity@^4.0.4: resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -19520,7 +19529,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -19534,6 +19543,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -21314,7 +21330,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -21332,6 +21348,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 7c40ad06b638fc8d76dc2b7c065d9f824be63ae8 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 19 Nov 2024 11:53:14 +0100 Subject: [PATCH 12/40] Remove account-portal package --- lerna.json | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lerna.json b/lerna.json index e5b0013535..bbcf25c841 100644 --- a/lerna.json +++ b/lerna.json @@ -2,11 +2,7 @@ "$schema": "node_modules/lerna/schemas/lerna-schema.json", "version": "3.2.5", "npmClient": "yarn", - "packages": [ - "packages/*", - "!packages/account-portal", - "packages/account-portal/packages/*" - ], + "packages": ["packages/*"], "concurrency": 20, "command": { "publish": { @@ -22,4 +18,4 @@ "loadEnvFiles": false } } -} \ No newline at end of file +} From 19416b46507ef3b52fcaeeee7b9a0b65149d2113 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Tue, 19 Nov 2024 14:41:07 +0000 Subject: [PATCH 13/40] Fix for row action. --- packages/server/src/api/routes/tests/rowAction.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/api/routes/tests/rowAction.spec.ts b/packages/server/src/api/routes/tests/rowAction.spec.ts index dabcd11b73..76046c06ea 100644 --- a/packages/server/src/api/routes/tests/rowAction.spec.ts +++ b/packages/server/src/api/routes/tests/rowAction.spec.ts @@ -978,7 +978,7 @@ describe("/rowsActions", () => { }) const descriptions = datasourceDescribe({ - exclude: [DatabaseName.SQS, DatabaseName.POSTGRES], + only: [DatabaseName.SQS, DatabaseName.POSTGRES], }) if (descriptions.length) { From c563bb64b52aa1220de82843cb18b43b9825780c Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 14:53:20 +0000 Subject: [PATCH 14/40] remove snowflake-promise lib, update curlconverter to use dynamic import --- packages/pro | 2 +- packages/server/package.json | 3 +- .../controllers/query/import/sources/curl.ts | 7 +- packages/server/src/integrations/snowflake.ts | 41 +- yarn.lock | 2173 +++-------------- 5 files changed, 372 insertions(+), 1854 deletions(-) diff --git a/packages/pro b/packages/pro index a2d61705e6..a3fb5faa97 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit a2d61705e6f75f74b31154f9ae74e4e3166376ca +Subproject commit a3fb5faa97ebee477e6f3d01116380e6409ab1e8 diff --git a/packages/server/package.json b/packages/server/package.json index dc51689b96..286cd906aa 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -83,7 +83,7 @@ "google-spreadsheet": "npm:@budibase/google-spreadsheet@4.1.5", "ioredis": "5.3.2", "isolated-vm": "^4.7.2", - "jimp": "0.22.12", + "jimp": "1.1.4", "joi": "17.6.0", "js-yaml": "4.1.0", "jsonschema": "1.4.0", @@ -111,7 +111,6 @@ "redis": "4", "serialize-error": "^7.0.1", "server-destroy": "1.0.1", - "snowflake-promise": "^4.5.0", "socket.io": "4.8.1", "tar": "6.2.1", "tmp": "0.2.3", diff --git a/packages/server/src/api/controllers/query/import/sources/curl.ts b/packages/server/src/api/controllers/query/import/sources/curl.ts index ba85d82be0..f1747c9fc7 100644 --- a/packages/server/src/api/controllers/query/import/sources/curl.ts +++ b/packages/server/src/api/controllers/query/import/sources/curl.ts @@ -2,9 +2,8 @@ import { ImportSource, ImportInfo } from "./base" import { Query } from "../../../../../definitions/common" import { URL } from "url" -const curlconverter = require("curlconverter") - -const parseCurl = (data: string): any => { +const parseCurl = async (data: string): any => { + const curlconverter = await import("curlconverter") const curlJson = curlconverter.toJsonString(data) return JSON.parse(curlJson) } @@ -53,7 +52,7 @@ export class Curl extends ImportSource { isSupported = async (data: string): Promise => { try { - const curl = parseCurl(data) + const curl = await parseCurl(data) this.curl = curl } catch (err) { return false diff --git a/packages/server/src/integrations/snowflake.ts b/packages/server/src/integrations/snowflake.ts index 9a1dac10e5..bb77a19547 100644 --- a/packages/server/src/integrations/snowflake.ts +++ b/packages/server/src/integrations/snowflake.ts @@ -6,7 +6,8 @@ import { QueryType, SqlQuery, } from "@budibase/types" -import { Snowflake } from "snowflake-promise" +import snowflakeSdk from "snowflake-sdk" +import { promisify } from "util" interface SnowflakeConfig { account: string @@ -17,6 +18,7 @@ interface SnowflakeConfig { schema: string } + const SCHEMA: Integration = { docs: "https://developers.snowflake.com/", description: @@ -71,11 +73,42 @@ const SCHEMA: Integration = { }, } -class SnowflakeIntegration { - private client: Snowflake +class SnowflakePromise { + config: SnowflakeConfig + client: snowflakeSdk constructor(config: SnowflakeConfig) { - this.client = new Snowflake(config) + this.config = config + } + + async connect() { + if (this.client?.isConnected()) return + + this.client = snowflakeSdk.createConnection(this.config) + const connectAsync = promisify(this.client.connect.bind(this.client)) + return connectAsync() + } + + async execute(sql: string) { + return new Promise((resolve, reject) => { + this.client.execute({ + sqlText: sql, + complete: function(err: Error, statementExecuted: string, rows: any) { + if (err) { + return reject(err) + } + resolve(rows) + }, + }) + }) + } +} + +class SnowflakeIntegration { + private client: SnowflakePromise + + constructor(config: SnowflakeConfig) { + this.client = new SnowflakePromise(config) } async testConnection(): Promise { diff --git a/yarn.lock b/yarn.lock index 25009fa8b3..7008a741be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -82,562 +82,6 @@ call-me-maybe "^1.0.1" z-schema "^5.0.1" -"@aws-crypto/crc32@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa" - integrity "sha1-BzAOyiFECcM+P/dpzVaXtX/dOPo= sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==" - dependencies: - "@aws-crypto/util" "^3.0.0" - "@aws-sdk/types" "^3.222.0" - tslib "^1.11.1" - -"@aws-crypto/crc32c@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz#016c92da559ef638a84a245eecb75c3e97cb664f" - integrity "sha1-AWyS2lWe9jioSiRe7LdcPpfLZk8= sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==" - dependencies: - "@aws-crypto/util" "^3.0.0" - "@aws-sdk/types" "^3.222.0" - tslib "^1.11.1" - -"@aws-crypto/ie11-detection@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz#640ae66b4ec3395cee6a8e94ebcd9f80c24cd688" - integrity "sha1-ZArma07DOVzuao6U682fgMJM1og= sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==" - dependencies: - tslib "^1.11.1" - -"@aws-crypto/sha1-browser@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz#f9083c00782b24714f528b1a1fef2174002266a3" - integrity "sha1-+Qg8AHgrJHFPUosaH+8hdAAiZqM= sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==" - dependencies: - "@aws-crypto/ie11-detection" "^3.0.0" - "@aws-crypto/supports-web-crypto" "^3.0.0" - "@aws-crypto/util" "^3.0.0" - "@aws-sdk/types" "^3.222.0" - "@aws-sdk/util-locate-window" "^3.0.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-crypto/sha256-browser@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz#05f160138ab893f1c6ba5be57cfd108f05827766" - integrity "sha1-BfFgE4q4k/HGulvlfP0QjwWCd2Y= sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==" - dependencies: - "@aws-crypto/ie11-detection" "^3.0.0" - "@aws-crypto/sha256-js" "^3.0.0" - "@aws-crypto/supports-web-crypto" "^3.0.0" - "@aws-crypto/util" "^3.0.0" - "@aws-sdk/types" "^3.222.0" - "@aws-sdk/util-locate-window" "^3.0.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-crypto/sha256-js@3.0.0", "@aws-crypto/sha256-js@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz#f06b84d550d25521e60d2a0e2a90139341e007c2" - integrity "sha1-8GuE1VDSVSHmDSoOKpATk0HgB8I= sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==" - dependencies: - "@aws-crypto/util" "^3.0.0" - "@aws-sdk/types" "^3.222.0" - tslib "^1.11.1" - -"@aws-crypto/supports-web-crypto@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz#5d1bf825afa8072af2717c3e455f35cda0103ec2" - integrity "sha1-XRv4Ja+oByrycXw+RV81zaAQPsI= sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==" - dependencies: - tslib "^1.11.1" - -"@aws-crypto/util@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-3.0.0.tgz#1c7ca90c29293f0883468ad48117937f0fe5bfb0" - integrity "sha1-HHypDCkpPwiDRorUgReTfw/lv7A= sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==" - dependencies: - "@aws-sdk/types" "^3.222.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-sdk/client-s3@^3.388.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.423.0.tgz#b15fc64db09f1698bf4ad19f6f8e3b57c15e5305" - integrity "sha1-sV/GTbCfFpi/StGfb447V8FeUwU= sha512-Sn/6fotTDGp+uUfPU0JrKszHT/cYwZonly6Ahi4R/uxASLQnOEAF7MwVSjms+/LGu72Qs0Tt7B7RKW76GI4OIA==" - dependencies: - "@aws-crypto/sha1-browser" "3.0.0" - "@aws-crypto/sha256-browser" "3.0.0" - "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.423.0" - "@aws-sdk/credential-provider-node" "3.423.0" - "@aws-sdk/middleware-bucket-endpoint" "3.418.0" - "@aws-sdk/middleware-expect-continue" "3.418.0" - "@aws-sdk/middleware-flexible-checksums" "3.418.0" - "@aws-sdk/middleware-host-header" "3.418.0" - "@aws-sdk/middleware-location-constraint" "3.418.0" - "@aws-sdk/middleware-logger" "3.418.0" - "@aws-sdk/middleware-recursion-detection" "3.418.0" - "@aws-sdk/middleware-sdk-s3" "3.418.0" - "@aws-sdk/middleware-signing" "3.418.0" - "@aws-sdk/middleware-ssec" "3.418.0" - "@aws-sdk/middleware-user-agent" "3.418.0" - "@aws-sdk/region-config-resolver" "3.418.0" - "@aws-sdk/signature-v4-multi-region" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-endpoints" "3.418.0" - "@aws-sdk/util-user-agent-browser" "3.418.0" - "@aws-sdk/util-user-agent-node" "3.418.0" - "@aws-sdk/xml-builder" "3.310.0" - "@smithy/config-resolver" "^2.0.10" - "@smithy/eventstream-serde-browser" "^2.0.9" - "@smithy/eventstream-serde-config-resolver" "^2.0.9" - "@smithy/eventstream-serde-node" "^2.0.9" - "@smithy/fetch-http-handler" "^2.1.5" - "@smithy/hash-blob-browser" "^2.0.9" - "@smithy/hash-node" "^2.0.9" - "@smithy/hash-stream-node" "^2.0.9" - "@smithy/invalid-dependency" "^2.0.9" - "@smithy/md5-js" "^2.0.9" - "@smithy/middleware-content-length" "^2.0.11" - "@smithy/middleware-endpoint" "^2.0.9" - "@smithy/middleware-retry" "^2.0.12" - "@smithy/middleware-serde" "^2.0.9" - "@smithy/middleware-stack" "^2.0.2" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/node-http-handler" "^2.1.5" - "@smithy/protocol-http" "^3.0.5" - "@smithy/smithy-client" "^2.1.6" - "@smithy/types" "^2.3.3" - "@smithy/url-parser" "^2.0.9" - "@smithy/util-base64" "^2.0.0" - "@smithy/util-body-length-browser" "^2.0.0" - "@smithy/util-body-length-node" "^2.1.0" - "@smithy/util-defaults-mode-browser" "^2.0.10" - "@smithy/util-defaults-mode-node" "^2.0.12" - "@smithy/util-retry" "^2.0.2" - "@smithy/util-stream" "^2.0.12" - "@smithy/util-utf8" "^2.0.0" - "@smithy/util-waiter" "^2.0.9" - fast-xml-parser "4.2.5" - tslib "^2.5.0" - -"@aws-sdk/client-sso@3.423.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.423.0.tgz#99db1f73419443cef544892337a1344aba10abc2" - integrity "sha1-mdsfc0GUQ871RIkjN6E0SroQq8I= sha512-znIufHkwhCIePgaYciIs3x/+BpzR57CZzbCKHR9+oOvGyufEPPpUT5bFLvbwTgfiVkTjuk6sG/ES3U5Bc+xtrA==" - dependencies: - "@aws-crypto/sha256-browser" "3.0.0" - "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/middleware-host-header" "3.418.0" - "@aws-sdk/middleware-logger" "3.418.0" - "@aws-sdk/middleware-recursion-detection" "3.418.0" - "@aws-sdk/middleware-user-agent" "3.418.0" - "@aws-sdk/region-config-resolver" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-endpoints" "3.418.0" - "@aws-sdk/util-user-agent-browser" "3.418.0" - "@aws-sdk/util-user-agent-node" "3.418.0" - "@smithy/config-resolver" "^2.0.10" - "@smithy/fetch-http-handler" "^2.1.5" - "@smithy/hash-node" "^2.0.9" - "@smithy/invalid-dependency" "^2.0.9" - "@smithy/middleware-content-length" "^2.0.11" - "@smithy/middleware-endpoint" "^2.0.9" - "@smithy/middleware-retry" "^2.0.12" - "@smithy/middleware-serde" "^2.0.9" - "@smithy/middleware-stack" "^2.0.2" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/node-http-handler" "^2.1.5" - "@smithy/protocol-http" "^3.0.5" - "@smithy/smithy-client" "^2.1.6" - "@smithy/types" "^2.3.3" - "@smithy/url-parser" "^2.0.9" - "@smithy/util-base64" "^2.0.0" - "@smithy/util-body-length-browser" "^2.0.0" - "@smithy/util-body-length-node" "^2.1.0" - "@smithy/util-defaults-mode-browser" "^2.0.10" - "@smithy/util-defaults-mode-node" "^2.0.12" - "@smithy/util-retry" "^2.0.2" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.5.0" - -"@aws-sdk/client-sts@3.423.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.423.0.tgz#530a9cd58baef40cc6bbc6321c6ed93175e0e5b2" - integrity "sha1-Uwqc1Yuu9AzGu8YyHG7ZMXXg5bI= sha512-EcpkKu02QZbRX6dQE0u7a8RgWrn/5riz1qAlKd7rM8FZJpr/D6GGX8ZzWxjgp7pRUgfNvinTmIudDnyQY3v9Mg==" - dependencies: - "@aws-crypto/sha256-browser" "3.0.0" - "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/credential-provider-node" "3.423.0" - "@aws-sdk/middleware-host-header" "3.418.0" - "@aws-sdk/middleware-logger" "3.418.0" - "@aws-sdk/middleware-recursion-detection" "3.418.0" - "@aws-sdk/middleware-sdk-sts" "3.418.0" - "@aws-sdk/middleware-signing" "3.418.0" - "@aws-sdk/middleware-user-agent" "3.418.0" - "@aws-sdk/region-config-resolver" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-endpoints" "3.418.0" - "@aws-sdk/util-user-agent-browser" "3.418.0" - "@aws-sdk/util-user-agent-node" "3.418.0" - "@smithy/config-resolver" "^2.0.10" - "@smithy/fetch-http-handler" "^2.1.5" - "@smithy/hash-node" "^2.0.9" - "@smithy/invalid-dependency" "^2.0.9" - "@smithy/middleware-content-length" "^2.0.11" - "@smithy/middleware-endpoint" "^2.0.9" - "@smithy/middleware-retry" "^2.0.12" - "@smithy/middleware-serde" "^2.0.9" - "@smithy/middleware-stack" "^2.0.2" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/node-http-handler" "^2.1.5" - "@smithy/protocol-http" "^3.0.5" - "@smithy/smithy-client" "^2.1.6" - "@smithy/types" "^2.3.3" - "@smithy/url-parser" "^2.0.9" - "@smithy/util-base64" "^2.0.0" - "@smithy/util-body-length-browser" "^2.0.0" - "@smithy/util-body-length-node" "^2.1.0" - "@smithy/util-defaults-mode-browser" "^2.0.10" - "@smithy/util-defaults-mode-node" "^2.0.12" - "@smithy/util-retry" "^2.0.2" - "@smithy/util-utf8" "^2.0.0" - fast-xml-parser "4.2.5" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-env@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.418.0.tgz#7b14169350d9c14c9f656da06edf46f40a224ed2" - integrity "sha1-exQWk1DZwUyfZW2gbt9G9AoiTtI= sha512-e74sS+x63EZUBO+HaI8zor886YdtmULzwKdctsZp5/37Xho1CVUNtEC+fYa69nigBD9afoiH33I4JggaHgrekQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-ini@3.423.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.423.0.tgz#62690a3c49b0223c3d239c8a3d2f2708e967a767" - integrity "sha1-YmkKPEmwIjw9I5yKPS8nCOlnp2c= sha512-7CsFWz8g7dQmblp57XzzxMirO4ClowGZIOwAheBkmk6q1XHbllcHFnbh2kdPyQQ0+JmjDg6waztIc7dY7Ycfvw==" - dependencies: - "@aws-sdk/credential-provider-env" "3.418.0" - "@aws-sdk/credential-provider-process" "3.418.0" - "@aws-sdk/credential-provider-sso" "3.423.0" - "@aws-sdk/credential-provider-web-identity" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@smithy/credential-provider-imds" "^2.0.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/shared-ini-file-loader" "^2.0.6" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-node@3.423.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.423.0.tgz#80d05ea89b1a4f245786171ae516c331aa315908" - integrity "sha1-gNBeqJsaTyRXhhca5RbDMaoxWQg= sha512-lygbGJJUnDpgo8OEqdoYd51BKkyBVQ1Catiua/m0aHvL+SCmVrHiYPQPawWYGxpH8X3DXdXa0nd0LkEaevrHRg==" - dependencies: - "@aws-sdk/credential-provider-env" "3.418.0" - "@aws-sdk/credential-provider-ini" "3.423.0" - "@aws-sdk/credential-provider-process" "3.418.0" - "@aws-sdk/credential-provider-sso" "3.423.0" - "@aws-sdk/credential-provider-web-identity" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@smithy/credential-provider-imds" "^2.0.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/shared-ini-file-loader" "^2.0.6" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-process@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.418.0.tgz#1cb6d816bd471db3f9724715b007035ef18b5b2b" - integrity "sha1-HLbYFr1HHbP5ckcVsAcDXvGLWys= sha512-xPbdm2WKz1oH6pTkrJoUmr3OLuqvvcPYTQX0IIlc31tmDwDWPQjXGGFD/vwZGIZIkKaFpFxVMgAzfFScxox7dw==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/shared-ini-file-loader" "^2.0.6" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-sso@3.423.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.423.0.tgz#a04f1715e5d9c75370d17ceac645379ca57cbb0b" - integrity "sha1-oE8XFeXZx1Nw0XzqxkU3nKV8uws= sha512-zAH68IjRMmW22USbsCVQ5Q6AHqhmWABwLbZAMocSGMasddTGv/nkA/nUiVCJ/B4LI3P81FoPQVrG5JxNmkNH0w==" - dependencies: - "@aws-sdk/client-sso" "3.423.0" - "@aws-sdk/token-providers" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/shared-ini-file-loader" "^2.0.6" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-web-identity@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.418.0.tgz#c2aed2a79bf193c1fef2b98391aaa9de7336aaaf" - integrity "sha1-wq7Sp5vxk8H+8rmDkaqp3nM2qq8= sha512-do7ang565n9p3dS1JdsQY01rUfRx8vkxQqz5M8OlcEHBNiCdi2PvSjNwcBdrv/FKkyIxZb0TImOfBSt40hVdxQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-bucket-endpoint@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.418.0.tgz#1c330fb4dd583454872db7eba3b6e06c0699d59d" - integrity "sha1-HDMPtN1YNFSHLbfro7bgbAaZ1Z0= sha512-gj/mj1UfbKkGbQ1N4YUvjTTp8BVs5fO1QAL2AjFJ+jfJOToLReX72aNEkm7sPGbHML0TqOY4cQbJuWYy+zdD5g==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-arn-parser" "3.310.0" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - "@smithy/util-config-provider" "^2.0.0" - tslib "^2.5.0" - -"@aws-sdk/middleware-expect-continue@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.418.0.tgz#b621c6a8bc281f23bfd3791eaab25f687946d4a7" - integrity "sha1-tiHGqLwoHyO/03keqrJfaHlG1Kc= sha512-6x4rcIj685EmqDLQkbWoCur3Dg5DRClHMen6nHXmD3CR5Xyt3z1Gk/+jmZICxyJo9c6M4AeZht8o95BopkmYAQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-flexible-checksums@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.418.0.tgz#a79f44739ec918d8947294d0acc52eb7eb358773" - integrity "sha1-p59Ec57JGNiUcpTQrMUut+s1h3M= sha512-3O203dqS2JU5P1TAAbo7p1qplXQh59pevw9nqzPVb3EG8B+mSucVf2kKmF7kGHqKSk+nK/mB/4XGSsZBzGt6Wg==" - dependencies: - "@aws-crypto/crc32" "3.0.0" - "@aws-crypto/crc32c" "3.0.0" - "@aws-sdk/types" "3.418.0" - "@smithy/is-array-buffer" "^2.0.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.5.0" - -"@aws-sdk/middleware-host-header@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.418.0.tgz#35d682e14f36c9d9d7464c7c1dd582bf6611436d" - integrity "sha1-NdaC4U82ydnXRkx8HdWCv2YRQ20= sha512-LrMTdzalkPw/1ujLCKPLwCGvPMCmT4P+vOZQRbSEVZPnlZk+Aj++aL/RaHou0jL4kJH3zl8iQepriBt4a7UvXQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-location-constraint@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.418.0.tgz#e62e213a72ce583ba6135db51dcc60d07825b8ee" - integrity "sha1-5i4hOnLOWDumE121Hcxg0HgluO4= sha512-cc8M3VEaESHJhDsDV8tTpt2QYUprDWhvAVVSlcL43cTdZ54Quc0W+toDiaVOUlwrAZz2Y7g5NDj22ibJGFbOvw==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-logger@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.418.0.tgz#08d7419f4220c36032a070a7dbb8bbf7e744a9ce" - integrity "sha1-CNdBn0Igw2AyoHCn27i79+dEqc4= sha512-StKGmyPVfoO/wdNTtKemYwoJsqIl4l7oqarQY7VSf2Mp3mqaa+njLViHsQbirYpyqpgUEusOnuTlH5utxJ1NsQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-recursion-detection@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.418.0.tgz#2bb80d084f946846ad4907f3d6e0b451787d62b1" - integrity "sha1-K7gNCE+UaEatSQfz1uC0UXh9YrE= sha512-kKFrIQglBLUFPbHSDy1+bbe3Na2Kd70JSUC3QLMbUHmqipXN8KeXRfAj7vTv97zXl0WzG0buV++WcNwOm1rFjg==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-sdk-s3@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.418.0.tgz#b1de52d54e0cbc8d46ce0bc4c6c54b527f409aaf" - integrity "sha1-sd5S1U4MvI1GzgvExsVLUn9Amq8= sha512-rei32LF45SyqL3NlWDjEOfMwAca9A5F4QgUyXJqvASc43oWC1tJnLIhiCxNh8qkWAiRyRzFpcanTeqyaRSsZpA==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-arn-parser" "3.310.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/smithy-client" "^2.1.6" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-sdk-sts@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.418.0.tgz#f167f16050e055282ddd60226a2216c84873d464" - integrity "sha1-8WfxYFDgVSgt3WAiaiIWyEhz1GQ= sha512-cW8ijrCTP+mgihvcq4+TbhAcE/we5lFl4ydRqvTdtcSnYQAVQADg47rnTScQiFsPFEB3NKq7BGeyTJF9MKolPA==" - dependencies: - "@aws-sdk/middleware-signing" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-signing@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.418.0.tgz#c7242b84069067bb671cb4191d412b59713a375e" - integrity "sha1-xyQrhAaQZ7tnHLQZHUErWXE6N14= sha512-onvs5KoYQE8OlOE740RxWBGtsUyVIgAo0CzRKOQO63ZEYqpL1Os+MS1CGzdNhvQnJgJruE1WW+Ix8fjN30zKPA==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/signature-v4" "^2.0.0" - "@smithy/types" "^2.3.3" - "@smithy/util-middleware" "^2.0.2" - tslib "^2.5.0" - -"@aws-sdk/middleware-ssec@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.418.0.tgz#67b554c4acad81c7aa93421c8fcba8a18e138294" - integrity "sha1-Z7VUxKytgceqk0Icj8uooY4TgpQ= sha512-J7K+5h6aP7IYMlu/NwHEIjb0+WDu1eFvO8TCPo6j1H9xYRi8B/6h+6pa9Rk9IgRUzFnrdlDu9FazG8Tp0KKLyg==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-user-agent@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.418.0.tgz#37426cf801332165fb170b1fd62dea8bb967a1ef" - integrity "sha1-N0Js+AEzIWX7Fwsf1i3qi7lnoe8= sha512-Jdcztg9Tal9SEAL0dKRrnpKrm6LFlWmAhvuwv0dQ7bNTJxIxyEFbpqdgy7mpQHsLVZgq1Aad/7gT/72c9igyZw==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-endpoints" "3.418.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/region-config-resolver@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.418.0.tgz#53b99e4bd92f3369f51e9a76534b7d884db67526" - integrity "sha1-U7meS9kvM2n1Hpp2U0t9iE22dSY= sha512-lJRZ/9TjZU6yLz+mAwxJkcJZ6BmyYoIJVo1p5+BN//EFdEmC8/c0c9gXMRzfISV/mqWSttdtccpAyN4/goHTYA==" - dependencies: - "@smithy/node-config-provider" "^2.0.12" - "@smithy/types" "^2.3.3" - "@smithy/util-config-provider" "^2.0.0" - "@smithy/util-middleware" "^2.0.2" - tslib "^2.5.0" - -"@aws-sdk/signature-v4-multi-region@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.418.0.tgz#984c8fc948c61a7ad02f1ccc6c2ddecf43a265b1" - integrity "sha1-mEyPyUjGGnrQLxzMbC3ez0OiZbE= sha512-LeVYMZeUQUURFqDf4yZxTEv016g64hi0LqYBjU0mjwd8aPc0k6hckwvshezc80jCNbuLyjNfQclvlg3iFliItQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/signature-v4" "^2.0.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/token-providers@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.418.0.tgz#cbfac922df397e72daf6dbdd8c1e9a140df0aa0e" - integrity "sha1-y/rJIt85fnLa9tvdjB6aFA3wqg4= sha512-9P7Q0VN0hEzTngy3Sz5eya2qEOEf0Q8qf1vB3um0gE6ID6EVAdz/nc/DztfN32MFxk8FeVBrCP5vWdoOzmd72g==" - dependencies: - "@aws-crypto/sha256-browser" "3.0.0" - "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/middleware-host-header" "3.418.0" - "@aws-sdk/middleware-logger" "3.418.0" - "@aws-sdk/middleware-recursion-detection" "3.418.0" - "@aws-sdk/middleware-user-agent" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-endpoints" "3.418.0" - "@aws-sdk/util-user-agent-browser" "3.418.0" - "@aws-sdk/util-user-agent-node" "3.418.0" - "@smithy/config-resolver" "^2.0.10" - "@smithy/fetch-http-handler" "^2.1.5" - "@smithy/hash-node" "^2.0.9" - "@smithy/invalid-dependency" "^2.0.9" - "@smithy/middleware-content-length" "^2.0.11" - "@smithy/middleware-endpoint" "^2.0.9" - "@smithy/middleware-retry" "^2.0.12" - "@smithy/middleware-serde" "^2.0.9" - "@smithy/middleware-stack" "^2.0.2" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/node-http-handler" "^2.1.5" - "@smithy/property-provider" "^2.0.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/shared-ini-file-loader" "^2.0.6" - "@smithy/smithy-client" "^2.1.6" - "@smithy/types" "^2.3.3" - "@smithy/url-parser" "^2.0.9" - "@smithy/util-base64" "^2.0.0" - "@smithy/util-body-length-browser" "^2.0.0" - "@smithy/util-body-length-node" "^2.1.0" - "@smithy/util-defaults-mode-browser" "^2.0.10" - "@smithy/util-defaults-mode-node" "^2.0.12" - "@smithy/util-retry" "^2.0.2" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.5.0" - -"@aws-sdk/types@3.418.0", "@aws-sdk/types@^3.222.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.418.0.tgz#c23213110b0c313d5546c810da032a441682f49a" - integrity "sha1-wjITEQsMMT1VRsgQ2gMqRBaC9Jo= sha512-y4PQSH+ulfFLY0+FYkaK4qbIaQI9IJNMO2xsxukW6/aNoApNymN1D2FSi2la8Qbp/iPjNDKsG8suNPm9NtsWXQ==" - dependencies: - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/util-arn-parser@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.310.0.tgz#861ff8810851be52a320ec9e4786f15b5fc74fba" - integrity "sha1-hh/4gQhRvlKjIOyeR4bxW1/HT7o= sha512-jL8509owp/xB9+Or0pvn3Fe+b94qfklc2yPowZZIFAkFcCSIdkIglz18cPDWnYAcy9JGewpMS1COXKIUhZkJsA==" - dependencies: - tslib "^2.5.0" - -"@aws-sdk/util-endpoints@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.418.0.tgz#462c976f054fe260562d4d2844152a04dd883fd7" - integrity "sha1-RiyXbwVP4mBWLU0oRBUqBN2IP9c= sha512-sYSDwRTl7yE7LhHkPzemGzmIXFVHSsi3AQ1KeNEk84eBqxMHHcCc2kqklaBk2roXWe50QDgRMy1ikZUxvtzNHQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - tslib "^2.5.0" - -"@aws-sdk/util-locate-window@^3.0.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz#b071baf050301adee89051032bd4139bba32cc40" - integrity "sha1-sHG68FAwGt7okFEDK9QTm7oyzEA= sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==" - dependencies: - tslib "^2.5.0" - -"@aws-sdk/util-user-agent-browser@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.418.0.tgz#dc76b8e7e5cae3f827d68cd4a3ee30c0d475a39c" - integrity "sha1-3Ha45+XK4/gn1ozUo+4wwNR1o5w= sha512-c4p4mc0VV/jIeNH0lsXzhJ1MpWRLuboGtNEpqE4s1Vl9ck2amv9VdUUZUmHbg+bVxlMgRQ4nmiovA4qIrqGuyg==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/types" "^2.3.3" - bowser "^2.11.0" - tslib "^2.5.0" - -"@aws-sdk/util-user-agent-node@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.418.0.tgz#7d5a1c82ce3265ff0f70b13d58d08593113ab99a" - integrity "sha1-fVocgs4yZf8PcLE9WNCFkxE6uZo= sha512-BXMskXFtg+dmzSCgmnWOffokxIbPr1lFqa1D9kvM3l3IFRiFGx2IyDg+8MAhq11aPDLvoa/BDuQ0Yqma5izOhg==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/util-utf8-browser@^3.0.0": - version "3.259.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz#3275a6f5eb334f96ca76635b961d3c50259fd9ff" - integrity "sha1-MnWm9eszT5bKdmNblh08UCWf2f8= sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==" - dependencies: - tslib "^2.3.1" - -"@aws-sdk/xml-builder@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.310.0.tgz#f0236f2103b438d16117e0939a6305ad69b7ff76" - integrity "sha1-8CNvIQO0ONFhF+CTmmMFrWm3/3Y= sha512-TqELu4mOuSIKQCqj63fGVs86Yh+vBx5nHRpWKNUNhB2nPTpfbziTs5c1X358be3peVWA4wPxW7Nt53KIg1tnNw==" - dependencies: - tslib "^2.5.0" - "@azure/abort-controller@^1.0.0", "@azure/abort-controller@^1.0.4": version "1.1.0" resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" @@ -683,26 +127,6 @@ "@azure/core-client" "^1.3.0" "@azure/core-rest-pipeline" "^1.3.0" -"@azure/core-http@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@azure/core-http/-/core-http-3.0.0.tgz#345845f9ba479a5ee41efc3fd7a13e82d2a0ec47" - integrity sha512-BxI2SlGFPPz6J1XyZNIVUf0QZLBKFX+ViFjKOkzqD18J1zOINIQ8JSBKKr+i+v8+MB6LacL6Nn/sP/TE13+s2Q== - dependencies: - "@azure/abort-controller" "^1.0.0" - "@azure/core-auth" "^1.3.0" - "@azure/core-tracing" "1.0.0-preview.13" - "@azure/core-util" "^1.1.1" - "@azure/logger" "^1.0.0" - "@types/node-fetch" "^2.5.0" - "@types/tunnel" "^0.0.3" - form-data "^4.0.0" - node-fetch "^2.6.7" - process "^0.11.10" - tslib "^2.2.0" - tunnel "^0.0.6" - uuid "^8.3.0" - xml2js "^0.4.19" - "@azure/core-lro@^2.2.0": version "2.5.1" resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-2.5.1.tgz#9c6be24b84f8a8c8e8ac376c5018460c5a585d0b" @@ -734,14 +158,6 @@ https-proxy-agent "^5.0.0" tslib "^2.2.0" -"@azure/core-tracing@1.0.0-preview.13": - version "1.0.0-preview.13" - resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz#55883d40ae2042f6f1e12b17dd0c0d34c536d644" - integrity sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ== - dependencies: - "@opentelemetry/api" "^1.0.1" - tslib "^2.2.0" - "@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" @@ -749,7 +165,7 @@ dependencies: tslib "^2.2.0" -"@azure/core-util@^1.0.0", "@azure/core-util@^1.1.0", "@azure/core-util@^1.1.1", "@azure/core-util@^1.3.0", "@azure/core-util@^1.6.1": +"@azure/core-util@^1.0.0", "@azure/core-util@^1.1.0", "@azure/core-util@^1.3.0", "@azure/core-util@^1.6.1": version "1.6.1" resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.6.1.tgz#fea221c4fa43c26543bccf799beb30c1c7878f5a" integrity sha512-h5taHeySlsV9qxuK64KZxy4iln1BtMYlNt5jbuEFN3UFSAd1EwKg/Gjl5a6tZ/W8t6li3xPnutOx7zbDyXnPmQ== @@ -822,20 +238,6 @@ jsonwebtoken "^9.0.0" uuid "^8.3.0" -"@azure/storage-blob@^12.11.0": - version "12.13.0" - resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.13.0.tgz#9209cbb5c2cd463fb967a0f2ae144ace20879160" - integrity sha512-t3Q2lvBMJucgTjQcP5+hvEJMAsJSk0qmAnjDLie2td017IiduZbbC9BOcFfmwzR6y6cJdZOuewLCNFmEx9IrXA== - dependencies: - "@azure/abort-controller" "^1.0.0" - "@azure/core-http" "^3.0.0" - "@azure/core-lro" "^2.2.0" - "@azure/core-paging" "^1.1.1" - "@azure/core-tracing" "1.0.0-preview.13" - "@azure/logger" "^1.0.0" - events "^3.0.0" - tslib "^2.2.0" - "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.22.5", "@babel/code-frame@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" @@ -2044,7 +1446,7 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@3.2.5": +"@budibase/backend-core@3.2.6": version "0.0.0" dependencies: "@budibase/nano" "10.1.5" @@ -2125,15 +1527,15 @@ through2 "^2.0.0" "@budibase/pro@npm:@budibase/pro@latest": - version "3.2.5" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.5.tgz#7d58aca194e2cd23f976ff0241f022aabc62daa4" - integrity sha512-E+P0M4p0hj/FVx2lUmqlXPskqjHCor4RKoBL9dE+wiaIr3PMojnIsy5bxU8z7x2gQrpEp/WvJRo0A6KRPdW6mA== + version "3.2.6" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.6.tgz#e6eeb1de9dd39b06b4bf7115d0decfa5b216ecbb" + integrity sha512-AUHXe6AkENxKD7DogDvUhTTqK/11GMtEwCodCzvBQ2h97AJNYykZzRK4G4DtCyliD9AvUMAJFIROfhb31x0LFw== dependencies: "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "3.2.5" - "@budibase/shared-core" "3.2.5" - "@budibase/string-templates" "3.2.5" - "@budibase/types" "3.2.5" + "@budibase/backend-core" "3.2.6" + "@budibase/shared-core" "3.2.6" + "@budibase/string-templates" "3.2.6" + "@budibase/types" "3.2.6" "@koa/router" "8.0.8" bull "4.10.1" dd-trace "5.2.0" @@ -2146,13 +1548,13 @@ scim-patch "^0.8.1" scim2-parse-filter "^0.2.8" -"@budibase/shared-core@3.2.5": +"@budibase/shared-core@3.2.6": version "0.0.0" dependencies: "@budibase/types" "0.0.0" cron-validate "1.4.5" -"@budibase/string-templates@3.2.5": +"@budibase/string-templates@3.2.6": version "0.0.0" dependencies: "@budibase/handlebars-helpers" "^0.13.2" @@ -2160,7 +1562,7 @@ handlebars "^4.7.8" lodash.clonedeep "^4.5.0" -"@budibase/types@3.2.5": +"@budibase/types@3.2.6": version "0.0.0" dependencies: scim-patch "^0.8.1" @@ -2271,11 +1673,6 @@ style-mod "^4.0.0" w3c-keyname "^2.2.4" -"@colors/colors@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" - integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== - "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -2283,15 +1680,6 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@dabh/diagnostics@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" - integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== - dependencies: - colorspace "1.1.x" - enabled "2.0.x" - kuler "^2.0.0" - "@dagrejs/dagre@1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@dagrejs/dagre/-/dagre-1.1.4.tgz#66f9c0e2b558308f2c268f60e2c28f22ee17e339" @@ -2591,48 +1979,6 @@ google-gax "^4.3.3" protobufjs "^7.2.6" -"@google-cloud/paginator@^3.0.7": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.7.tgz#fb6f8e24ec841f99defaebf62c75c2e744dd419b" - integrity "sha1-+2+OJOyEH5ne+uv2LHXC50TdQZs= sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ==" - dependencies: - arrify "^2.0.0" - extend "^3.0.2" - -"@google-cloud/projectify@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-3.0.0.tgz#302b25f55f674854dce65c2532d98919b118a408" - integrity "sha1-MCsl9V9nSFTc5lwlMtmJGbEYpAg= sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA==" - -"@google-cloud/promisify@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-3.0.1.tgz#8d724fb280f47d1ff99953aee0c1669b25238c2e" - integrity "sha1-jXJPsoD0fR/5mVOu4MFmmyUjjC4= sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA==" - -"@google-cloud/storage@^6.9.3": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-6.12.0.tgz#a5d3093cc075252dca5bd19a3cfda406ad3a9de1" - integrity "sha1-pdMJPMB1JS3KW9GaPP2kBq06neE= sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw==" - dependencies: - "@google-cloud/paginator" "^3.0.7" - "@google-cloud/projectify" "^3.0.0" - "@google-cloud/promisify" "^3.0.0" - abort-controller "^3.0.0" - async-retry "^1.3.3" - compressible "^2.0.12" - duplexify "^4.0.0" - ent "^2.2.0" - extend "^3.0.2" - fast-xml-parser "^4.2.2" - gaxios "^5.0.0" - google-auth-library "^8.0.1" - mime "^3.0.0" - mime-types "^2.0.8" - p-limit "^3.0.1" - retry-request "^5.0.0" - teeny-request "^8.0.0" - uuid "^8.0.0" - "@grpc/grpc-js@^1.10.9": version "1.10.10" resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.10.10.tgz#476d315feeb9dbb0f2d6560008c92688c30f13e0" @@ -2946,262 +2292,277 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jimp/bmp@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/bmp/-/bmp-0.22.12.tgz#0316044dc7b1a90274aef266d50349347fb864d4" - integrity sha512-aeI64HD0npropd+AR76MCcvvRaa+Qck6loCOS03CkkxGHN5/r336qTM5HPUdHKMDOGzqknuVPA8+kK1t03z12g== +"@jimp/core@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/core/-/core-1.1.4.tgz#54f0c0877bb015361f2cf7d1e1de6fed07e026a9" + integrity sha512-Pokt0rq2qT9oTbQkYVd4z8nIA0eHu2yI3Gd5SmkKQjQa/lRVWRFazqAJMpPkIQt32gSf2rRUVopp7O7wkjjV8w== dependencies: - "@jimp/utils" "^0.22.12" - bmp-js "^0.1.0" - -"@jimp/core@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/core/-/core-0.22.12.tgz#70785ea7d10b138fb65bcfe9f712826f00a10e1d" - integrity sha512-l0RR0dOPyzMKfjUW1uebzueFEDtCOj9fN6pyTYWWOM/VS4BciXQ1VVrJs8pO3kycGYZxncRKhCoygbNr8eEZQA== - dependencies: - "@jimp/utils" "^0.22.12" - any-base "^1.1.0" - buffer "^5.2.0" + "@jimp/file-ops" "1.1.4" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" + await-to-js "^3.0.0" exif-parser "^0.1.12" - file-type "^16.5.4" - isomorphic-fetch "^3.0.0" - pixelmatch "^4.0.2" - tinycolor2 "^1.6.0" + file-type "^16.0.0" + mime "3" -"@jimp/custom@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/custom/-/custom-0.22.12.tgz#236f2a3f016b533c50869ff22ad1ac00dd0c36be" - integrity sha512-xcmww1O/JFP2MrlGUMd3Q78S3Qu6W3mYTXYuIqFq33EorgYHV/HqymHfXy9GjiCJ7OI+7lWx6nYFOzU7M4rd1Q== +"@jimp/diff@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/diff/-/diff-1.1.4.tgz#505b6f9f738f9a6495f36960662738937fea529b" + integrity sha512-Xc/g1SfphHT9+aeghCxQou8cCmzIArLot31PNXYhx/Bip0Px1wtZHW22sFgCPjGJS6pE/74qRjM0V8VJQYup3w== dependencies: - "@jimp/core" "^0.22.12" + "@jimp/plugin-resize" "1.1.4" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" + pixelmatch "^5.3.0" -"@jimp/gif@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/gif/-/gif-0.22.12.tgz#6caccb45df497fb971b7a88690345596e22163c0" - integrity sha512-y6BFTJgch9mbor2H234VSjd9iwAhaNf/t3US5qpYIs0TSbAvM02Fbc28IaDETj9+4YB4676sz4RcN/zwhfu1pg== +"@jimp/file-ops@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/file-ops/-/file-ops-1.1.4.tgz#3a1670c1ffdd72a848c10a80187b53556fd05131" + integrity sha512-vJqidRRZlQfaOS/DE9FnkFDmu6Fyx5ZtqTRfBDRr8fAPPDC+N6Fh4//0YQ2CO1xstI35WoPPkJDu6Geq+f1b5Q== + +"@jimp/js-bmp@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/js-bmp/-/js-bmp-1.1.4.tgz#c8c777e2100db8fa69583e7c2ca4cf1d145b7e51" + integrity sha512-fO8dhqfDF08Zw4SXdXD2GqLakR4KInUY6dWkNyOLH+fADsi2jmx/UgcdNiZMGm/iaQSdTdUovgpmLJrr5kQ3Kg== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" + bmp-ts "^1.0.9" + +"@jimp/js-gif@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/js-gif/-/js-gif-1.1.4.tgz#5f6d18b250ca3d241de0fd1a0421cff679956ee3" + integrity sha512-/+W2hCPljZg4xEC82W4Zl/gy3ZzQVD05jYovviuHx+T3d/8y/GZWElDp6dHkBefnZ1P3ZEC+sBtLUIyuAz7c4A== + dependencies: + "@jimp/core" "1.1.4" + "@jimp/types" "1.1.4" gifwrap "^0.10.1" - omggif "^1.0.9" + omggif "^1.0.10" -"@jimp/jpeg@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/jpeg/-/jpeg-0.22.12.tgz#b5c74a5aac9826245311370dda8c71a1fcca05ed" - integrity sha512-Rq26XC/uQWaQKyb/5lksCTCxXhtY01NJeBN+dQv5yNYedN0i7iYu+fXEoRsfaJ8xZzjoANH8sns7rVP4GE7d/Q== +"@jimp/js-jpeg@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/js-jpeg/-/js-jpeg-1.1.4.tgz#b84065aca4f5631497321883f09e841fae7ffc1a" + integrity sha512-Qt7U2MLuLd7fpA9m7LEUvf4oEjYofJtxi7a4XApkHOtRC7+l2KBEpiw2EGwCd1AQ8dnryaO5ehFqALhiIjcv+w== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/types" "1.1.4" jpeg-js "^0.4.4" -"@jimp/plugin-blit@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-blit/-/plugin-blit-0.22.12.tgz#0fa8320767fda77434b4408798655ff7c7e415d4" - integrity sha512-xslz2ZoFZOPLY8EZ4dC29m168BtDx95D6K80TzgUi8gqT7LY6CsajWO0FAxDwHz6h0eomHMfyGX0stspBrTKnQ== +"@jimp/js-png@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/js-png/-/js-png-1.1.4.tgz#128670c6f3de2d7291bb53cbac7fdce95838c2c4" + integrity sha512-F+8d0cHlS5MJnvle5TbQRhe7UIyqbZJlrqYemrfARTeoyhUQo5NYfeOmnnyABl1Jiwvhe7cWzKnlXRkhJZzS6g== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/types" "1.1.4" + pngjs "^7.0.0" -"@jimp/plugin-blur@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-blur/-/plugin-blur-0.22.12.tgz#0c37b2ff4e588b45f4307b4f13d3d0eef813920d" - integrity sha512-S0vJADTuh1Q9F+cXAwFPlrKWzDj2F9t/9JAbUvaaDuivpyWuImEKXVz5PUZw2NbpuSHjwssbTpOZ8F13iJX4uw== +"@jimp/js-tiff@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/js-tiff/-/js-tiff-1.1.4.tgz#e85a7e228e91098c01f84045f9f0e63bfab1d121" + integrity sha512-kopUh2c2vxNjeAljniP8jQnWGWdhlFUfP6RySAnRpRDbp9LhTrpYGngKf/fOxv8MMEXOifGNvQlvzgOrnmF4sQ== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/types" "1.1.4" + utif2 "^4.1.0" -"@jimp/plugin-circle@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-circle/-/plugin-circle-0.22.12.tgz#9fffda83d3fc5bad8c1e1492b15b1433cb42e16e" - integrity sha512-SWVXx1yiuj5jZtMijqUfvVOJBwOifFn0918ou4ftoHgegc5aHWW5dZbYPjvC9fLpvz7oSlptNl2Sxr1zwofjTg== +"@jimp/plugin-blit@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-blit/-/plugin-blit-1.1.4.tgz#07a0ec5c5890697cf4905b5eaf58403920c6848a" + integrity sha512-mwiZp7tSId/2LyFzct456rMulbi+J9Mm9jQ1jhWt7TPM4qjobFXHem5glyU1aNf9CpHcsOP83RUj5me7DavvEg== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" + zod "^3.23.8" -"@jimp/plugin-color@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-color/-/plugin-color-0.22.12.tgz#1e49f2e7387186507e917b0686599767c15be336" - integrity sha512-xImhTE5BpS8xa+mAN6j4sMRWaUgUDLoaGHhJhpC+r7SKKErYDR0WQV4yCE4gP+N0gozD0F3Ka1LUSaMXrn7ZIA== +"@jimp/plugin-blur@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-blur/-/plugin-blur-1.1.4.tgz#e55fba4af64f095d51036b2dcbdd2d9f93d3c81a" + integrity sha512-XH+NGrKOQbs5Q0WF4HToWSUz5ts4xRABFcAIDgs9O34iYdTL3K9lPMHAOH+LrB+2uWMzguQQncdEJrPKgNXC4Q== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/utils" "1.1.4" + +"@jimp/plugin-circle@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-circle/-/plugin-circle-1.1.4.tgz#bad7981483219554587ded91e63ec4aa69eb0884" + integrity sha512-zOemNyA5VIgWnC+NQys7FCqpFt6jN7Hvp//G9pL+oD9sXDLQbkR65ZHdpI7iglVtxsq3yc7hFe2ojCRCu3AbSg== + dependencies: + "@jimp/types" "1.1.4" + zod "^3.23.8" + +"@jimp/plugin-color@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-color/-/plugin-color-1.1.4.tgz#bf142840d7570e7964a136f278de6f8134686417" + integrity sha512-j7xJqO9Cr45sLw+UYwCRtoeWl8/mZsBmZEAGdpx4ny2vHD0IMD3S56NcTuSLJ9zFtuyIEJkQFUNFUDaxVxVjag== + dependencies: + "@jimp/core" "1.1.4" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" tinycolor2 "^1.6.0" + zod "^3.23.8" -"@jimp/plugin-contain@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-contain/-/plugin-contain-0.22.12.tgz#ed5ed9af3d4afd02a7568ff8d60603cff340e3f3" - integrity sha512-Eo3DmfixJw3N79lWk8q/0SDYbqmKt1xSTJ69yy8XLYQj9svoBbyRpSnHR+n9hOw5pKXytHwUW6nU4u1wegHNoQ== +"@jimp/plugin-contain@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-contain/-/plugin-contain-1.1.4.tgz#185b9b3fdb85d61b38c8ea9ac060bb05df4e9e68" + integrity sha512-XIMURmXFDdZYyKsETyopBloqndJKk7ohtE6ujO/o//O5/Op9A15deh8yais39A5j8uSyHEsvBwdGtGm4co7rnw== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/plugin-blit" "1.1.4" + "@jimp/plugin-resize" "1.1.4" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" + zod "^3.23.8" -"@jimp/plugin-cover@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-cover/-/plugin-cover-0.22.12.tgz#4abbfabe4c78c71d8d46e707c35a65dc55f08afd" - integrity sha512-z0w/1xH/v/knZkpTNx+E8a7fnasQ2wHG5ze6y5oL2dhH1UufNua8gLQXlv8/W56+4nJ1brhSd233HBJCo01BXA== +"@jimp/plugin-cover@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-cover/-/plugin-cover-1.1.4.tgz#3b270c4526e24652f772f8a1aa940dc88118e24a" + integrity sha512-VxaQhcCYeJRQcNXrLbOUcn/KAVmVgTNexLucjUvm8uSWCyDfO+HJ6okL/qyux2h05asyCcFXz7zeNswEqjePSg== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/plugin-crop" "1.1.4" + "@jimp/plugin-resize" "1.1.4" + "@jimp/types" "1.1.4" + zod "^3.23.8" -"@jimp/plugin-crop@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-crop/-/plugin-crop-0.22.12.tgz#e28329a9f285071442998560b040048d2ef5c32e" - integrity sha512-FNuUN0OVzRCozx8XSgP9MyLGMxNHHJMFt+LJuFjn1mu3k0VQxrzqbN06yIl46TVejhyAhcq5gLzqmSCHvlcBVw== +"@jimp/plugin-crop@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-crop/-/plugin-crop-1.1.4.tgz#4d6729532f9229b6e54ccf45a72c147872ab3f9f" + integrity sha512-RejGsKWoG0ji2YwvlKKIEnCxZFGHZ7dwcmFIHiWOZs+fhT+HoHbDy9QEIT+MmgWeeIVm0B3MrA/oBMLEwaJbzg== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" + zod "^3.23.8" -"@jimp/plugin-displace@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-displace/-/plugin-displace-0.22.12.tgz#2e4b2b989a23da6687c49f2f628e1e6d686ec9b6" - integrity sha512-qpRM8JRicxfK6aPPqKZA6+GzBwUIitiHaZw0QrJ64Ygd3+AsTc7BXr+37k2x7QcyCvmKXY4haUrSIsBug4S3CA== +"@jimp/plugin-displace@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-displace/-/plugin-displace-1.1.4.tgz#63b536a9f550cb03d233970478640fa5973cfae3" + integrity sha512-X+yMdj4DZu/p5YZ9Go7k3HfkC2XTw/5am/p9Fn2xoOJwGa+LIDCAAJ/xuVw+qJMuyvhjIa5rck39yePvBumLyg== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" + zod "^3.23.8" -"@jimp/plugin-dither@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-dither/-/plugin-dither-0.22.12.tgz#3cc5f3a58dbf85653c4e532d31a756a4fc8cabf7" - integrity sha512-jYgGdSdSKl1UUEanX8A85v4+QUm+PE8vHFwlamaKk89s+PXQe7eVE3eNeSZX4inCq63EHL7cX580dMqkoC3ZLw== +"@jimp/plugin-dither@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-dither/-/plugin-dither-1.1.4.tgz#96ae3a59b66f5f9ee9b7dc0a4e7d572a6c38e2a0" + integrity sha512-GvyRicPVpxlyol304C4v3T/OpJiuER4ibIhMTAKPx393ByvRgoo1r69nVRfEbmYoKAlwxEA+DISoDgBWYFq4yw== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/types" "1.1.4" -"@jimp/plugin-fisheye@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-fisheye/-/plugin-fisheye-0.22.12.tgz#77aef2f3ec59c0bafbd2dbc94b89eab60ce05a3e" - integrity sha512-LGuUTsFg+fOp6KBKrmLkX4LfyCy8IIsROwoUvsUPKzutSqMJnsm3JGDW2eOmWIS/jJpPaeaishjlxvczjgII+Q== +"@jimp/plugin-fisheye@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-fisheye/-/plugin-fisheye-1.1.4.tgz#1f2b611e939c9546c5d9d9abe416d1e10407d88a" + integrity sha512-mX2yUzndi9esrcEIv9wQIChTLhehZ0SNjRY81BMS9vxa3poxrLyNDq2GHSVmWcehSpkMmATVYKQy6AcLcfynSA== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" + zod "^3.23.8" -"@jimp/plugin-flip@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-flip/-/plugin-flip-0.22.12.tgz#7e2154592da01afcf165a3f9d1d25032aa8d8c57" - integrity sha512-m251Rop7GN8W0Yo/rF9LWk6kNclngyjIJs/VXHToGQ6EGveOSTSQaX2Isi9f9lCDLxt+inBIb7nlaLLxnvHX8Q== +"@jimp/plugin-flip@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-flip/-/plugin-flip-1.1.4.tgz#ef8c6734a16b4385cb70bd8b84a2dbd14941f295" + integrity sha512-dhhM1tY21QqnaSvgh9Evpq09+IgAfeZJwLTTJnoWN5j+suE/+K9fIlMSx8XKbv3hBvOBVPHUrq8xoiTLHryr5w== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/types" "1.1.4" + zod "^3.23.8" -"@jimp/plugin-gaussian@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-gaussian/-/plugin-gaussian-0.22.12.tgz#49a40950cedbbea6c84b3a6bccc45365fe78d6b7" - integrity sha512-sBfbzoOmJ6FczfG2PquiK84NtVGeScw97JsCC3rpQv1PHVWyW+uqWFF53+n3c8Y0P2HWlUjflEla2h/vWShvhg== +"@jimp/plugin-hash@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-hash/-/plugin-hash-1.1.4.tgz#3af4a37bf31fbfb15a3263245efd07da10b7981f" + integrity sha512-nmjnQwxcNVTq7qlkUuX5OzdwO/F+mnE2QT+TZ6VEAphPT8Iu7ZaJfYd3wxAbon9UrbxZULFnhiEOs6yE2dWYaw== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/js-bmp" "1.1.4" + "@jimp/js-jpeg" "1.1.4" + "@jimp/js-png" "1.1.4" + "@jimp/js-tiff" "1.1.4" + "@jimp/plugin-color" "1.1.4" + "@jimp/plugin-resize" "1.1.4" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" + any-base "^1.1.0" -"@jimp/plugin-invert@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-invert/-/plugin-invert-0.22.12.tgz#c569e85c1f59911a9a33ef36a51c9cf26065078e" - integrity sha512-N+6rwxdB+7OCR6PYijaA/iizXXodpxOGvT/smd/lxeXsZ/empHmFFFJ/FaXcYh19Tm04dGDaXcNF/dN5nm6+xQ== +"@jimp/plugin-mask@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-mask/-/plugin-mask-1.1.4.tgz#6ad63a0f8c3c5b99439ba79e2a48bb00bfbc7e36" + integrity sha512-86Duc7r9kdv26oaApwHtFULMHxLCBoBdeAA/PyH1RRsZy2eu+M8hGFYf99vJlLBgJslyToGjxIgDE1nsuB1uHA== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/types" "1.1.4" + zod "^3.23.8" -"@jimp/plugin-mask@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-mask/-/plugin-mask-0.22.12.tgz#0ac0d9c282f403255b126556521f90fb8e2997f0" - integrity sha512-4AWZg+DomtpUA099jRV8IEZUfn1wLv6+nem4NRJC7L/82vxzLCgXKTxvNvBcNmJjT9yS1LAAmiJGdWKXG63/NA== +"@jimp/plugin-print@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-print/-/plugin-print-1.1.4.tgz#dc3c4c9130cda0c3571b3c352546f0d69aae4046" + integrity sha512-EMkakkwi1qrcmQ4nexD2w5ZEUxgesFd7lcYR7DBCXKBYabvC9RDHXaWTxzeFa0VWy3/ZnpoJJ3Qq8I8WqHvjmw== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/js-jpeg" "1.1.4" + "@jimp/js-png" "1.1.4" + "@jimp/plugin-blit" "1.1.4" + "@jimp/types" "1.1.4" + parse-bmfont-ascii "^1.0.6" + parse-bmfont-binary "^1.0.6" + parse-bmfont-xml "^1.1.6" + zod "^3.23.8" -"@jimp/plugin-normalize@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-normalize/-/plugin-normalize-0.22.12.tgz#6c44d216f2489cf9b0e0f1e03aa5dfb97f198c53" - integrity sha512-0So0rexQivnWgnhacX4cfkM2223YdExnJTTy6d06WbkfZk5alHUx8MM3yEzwoCN0ErO7oyqEWRnEkGC+As1FtA== +"@jimp/plugin-quantize@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-quantize/-/plugin-quantize-1.1.4.tgz#a883eeef1f6144354bb868921895a89ca40d557f" + integrity sha512-+DuC7ZXjNGFoZtsYU2MxXz06E48AIBNg1G/2sq2bXu+PJEU0xvQctEvJEdl+xhRo4sQNQpwOzCZtBvY49VqfNA== dependencies: - "@jimp/utils" "^0.22.12" + image-q "^4.0.0" + zod "^3.23.8" -"@jimp/plugin-print@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-print/-/plugin-print-0.22.12.tgz#6a49020947a9bf21a5a28324425670a25587ca65" - integrity sha512-c7TnhHlxm87DJeSnwr/XOLjJU/whoiKYY7r21SbuJ5nuH+7a78EW1teOaj5gEr2wYEd7QtkFqGlmyGXY/YclyQ== +"@jimp/plugin-resize@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-resize/-/plugin-resize-1.1.4.tgz#2107bda637dfa05e01aab341b2ba96cbb8b78835" + integrity sha512-+KY0A5agiOpV60cfs28DZCl3t/8QRVO9kyzrdDqCLkhc/7g2YYrdyhkJZYUq5GBJirkpGGzXZQR2t+g7Sc9dEQ== dependencies: - "@jimp/utils" "^0.22.12" - load-bmfont "^1.4.1" + "@jimp/core" "1.1.4" + "@jimp/types" "1.1.4" + zod "^3.23.8" -"@jimp/plugin-resize@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-resize/-/plugin-resize-0.22.12.tgz#f92acbf73beb97dd1fe93b166ef367a323b81e81" - integrity sha512-3NyTPlPbTnGKDIbaBgQ3HbE6wXbAlFfxHVERmrbqAi8R3r6fQPxpCauA8UVDnieg5eo04D0T8nnnNIX//i/sXg== +"@jimp/plugin-rotate@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-rotate/-/plugin-rotate-1.1.4.tgz#2c1c963ba5e522a81514fe3870e1c6c823113a47" + integrity sha512-9yRcL5cFcA88kVDt9nco1BUipAjw6uto6AOJi2Bp3FFfdJ84F3rU6Jvcbl4aDyywoJ+J93gKXRo/GAEPk8xpvg== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/plugin-crop" "1.1.4" + "@jimp/plugin-resize" "1.1.4" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" + zod "^3.23.8" -"@jimp/plugin-rotate@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-rotate/-/plugin-rotate-0.22.12.tgz#2235d45aeb4914ff70d99e95750a6d9de45a0d9f" - integrity sha512-9YNEt7BPAFfTls2FGfKBVgwwLUuKqy+E8bDGGEsOqHtbuhbshVGxN2WMZaD4gh5IDWvR+emmmPPWGgaYNYt1gA== +"@jimp/plugin-threshold@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/plugin-threshold/-/plugin-threshold-1.1.4.tgz#6625758b6392124d284dbed07156c63fb155b874" + integrity sha512-d2uTz8iNuW3ogjH/OVEmPtiSzIpr99Dk5mTOXmnojSqT/5Ufs2ngJf3JQ2wIwOyb6pXph+xRqseQjhf1EUXasA== dependencies: - "@jimp/utils" "^0.22.12" + "@jimp/core" "1.1.4" + "@jimp/plugin-color" "1.1.4" + "@jimp/plugin-hash" "1.1.4" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" + zod "^3.23.8" -"@jimp/plugin-scale@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-scale/-/plugin-scale-0.22.12.tgz#91f1ec3d114ff44092b946a16e66b14d918e32ed" - integrity sha512-dghs92qM6MhHj0HrV2qAwKPMklQtjNpoYgAB94ysYpsXslhRTiPisueSIELRwZGEr0J0VUxpUY7HgJwlSIgGZw== +"@jimp/types@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/types/-/types-1.1.4.tgz#b46881102fc6d353451e18ccf06a3dab4dbfb0d5" + integrity sha512-Ck7ShGOeRjN1E2NH9YQs1UDD8Sh54XzSjLhbNq3gtbXrDgSAUH2e47K1VLoUHVBdq7COTDlDCBPOFb/kgQz0zQ== dependencies: - "@jimp/utils" "^0.22.12" + zod "^3.23.8" -"@jimp/plugin-shadow@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-shadow/-/plugin-shadow-0.22.12.tgz#52e3a1d55f61ddfcfb3265544f8d23b887a667b8" - integrity sha512-FX8mTJuCt7/3zXVoeD/qHlm4YH2bVqBuWQHXSuBK054e7wFRnRnbSLPUqAwSeYP3lWqpuQzJtgiiBxV3+WWwTg== +"@jimp/utils@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@jimp/utils/-/utils-1.1.4.tgz#5af44854cc74be08253e6ed7dee82a9058765406" + integrity sha512-mkfoOtC3/vVibCQz3MQkbt8FMtuJI56ekcoDBJqcY9Pjyyd7nbOhfWhiLiLYIfcrslJX8pLEq4ewR2PTNRXTfA== dependencies: - "@jimp/utils" "^0.22.12" - -"@jimp/plugin-threshold@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugin-threshold/-/plugin-threshold-0.22.12.tgz#1efe20e154bf3a1fc4a5cc016092dbacaa60c958" - integrity sha512-4x5GrQr1a/9L0paBC/MZZJjjgjxLYrqSmWd+e+QfAEPvmRxdRoQ5uKEuNgXnm9/weHQBTnQBQsOY2iFja+XGAw== - dependencies: - "@jimp/utils" "^0.22.12" - -"@jimp/plugins@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/plugins/-/plugins-0.22.12.tgz#45a3b96d2d24cec21d4f8b79d1cfcec6fcb2f1d4" - integrity sha512-yBJ8vQrDkBbTgQZLty9k4+KtUQdRjsIDJSPjuI21YdVeqZxYywifHl4/XWILoTZsjTUASQcGoH0TuC0N7xm3ww== - dependencies: - "@jimp/plugin-blit" "^0.22.12" - "@jimp/plugin-blur" "^0.22.12" - "@jimp/plugin-circle" "^0.22.12" - "@jimp/plugin-color" "^0.22.12" - "@jimp/plugin-contain" "^0.22.12" - "@jimp/plugin-cover" "^0.22.12" - "@jimp/plugin-crop" "^0.22.12" - "@jimp/plugin-displace" "^0.22.12" - "@jimp/plugin-dither" "^0.22.12" - "@jimp/plugin-fisheye" "^0.22.12" - "@jimp/plugin-flip" "^0.22.12" - "@jimp/plugin-gaussian" "^0.22.12" - "@jimp/plugin-invert" "^0.22.12" - "@jimp/plugin-mask" "^0.22.12" - "@jimp/plugin-normalize" "^0.22.12" - "@jimp/plugin-print" "^0.22.12" - "@jimp/plugin-resize" "^0.22.12" - "@jimp/plugin-rotate" "^0.22.12" - "@jimp/plugin-scale" "^0.22.12" - "@jimp/plugin-shadow" "^0.22.12" - "@jimp/plugin-threshold" "^0.22.12" - timm "^1.6.1" - -"@jimp/png@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/png/-/png-0.22.12.tgz#e033586caf38d9c9d33808e92eb87c4d7f0aa1eb" - integrity sha512-Mrp6dr3UTn+aLK8ty/dSKELz+Otdz1v4aAXzV5q53UDD2rbB5joKVJ/ChY310B+eRzNxIovbUF1KVrUsYdE8Hg== - dependencies: - "@jimp/utils" "^0.22.12" - pngjs "^6.0.0" - -"@jimp/tiff@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/tiff/-/tiff-0.22.12.tgz#67cac3f2ded6fde3ef631fbf74bea0fa53800123" - integrity sha512-E1LtMh4RyJsoCAfAkBRVSYyZDTtLq9p9LUiiYP0vPtXyxX4BiYBUYihTLSBlCQg5nF2e4OpQg7SPrLdJ66u7jg== - dependencies: - utif2 "^4.0.1" - -"@jimp/types@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/types/-/types-0.22.12.tgz#6f83761ba171cb8cd5998fa66a5cbfb0b22d3d8c" - integrity sha512-wwKYzRdElE1MBXFREvCto5s699izFHNVvALUv79GXNbsOVqlwlOxlWJ8DuyOGIXoLP4JW/m30YyuTtfUJgMRMA== - dependencies: - "@jimp/bmp" "^0.22.12" - "@jimp/gif" "^0.22.12" - "@jimp/jpeg" "^0.22.12" - "@jimp/png" "^0.22.12" - "@jimp/tiff" "^0.22.12" - timm "^1.6.1" - -"@jimp/utils@^0.22.12": - version "0.22.12" - resolved "https://registry.yarnpkg.com/@jimp/utils/-/utils-0.22.12.tgz#8ffaed8f2dc2962539ccaf14727ac60793c7a537" - integrity sha512-yJ5cWUknGnilBq97ZXOyOS0HhsHOyAyjHwYfHxGbSyMTohgQI6sVyE8KPgDwH8HHW/nMKXk8TrSwAE71zt716Q== - dependencies: - regenerator-runtime "^0.13.3" + "@jimp/types" "1.1.4" + tinycolor2 "^1.6.0" "@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": version "0.3.5" @@ -3765,11 +3126,6 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== -"@opentelemetry/api@^1.0.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.7.0.tgz#b139c81999c23e3c8d3c0a7234480e945920fc40" - integrity sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw== - "@opentelemetry/core@^1.14.0": version "1.19.0" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.19.0.tgz#6563bb65465bf232d8435553b9a122d9351c0fbb" @@ -4201,442 +3557,6 @@ dependencies: "@sinonjs/commons" "^2.0.0" -"@smithy/abort-controller@^2.0.10": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-2.0.10.tgz#a6d0d24973ac35b59cc450c34decd68485fbe2c0" - integrity "sha1-ptDSSXOsNbWcxFDDTezWhIX74sA= sha512-xn7PnFD3m4rQIG00h1lPuDVnC2QMtTFhzRLX3y56KkgFaCysS7vpNevNBgmNUtmJ4eVFc+66Zucwo2KDLdicOg==" - dependencies: - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/chunked-blob-reader-native@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.0.0.tgz#f6d0eeeb5481026b68b054f45540d924c194d558" - integrity "sha1-9tDu61SBAmtosFT0VUDZJMGU1Vg= sha512-HM8V2Rp1y8+1343tkZUKZllFhEQPNmpNdgFAncbTsxkZ18/gqjk23XXv3qGyXWp412f3o43ZZ1UZHVcHrpRnCQ==" - dependencies: - "@smithy/util-base64" "^2.0.0" - tslib "^2.5.0" - -"@smithy/chunked-blob-reader@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.0.0.tgz#c44fe2c780eaf77f9e5381d982ac99a880cce51b" - integrity "sha1-xE/ix4Dq93+eU4HZgqyZqIDM5Rs= sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==" - dependencies: - tslib "^2.5.0" - -"@smithy/config-resolver@^2.0.10", "@smithy/config-resolver@^2.0.11": - version "2.0.11" - resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-2.0.11.tgz#20c4711b4e80f94527ee9e4e092cf024471bb09d" - integrity "sha1-IMRxG06A+UUn7p5OCSzwJEcbsJ0= sha512-q97FnlUmbai1c4JlQJgLVBsvSxgV/7Nvg/JK76E1nRq/U5UM56Eqo3dn2fY7JibqgJLg4LPsGdwtIyqyOk35CQ==" - dependencies: - "@smithy/node-config-provider" "^2.0.13" - "@smithy/types" "^2.3.4" - "@smithy/util-config-provider" "^2.0.0" - "@smithy/util-middleware" "^2.0.3" - tslib "^2.5.0" - -"@smithy/credential-provider-imds@^2.0.0", "@smithy/credential-provider-imds@^2.0.13": - version "2.0.13" - resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-2.0.13.tgz#9904912bc236d25d870add10b6eb138570bf5732" - integrity "sha1-mQSRK8I20l2HCt0QtusThXC/VzI= sha512-/xe3wNoC4j+BeTemH9t2gSKLBfyZmk8LXB2pQm/TOEYi+QhBgT+PSolNDfNAhrR68eggNE17uOimsrnwSkCt4w==" - dependencies: - "@smithy/node-config-provider" "^2.0.13" - "@smithy/property-provider" "^2.0.11" - "@smithy/types" "^2.3.4" - "@smithy/url-parser" "^2.0.10" - tslib "^2.5.0" - -"@smithy/eventstream-codec@^2.0.10": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-2.0.10.tgz#dbd46d0ed13abc61b1f08ab249f3097602752933" - integrity "sha1-29RtDtE6vGGx8IqySfMJdgJ1KTM= sha512-3SSDgX2nIsFwif6m+I4+ar4KDcZX463Noes8ekBgQHitULiWvaDZX8XqPaRQSQ4bl1vbeVXHklJfv66MnVO+lw==" - dependencies: - "@aws-crypto/crc32" "3.0.0" - "@smithy/types" "^2.3.4" - "@smithy/util-hex-encoding" "^2.0.0" - tslib "^2.5.0" - -"@smithy/eventstream-serde-browser@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.10.tgz#93054f85194655d7eba27125f4935d247bdc2a8f" - integrity "sha1-kwVPhRlGVdfronEl9JNdJHvcKo8= sha512-/NSUNrWedO9Se80jo/2WcPvqobqCM/0drZ03Kqn1GZpGwVTsdqNj7frVTCUJs/W/JEzOShdMv8ewoKIR7RWPmA==" - dependencies: - "@smithy/eventstream-serde-universal" "^2.0.10" - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/eventstream-serde-config-resolver@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.10.tgz#ea2f6675a4270fc3eccbb9fda4086f611887b510" - integrity "sha1-6i9mdaQnD8Psy7n9pAhvYRiHtRA= sha512-ag1U0vsC5rhRm7okFzsS6YsvyTRe62jIgJ82+Wr4qoOASx7eCDWdjoqLnrdDY0S4UToF9hZAyo4Du/xrSSSk4g==" - dependencies: - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/eventstream-serde-node@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.10.tgz#54af54b9719aa8f74fae5885a72e69b33d5661cf" - integrity "sha1-VK9UuXGaqPdPrliFpy5psz1WYc8= sha512-3+VeofxoVCa+dvqcuzEpnFve8EQJKaYR7UslDFpj6UTZfa7Hxr8o1/cbFkTftFo71PxzYVsR+bsD56EbAO432A==" - dependencies: - "@smithy/eventstream-serde-universal" "^2.0.10" - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/eventstream-serde-universal@^2.0.10": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.10.tgz#575a6160a12508341c9c345bf3da7422a590aaae" - integrity "sha1-V1phYKElCDQcnDRb89p0IqWQqq4= sha512-JhJJU1ULLsn5kxKfFe8zOF2tibjxlPIvIB71Kn20aa/OFs+lvXBR0hBGswpovyYyckXH3qU8VxuIOEuS+2G+3A==" - dependencies: - "@smithy/eventstream-codec" "^2.0.10" - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/fetch-http-handler@^2.1.5", "@smithy/fetch-http-handler@^2.2.1": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-2.2.1.tgz#a8abbd339c2c3d76456f4d16e65cf934727fc7ad" - integrity "sha1-qKu9M5wsPXZFb00W5lz5NHJ/x60= sha512-bXyM8PBAIKxVV++2ZSNBEposTDjFQ31XWOdHED+2hWMNvJHUoQqFbECg/uhcVOa6vHie2/UnzIZfXBSTpDBnEw==" - dependencies: - "@smithy/protocol-http" "^3.0.6" - "@smithy/querystring-builder" "^2.0.10" - "@smithy/types" "^2.3.4" - "@smithy/util-base64" "^2.0.0" - tslib "^2.5.0" - -"@smithy/hash-blob-browser@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-2.0.10.tgz#fa761e02c9a21b9c4bf827139d65376d50356c69" - integrity "sha1-+nYeAsmiG5xL+CcTnWU3bVA1bGk= sha512-U2+wIWWloOZ9DaRuz2sk9f7A6STRTlwdcv+q6abXDvS0TRDk8KGgUmfV5lCZy8yxFxZIA0hvHDNqcd25r4Hrew==" - dependencies: - "@smithy/chunked-blob-reader" "^2.0.0" - "@smithy/chunked-blob-reader-native" "^2.0.0" - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/hash-node@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-2.0.10.tgz#af13889a008880bdc30278b148e0e0b2a6e2d243" - integrity "sha1-rxOImgCIgL3DAnixSODgsqbi0kM= sha512-jSTf6uzPk/Vf+8aQ7tVXeHfjxe9wRXSCqIZcBymSDTf7/YrVxniBdpyN74iI8ZUOx/Pyagc81OK5FROLaEjbXQ==" - dependencies: - "@smithy/types" "^2.3.4" - "@smithy/util-buffer-from" "^2.0.0" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.5.0" - -"@smithy/hash-stream-node@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-2.0.10.tgz#6e693b4362fbb031b8fc60e105220874d044ec8d" - integrity "sha1-bmk7Q2L7sDG4/GDhBSIIdNBE7I0= sha512-L58XEGrownZZSpF7Lp0gc0hy+eYKXuPgNz3pQgP5lPFGwBzHdldx2X6o3c6swD6RkcPvTRh0wTUVVGwUotbgnQ==" - dependencies: - "@smithy/types" "^2.3.4" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.5.0" - -"@smithy/invalid-dependency@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-2.0.10.tgz#b708e7cfc35214ce664db6aa67465567b97ffd36" - integrity "sha1-twjnz8NSFM5mTbaqZ0ZVZ7l//TY= sha512-zw9p/zsmJ2cFcW4KMz3CJoznlbRvEA6HG2mvEaX5eAca5dq4VGI2MwPDTfmteC/GsnURS4ogoMQ0p6aHM2SDVQ==" - dependencies: - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/is-array-buffer@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz#8fa9b8040651e7ba0b2f6106e636a91354ff7d34" - integrity "sha1-j6m4BAZR57oLL2EG5japE1T/fTQ= sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==" - dependencies: - tslib "^2.5.0" - -"@smithy/md5-js@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-2.0.10.tgz#8480de1b42abc581cf515e2b8e35542e9248f520" - integrity "sha1-hIDeG0KrxYHPUV4rjjVULpJI9SA= sha512-eA/Ova4/UdQUbMlrbBmnewmukH0zWU6C67HFFR/719vkFNepbnliGjmGksQ9vylz9eD4nfGkZZ5NKZMAcUuzjQ==" - dependencies: - "@smithy/types" "^2.3.4" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.5.0" - -"@smithy/middleware-content-length@^2.0.11": - version "2.0.12" - resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-2.0.12.tgz#e6f874f5eef880561f774a4376b73f04b97efc53" - integrity "sha1-5vh09e74gFYfd0pDdrc/BLl+/FM= sha512-QRhJTo5TjG7oF7np6yY4ZO9GDKFVzU/GtcqUqyEa96bLHE3yZHgNmsolOQ97pfxPHmFhH4vDP//PdpAIN3uI1Q==" - dependencies: - "@smithy/protocol-http" "^3.0.6" - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/middleware-endpoint@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-2.0.10.tgz#c11d9f75549116453eea0e812e17ec7917ce5bb1" - integrity "sha1-wR2fdVSRFkU+6g6BLhfseRfOW7E= sha512-O6m4puZc16xfenotZUHL4bRlMrwf4gTp+0I5l954M5KNd3dOK18P+FA/IIUgnXF/dX6hlCUcJkBp7nAzwrePKA==" - dependencies: - "@smithy/middleware-serde" "^2.0.10" - "@smithy/types" "^2.3.4" - "@smithy/url-parser" "^2.0.10" - "@smithy/util-middleware" "^2.0.3" - tslib "^2.5.0" - -"@smithy/middleware-retry@^2.0.12": - version "2.0.13" - resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-2.0.13.tgz#ef33b1511a4b01a77e54567165b78e6d0c266e88" - integrity "sha1-7zOxURpLAad+VFZxZbeObQwmbog= sha512-zuOva8xgWC7KYG8rEXyWIcZv2GWszO83DCTU6IKcf/FKu6OBmSE+EYv3EUcCGY+GfiwCX0EyJExC9Lpq9b0w5Q==" - dependencies: - "@smithy/node-config-provider" "^2.0.13" - "@smithy/protocol-http" "^3.0.6" - "@smithy/service-error-classification" "^2.0.3" - "@smithy/types" "^2.3.4" - "@smithy/util-middleware" "^2.0.3" - "@smithy/util-retry" "^2.0.3" - tslib "^2.5.0" - uuid "^8.3.2" - -"@smithy/middleware-serde@^2.0.10", "@smithy/middleware-serde@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-2.0.10.tgz#4b0e5f838c7d7621cabf7cfdd6cec4c7f4d52a3f" - integrity "sha1-Sw5fg4x9diHKv3z91s7Ex/TVKj8= sha512-+A0AFqs768256H/BhVEsBF6HijFbVyAwYRVXY/izJFkTalVWJOp4JA0YdY0dpXQd+AlW0tzs+nMQCE1Ew+DcgQ==" - dependencies: - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/middleware-stack@^2.0.2", "@smithy/middleware-stack@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-2.0.4.tgz#cf199dd4d6eb3a3562e6757804faa91165693395" - integrity "sha1-zxmd1NbrOjVi5nV4BPqpEWVpM5U= sha512-MW0KNKfh8ZGLagMZnxcLJWPNXoKqW6XV/st5NnCBmmA2e2JhrUjU0AJ5Ca/yjTyNEKs3xH7AQDwp1YmmpEpmQQ==" - dependencies: - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/node-config-provider@^2.0.12", "@smithy/node-config-provider@^2.0.13": - version "2.0.13" - resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-2.0.13.tgz#26c95cebbb8bf9ef5dd703ab4e00ff80de34e15f" - integrity "sha1-Jslc67uL+e9d1wOrTgD/gN404V8= sha512-pPpLqYuJcOq1sj1EGu+DoZK47DUS4gepqSTNgRezmrjnzNlSU2/Dcc9Ebzs+WZ0Z5vXKazuE+k+NksFLo07/AA==" - dependencies: - "@smithy/property-provider" "^2.0.11" - "@smithy/shared-ini-file-loader" "^2.0.12" - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/node-http-handler@^2.1.5", "@smithy/node-http-handler@^2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-2.1.6.tgz#c2913363bbf28f315461bd54ef9a5394f1686776" - integrity "sha1-wpEzY7vyjzFUYb1U75pTlPFoZ3Y= sha512-NspvD3aCwiUNtoSTcVHz0RZz1tQ/SaRIe1KPF+r0mAdCZ9eWuhIeJT8ZNPYa1ITn7/Lgg64IyFjqPynZ8KnYQw==" - dependencies: - "@smithy/abort-controller" "^2.0.10" - "@smithy/protocol-http" "^3.0.6" - "@smithy/querystring-builder" "^2.0.10" - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/property-provider@^2.0.0", "@smithy/property-provider@^2.0.11": - version "2.0.11" - resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-2.0.11.tgz#c6e03e4f6f886851339c3dfaf8cd8ae3b2878fa3" - integrity "sha1-xuA+T2+IaFEznD36+M2K47KHj6M= sha512-kzuOadu6XvrnlF1iXofpKXYmo4oe19st9/DE8f5gHNaFepb4eTkR8gD8BSdTnNnv7lxfv6uOwZPg4VS6hemX1w==" - dependencies: - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/protocol-http@^3.0.5", "@smithy/protocol-http@^3.0.6": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-3.0.6.tgz#c33c128cc0f7096bf4fcdcc6d14d156ba5cd5b7c" - integrity "sha1-wzwSjMD3CWv0/NzG0U0Va6XNW3w= sha512-F0jAZzwznMmHaggiZgc7YoS08eGpmLvhVktY/Taz6+OAOHfyIqWSDNgFqYR+WHW9z5fp2XvY4mEUrQgYMQ71jw==" - dependencies: - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/querystring-builder@^2.0.10": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-2.0.10.tgz#b06aa958b6ec1c56254d8cc41a19882625fd1c05" - integrity "sha1-sGqpWLbsHFYlTYzEGhmIJiX9HAU= sha512-uujJGp8jzrrU1UHme8sUKEbawQTcTmUWsh8rbGXYD/lMwNLQ+9jQ9dMDWbbH9Hpoa9RER1BeL/38WzGrbpob2w==" - dependencies: - "@smithy/types" "^2.3.4" - "@smithy/util-uri-escape" "^2.0.0" - tslib "^2.5.0" - -"@smithy/querystring-parser@^2.0.10": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-2.0.10.tgz#074d770a37feafb0d550094dd8463bdff58515f5" - integrity "sha1-B013Cjf+r7DVUAlN2EY73/WFFfU= sha512-WSD4EU60Q8scacT5PIpx4Bahn6nWpt+MiYLcBkFt6fOj7AssrNeaNIU2Z0g40ftVmrwLcEOIKGX92ynbVDb3ZA==" - dependencies: - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/service-error-classification@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-2.0.3.tgz#4c7de61d06db5f72437557d429bd74c74988b19e" - integrity "sha1-TH3mHQbbX3JDdVfUKb10x0mIsZ4= sha512-b+m4QCHXb7oKAkM/jHwHrl5gpqhFoMTHF643L0/vAEkegrcUWyh1UjyoHttuHcP5FnHVVy4EtpPtLkEYD+xMFw==" - dependencies: - "@smithy/types" "^2.3.4" - -"@smithy/shared-ini-file-loader@^2.0.12", "@smithy/shared-ini-file-loader@^2.0.6": - version "2.0.12" - resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.0.12.tgz#30c8a7a36f49734fde2f052bfaeaaf40c1980b55" - integrity "sha1-MMino29Jc0/eLwUr+uqvQMGYC1U= sha512-umi0wc4UBGYullAgYNUVfGLgVpxQyES47cnomTqzCKeKO5oudO4hyDNj+wzrOjqDFwK2nWYGVgS8Y0JgGietrw==" - dependencies: - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/signature-v4@^2.0.0": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-2.0.10.tgz#89161b3f59071b77713cdf06f98b2e6780580742" - integrity "sha1-iRYbP1kHG3dxPN8G+YsuZ4BYB0I= sha512-S6gcP4IXfO/VMswovrhxPpqvQvMal7ZRjM4NvblHSPpE5aNBYx67UkHFF3kg0hR3tJKqNpBGbxwq0gzpdHKLRA==" - dependencies: - "@smithy/eventstream-codec" "^2.0.10" - "@smithy/is-array-buffer" "^2.0.0" - "@smithy/types" "^2.3.4" - "@smithy/util-hex-encoding" "^2.0.0" - "@smithy/util-middleware" "^2.0.3" - "@smithy/util-uri-escape" "^2.0.0" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.5.0" - -"@smithy/smithy-client@^2.1.6", "@smithy/smithy-client@^2.1.9": - version "2.1.9" - resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-2.1.9.tgz#5a0a185947ae4e66d12d2a6135628dd2fc36924c" - integrity "sha1-WgoYWUeuTmbRLSphNWKN0vw2kkw= sha512-HTicQSn/lOcXKJT+DKJ4YMu51S6PzbWsO8Z6Pwueo30mSoFKXg5P0BDkg2VCDqCVR0mtddM/F6hKhjW6YAV/yg==" - dependencies: - "@smithy/middleware-stack" "^2.0.4" - "@smithy/types" "^2.3.4" - "@smithy/util-stream" "^2.0.14" - tslib "^2.5.0" - -"@smithy/types@^2.3.3", "@smithy/types@^2.3.4": - version "2.3.4" - resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.3.4.tgz#3b9bc15000af0a0b1f4fda741f78c1580ba15e92" - integrity "sha1-O5vBUACvCgsfT9p0H3jBWAuhXpI= sha512-D7xlM9FOMFyFw7YnMXn9dK2KuN6+JhnrZwVt1fWaIu8hCk5CigysweeIT/H/nCo4YV+s8/oqUdLfexbkPZtvqw==" - dependencies: - tslib "^2.5.0" - -"@smithy/url-parser@^2.0.10", "@smithy/url-parser@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-2.0.10.tgz#3261a463b87901d7686f66a9f26efb9f57d8d555" - integrity "sha1-MmGkY7h5Addob2ap8m77n1fY1VU= sha512-4TXQFGjHcqru8aH5VRB4dSnOFKCYNX6SR1Do6fwxZ+ExT2onLsh2W77cHpks7ma26W5jv6rI1u7d0+KX9F0aOw==" - dependencies: - "@smithy/querystring-parser" "^2.0.10" - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/util-base64@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-2.0.0.tgz#1beeabfb155471d1d41c8d0603be1351f883c444" - integrity "sha1-G+6r+xVUcdHUHI0GA74TUfiDxEQ= sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==" - dependencies: - "@smithy/util-buffer-from" "^2.0.0" - tslib "^2.5.0" - -"@smithy/util-body-length-browser@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.0.tgz#5447853003b4c73da3bc5f3c5e82c21d592d1650" - integrity "sha1-VEeFMAO0xz2jvF88XoLCHVktFlA= sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==" - dependencies: - tslib "^2.5.0" - -"@smithy/util-body-length-node@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz#313a5f7c5017947baf5fa018bfc22628904bbcfa" - integrity "sha1-MTpffFAXlHuvX6AYv8ImKJBLvPo= sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==" - dependencies: - tslib "^2.5.0" - -"@smithy/util-buffer-from@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz#7eb75d72288b6b3001bc5f75b48b711513091deb" - integrity "sha1-frddciiLazABvF91tItxFRMJHes= sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==" - dependencies: - "@smithy/is-array-buffer" "^2.0.0" - tslib "^2.5.0" - -"@smithy/util-config-provider@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz#4dd6a793605559d94267312fd06d0f58784b4c38" - integrity "sha1-Tdank2BVWdlCZzEv0G0PWHhLTDg= sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==" - dependencies: - tslib "^2.5.0" - -"@smithy/util-defaults-mode-browser@^2.0.10": - version "2.0.13" - resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.13.tgz#8136955f1bef6e66cb8a8702693e7685dcd33e26" - integrity "sha1-gTaVXxvvbmbLiocCaT52hdzTPiY= sha512-UmmOdUzaQjqdsl1EjbpEaQxM0VDFqTj6zDuI26/hXN7L/a1k1koTwkYpogHMvunDX3fjrQusg5gv1Td4UsGyog==" - dependencies: - "@smithy/property-provider" "^2.0.11" - "@smithy/smithy-client" "^2.1.9" - "@smithy/types" "^2.3.4" - bowser "^2.11.0" - tslib "^2.5.0" - -"@smithy/util-defaults-mode-node@^2.0.12": - version "2.0.15" - resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.15.tgz#24f7b9de978206909ced7b522f24e7f450187372" - integrity "sha1-JPe53peCBpCc7XtSLyTn9FAYc3I= sha512-g6J7MHAibVPMTlXyH3mL+Iet4lMJKFVhsOhJmn+IKG81uy9m42CkRSDlwdQSJAcprLQBIaOPdFxNXQvrg2w1Uw==" - dependencies: - "@smithy/config-resolver" "^2.0.11" - "@smithy/credential-provider-imds" "^2.0.13" - "@smithy/node-config-provider" "^2.0.13" - "@smithy/property-provider" "^2.0.11" - "@smithy/smithy-client" "^2.1.9" - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/util-hex-encoding@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz#0aa3515acd2b005c6d55675e377080a7c513b59e" - integrity "sha1-CqNRWs0rAFxtVWdeN3CAp8UTtZ4= sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==" - dependencies: - tslib "^2.5.0" - -"@smithy/util-middleware@^2.0.2", "@smithy/util-middleware@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-2.0.3.tgz#478cbf957eaffa36aed624350be342bbf15d3c42" - integrity "sha1-R4y/lX6v+jau1iQ1C+NCu/FdPEI= sha512-+FOCFYOxd2HO7v/0hkFSETKf7FYQWa08wh/x/4KUeoVBnLR4juw8Qi+TTqZI6E2h5LkzD9uOaxC9lAjrpVzaaA==" - dependencies: - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/util-retry@^2.0.2", "@smithy/util-retry@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-2.0.3.tgz#a053855ddb51800bd679da03454cf626bc440918" - integrity "sha1-oFOFXdtRgAvWedoDRUz2JrxECRg= sha512-gw+czMnj82i+EaH7NL7XKkfX/ZKrCS2DIWwJFPKs76bMgkhf0y1C94Lybn7f8GkBI9lfIOUdPYtzm19zQOC8sw==" - dependencies: - "@smithy/service-error-classification" "^2.0.3" - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - -"@smithy/util-stream@^2.0.12", "@smithy/util-stream@^2.0.14": - version "2.0.14" - resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-2.0.14.tgz#3fdd934e2bced80331dcaff18aefbcfe39ebf3cd" - integrity "sha1-P92TTivO2AMx3K/xiu+8/jnr880= sha512-XjvlDYe+9DieXhLf7p+EgkXwFtl34kHZcWfHnc5KaILbhyVfDLWuqKTFx6WwCFqb01iFIig8trGwExRIqqkBYg==" - dependencies: - "@smithy/fetch-http-handler" "^2.2.1" - "@smithy/node-http-handler" "^2.1.6" - "@smithy/types" "^2.3.4" - "@smithy/util-base64" "^2.0.0" - "@smithy/util-buffer-from" "^2.0.0" - "@smithy/util-hex-encoding" "^2.0.0" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.5.0" - -"@smithy/util-uri-escape@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz#19955b1a0f517a87ae77ac729e0e411963dfda95" - integrity "sha1-GZVbGg9Reoeud6xyng5BGWPf2pU= sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==" - dependencies: - tslib "^2.5.0" - -"@smithy/util-utf8@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.0.0.tgz#b4da87566ea7757435e153799df9da717262ad42" - integrity "sha1-tNqHVm6ndXQ14VN5nfnacXJirUI= sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==" - dependencies: - "@smithy/util-buffer-from" "^2.0.0" - tslib "^2.5.0" - -"@smithy/util-waiter@^2.0.9": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-2.0.10.tgz#6cd28af8340ab54fa9adf10d193c4476a5673363" - integrity "sha1-bNKK+DQKtU+prfENGTxEdqVnM2M= sha512-yQjwWVrwYw+/f3hFQccE3zZF7lk6N6xtNcA6jvhWFYhnyKAm6B2mX8Gzftl0TbgoPUpzCvKYlvhaEpVtRpVfVw==" - dependencies: - "@smithy/abort-controller" "^2.0.10" - "@smithy/types" "^2.3.4" - tslib "^2.5.0" - "@socket.io/component-emitter@~3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" @@ -5001,17 +3921,6 @@ oauth "~0.9.0" passport-strategy "^1.0.0" -"@techteamer/ocsp@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@techteamer/ocsp/-/ocsp-1.0.0.tgz#7b82b02093fbe351e915bb37685ac1ac5a1233d3" - integrity sha512-lNAOoFHaZN+4huo30ukeqVrUmfC+avoEBYQ11QAnAw1PFhnI5oBCg8O/TNiCoEWix7gNGBIEjrQwtPREqKMPog== - dependencies: - asn1.js "^5.4.1" - asn1.js-rfc2560 "^5.0.1" - asn1.js-rfc5280 "^3.0.0" - async "^3.2.1" - simple-lru-cache "^0.0.2" - "@tediousjs/connection-string@^0.5.0": version "0.5.0" resolved "https://registry.yarnpkg.com/@tediousjs/connection-string/-/connection-string-0.5.0.tgz#9b3d858c040aac6bdf5584bf45370cef5b6522b4" @@ -5520,7 +4429,7 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node-fetch@^2.5.0", "@types/node-fetch@^2.6.4": +"@types/node-fetch@^2.6.4": version "2.6.11" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24" integrity sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g== @@ -5955,18 +4864,6 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397" integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw== -"@types/triple-beam@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.2.tgz#38ecb64f01aa0d02b7c8f4222d7c38af6316fef8" - integrity sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g== - -"@types/tunnel@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.3.tgz#f109e730b072b3136347561fc558c9358bb8c6e9" - integrity sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA== - dependencies: - "@types/node" "*" - "@types/uuid@8.3.4": version "8.3.4" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" @@ -6854,7 +5751,7 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== -arrify@^2.0.0, arrify@^2.0.1: +arrify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== @@ -6864,20 +5761,6 @@ asap@^2.0.0: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== -asn1.js-rfc2560@^5.0.0, asn1.js-rfc2560@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/asn1.js-rfc2560/-/asn1.js-rfc2560-5.0.1.tgz#cff99b903e714756b29503ad49de01c72f131e60" - integrity sha512-1PrVg6kuBziDN3PGFmRk3QrjpKvP9h/Hv5yMrFZvC1kpzP6dQRzf5BpKstANqHBkaOUmTpakJWhicTATOA/SbA== - dependencies: - asn1.js-rfc5280 "^3.0.0" - -asn1.js-rfc5280@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/asn1.js-rfc5280/-/asn1.js-rfc5280-3.0.0.tgz#94e60498d5d4984b842d1a825485837574ccc902" - integrity sha512-Y2LZPOWeZ6qehv698ZgOGGCZXBQShObWnGthTrIFlIQjuV1gg2B8QOhWFRExq/MR1VnPpIIe7P9vX2vElxv+Pg== - dependencies: - asn1.js "^5.0.0" - asn1.js@^4.10.1: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -6887,16 +5770,6 @@ asn1.js@^4.10.1: inherits "^2.0.1" minimalistic-assert "^1.0.0" -asn1.js@^5.0.0, asn1.js@^5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - asn1@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" @@ -6929,14 +5802,7 @@ async-lock@^1.4.1: resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.4.1.tgz#56b8718915a9b68b10fce2f2a9a3dddf765ef53f" integrity sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ== -async-retry@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" - integrity "sha1-Dn82wE2EeOeli9vtgM7fl3eF8oA= sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==" - dependencies: - retry "0.13.1" - -async@^3.2.1, async@^3.2.3, async@^3.2.4: +async@^3.2.3, async@^3.2.4: version "3.2.5" resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg== @@ -6975,6 +5841,11 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" +await-to-js@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/await-to-js/-/await-to-js-3.0.0.tgz#70929994185616f4675a91af6167eb61cc92868f" + integrity sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g== + aws-cloudfront-sign@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/aws-cloudfront-sign/-/aws-cloudfront-sign-3.0.2.tgz#da5273b0301bcd70312c8c76293d5fec6d414f0a" @@ -6995,7 +5866,7 @@ aws-sdk@2.1030.0: uuid "3.3.2" xml2js "0.4.19" -axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.5.0, axios@^1.6.2: +axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -7216,16 +6087,6 @@ before-after-hook@^2.2.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== -big-integer@^1.6.43: - version "1.6.51" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" - integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== - -bignumber.js@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.4.0.tgz#838a992da9f9d737e0f4b2db0be62bb09dd0c5e8" - integrity sha512-uw4ra6Cv483Op/ebM0GBKKfxZlSmn6NgFRby5L3yGTlunLj53KQgndDlqy2WVFOwgvurocApYkSud0aO+mvrpQ== - bignumber.js@^9.0.0: version "9.1.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" @@ -7236,11 +6097,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -binascii@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/binascii/-/binascii-0.0.2.tgz#a7f8a8801dbccf8b1756b743daa0fee9e2d9e0ee" - integrity sha512-rA2CrUl1+6yKrn+XgLs8Hdy18OER1UW146nM+ixzhQXDY+Bd3ySkyIJGwF2a4I45JwbvF1mDL/nWkqBwpOcdBA== - bl@^1.0.0: version "1.2.3" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" @@ -7280,10 +6136,10 @@ bluebird@^3.5.1, bluebird@^3.7.2: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -bmp-js@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.1.0.tgz#e05a63f796a6c1ff25f4771ec7adadc148c07233" - integrity sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw== +bmp-ts@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/bmp-ts/-/bmp-ts-1.0.9.tgz#0fd124ba812be9b786b29e5b186ee76d74ff5538" + integrity sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw== bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.0" @@ -7305,11 +6161,6 @@ boolean@^3.0.1: resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b" integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw== -bowser@^2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" - integrity "sha1-XKPDV1enqldxUAxwpzqfke9CCo8= sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" - boxen@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" @@ -7356,11 +6207,6 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browser-request@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/browser-request/-/browser-request-0.3.3.tgz#9ece5b5aca89a29932242e18bf933def9876cc17" - integrity sha512-YyNI4qJJ+piQG6MMEuo7J3Bzaqssufx04zpEKYfSrl/1Op59HWali9zMtBpXnkmqMcOuWJPZvudrm9wISmnCbg== - browserify-aes@^1.0.4, browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -7482,11 +6328,6 @@ buffer-equal-constant-time@1.0.1: resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== -buffer-equal@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" - integrity sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA== - buffer-es6@^4.9.2, buffer-es6@^4.9.3: version "4.9.3" resolved "https://registry.yarnpkg.com/buffer-es6/-/buffer-es6-4.9.3.tgz#f26347b82df76fd37e18bcb5288c4970cfd5c404" @@ -7534,7 +6375,7 @@ buffer@6.0.3, buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -buffer@^5.1.0, buffer@^5.2.0, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: +buffer@^5.1.0, buffer@^5.2.1, buffer@^5.5.0, buffer@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -8034,7 +6875,7 @@ collect-v8-coverage@^1.0.0: resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== -color-convert@^1.9.0, color-convert@^1.9.3: +color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -8053,32 +6894,16 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== -color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4: +color-name@^1.1.4, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.6.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" - integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - color-support@^1.1.2, color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -color@^3.1.3: - version "3.2.1" - resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" - integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== - dependencies: - color-convert "^1.9.3" - color-string "^1.6.0" - colord@^2.9.1: version "2.9.3" resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" @@ -8089,14 +6914,6 @@ colorette@2.0.19, colorette@^2.0.7: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== -colorspace@1.1.x: - version "1.1.4" - resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" - integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w== - dependencies: - color "^3.1.3" - text-hex "1.0.x" - columnify@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3" @@ -8201,7 +7018,7 @@ compress-commons@^6.0.2: normalize-path "^3.0.0" readable-stream "^4.0.0" -compressible@^2.0.0, compressible@^2.0.12: +compressible@^2.0.0: version "2.0.18" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== @@ -8980,7 +7797,7 @@ debug@4.3.4: dependencies: ms "2.1.2" -debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: +debug@^3.1.0, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== @@ -9784,11 +8601,6 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== -enabled@2.0.x: - version "2.0.0" - resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" - integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== - encodeurl@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -9872,11 +8684,6 @@ enquirer@~2.3.6: dependencies: ansi-colors "^4.1.1" -ent@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" - integrity "sha1-6WQhkyWiHQX0RGai9obtbOX13R0= sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA==" - entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" @@ -10473,13 +9280,6 @@ expand-template@^2.0.3: resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== -expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== - dependencies: - homedir-polyfill "^1.0.1" - expect@^29.0.0, expect@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" @@ -10583,11 +9383,6 @@ fast-safe-stringify@^2.1.1: resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== -fast-text-encoding@^1.0.0: - version "1.0.6" - resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz#0aa25f7f638222e3396d72bf936afcf1d42d6867" - integrity sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w== - fast-uri@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.1.tgz#cddd2eecfc83a71c1be2cc2ef2061331be8a7134" @@ -10600,7 +9395,7 @@ fast-url-parser@^1.1.3: dependencies: punycode "^1.3.2" -fast-xml-parser@4.2.5, fast-xml-parser@4.4.1, fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: +fast-xml-parser@4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== @@ -10628,11 +9423,6 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" -fecha@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" - integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== - fengari-interop@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/fengari-interop/-/fengari-interop-0.1.3.tgz#3ad37a90e7430b69b365441e9fc0ba168942a146" @@ -10691,7 +9481,7 @@ file-type@^12.1.0: resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.4.2.tgz#a344ea5664a1d01447ee7fb1b635f72feb6169d9" integrity sha512-UssQP5ZgIOKelfsaB5CuGAL+Y+q7EmONuiwF3N5HAH0t27rvrttgi6Ra9k/+DVaY9UF6+ybxu5pOXLUdA8N7Vg== -file-type@^16.5.4: +file-type@^16.0.0: version "16.5.4" resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.5.4.tgz#474fb4f704bee427681f98dd390058a172a6c2fd" integrity sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw== @@ -10825,11 +9615,6 @@ flatten@^1.0.2: resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== -fn.name@1.x.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" - integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== - follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" @@ -11032,16 +9817,6 @@ gauge@^4.0.3: strip-ansi "^6.0.1" wide-align "^1.1.5" -gaxios@^5.0.0, gaxios@^5.0.1: - version "5.1.3" - resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-5.1.3.tgz#f7fa92da0fe197c846441e5ead2573d4979e9013" - integrity sha512-95hVgBRgEIRQQQHIbnxBXeHbW4TqFk4ZDJW7wmVtvYar72FdhRIo1UGOLS2eRAKCPEdPBWu+M7+A33D9CdX9rA== - dependencies: - extend "^3.0.2" - https-proxy-agent "^5.0.0" - is-stream "^2.0.0" - node-fetch "^2.6.9" - gaxios@^6.0.0, gaxios@^6.1.1: version "6.7.0" resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-6.7.0.tgz#37b7c5961cb67d8d4b0ae8110dcd83cc6791eb6d" @@ -11053,14 +9828,6 @@ gaxios@^6.0.0, gaxios@^6.1.1: node-fetch "^2.6.9" uuid "^10.0.0" -gcp-metadata@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-5.3.0.tgz#6f45eb473d0cb47d15001476b48b663744d25408" - integrity sha512-FNTkdNEnBdlqF2oatizolQqNANMrcqJt6AAYt99B3y1aLLC8Hc5IOBb+ZnnzllodEEf6xMBp6wRcBbc16fa65w== - dependencies: - gaxios "^5.0.0" - json-bigint "^1.0.0" - gcp-metadata@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-6.1.0.tgz#9b0dd2b2445258e7597f2024332d20611cbd6b8c" @@ -11083,7 +9850,7 @@ generic-names@^4.0.0: dependencies: loader-utils "^3.2.0" -generic-pool@3.9.0, generic-pool@^3.8.2: +generic-pool@3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4" integrity sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g== @@ -11462,21 +10229,6 @@ gonzales-pe@^4.2.3, gonzales-pe@^4.3.0: dependencies: minimist "^1.2.5" -google-auth-library@^8.0.1: - version "8.9.0" - resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-8.9.0.tgz#15a271eb2ec35d43b81deb72211bd61b1ef14dd0" - integrity sha512-f7aQCJODJFmYWN6PeNKzgvy9LI2tYmXnzpNDHEjG5sDNPgGb2FXQyTBnXeSH+PAtpKESFD+LmHw3Ox3mN7e1Fg== - dependencies: - arrify "^2.0.0" - base64-js "^1.3.0" - ecdsa-sig-formatter "^1.0.11" - fast-text-encoding "^1.0.0" - gaxios "^5.0.0" - gcp-metadata "^5.3.0" - gtoken "^6.1.0" - jws "^4.0.0" - lru-cache "^6.0.0" - google-auth-library@^9.3.0: version "9.11.0" resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-9.11.0.tgz#bd6da364bcde4e0cc4ed70a0e0df5112b6a671dd" @@ -11507,13 +10259,6 @@ google-gax@^4.3.3: retry-request "^7.0.0" uuid "^9.0.1" -google-p12-pem@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/google-p12-pem/-/google-p12-pem-4.0.1.tgz#82841798253c65b7dc2a4e5fe9df141db670172a" - integrity sha512-WPkN4yGtz05WZ5EhtlxNDWPhC4JIic6G8ePitwUWy4l+XPVYec+a0j0Ts47PDtW59y3RwAhUd9/h9ZZ63px6RQ== - dependencies: - node-forge "^1.3.1" - "google-spreadsheet@npm:@budibase/google-spreadsheet@4.1.5": version "4.1.5" resolved "https://registry.yarnpkg.com/@budibase/google-spreadsheet/-/google-spreadsheet-4.1.5.tgz#c89ffcbfcb1a3538e910d9275f73efc1d7deb85f" @@ -11579,15 +10324,6 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -gtoken@^6.1.0: - version "6.1.2" - resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-6.1.2.tgz#aeb7bdb019ff4c3ba3ac100bbe7b6e74dce0e8bc" - integrity sha512-4ccGpzz7YAr7lxrT2neugmXQ3hP9ho2gcaityLVkiUecAiwiy60Ii8gRbZeOsXV19fYaRjgBSshs8kXw+NKCPQ== - dependencies: - gaxios "^5.0.1" - google-p12-pem "^4.0.0" - jws "^4.0.0" - gtoken@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-7.1.0.tgz#d61b4ebd10132222817f7222b1e6064bd463fc26" @@ -11756,13 +10492,6 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -homedir-polyfill@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== - dependencies: - parse-passwd "^1.0.0" - hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -11939,11 +10668,6 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== -husky@^9.1.4: - version "9.1.5" - resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.5.tgz#2b6edede53ee1adbbd3a3da490628a23f5243b83" - integrity sha512-rowAVRUBfI0b4+niA4SJMhfQwc107VLkBUgEYYAOQAbqDCnra1nYh83hF/MDmhYs9t9n1E3DuKOrs2LYNC+0Ag== - ical-generator@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ical-generator/-/ical-generator-4.1.0.tgz#2a336c951864c5583a2aa715d16f2edcdfd2d90b" @@ -12300,11 +11024,6 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -12717,7 +11436,7 @@ is-whitespace@^0.3.0: resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f" integrity sha512-RydPhl4S6JwAyj0JJjshWJEFG6hNye3pZFBRZaTUfZFwGHxzppNaNOVgQuS/E/SlhrApuMXrpnK1EEIXfdo3Dg== -is-wsl@^2.1.1, is-wsl@^2.2.0: +is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== @@ -12788,14 +11507,6 @@ isolated-vm@^4.7.2: dependencies: prebuild-install "^7.1.1" -isomorphic-fetch@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4" - integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA== - dependencies: - node-fetch "^2.6.1" - whatwg-fetch "^3.4.1" - isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -13294,15 +12005,38 @@ jest@29.7.0: import-local "^3.0.2" jest-cli "^29.7.0" -jimp@0.22.12: - version "0.22.12" - resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.22.12.tgz#f99d1f3ec0d9d930cb7bd8f5b479859ee3a15694" - integrity sha512-R5jZaYDnfkxKJy1dwLpj/7cvyjxiclxU3F4TrI/J4j2rS0niq6YDUMoPn5hs8GDpO+OZGo7Ky057CRtWesyhfg== +jimp@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/jimp/-/jimp-1.1.4.tgz#943356f27559815690a3c2e29fa67ecfd9a92658" + integrity sha512-DL82Spu4H7B332nhddz5Cq9J0WEa5mc9d6BJQfeLHf2LOAMg79A+74KRKKzogaLgqK8APGfoWLwca7KjjvBgig== dependencies: - "@jimp/custom" "^0.22.12" - "@jimp/plugins" "^0.22.12" - "@jimp/types" "^0.22.12" - regenerator-runtime "^0.13.3" + "@jimp/core" "1.1.4" + "@jimp/diff" "1.1.4" + "@jimp/js-bmp" "1.1.4" + "@jimp/js-gif" "1.1.4" + "@jimp/js-jpeg" "1.1.4" + "@jimp/js-png" "1.1.4" + "@jimp/js-tiff" "1.1.4" + "@jimp/plugin-blit" "1.1.4" + "@jimp/plugin-blur" "1.1.4" + "@jimp/plugin-circle" "1.1.4" + "@jimp/plugin-color" "1.1.4" + "@jimp/plugin-contain" "1.1.4" + "@jimp/plugin-cover" "1.1.4" + "@jimp/plugin-crop" "1.1.4" + "@jimp/plugin-displace" "1.1.4" + "@jimp/plugin-dither" "1.1.4" + "@jimp/plugin-fisheye" "1.1.4" + "@jimp/plugin-flip" "1.1.4" + "@jimp/plugin-hash" "1.1.4" + "@jimp/plugin-mask" "1.1.4" + "@jimp/plugin-print" "1.1.4" + "@jimp/plugin-quantize" "1.1.4" + "@jimp/plugin-resize" "1.1.4" + "@jimp/plugin-rotate" "1.1.4" + "@jimp/plugin-threshold" "1.1.4" + "@jimp/types" "1.1.4" + "@jimp/utils" "1.1.4" jmespath@0.15.0: version "0.15.0" @@ -13875,11 +12609,6 @@ koalas@^1.0.2: resolved "https://registry.yarnpkg.com/koalas/-/koalas-1.0.2.tgz#318433f074235db78fae5661a02a8ca53ee295cd" integrity sha512-RYhBbYaTTTHId3l6fnMZc3eGQNW6FVCqMG6AMwA5I1Mafr6AflaXeoi6x3xQuATRotGYRLk6+1ELZH4dstFNOA== -kuler@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" - integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== - latest-version@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" @@ -14252,20 +12981,6 @@ lines-and-columns@~2.0.3: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.3.tgz#b2f0badedb556b747020ab8ea7f0373e22efac1b" integrity sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w== -load-bmfont@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.1.tgz#c0f5f4711a1e2ccff725a7b6078087ccfcddd3e9" - integrity sha512-8UyQoYmdRDy81Brz6aLAUhfZLwr5zV0L3taTQ4hju7m6biuwiWiJXjPhBJxbUQJA8PrkvJ/7Enqmwk2sM14soA== - dependencies: - buffer-equal "0.0.1" - mime "^1.3.4" - parse-bmfont-ascii "^1.0.3" - parse-bmfont-binary "^1.0.5" - parse-bmfont-xml "^1.1.4" - phin "^2.9.1" - xhr "^2.0.1" - xtend "^4.0.0" - load-json-file@6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-6.2.0.tgz#5c7770b42cafa97074ca2848707c61662f4251a1" @@ -14491,23 +13206,6 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -logform@^2.3.2, logform@^2.4.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.5.1.tgz#44c77c34becd71b3a42a3970c77929e52c6ed48b" - integrity sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg== - dependencies: - "@colors/colors" "1.5.0" - "@types/triple-beam" "^1.3.2" - fecha "^4.2.0" - ms "^2.1.1" - safe-stable-stringify "^2.3.1" - triple-beam "^1.3.0" - -long@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" - integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== - long@^5.0.0, long@^5.2.1: version "5.2.3" resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" @@ -14888,7 +13586,7 @@ mime-kind@^3.0.0: file-type "^12.1.0" mime-types "^2.1.24" -mime-types@^2.0.8, mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.24, mime-types@^2.1.29, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.24, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -14900,16 +13598,16 @@ mime@2.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== +mime@3, mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mime@^1.3.4: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" - integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== - mimic-fn@^2.0.0, mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -15160,18 +13858,6 @@ module-lookup-amd@^7.0.1: requirejs "^2.3.5" requirejs-config-file "^4.0.0" -moment-timezone@^0.5.15: - version "0.5.41" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.41.tgz#a7ad3285fd24aaf5f93b8119a9d749c8039c64c5" - integrity sha512-e0jGNZDOHfBXJGz8vR/sIMXvBIGJJcqFjmlg9lmE+5KX1U7/RZNMswfD8nKnNCnQdKTIj50IaRKwl1fvMLyyRg== - dependencies: - moment "^2.29.4" - -moment@^2.29.4: - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== - mongodb-connection-string-url@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz#b4f87f92fd8593f3b9365f592515a06d304a1e9c" @@ -15424,11 +14110,6 @@ node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-f dependencies: whatwg-url "^5.0.0" -node-forge@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== - node-gyp-build-optional-packages@5.0.7: version "5.0.7" resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz#5d2632bbde0ab2f6e22f1bbac2199b07244ae0b3" @@ -15940,7 +14621,7 @@ octal@^1.0.0: resolved "https://registry.yarnpkg.com/octal/-/octal-1.0.0.tgz#63e7162a68efbeb9e213588d58e989d1e5c4530b" integrity sha512-nnda7W8d+A3vEIY+UrDQzzboPf1vhs4JYVhff5CDkq9QNoZY7Xrxeo/htox37j9dZf7yNHevZzqtejWgy1vCqQ== -omggif@^1.0.10, omggif@^1.0.9: +omggif@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19" integrity sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw== @@ -15969,13 +14650,6 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -one-time@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" - integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== - dependencies: - fn.name "1.x.x" - onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -15988,14 +14662,6 @@ only@~0.0.2: resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" integrity sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ== -open@^7.3.1: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - open@^8.0.0, open@^8.4.0, open@~8.4.0: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" @@ -16185,7 +14851,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.1, p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -16361,23 +15027,23 @@ parse-asn1@^5.0.0, parse-asn1@^5.1.7: pbkdf2 "^3.1.2" safe-buffer "^5.2.1" -parse-bmfont-ascii@^1.0.3: +parse-bmfont-ascii@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz#11ac3c3ff58f7c2020ab22769079108d4dfa0285" integrity sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA== -parse-bmfont-binary@^1.0.5: +parse-bmfont-binary@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz#d038b476d3e9dd9db1e11a0b0e53a22792b69006" integrity sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA== -parse-bmfont-xml@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz#015319797e3e12f9e739c4d513872cd2fa35f389" - integrity sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ== +parse-bmfont-xml@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz#016b655da7aebe6da38c906aca16bf0415773767" + integrity sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA== dependencies: xml-parse-from-string "^1.0.0" - xml2js "^0.4.5" + xml2js "^0.5.0" parse-headers@^2.0.0: version "2.0.5" @@ -16407,11 +15073,6 @@ parse-ms@^2.1.0: resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== - parse-path@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-7.0.0.tgz#605a2d58d0a749c8594405d8cc3a2bf76d16099b" @@ -16692,11 +15353,6 @@ pgpass@1.x: dependencies: split2 "^4.1.0" -phin@^2.9.1: - version "2.9.3" - resolved "https://registry.yarnpkg.com/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c" - integrity sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA== - picocolors@^1.0.0, picocolors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" @@ -16849,12 +15505,12 @@ pirates@^4.0.4: resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== -pixelmatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-4.0.2.tgz#8f47dcec5011b477b67db03c243bc1f3085e8854" - integrity sha512-J8B6xqiO37sU/gkcMglv6h5Jbd9xNER7aHzpfRdNmV4IbQBzBpe4l9XmbG+xPF/znacgu2jfEw+wHffaq/YkXA== +pixelmatch@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-5.3.0.tgz#5e5321a7abedfb7962d60dbf345deda87cb9560a" + integrity sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q== dependencies: - pngjs "^3.0.0" + pngjs "^6.0.0" pkg-dir@^4.2.0: version "4.2.0" @@ -16877,16 +15533,16 @@ pluralize@^8.0.0: resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== -pngjs@^3.0.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" - integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== - pngjs@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-6.0.0.tgz#ca9e5d2aa48db0228a52c419c3308e87720da821" integrity sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg== +pngjs@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-7.0.0.tgz#a8b7446020ebbc6ac739db6c5415a65d17090e26" + integrity sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow== + possible-typed-array-names@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" @@ -17815,13 +16471,6 @@ pure-rand@^6.0.0: resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.1.tgz#31207dddd15d43f299fdcdb2f572df65030c19af" integrity sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg== -python-struct@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/python-struct/-/python-struct-1.1.3.tgz#f0ff1845ec520408e94dd8492bfd770aad26cae3" - integrity sha512-UsI/mNvk25jRpGKYI38Nfbv84z48oiIWwG67DLVvjRhy8B/0aIK+5Ju5WOHgw/o9rnEmbAS00v4rgKFQeC332Q== - dependencies: - long "^4.0.0" - q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -18175,11 +16824,6 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.13.3: - version "0.13.11" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" - integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== - regenerator-runtime@^0.14.0: version "0.14.0" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" @@ -18349,14 +16993,6 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -retry-request@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-5.0.2.tgz#143d85f90c755af407fcc46b7166a4ba520e44da" - integrity sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ== - dependencies: - debug "^4.1.1" - extend "^3.0.2" - retry-request@^7.0.0: version "7.0.2" resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-7.0.2.tgz#60bf48cfb424ec01b03fca6665dee91d06dd95f3" @@ -18366,16 +17002,16 @@ retry-request@^7.0.0: extend "^3.0.2" teeny-request "^9.0.0" -retry@0.13.1, retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity "sha1-GFsVh6z2eRnWOzVzSeA1N7JIRlg= sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" - retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== +retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity "sha1-GFsVh6z2eRnWOzVzSeA1N7JIRlg= sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -18672,7 +17308,7 @@ safe-stable-stringify@^2.1.0, safe-stable-stringify@^2.3.1: resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -18975,18 +17611,6 @@ simple-get@^4.0.0: once "^1.3.1" simple-concat "^1.0.0" -simple-lru-cache@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/simple-lru-cache/-/simple-lru-cache-0.0.2.tgz#d59cc3a193c1a5d0320f84ee732f6e4713e511dd" - integrity sha512-uEv/AFO0ADI7d99OHDmh1QfYzQk/izT1vCmu/riQfh7qjBVUUgRT87E5s5h7CxWCA/+YoZerykpEthzVrW3LIw== - -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== - dependencies: - is-arrayish "^0.3.1" - sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -19020,51 +17644,6 @@ smob@^1.0.0: resolved "https://registry.yarnpkg.com/smob/-/smob-1.5.0.tgz#85d79a1403abf128d24d3ebc1cdc5e1a9548d3ab" integrity sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig== -snowflake-promise@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/snowflake-promise/-/snowflake-promise-4.5.0.tgz#ceba611d27b3792966bc752c545760e0ce168c1c" - integrity sha512-IFY7Y1alCTY1WRFPIEcgCbjy7wCajwLNnJsvw2L7xdePir7y5ohh+S00PnF9zFRGbfVVlRh/VYqOYHEfERK2lg== - dependencies: - snowflake-sdk "^1.6.0" - -snowflake-sdk@^1.6.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/snowflake-sdk/-/snowflake-sdk-1.9.0.tgz#3bd089427549efc8efa4829c2d08deeffe4aded3" - integrity "sha1-O9CJQnVJ78jvpIKcLQje7/5K3tM= sha512-RtFRV2KC+ebQk/kOUg8WV42LnAu9puoan2wMXykgrAj1u4sGP/GgQyQhsAfLGwXWzn+J9JAwij07h3+6HYBmFw==" - dependencies: - "@aws-sdk/client-s3" "^3.388.0" - "@azure/storage-blob" "^12.11.0" - "@google-cloud/storage" "^6.9.3" - "@techteamer/ocsp" "1.0.0" - agent-base "^6.0.2" - asn1.js-rfc2560 "^5.0.0" - asn1.js-rfc5280 "^3.0.0" - axios "^1.5.0" - big-integer "^1.6.43" - bignumber.js "^2.4.0" - binascii "0.0.2" - bn.js "^5.2.1" - browser-request "^0.3.3" - debug "^3.2.6" - expand-tilde "^2.0.2" - extend "^3.0.2" - fast-xml-parser "^4.2.5" - generic-pool "^3.8.2" - glob "^7.1.6" - https-proxy-agent "^5.0.1" - jsonwebtoken "^9.0.0" - mime-types "^2.1.29" - mkdirp "^1.0.3" - moment "^2.29.4" - moment-timezone "^0.5.15" - open "^7.3.1" - python-struct "^1.1.3" - simple-lru-cache "^0.0.2" - string-similarity "^4.0.4" - tmp "^0.2.1" - uuid "^8.3.2" - winston "^3.1.0" - socket.io-adapter@~2.5.2: version "2.5.5" resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz#c7a1f9c703d7756844751b6ff9abfc1780664082" @@ -19331,11 +17910,6 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== - stack-utils@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" @@ -19432,21 +18006,7 @@ string-range@~1.2, string-range@~1.2.1: resolved "https://registry.yarnpkg.com/string-range/-/string-range-1.2.2.tgz#a893ed347e72299bc83befbbf2a692a8d239d5dd" integrity sha512-tYft6IFi8SjplJpxCUxyqisD3b+R2CSkomrtJYCkvuf1KuCAWgz7YXt4O0jip7efpfCemwHEzTEAO8EuOYgh3w== -string-similarity@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-4.0.4.tgz#42d01ab0b34660ea8a018da8f56a3309bb8b2a5b" - integrity sha512-/q/8Q4Bl4ZKAPjj8WerIBJWALKkaPRfrvhfF8k/B23i4nzrlRj2/go1m90In7nG/3XDSbOo0+pu6RvCTM9RGMQ== - -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -19529,7 +18089,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -19543,13 +18103,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -20010,17 +18563,6 @@ tedious@^16.4.0: node-abort-controller "^3.1.1" sprintf-js "^1.1.2" -teeny-request@^8.0.0: - version "8.0.3" - resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-8.0.3.tgz#5cb9c471ef5e59f2fca8280dc3c5909595e6ca24" - integrity "sha1-XLnEce9eWfL8qCgNw8WQlZXmyiQ= sha512-jJZpA5He2y52yUhA7pyAGZlgQpcB+xLjcN0eUFxr9c8hP/H7uOXbBNVo/O0C/xVfJLJs680jvkFgVJEEvk9+ww==" - dependencies: - http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.0" - node-fetch "^2.6.1" - stream-events "^1.0.5" - uuid "^9.0.0" - teeny-request@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-9.0.0.tgz#18140de2eb6595771b1b02203312dfad79a4716d" @@ -20082,11 +18624,6 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== -text-hex@1.0.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" - integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== - text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -20161,11 +18698,6 @@ timekeeper@^2.2.0: resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.3.1.tgz#2deb6e0b95d93625fda84c18d47f84a99e4eba01" integrity sha512-LeQRS7/4JcC0PgdSFnfUiStQEdiuySlCj/5SJ18D+T1n9BoY7PxKFfCwLulpHXoLUFr67HxBddQdEX47lDGx1g== -timm@^1.6.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/timm/-/timm-1.7.1.tgz#96bab60c7d45b5a10a8a4d0f0117c6b7e5aff76f" - integrity sha512-IjZc9KIotudix8bMaBW6QvMuq64BrJWFs1+4V0lXwWGQZwH+LnX87doAYhem4caOEusRP9/g6jVDQmZ8XOk1nw== - tiny-glob@^0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2" @@ -20342,11 +18874,6 @@ trim-repeated@^1.0.0: dependencies: escape-string-regexp "^1.0.2" -triple-beam@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" - integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== - ts-api-utils@^1.0.1, ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" @@ -20418,12 +18945,12 @@ tsconfig-paths@^4.1.2, tsconfig-paths@^4.2.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.10.0, tslib@^1.11.1, tslib@^1.8.1, tslib@^1.9.0: +tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.5.0, tslib@^2.6.2: +tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== @@ -20456,11 +18983,6 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -tunnel@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" - integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== - tweetnacl@^0.14.3: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -20879,7 +19401,7 @@ utf-8-validate@^5.0.2: dependencies: node-gyp-build "^4.3.0" -utif2@^4.0.1: +utif2@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/utif2/-/utif2-4.1.0.tgz#e768d37bd619b995d56d9780b5d2b4611a3d932b" integrity sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w== @@ -20911,7 +19433,7 @@ uuid@8.1.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d" integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg== -uuid@8.3.2, uuid@^8.0.0, uuid@^8.3.0, uuid@^8.3.1, uuid@^8.3.2: +uuid@8.3.2, uuid@^8.3.0, uuid@^8.3.1, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -21159,11 +19681,6 @@ whatwg-encoding@^2.0.0: dependencies: iconv-lite "0.6.3" -whatwg-fetch@^3.4.1: - version "3.6.20" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" - integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== - whatwg-mimetype@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" @@ -21287,32 +19804,6 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -winston-transport@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" - integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q== - dependencies: - logform "^2.3.2" - readable-stream "^3.6.0" - triple-beam "^1.3.0" - -winston@^3.1.0: - version "3.8.2" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.8.2.tgz#56e16b34022eb4cff2638196d9646d7430fdad50" - integrity sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew== - dependencies: - "@colors/colors" "1.5.0" - "@dabh/diagnostics" "^2.0.2" - async "^3.2.3" - is-stream "^2.0.0" - logform "^2.4.0" - one-time "^1.0.0" - readable-stream "^3.4.0" - safe-stable-stringify "^2.3.1" - stack-trace "0.0.x" - triple-beam "^1.3.0" - winston-transport "^4.5.0" - word-wrap@~1.2.3: version "1.2.5" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" @@ -21330,7 +19821,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -21348,15 +19839,6 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -21459,7 +19941,7 @@ xdg-basedir@^4.0.0: resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== -xhr@^2.0.1, xhr@^2.4.1: +xhr@^2.4.1: version "2.6.0" resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.6.0.tgz#b69d4395e792b4173d6b7df077f0fc5e4e2b249d" integrity sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA== @@ -21484,7 +19966,7 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.4.19, xml2js@0.5.0, xml2js@0.6.2, xml2js@^0.4.19, xml2js@^0.4.5: +xml2js@0.4.19, xml2js@0.5.0, xml2js@0.6.2, xml2js@^0.5.0: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== @@ -21744,3 +20226,8 @@ zip-stream@^6.0.1: archiver-utils "^5.0.0" compress-commons "^6.0.2" readable-stream "^4.0.0" + +zod@^3.23.8: + version "3.23.8" + resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d" + integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g== From 30d311f784adb9e124be7165f7d5f183ed957f73 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 17:06:44 +0000 Subject: [PATCH 15/40] pin deps --- packages/backend-core/package.json | 2 +- packages/server/package.json | 2 +- packages/worker/package.json | 4 +- yarn.lock | 379 +++++++++++------------------ 4 files changed, 146 insertions(+), 241 deletions(-) diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 4ab7b91a79..91b37ee566 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -65,7 +65,7 @@ "@types/jest": "29.5.5", "@types/lodash": "4.14.200", "@types/node-fetch": "2.6.4", - "@types/pouchdb": "^6.4.2", + "@types/pouchdb": "6.4.2", "@types/redlock": "4.0.7", "@types/semver": "7.3.7", "@types/tar-fs": "2.0.1", diff --git a/packages/server/package.json b/packages/server/package.json index 286cd906aa..71de972786 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -135,7 +135,7 @@ "@types/node-fetch": "2.6.4", "@types/oracledb": "6.5.1", "@types/pg": "8.6.6", - "@types/pouchdb": "^6.4.2", + "@types/pouchdb": "6.4.2", "@types/server-destroy": "1.0.1", "@types/supertest": "2.0.14", "@types/tar": "6.1.5", diff --git a/packages/worker/package.json b/packages/worker/package.json index e4054209c1..cb33934bdc 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -41,8 +41,8 @@ "@budibase/pro": "0.0.0", "@budibase/string-templates": "0.0.0", "@budibase/types": "0.0.0", - "@koa/router": "^13.1.0", - "@techpass/passport-openidconnect": "^1.0.0", + "@koa/router": "13.1.0", + "@techpass/passport-openidconnect": "1.0.0", "@types/global-agent": "2.1.1", "aws-sdk": "2.1030.0", "bcrypt": "5.1.0", diff --git a/yarn.lock b/yarn.lock index 7008a741be..c8e1676407 100644 --- a/yarn.lock +++ b/yarn.lock @@ -173,7 +173,7 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/identity@4.2.1", "@azure/identity@^3.4.1": +"@azure/identity@4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -193,6 +193,26 @@ stoppable "^1.1.0" tslib "^2.2.0" +"@azure/identity@^3.4.1": + version "3.4.2" + resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-3.4.2.tgz#6b01724c9caac7cadab6b63c76584345bda8e2de" + integrity sha512-0q5DL4uyR0EZ4RXQKD8MadGH6zTIcloUoS/RVbCpNpej4pwte0xpqYxk8K97Py2RiuUvI7F4GXpoT4046VfufA== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-auth" "^1.5.0" + "@azure/core-client" "^1.4.0" + "@azure/core-rest-pipeline" "^1.1.0" + "@azure/core-tracing" "^1.0.0" + "@azure/core-util" "^1.6.1" + "@azure/logger" "^1.0.0" + "@azure/msal-browser" "^3.5.0" + "@azure/msal-node" "^2.5.1" + events "^3.0.0" + jws "^4.0.0" + open "^8.0.0" + stoppable "^1.1.0" + tslib "^2.2.0" + "@azure/keyvault-keys@^4.4.0": version "4.7.1" resolved "https://registry.yarnpkg.com/@azure/keyvault-keys/-/keyvault-keys-4.7.1.tgz#c35415610ca5301f92e2ad7b30fd569609d4b32d" @@ -217,7 +237,7 @@ dependencies: tslib "^2.2.0" -"@azure/msal-browser@^3.11.1": +"@azure/msal-browser@^3.11.1", "@azure/msal-browser@^3.5.0": version "3.27.0" resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.27.0.tgz#b6f02f73c8e102d3f115009b4677539fb173fe2b" integrity sha512-+b4ZKSD8+vslCtVRVetkegEhOFMLP3rxDWJY212ct+2r6jVg6OSQKc1Qz3kCoXo0FgwaXkb+76TMZfpHp8QtgA== @@ -229,7 +249,7 @@ resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.16.0.tgz#f3470fcaec788dbe50859952cd499340bda23d7a" integrity sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA== -"@azure/msal-node@^2.9.2": +"@azure/msal-node@^2.5.1", "@azure/msal-node@^2.9.2": version "2.16.1" resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.16.1.tgz#89828832e8e6c8a88cecc4ef6d8d4e4352116b77" integrity sha512-1NEFpTmMMT2A7RnZuvRl/hUmJU+GLPjh+ShyIqPktG2PvSd2yvPnzGd/BxIBAAvJG5nr9lH4oYcQXepDbaE7fg== @@ -1446,44 +1466,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@3.2.6": - version "0.0.0" - dependencies: - "@budibase/nano" "10.1.5" - "@budibase/pouchdb-replication-stream" "1.2.11" - "@budibase/shared-core" "0.0.0" - "@budibase/types" "0.0.0" - aws-cloudfront-sign "3.0.2" - aws-sdk "2.1030.0" - bcrypt "5.1.0" - bcryptjs "2.4.3" - bull "4.10.1" - correlation-id "4.0.0" - dd-trace "5.23.0" - dotenv "16.0.1" - ioredis "5.3.2" - joi "17.6.0" - jsonwebtoken "9.0.2" - knex "2.4.2" - koa-passport "^6.0.0" - koa-pino-logger "4.0.0" - lodash "4.17.21" - node-fetch "2.6.7" - passport-google-oauth "2.0.0" - passport-local "1.0.0" - passport-oauth2-refresh "^2.1.0" - pino "8.11.0" - pino-http "8.3.3" - posthog-node "4.0.1" - pouchdb "9.0.0" - pouchdb-find "9.0.0" - redlock "4.2.0" - rotating-file-stream "3.1.0" - sanitize-s3-objectkey "0.0.1" - semver "^7.5.4" - tar-fs "2.1.1" - uuid "^8.3.2" - "@budibase/handlebars-helpers@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77" @@ -1526,47 +1508,6 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@npm:@budibase/pro@latest": - version "3.2.6" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.6.tgz#e6eeb1de9dd39b06b4bf7115d0decfa5b216ecbb" - integrity sha512-AUHXe6AkENxKD7DogDvUhTTqK/11GMtEwCodCzvBQ2h97AJNYykZzRK4G4DtCyliD9AvUMAJFIROfhb31x0LFw== - dependencies: - "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "3.2.6" - "@budibase/shared-core" "3.2.6" - "@budibase/string-templates" "3.2.6" - "@budibase/types" "3.2.6" - "@koa/router" "8.0.8" - bull "4.10.1" - dd-trace "5.2.0" - joi "17.6.0" - jsonwebtoken "9.0.2" - lru-cache "^7.14.1" - memorystream "^0.3.1" - node-fetch "2.6.7" - openai "4.59.0" - scim-patch "^0.8.1" - scim2-parse-filter "^0.2.8" - -"@budibase/shared-core@3.2.6": - version "0.0.0" - dependencies: - "@budibase/types" "0.0.0" - cron-validate "1.4.5" - -"@budibase/string-templates@3.2.6": - version "0.0.0" - dependencies: - "@budibase/handlebars-helpers" "^0.13.2" - dayjs "^1.10.8" - handlebars "^4.7.8" - lodash.clonedeep "^4.5.0" - -"@budibase/types@3.2.6": - version "0.0.0" - dependencies: - scim-patch "^0.8.1" - "@bull-board/api@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3" @@ -1692,13 +1633,6 @@ resolved "https://registry.yarnpkg.com/@dagrejs/graphlib/-/graphlib-2.2.4.tgz#d77bfa9ff49e2307c0c6e6b8b26b5dd3c05816c4" integrity sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw== -"@datadog/native-appsec@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-7.0.0.tgz#a380174dd49aef2d9bb613a0ec8ead6dc7822095" - integrity sha512-bywstWFW2hWxzPuS0+mFMVHHL0geulx5yQFtsjfszaH2LTAgk2D+Rt40MKbAoZ8q3tRw2dy6aYQ7svO3ca8jpA== - dependencies: - node-gyp-build "^3.9.0" - "@datadog/native-appsec@8.1.1": version "8.1.1" resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.1.1.tgz#76aa34697e6ecbd3d9ef7e6938d3cdcfa689b1f3" @@ -1706,14 +1640,6 @@ dependencies: node-gyp-build "^3.9.0" -"@datadog/native-iast-rewriter@2.2.2": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.2.2.tgz#3f7feaf6be1af4c83ad063065b8ed509bbaf11cb" - integrity sha512-13ZBhJpjZ/tiV6rYfyAf/ITye9cyd3x12M/2NKhD4Ivev4N4uKBREAjpArOtzKtPXZ5b6oXwVV4ofT1SHoYyzA== - dependencies: - lru-cache "^7.14.0" - node-gyp-build "^4.5.0" - "@datadog/native-iast-rewriter@2.4.1": version "2.4.1" resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.4.1.tgz#e8211f78c818906513fb96a549374da0382c7623" @@ -1722,13 +1648,6 @@ lru-cache "^7.14.0" node-gyp-build "^4.5.0" -"@datadog/native-iast-taint-tracking@1.6.4": - version "1.6.4" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-1.6.4.tgz#16c21ad7c36a53420c0d3c5a3720731809cc7e98" - integrity sha512-Owxk7hQ4Dxwv4zJAoMjRga0IvE6lhvxnNc8pJCHsemCWBXchjr/9bqg05Zy5JnMbKUWn4XuZeJD6RFZpRa8bfw== - dependencies: - node-gyp-build "^3.9.0" - "@datadog/native-iast-taint-tracking@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.1.0.tgz#7b2ed7f8fad212d65e5ab03bcdea8b42a3051b2e" @@ -1744,17 +1663,6 @@ node-addon-api "^6.1.0" node-gyp-build "^3.9.0" -"@datadog/pprof@5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.0.0.tgz#0c0aaf06def6d2bc4b2d353ec7b264dadbfbefab" - integrity sha512-vhNan4SBuNWLpexunDJQ+hNbRAgWdk2qy5Iyh7Nn94uSSHXigAJMAvu4jwMKKQKFfchtobOkWT8GQUWW3tgpFg== - dependencies: - delay "^5.0.0" - node-gyp-build "<4.0" - p-limit "^3.1.0" - pprof-format "^2.0.7" - source-map "^0.7.4" - "@datadog/pprof@5.3.0": version "5.3.0" resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.3.0.tgz#c2f58d328ecced7f99887f1a559d7fe3aecb9219" @@ -2646,18 +2554,6 @@ koa-compose "^4.1.0" path-to-regexp "^6.3.0" -"@koa/router@8.0.8": - version "8.0.8" - resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.8.tgz#95f32d11373d03d89dcb63fabe9ac6f471095236" - integrity sha512-FnT93N4NUehnXr+juupDmG2yfi0JnWdCmNEuIXpCG4TtG+9xvtrLambBH3RclycopVUOEYAim2lydiNBI7IRVg== - dependencies: - debug "^4.1.1" - http-errors "^1.7.3" - koa-compose "^4.1.0" - methods "^1.1.2" - path-to-regexp "1.x" - urijs "^1.19.2" - "@lerna/child-process@7.4.2": version "7.4.2" resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-7.4.2.tgz#a2fd013ac2150dc288270d3e0d0b850c06bec511" @@ -3121,11 +3017,6 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== -"@opentelemetry/api@^1.0.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" - integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== - "@opentelemetry/core@^1.14.0": version "1.19.0" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.19.0.tgz#6563bb65465bf232d8435553b9a122d9351c0fbb" @@ -3913,7 +3804,7 @@ dependencies: defer-to-connect "^1.0.1" -"@techpass/passport-openidconnect@^1.0.0": +"@techpass/passport-openidconnect@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-1.0.0.tgz#e79a70b2ccd54d04122b774a33469cb52858a6bd" integrity sha512-jcTny/3ZUlp1wN9xrUPjPQpVOfMtZ9ehSF/1T6AXse/FvgiWXDIVZUPW/QcoDsXXqYeI6huWPMGM4AwxtMe8bA== @@ -4626,10 +4517,10 @@ "@types/pouchdb-core" "*" "@types/pouchdb-find" "*" -"@types/pouchdb@^6.4.0": - version "6.4.0" - resolved "https://registry.yarnpkg.com/@types/pouchdb/-/pouchdb-6.4.0.tgz#f9c41ca64b23029f9bf2eb4bf6956e6431cb79f8" - integrity sha512-eGCpX+NXhd5VLJuJMzwe3L79fa9+IDTrAG3CPaf4s/31PD56hOrhDJTSmRELSXuiqXr6+OHzzP0PldSaWsFt7w== +"@types/pouchdb@6.4.2": + version "6.4.2" + resolved "https://registry.yarnpkg.com/@types/pouchdb/-/pouchdb-6.4.2.tgz#54777533d86f4abd1a3989b272e085323623bbe1" + integrity sha512-YsI47rASdtzR+3V3JE2UKY58snhm0AglHBpyckQBkRYoCbTvGagXHtV0x5n8nzN04jQmvTG+Sm85cIzKT3KXBA== dependencies: "@types/pouchdb-adapter-cordova-sqlite" "*" "@types/pouchdb-adapter-fruitdown" "*" @@ -4647,10 +4538,10 @@ "@types/pouchdb-node" "*" "@types/pouchdb-replication" "*" -"@types/pouchdb@^6.4.2": - version "6.4.2" - resolved "https://registry.yarnpkg.com/@types/pouchdb/-/pouchdb-6.4.2.tgz#54777533d86f4abd1a3989b272e085323623bbe1" - integrity sha512-YsI47rASdtzR+3V3JE2UKY58snhm0AglHBpyckQBkRYoCbTvGagXHtV0x5n8nzN04jQmvTG+Sm85cIzKT3KXBA== +"@types/pouchdb@^6.4.0": + version "6.4.0" + resolved "https://registry.yarnpkg.com/@types/pouchdb/-/pouchdb-6.4.0.tgz#f9c41ca64b23029f9bf2eb4bf6956e6431cb79f8" + integrity sha512-eGCpX+NXhd5VLJuJMzwe3L79fa9+IDTrAG3CPaf4s/31PD56hOrhDJTSmRELSXuiqXr6+OHzzP0PldSaWsFt7w== dependencies: "@types/pouchdb-adapter-cordova-sqlite" "*" "@types/pouchdb-adapter-fruitdown" "*" @@ -5866,7 +5757,23 @@ aws-sdk@2.1030.0: uuid "3.3.2" xml2js "0.4.19" -axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2: +axios@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" + integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + +axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -7704,48 +7611,11 @@ dayjs@^1.10.8: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -dc-polyfill@^0.1.2, dc-polyfill@^0.1.4: +dc-polyfill@^0.1.4: version "0.1.6" resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== -dd-trace@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.2.0.tgz#6ca2d76ece95f08d98468d7782c22f24192afa53" - integrity sha512-Z5ql3ZKzVW3DPstHPkTPcIPvKljHNtzTYY/WuZRlgT4XK7rMaN0j5nA8LlUh7m+tOPWs05IiKngbYVZjsqhRgA== - dependencies: - "@datadog/native-appsec" "7.0.0" - "@datadog/native-iast-rewriter" "2.2.2" - "@datadog/native-iast-taint-tracking" "1.6.4" - "@datadog/native-metrics" "^2.0.0" - "@datadog/pprof" "5.0.0" - "@datadog/sketches-js" "^2.1.0" - "@opentelemetry/api" "^1.0.0" - "@opentelemetry/core" "^1.14.0" - crypto-randomuuid "^1.0.0" - dc-polyfill "^0.1.2" - ignore "^5.2.4" - import-in-the-middle "^1.7.3" - int64-buffer "^0.1.9" - ipaddr.js "^2.1.0" - istanbul-lib-coverage "3.2.0" - jest-docblock "^29.7.0" - koalas "^1.0.2" - limiter "1.1.5" - lodash.sortby "^4.7.0" - lru-cache "^7.14.0" - methods "^1.1.2" - module-details-from-path "^1.0.3" - msgpack-lite "^0.1.26" - node-abort-controller "^3.1.1" - opentracing ">=0.12.1" - path-to-regexp "^0.1.2" - pprof-format "^2.0.7" - protobufjs "^7.2.5" - retry "^0.13.1" - semver "^7.5.4" - tlhunter-sorted-set "^0.1.0" - dd-trace@5.23.0: version "5.23.0" resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.23.0.tgz#a0c11863406de440a6675648caf06e1d07d67ba8" @@ -9395,13 +9265,6 @@ fast-url-parser@^1.1.3: dependencies: punycode "^1.3.2" -fast-xml-parser@4.4.1: - version "4.4.1" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" - integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== - dependencies: - strnum "^1.0.5" - fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -9615,7 +9478,7 @@ flatten@^1.0.2: resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== -follow-redirects@^1.15.6: +follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -10573,7 +10436,12 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -10668,6 +10536,11 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +husky@^9.1.4: + version "9.1.7" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" + integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== + ical-generator@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ical-generator/-/ical-generator-4.1.0.tgz#2a336c951864c5583a2aa715d16f2edcdfd2d90b" @@ -10784,7 +10657,7 @@ import-from@^3.0.0: dependencies: resolve-from "^5.0.0" -import-in-the-middle@1.11.2, import-in-the-middle@^1.7.3: +import-in-the-middle@1.11.2: version "1.11.2" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz#dd848e72b63ca6cd7c34df8b8d97fc9baee6174f" integrity sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA== @@ -10998,11 +10871,6 @@ ip@^2.0.0: resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== -ipaddr.js@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" - integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== - is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -11046,6 +10914,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -11495,11 +11368,6 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isobject@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" - integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== - isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -12376,7 +12244,14 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@^3.0.2, kind-of@^3.1.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -13909,7 +13784,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@1.10.1, msgpackr@^1.5.2: +msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -14103,13 +13978,27 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: +node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.9, node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-gyp-build-optional-packages@5.0.7: version "5.0.7" resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz#5d2632bbde0ab2f6e22f1bbac2199b07244ae0b3" @@ -15168,7 +15057,15 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@0.6.0, passport@^0.4.0, passport@^0.6.0: +passport@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" + integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + +passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -15223,14 +15120,7 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@1.x: - version "1.9.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" - integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== - dependencies: - isarray "0.0.1" - -path-to-regexp@^0.1.10, path-to-regexp@^0.1.2: +path-to-regexp@^0.1.10: version "0.1.11" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.11.tgz#a527e662c89efc4646dbfa8100bf3e847e495761" integrity sha512-c0t+KCuUkO/YDLPG4WWzEwx3J5F/GHXsD1h/SNZfySqAIKe/BaP95x8fWtOfRJokpS5yYHRJjMtYlXD8jxnpbw== @@ -16131,7 +16021,7 @@ pouchdb@9.0.0: uuid "8.3.2" vuvuzela "1.0.3" -pprof-format@^2.0.7, pprof-format@^2.1.0: +pprof-format@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.1.0.tgz#acc8d7773bcf4faf0a3d3df11bceefba7ac06664" integrity sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw== @@ -17414,13 +17304,33 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.4, semver@^7.6.0: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +semver@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" + integrity sha512-abLdIKCosKfpnmhS52NCTjO4RiLspDfsn37prjzGrp9im5DPJOgh82Os92vtwGh6XdQryKI/7SREZnV+aqiXrA== + seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -18180,11 +18090,6 @@ striptags@^3.1.1: resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.2.0.tgz#cc74a137db2de8b0b9a370006334161f7dd67052" integrity sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw== -strnum@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" - integrity "sha1-XE6Cn+Fa1P8NIMPbWsl7c8mwcts= sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" - strong-log-transformer@2.1.0, strong-log-transformer@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" @@ -18817,7 +18722,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -19303,14 +19208,6 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unset-value@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" - integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== - dependencies: - has-value "^2.0.2" - isobject "^4.0.0" - untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -19361,11 +19258,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urijs@^1.19.2: - version "1.19.11" - resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" - integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== - url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -19966,10 +19858,18 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.4.19, xml2js@0.5.0, xml2js@0.6.2, xml2js@^0.5.0: - version "0.6.2" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" - integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== +xml2js@0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" + integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== + dependencies: + sax ">=0.6.0" + xmlbuilder "~9.0.1" + +xml2js@0.5.0, xml2js@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== dependencies: sax ">=0.6.0" xmlbuilder "~11.0.0" @@ -19979,6 +19879,11 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== +xmlbuilder@~9.0.1: + version "9.0.7" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" + integrity sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ== + xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" From a89d5f3159a82feee93e167fcaae53cb8322f85f Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 17:11:08 +0000 Subject: [PATCH 16/40] re-added bb deps --- yarn.lock | 356 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 228 insertions(+), 128 deletions(-) diff --git a/yarn.lock b/yarn.lock index c8e1676407..28f630d81a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -173,7 +173,7 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/identity@4.2.1": +"@azure/identity@4.2.1", "@azure/identity@^3.4.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -193,26 +193,6 @@ stoppable "^1.1.0" tslib "^2.2.0" -"@azure/identity@^3.4.1": - version "3.4.2" - resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-3.4.2.tgz#6b01724c9caac7cadab6b63c76584345bda8e2de" - integrity sha512-0q5DL4uyR0EZ4RXQKD8MadGH6zTIcloUoS/RVbCpNpej4pwte0xpqYxk8K97Py2RiuUvI7F4GXpoT4046VfufA== - dependencies: - "@azure/abort-controller" "^1.0.0" - "@azure/core-auth" "^1.5.0" - "@azure/core-client" "^1.4.0" - "@azure/core-rest-pipeline" "^1.1.0" - "@azure/core-tracing" "^1.0.0" - "@azure/core-util" "^1.6.1" - "@azure/logger" "^1.0.0" - "@azure/msal-browser" "^3.5.0" - "@azure/msal-node" "^2.5.1" - events "^3.0.0" - jws "^4.0.0" - open "^8.0.0" - stoppable "^1.1.0" - tslib "^2.2.0" - "@azure/keyvault-keys@^4.4.0": version "4.7.1" resolved "https://registry.yarnpkg.com/@azure/keyvault-keys/-/keyvault-keys-4.7.1.tgz#c35415610ca5301f92e2ad7b30fd569609d4b32d" @@ -237,7 +217,7 @@ dependencies: tslib "^2.2.0" -"@azure/msal-browser@^3.11.1", "@azure/msal-browser@^3.5.0": +"@azure/msal-browser@^3.11.1": version "3.27.0" resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.27.0.tgz#b6f02f73c8e102d3f115009b4677539fb173fe2b" integrity sha512-+b4ZKSD8+vslCtVRVetkegEhOFMLP3rxDWJY212ct+2r6jVg6OSQKc1Qz3kCoXo0FgwaXkb+76TMZfpHp8QtgA== @@ -249,7 +229,7 @@ resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.16.0.tgz#f3470fcaec788dbe50859952cd499340bda23d7a" integrity sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA== -"@azure/msal-node@^2.5.1", "@azure/msal-node@^2.9.2": +"@azure/msal-node@^2.9.2": version "2.16.1" resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.16.1.tgz#89828832e8e6c8a88cecc4ef6d8d4e4352116b77" integrity sha512-1NEFpTmMMT2A7RnZuvRl/hUmJU+GLPjh+ShyIqPktG2PvSd2yvPnzGd/BxIBAAvJG5nr9lH4oYcQXepDbaE7fg== @@ -1466,6 +1446,44 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@budibase/backend-core@3.2.7": + version "0.0.0" + dependencies: + "@budibase/nano" "10.1.5" + "@budibase/pouchdb-replication-stream" "1.2.11" + "@budibase/shared-core" "0.0.0" + "@budibase/types" "0.0.0" + aws-cloudfront-sign "3.0.2" + aws-sdk "2.1030.0" + bcrypt "5.1.0" + bcryptjs "2.4.3" + bull "4.10.1" + correlation-id "4.0.0" + dd-trace "5.23.0" + dotenv "16.0.1" + ioredis "5.3.2" + joi "17.6.0" + jsonwebtoken "9.0.2" + knex "2.4.2" + koa-passport "^6.0.0" + koa-pino-logger "4.0.0" + lodash "4.17.21" + node-fetch "2.6.7" + passport-google-oauth "2.0.0" + passport-local "1.0.0" + passport-oauth2-refresh "^2.1.0" + pino "8.11.0" + pino-http "8.3.3" + posthog-node "4.0.1" + pouchdb "9.0.0" + pouchdb-find "9.0.0" + redlock "4.2.0" + rotating-file-stream "3.1.0" + sanitize-s3-objectkey "0.0.1" + semver "^7.5.4" + tar-fs "2.1.1" + uuid "^8.3.2" + "@budibase/handlebars-helpers@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77" @@ -1508,6 +1526,47 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" +"@budibase/pro@npm:@budibase/pro@latest": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.7.tgz#4dfc48f3e2ba3a3b235872e54c3de4de54ea7941" + integrity sha512-GRRaf1qSqQfoodjvKjBDvNOVHZrcSXF7so6Y9Xv/MiRTjDES5nmhIT5rL/PQ1+Mb+sPytYmMaJ2mlTtwqSQZgQ== + dependencies: + "@anthropic-ai/sdk" "^0.27.3" + "@budibase/backend-core" "3.2.7" + "@budibase/shared-core" "3.2.7" + "@budibase/string-templates" "3.2.7" + "@budibase/types" "3.2.7" + "@koa/router" "8.0.8" + bull "4.10.1" + dd-trace "5.2.0" + joi "17.6.0" + jsonwebtoken "9.0.2" + lru-cache "^7.14.1" + memorystream "^0.3.1" + node-fetch "2.6.7" + openai "4.59.0" + scim-patch "^0.8.1" + scim2-parse-filter "^0.2.8" + +"@budibase/shared-core@3.2.7": + version "0.0.0" + dependencies: + "@budibase/types" "0.0.0" + cron-validate "1.4.5" + +"@budibase/string-templates@3.2.7": + version "0.0.0" + dependencies: + "@budibase/handlebars-helpers" "^0.13.2" + dayjs "^1.10.8" + handlebars "^4.7.8" + lodash.clonedeep "^4.5.0" + +"@budibase/types@3.2.7": + version "0.0.0" + dependencies: + scim-patch "^0.8.1" + "@bull-board/api@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3" @@ -1633,6 +1692,13 @@ resolved "https://registry.yarnpkg.com/@dagrejs/graphlib/-/graphlib-2.2.4.tgz#d77bfa9ff49e2307c0c6e6b8b26b5dd3c05816c4" integrity sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw== +"@datadog/native-appsec@7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-7.0.0.tgz#a380174dd49aef2d9bb613a0ec8ead6dc7822095" + integrity sha512-bywstWFW2hWxzPuS0+mFMVHHL0geulx5yQFtsjfszaH2LTAgk2D+Rt40MKbAoZ8q3tRw2dy6aYQ7svO3ca8jpA== + dependencies: + node-gyp-build "^3.9.0" + "@datadog/native-appsec@8.1.1": version "8.1.1" resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.1.1.tgz#76aa34697e6ecbd3d9ef7e6938d3cdcfa689b1f3" @@ -1640,6 +1706,14 @@ dependencies: node-gyp-build "^3.9.0" +"@datadog/native-iast-rewriter@2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.2.2.tgz#3f7feaf6be1af4c83ad063065b8ed509bbaf11cb" + integrity sha512-13ZBhJpjZ/tiV6rYfyAf/ITye9cyd3x12M/2NKhD4Ivev4N4uKBREAjpArOtzKtPXZ5b6oXwVV4ofT1SHoYyzA== + dependencies: + lru-cache "^7.14.0" + node-gyp-build "^4.5.0" + "@datadog/native-iast-rewriter@2.4.1": version "2.4.1" resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.4.1.tgz#e8211f78c818906513fb96a549374da0382c7623" @@ -1648,6 +1722,13 @@ lru-cache "^7.14.0" node-gyp-build "^4.5.0" +"@datadog/native-iast-taint-tracking@1.6.4": + version "1.6.4" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-1.6.4.tgz#16c21ad7c36a53420c0d3c5a3720731809cc7e98" + integrity sha512-Owxk7hQ4Dxwv4zJAoMjRga0IvE6lhvxnNc8pJCHsemCWBXchjr/9bqg05Zy5JnMbKUWn4XuZeJD6RFZpRa8bfw== + dependencies: + node-gyp-build "^3.9.0" + "@datadog/native-iast-taint-tracking@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.1.0.tgz#7b2ed7f8fad212d65e5ab03bcdea8b42a3051b2e" @@ -1663,6 +1744,17 @@ node-addon-api "^6.1.0" node-gyp-build "^3.9.0" +"@datadog/pprof@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.0.0.tgz#0c0aaf06def6d2bc4b2d353ec7b264dadbfbefab" + integrity sha512-vhNan4SBuNWLpexunDJQ+hNbRAgWdk2qy5Iyh7Nn94uSSHXigAJMAvu4jwMKKQKFfchtobOkWT8GQUWW3tgpFg== + dependencies: + delay "^5.0.0" + node-gyp-build "<4.0" + p-limit "^3.1.0" + pprof-format "^2.0.7" + source-map "^0.7.4" + "@datadog/pprof@5.3.0": version "5.3.0" resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.3.0.tgz#c2f58d328ecced7f99887f1a559d7fe3aecb9219" @@ -2554,6 +2646,18 @@ koa-compose "^4.1.0" path-to-regexp "^6.3.0" +"@koa/router@8.0.8": + version "8.0.8" + resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.8.tgz#95f32d11373d03d89dcb63fabe9ac6f471095236" + integrity sha512-FnT93N4NUehnXr+juupDmG2yfi0JnWdCmNEuIXpCG4TtG+9xvtrLambBH3RclycopVUOEYAim2lydiNBI7IRVg== + dependencies: + debug "^4.1.1" + http-errors "^1.7.3" + koa-compose "^4.1.0" + methods "^1.1.2" + path-to-regexp "1.x" + urijs "^1.19.2" + "@lerna/child-process@7.4.2": version "7.4.2" resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-7.4.2.tgz#a2fd013ac2150dc288270d3e0d0b850c06bec511" @@ -3017,6 +3121,11 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== +"@opentelemetry/api@^1.0.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" + integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== + "@opentelemetry/core@^1.14.0": version "1.19.0" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.19.0.tgz#6563bb65465bf232d8435553b9a122d9351c0fbb" @@ -5757,23 +5866,7 @@ aws-sdk@2.1030.0: uuid "3.3.2" xml2js "0.4.19" -axios@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" - integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - -axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2: +axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -7611,11 +7704,48 @@ dayjs@^1.10.8: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -dc-polyfill@^0.1.4: +dc-polyfill@^0.1.2, dc-polyfill@^0.1.4: version "0.1.6" resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== +dd-trace@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.2.0.tgz#6ca2d76ece95f08d98468d7782c22f24192afa53" + integrity sha512-Z5ql3ZKzVW3DPstHPkTPcIPvKljHNtzTYY/WuZRlgT4XK7rMaN0j5nA8LlUh7m+tOPWs05IiKngbYVZjsqhRgA== + dependencies: + "@datadog/native-appsec" "7.0.0" + "@datadog/native-iast-rewriter" "2.2.2" + "@datadog/native-iast-taint-tracking" "1.6.4" + "@datadog/native-metrics" "^2.0.0" + "@datadog/pprof" "5.0.0" + "@datadog/sketches-js" "^2.1.0" + "@opentelemetry/api" "^1.0.0" + "@opentelemetry/core" "^1.14.0" + crypto-randomuuid "^1.0.0" + dc-polyfill "^0.1.2" + ignore "^5.2.4" + import-in-the-middle "^1.7.3" + int64-buffer "^0.1.9" + ipaddr.js "^2.1.0" + istanbul-lib-coverage "3.2.0" + jest-docblock "^29.7.0" + koalas "^1.0.2" + limiter "1.1.5" + lodash.sortby "^4.7.0" + lru-cache "^7.14.0" + methods "^1.1.2" + module-details-from-path "^1.0.3" + msgpack-lite "^0.1.26" + node-abort-controller "^3.1.1" + opentracing ">=0.12.1" + path-to-regexp "^0.1.2" + pprof-format "^2.0.7" + protobufjs "^7.2.5" + retry "^0.13.1" + semver "^7.5.4" + tlhunter-sorted-set "^0.1.0" + dd-trace@5.23.0: version "5.23.0" resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.23.0.tgz#a0c11863406de440a6675648caf06e1d07d67ba8" @@ -9265,6 +9395,13 @@ fast-url-parser@^1.1.3: dependencies: punycode "^1.3.2" +fast-xml-parser@4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" + integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== + dependencies: + strnum "^1.0.5" + fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -9478,7 +9615,7 @@ flatten@^1.0.2: resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== -follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: +follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -10436,12 +10573,7 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== - -http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -10657,7 +10789,7 @@ import-from@^3.0.0: dependencies: resolve-from "^5.0.0" -import-in-the-middle@1.11.2: +import-in-the-middle@1.11.2, import-in-the-middle@^1.7.3: version "1.11.2" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz#dd848e72b63ca6cd7c34df8b8d97fc9baee6174f" integrity sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA== @@ -10871,6 +11003,11 @@ ip@^2.0.0: resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== +ipaddr.js@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== + is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -10914,11 +11051,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -11368,6 +11500,11 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -12244,14 +12381,7 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@^3.0.2, kind-of@^3.1.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== - dependencies: - is-buffer "^1.1.5" - -kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -13784,7 +13914,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@^1.5.2: +msgpackr@1.10.1, msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -13978,27 +14108,13 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" -node-fetch@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" - integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== - dependencies: - whatwg-url "^5.0.0" - -node-fetch@^2.6.9, node-fetch@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - node-gyp-build-optional-packages@5.0.7: version "5.0.7" resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz#5d2632bbde0ab2f6e22f1bbac2199b07244ae0b3" @@ -15057,15 +15173,7 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" - integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - -passport@^0.6.0: +passport@0.6.0, passport@^0.4.0, passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -15120,7 +15228,14 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@^0.1.10: +path-to-regexp@1.x: + version "1.9.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" + integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== + dependencies: + isarray "0.0.1" + +path-to-regexp@^0.1.10, path-to-regexp@^0.1.2: version "0.1.11" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.11.tgz#a527e662c89efc4646dbfa8100bf3e847e495761" integrity sha512-c0t+KCuUkO/YDLPG4WWzEwx3J5F/GHXsD1h/SNZfySqAIKe/BaP95x8fWtOfRJokpS5yYHRJjMtYlXD8jxnpbw== @@ -16021,7 +16136,7 @@ pouchdb@9.0.0: uuid "8.3.2" vuvuzela "1.0.3" -pprof-format@^2.1.0: +pprof-format@^2.0.7, pprof-format@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.1.0.tgz#acc8d7773bcf4faf0a3d3df11bceefba7ac06664" integrity sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw== @@ -17304,33 +17419,13 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: +"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.4, semver@^7.6.0: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== - -semver@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" - integrity sha512-abLdIKCosKfpnmhS52NCTjO4RiLspDfsn37prjzGrp9im5DPJOgh82Os92vtwGh6XdQryKI/7SREZnV+aqiXrA== - seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -18090,6 +18185,11 @@ striptags@^3.1.1: resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.2.0.tgz#cc74a137db2de8b0b9a370006334161f7dd67052" integrity sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + strong-log-transformer@2.1.0, strong-log-transformer@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" @@ -18722,7 +18822,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: +tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -19208,6 +19308,14 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unset-value@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" + integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== + dependencies: + has-value "^2.0.2" + isobject "^4.0.0" + untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -19258,6 +19366,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urijs@^1.19.2: + version "1.19.11" + resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" + integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== + url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -19858,18 +19971,10 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.4.19: - version "0.4.19" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" - integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q== - dependencies: - sax ">=0.6.0" - xmlbuilder "~9.0.1" - -xml2js@0.5.0, xml2js@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" - integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== +xml2js@0.4.19, xml2js@0.5.0, xml2js@0.6.2, xml2js@^0.5.0: + version "0.6.2" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" + integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== dependencies: sax ">=0.6.0" xmlbuilder "~11.0.0" @@ -19879,11 +19984,6 @@ xmlbuilder@~11.0.0: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== -xmlbuilder@~9.0.1: - version "9.0.7" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ== - xmlchars@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" From 415048c9ed68f6889aa5525eba414c707051269f Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 19 Nov 2024 18:50:44 +0100 Subject: [PATCH 17/40] Update yarn.lock --- yarn.lock | 987 +++++++++++------------------------------------------- 1 file changed, 194 insertions(+), 793 deletions(-) diff --git a/yarn.lock b/yarn.lock index 809877db6c..ed39c04b94 100644 --- a/yarn.lock +++ b/yarn.lock @@ -82,562 +82,6 @@ call-me-maybe "^1.0.1" z-schema "^5.0.1" -"@aws-crypto/crc32@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-3.0.0.tgz#07300eca214409c33e3ff769cd5697b57fdd38fa" - integrity "sha1-BzAOyiFECcM+P/dpzVaXtX/dOPo= sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==" - dependencies: - "@aws-crypto/util" "^3.0.0" - "@aws-sdk/types" "^3.222.0" - tslib "^1.11.1" - -"@aws-crypto/crc32c@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-3.0.0.tgz#016c92da559ef638a84a245eecb75c3e97cb664f" - integrity "sha1-AWyS2lWe9jioSiRe7LdcPpfLZk8= sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==" - dependencies: - "@aws-crypto/util" "^3.0.0" - "@aws-sdk/types" "^3.222.0" - tslib "^1.11.1" - -"@aws-crypto/ie11-detection@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz#640ae66b4ec3395cee6a8e94ebcd9f80c24cd688" - integrity "sha1-ZArma07DOVzuao6U682fgMJM1og= sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==" - dependencies: - tslib "^1.11.1" - -"@aws-crypto/sha1-browser@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-3.0.0.tgz#f9083c00782b24714f528b1a1fef2174002266a3" - integrity "sha1-+Qg8AHgrJHFPUosaH+8hdAAiZqM= sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==" - dependencies: - "@aws-crypto/ie11-detection" "^3.0.0" - "@aws-crypto/supports-web-crypto" "^3.0.0" - "@aws-crypto/util" "^3.0.0" - "@aws-sdk/types" "^3.222.0" - "@aws-sdk/util-locate-window" "^3.0.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-crypto/sha256-browser@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz#05f160138ab893f1c6ba5be57cfd108f05827766" - integrity "sha1-BfFgE4q4k/HGulvlfP0QjwWCd2Y= sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==" - dependencies: - "@aws-crypto/ie11-detection" "^3.0.0" - "@aws-crypto/sha256-js" "^3.0.0" - "@aws-crypto/supports-web-crypto" "^3.0.0" - "@aws-crypto/util" "^3.0.0" - "@aws-sdk/types" "^3.222.0" - "@aws-sdk/util-locate-window" "^3.0.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-crypto/sha256-js@3.0.0", "@aws-crypto/sha256-js@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz#f06b84d550d25521e60d2a0e2a90139341e007c2" - integrity "sha1-8GuE1VDSVSHmDSoOKpATk0HgB8I= sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==" - dependencies: - "@aws-crypto/util" "^3.0.0" - "@aws-sdk/types" "^3.222.0" - tslib "^1.11.1" - -"@aws-crypto/supports-web-crypto@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz#5d1bf825afa8072af2717c3e455f35cda0103ec2" - integrity "sha1-XRv4Ja+oByrycXw+RV81zaAQPsI= sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==" - dependencies: - tslib "^1.11.1" - -"@aws-crypto/util@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-3.0.0.tgz#1c7ca90c29293f0883468ad48117937f0fe5bfb0" - integrity "sha1-HHypDCkpPwiDRorUgReTfw/lv7A= sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==" - dependencies: - "@aws-sdk/types" "^3.222.0" - "@aws-sdk/util-utf8-browser" "^3.0.0" - tslib "^1.11.1" - -"@aws-sdk/client-s3@^3.388.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.423.0.tgz#b15fc64db09f1698bf4ad19f6f8e3b57c15e5305" - integrity "sha1-sV/GTbCfFpi/StGfb447V8FeUwU= sha512-Sn/6fotTDGp+uUfPU0JrKszHT/cYwZonly6Ahi4R/uxASLQnOEAF7MwVSjms+/LGu72Qs0Tt7B7RKW76GI4OIA==" - dependencies: - "@aws-crypto/sha1-browser" "3.0.0" - "@aws-crypto/sha256-browser" "3.0.0" - "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/client-sts" "3.423.0" - "@aws-sdk/credential-provider-node" "3.423.0" - "@aws-sdk/middleware-bucket-endpoint" "3.418.0" - "@aws-sdk/middleware-expect-continue" "3.418.0" - "@aws-sdk/middleware-flexible-checksums" "3.418.0" - "@aws-sdk/middleware-host-header" "3.418.0" - "@aws-sdk/middleware-location-constraint" "3.418.0" - "@aws-sdk/middleware-logger" "3.418.0" - "@aws-sdk/middleware-recursion-detection" "3.418.0" - "@aws-sdk/middleware-sdk-s3" "3.418.0" - "@aws-sdk/middleware-signing" "3.418.0" - "@aws-sdk/middleware-ssec" "3.418.0" - "@aws-sdk/middleware-user-agent" "3.418.0" - "@aws-sdk/region-config-resolver" "3.418.0" - "@aws-sdk/signature-v4-multi-region" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-endpoints" "3.418.0" - "@aws-sdk/util-user-agent-browser" "3.418.0" - "@aws-sdk/util-user-agent-node" "3.418.0" - "@aws-sdk/xml-builder" "3.310.0" - "@smithy/config-resolver" "^2.0.10" - "@smithy/eventstream-serde-browser" "^2.0.9" - "@smithy/eventstream-serde-config-resolver" "^2.0.9" - "@smithy/eventstream-serde-node" "^2.0.9" - "@smithy/fetch-http-handler" "^2.1.5" - "@smithy/hash-blob-browser" "^2.0.9" - "@smithy/hash-node" "^2.0.9" - "@smithy/hash-stream-node" "^2.0.9" - "@smithy/invalid-dependency" "^2.0.9" - "@smithy/md5-js" "^2.0.9" - "@smithy/middleware-content-length" "^2.0.11" - "@smithy/middleware-endpoint" "^2.0.9" - "@smithy/middleware-retry" "^2.0.12" - "@smithy/middleware-serde" "^2.0.9" - "@smithy/middleware-stack" "^2.0.2" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/node-http-handler" "^2.1.5" - "@smithy/protocol-http" "^3.0.5" - "@smithy/smithy-client" "^2.1.6" - "@smithy/types" "^2.3.3" - "@smithy/url-parser" "^2.0.9" - "@smithy/util-base64" "^2.0.0" - "@smithy/util-body-length-browser" "^2.0.0" - "@smithy/util-body-length-node" "^2.1.0" - "@smithy/util-defaults-mode-browser" "^2.0.10" - "@smithy/util-defaults-mode-node" "^2.0.12" - "@smithy/util-retry" "^2.0.2" - "@smithy/util-stream" "^2.0.12" - "@smithy/util-utf8" "^2.0.0" - "@smithy/util-waiter" "^2.0.9" - fast-xml-parser "4.2.5" - tslib "^2.5.0" - -"@aws-sdk/client-sso@3.423.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.423.0.tgz#99db1f73419443cef544892337a1344aba10abc2" - integrity "sha1-mdsfc0GUQ871RIkjN6E0SroQq8I= sha512-znIufHkwhCIePgaYciIs3x/+BpzR57CZzbCKHR9+oOvGyufEPPpUT5bFLvbwTgfiVkTjuk6sG/ES3U5Bc+xtrA==" - dependencies: - "@aws-crypto/sha256-browser" "3.0.0" - "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/middleware-host-header" "3.418.0" - "@aws-sdk/middleware-logger" "3.418.0" - "@aws-sdk/middleware-recursion-detection" "3.418.0" - "@aws-sdk/middleware-user-agent" "3.418.0" - "@aws-sdk/region-config-resolver" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-endpoints" "3.418.0" - "@aws-sdk/util-user-agent-browser" "3.418.0" - "@aws-sdk/util-user-agent-node" "3.418.0" - "@smithy/config-resolver" "^2.0.10" - "@smithy/fetch-http-handler" "^2.1.5" - "@smithy/hash-node" "^2.0.9" - "@smithy/invalid-dependency" "^2.0.9" - "@smithy/middleware-content-length" "^2.0.11" - "@smithy/middleware-endpoint" "^2.0.9" - "@smithy/middleware-retry" "^2.0.12" - "@smithy/middleware-serde" "^2.0.9" - "@smithy/middleware-stack" "^2.0.2" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/node-http-handler" "^2.1.5" - "@smithy/protocol-http" "^3.0.5" - "@smithy/smithy-client" "^2.1.6" - "@smithy/types" "^2.3.3" - "@smithy/url-parser" "^2.0.9" - "@smithy/util-base64" "^2.0.0" - "@smithy/util-body-length-browser" "^2.0.0" - "@smithy/util-body-length-node" "^2.1.0" - "@smithy/util-defaults-mode-browser" "^2.0.10" - "@smithy/util-defaults-mode-node" "^2.0.12" - "@smithy/util-retry" "^2.0.2" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.5.0" - -"@aws-sdk/client-sts@3.423.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.423.0.tgz#530a9cd58baef40cc6bbc6321c6ed93175e0e5b2" - integrity "sha1-Uwqc1Yuu9AzGu8YyHG7ZMXXg5bI= sha512-EcpkKu02QZbRX6dQE0u7a8RgWrn/5riz1qAlKd7rM8FZJpr/D6GGX8ZzWxjgp7pRUgfNvinTmIudDnyQY3v9Mg==" - dependencies: - "@aws-crypto/sha256-browser" "3.0.0" - "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/credential-provider-node" "3.423.0" - "@aws-sdk/middleware-host-header" "3.418.0" - "@aws-sdk/middleware-logger" "3.418.0" - "@aws-sdk/middleware-recursion-detection" "3.418.0" - "@aws-sdk/middleware-sdk-sts" "3.418.0" - "@aws-sdk/middleware-signing" "3.418.0" - "@aws-sdk/middleware-user-agent" "3.418.0" - "@aws-sdk/region-config-resolver" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-endpoints" "3.418.0" - "@aws-sdk/util-user-agent-browser" "3.418.0" - "@aws-sdk/util-user-agent-node" "3.418.0" - "@smithy/config-resolver" "^2.0.10" - "@smithy/fetch-http-handler" "^2.1.5" - "@smithy/hash-node" "^2.0.9" - "@smithy/invalid-dependency" "^2.0.9" - "@smithy/middleware-content-length" "^2.0.11" - "@smithy/middleware-endpoint" "^2.0.9" - "@smithy/middleware-retry" "^2.0.12" - "@smithy/middleware-serde" "^2.0.9" - "@smithy/middleware-stack" "^2.0.2" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/node-http-handler" "^2.1.5" - "@smithy/protocol-http" "^3.0.5" - "@smithy/smithy-client" "^2.1.6" - "@smithy/types" "^2.3.3" - "@smithy/url-parser" "^2.0.9" - "@smithy/util-base64" "^2.0.0" - "@smithy/util-body-length-browser" "^2.0.0" - "@smithy/util-body-length-node" "^2.1.0" - "@smithy/util-defaults-mode-browser" "^2.0.10" - "@smithy/util-defaults-mode-node" "^2.0.12" - "@smithy/util-retry" "^2.0.2" - "@smithy/util-utf8" "^2.0.0" - fast-xml-parser "4.2.5" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-env@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.418.0.tgz#7b14169350d9c14c9f656da06edf46f40a224ed2" - integrity "sha1-exQWk1DZwUyfZW2gbt9G9AoiTtI= sha512-e74sS+x63EZUBO+HaI8zor886YdtmULzwKdctsZp5/37Xho1CVUNtEC+fYa69nigBD9afoiH33I4JggaHgrekQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-ini@3.423.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.423.0.tgz#62690a3c49b0223c3d239c8a3d2f2708e967a767" - integrity "sha1-YmkKPEmwIjw9I5yKPS8nCOlnp2c= sha512-7CsFWz8g7dQmblp57XzzxMirO4ClowGZIOwAheBkmk6q1XHbllcHFnbh2kdPyQQ0+JmjDg6waztIc7dY7Ycfvw==" - dependencies: - "@aws-sdk/credential-provider-env" "3.418.0" - "@aws-sdk/credential-provider-process" "3.418.0" - "@aws-sdk/credential-provider-sso" "3.423.0" - "@aws-sdk/credential-provider-web-identity" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@smithy/credential-provider-imds" "^2.0.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/shared-ini-file-loader" "^2.0.6" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-node@3.423.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.423.0.tgz#80d05ea89b1a4f245786171ae516c331aa315908" - integrity "sha1-gNBeqJsaTyRXhhca5RbDMaoxWQg= sha512-lygbGJJUnDpgo8OEqdoYd51BKkyBVQ1Catiua/m0aHvL+SCmVrHiYPQPawWYGxpH8X3DXdXa0nd0LkEaevrHRg==" - dependencies: - "@aws-sdk/credential-provider-env" "3.418.0" - "@aws-sdk/credential-provider-ini" "3.423.0" - "@aws-sdk/credential-provider-process" "3.418.0" - "@aws-sdk/credential-provider-sso" "3.423.0" - "@aws-sdk/credential-provider-web-identity" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@smithy/credential-provider-imds" "^2.0.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/shared-ini-file-loader" "^2.0.6" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-process@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.418.0.tgz#1cb6d816bd471db3f9724715b007035ef18b5b2b" - integrity "sha1-HLbYFr1HHbP5ckcVsAcDXvGLWys= sha512-xPbdm2WKz1oH6pTkrJoUmr3OLuqvvcPYTQX0IIlc31tmDwDWPQjXGGFD/vwZGIZIkKaFpFxVMgAzfFScxox7dw==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/shared-ini-file-loader" "^2.0.6" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-sso@3.423.0": - version "3.423.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.423.0.tgz#a04f1715e5d9c75370d17ceac645379ca57cbb0b" - integrity "sha1-oE8XFeXZx1Nw0XzqxkU3nKV8uws= sha512-zAH68IjRMmW22USbsCVQ5Q6AHqhmWABwLbZAMocSGMasddTGv/nkA/nUiVCJ/B4LI3P81FoPQVrG5JxNmkNH0w==" - dependencies: - "@aws-sdk/client-sso" "3.423.0" - "@aws-sdk/token-providers" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/shared-ini-file-loader" "^2.0.6" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/credential-provider-web-identity@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.418.0.tgz#c2aed2a79bf193c1fef2b98391aaa9de7336aaaf" - integrity "sha1-wq7Sp5vxk8H+8rmDkaqp3nM2qq8= sha512-do7ang565n9p3dS1JdsQY01rUfRx8vkxQqz5M8OlcEHBNiCdi2PvSjNwcBdrv/FKkyIxZb0TImOfBSt40hVdxQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-bucket-endpoint@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.418.0.tgz#1c330fb4dd583454872db7eba3b6e06c0699d59d" - integrity "sha1-HDMPtN1YNFSHLbfro7bgbAaZ1Z0= sha512-gj/mj1UfbKkGbQ1N4YUvjTTp8BVs5fO1QAL2AjFJ+jfJOToLReX72aNEkm7sPGbHML0TqOY4cQbJuWYy+zdD5g==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-arn-parser" "3.310.0" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - "@smithy/util-config-provider" "^2.0.0" - tslib "^2.5.0" - -"@aws-sdk/middleware-expect-continue@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.418.0.tgz#b621c6a8bc281f23bfd3791eaab25f687946d4a7" - integrity "sha1-tiHGqLwoHyO/03keqrJfaHlG1Kc= sha512-6x4rcIj685EmqDLQkbWoCur3Dg5DRClHMen6nHXmD3CR5Xyt3z1Gk/+jmZICxyJo9c6M4AeZht8o95BopkmYAQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-flexible-checksums@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.418.0.tgz#a79f44739ec918d8947294d0acc52eb7eb358773" - integrity "sha1-p59Ec57JGNiUcpTQrMUut+s1h3M= sha512-3O203dqS2JU5P1TAAbo7p1qplXQh59pevw9nqzPVb3EG8B+mSucVf2kKmF7kGHqKSk+nK/mB/4XGSsZBzGt6Wg==" - dependencies: - "@aws-crypto/crc32" "3.0.0" - "@aws-crypto/crc32c" "3.0.0" - "@aws-sdk/types" "3.418.0" - "@smithy/is-array-buffer" "^2.0.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.5.0" - -"@aws-sdk/middleware-host-header@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.418.0.tgz#35d682e14f36c9d9d7464c7c1dd582bf6611436d" - integrity "sha1-NdaC4U82ydnXRkx8HdWCv2YRQ20= sha512-LrMTdzalkPw/1ujLCKPLwCGvPMCmT4P+vOZQRbSEVZPnlZk+Aj++aL/RaHou0jL4kJH3zl8iQepriBt4a7UvXQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-location-constraint@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.418.0.tgz#e62e213a72ce583ba6135db51dcc60d07825b8ee" - integrity "sha1-5i4hOnLOWDumE121Hcxg0HgluO4= sha512-cc8M3VEaESHJhDsDV8tTpt2QYUprDWhvAVVSlcL43cTdZ54Quc0W+toDiaVOUlwrAZz2Y7g5NDj22ibJGFbOvw==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-logger@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.418.0.tgz#08d7419f4220c36032a070a7dbb8bbf7e744a9ce" - integrity "sha1-CNdBn0Igw2AyoHCn27i79+dEqc4= sha512-StKGmyPVfoO/wdNTtKemYwoJsqIl4l7oqarQY7VSf2Mp3mqaa+njLViHsQbirYpyqpgUEusOnuTlH5utxJ1NsQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-recursion-detection@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.418.0.tgz#2bb80d084f946846ad4907f3d6e0b451787d62b1" - integrity "sha1-K7gNCE+UaEatSQfz1uC0UXh9YrE= sha512-kKFrIQglBLUFPbHSDy1+bbe3Na2Kd70JSUC3QLMbUHmqipXN8KeXRfAj7vTv97zXl0WzG0buV++WcNwOm1rFjg==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-sdk-s3@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.418.0.tgz#b1de52d54e0cbc8d46ce0bc4c6c54b527f409aaf" - integrity "sha1-sd5S1U4MvI1GzgvExsVLUn9Amq8= sha512-rei32LF45SyqL3NlWDjEOfMwAca9A5F4QgUyXJqvASc43oWC1tJnLIhiCxNh8qkWAiRyRzFpcanTeqyaRSsZpA==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-arn-parser" "3.310.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/smithy-client" "^2.1.6" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-sdk-sts@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.418.0.tgz#f167f16050e055282ddd60226a2216c84873d464" - integrity "sha1-8WfxYFDgVSgt3WAiaiIWyEhz1GQ= sha512-cW8ijrCTP+mgihvcq4+TbhAcE/we5lFl4ydRqvTdtcSnYQAVQADg47rnTScQiFsPFEB3NKq7BGeyTJF9MKolPA==" - dependencies: - "@aws-sdk/middleware-signing" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-signing@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.418.0.tgz#c7242b84069067bb671cb4191d412b59713a375e" - integrity "sha1-xyQrhAaQZ7tnHLQZHUErWXE6N14= sha512-onvs5KoYQE8OlOE740RxWBGtsUyVIgAo0CzRKOQO63ZEYqpL1Os+MS1CGzdNhvQnJgJruE1WW+Ix8fjN30zKPA==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/property-provider" "^2.0.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/signature-v4" "^2.0.0" - "@smithy/types" "^2.3.3" - "@smithy/util-middleware" "^2.0.2" - tslib "^2.5.0" - -"@aws-sdk/middleware-ssec@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.418.0.tgz#67b554c4acad81c7aa93421c8fcba8a18e138294" - integrity "sha1-Z7VUxKytgceqk0Icj8uooY4TgpQ= sha512-J7K+5h6aP7IYMlu/NwHEIjb0+WDu1eFvO8TCPo6j1H9xYRi8B/6h+6pa9Rk9IgRUzFnrdlDu9FazG8Tp0KKLyg==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/middleware-user-agent@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.418.0.tgz#37426cf801332165fb170b1fd62dea8bb967a1ef" - integrity "sha1-N0Js+AEzIWX7Fwsf1i3qi7lnoe8= sha512-Jdcztg9Tal9SEAL0dKRrnpKrm6LFlWmAhvuwv0dQ7bNTJxIxyEFbpqdgy7mpQHsLVZgq1Aad/7gT/72c9igyZw==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-endpoints" "3.418.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/region-config-resolver@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.418.0.tgz#53b99e4bd92f3369f51e9a76534b7d884db67526" - integrity "sha1-U7meS9kvM2n1Hpp2U0t9iE22dSY= sha512-lJRZ/9TjZU6yLz+mAwxJkcJZ6BmyYoIJVo1p5+BN//EFdEmC8/c0c9gXMRzfISV/mqWSttdtccpAyN4/goHTYA==" - dependencies: - "@smithy/node-config-provider" "^2.0.12" - "@smithy/types" "^2.3.3" - "@smithy/util-config-provider" "^2.0.0" - "@smithy/util-middleware" "^2.0.2" - tslib "^2.5.0" - -"@aws-sdk/signature-v4-multi-region@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.418.0.tgz#984c8fc948c61a7ad02f1ccc6c2ddecf43a265b1" - integrity "sha1-mEyPyUjGGnrQLxzMbC3ez0OiZbE= sha512-LeVYMZeUQUURFqDf4yZxTEv016g64hi0LqYBjU0mjwd8aPc0k6hckwvshezc80jCNbuLyjNfQclvlg3iFliItQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/signature-v4" "^2.0.0" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/token-providers@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.418.0.tgz#cbfac922df397e72daf6dbdd8c1e9a140df0aa0e" - integrity "sha1-y/rJIt85fnLa9tvdjB6aFA3wqg4= sha512-9P7Q0VN0hEzTngy3Sz5eya2qEOEf0Q8qf1vB3um0gE6ID6EVAdz/nc/DztfN32MFxk8FeVBrCP5vWdoOzmd72g==" - dependencies: - "@aws-crypto/sha256-browser" "3.0.0" - "@aws-crypto/sha256-js" "3.0.0" - "@aws-sdk/middleware-host-header" "3.418.0" - "@aws-sdk/middleware-logger" "3.418.0" - "@aws-sdk/middleware-recursion-detection" "3.418.0" - "@aws-sdk/middleware-user-agent" "3.418.0" - "@aws-sdk/types" "3.418.0" - "@aws-sdk/util-endpoints" "3.418.0" - "@aws-sdk/util-user-agent-browser" "3.418.0" - "@aws-sdk/util-user-agent-node" "3.418.0" - "@smithy/config-resolver" "^2.0.10" - "@smithy/fetch-http-handler" "^2.1.5" - "@smithy/hash-node" "^2.0.9" - "@smithy/invalid-dependency" "^2.0.9" - "@smithy/middleware-content-length" "^2.0.11" - "@smithy/middleware-endpoint" "^2.0.9" - "@smithy/middleware-retry" "^2.0.12" - "@smithy/middleware-serde" "^2.0.9" - "@smithy/middleware-stack" "^2.0.2" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/node-http-handler" "^2.1.5" - "@smithy/property-provider" "^2.0.0" - "@smithy/protocol-http" "^3.0.5" - "@smithy/shared-ini-file-loader" "^2.0.6" - "@smithy/smithy-client" "^2.1.6" - "@smithy/types" "^2.3.3" - "@smithy/url-parser" "^2.0.9" - "@smithy/util-base64" "^2.0.0" - "@smithy/util-body-length-browser" "^2.0.0" - "@smithy/util-body-length-node" "^2.1.0" - "@smithy/util-defaults-mode-browser" "^2.0.10" - "@smithy/util-defaults-mode-node" "^2.0.12" - "@smithy/util-retry" "^2.0.2" - "@smithy/util-utf8" "^2.0.0" - tslib "^2.5.0" - -"@aws-sdk/types@3.418.0", "@aws-sdk/types@^3.222.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.418.0.tgz#c23213110b0c313d5546c810da032a441682f49a" - integrity "sha1-wjITEQsMMT1VRsgQ2gMqRBaC9Jo= sha512-y4PQSH+ulfFLY0+FYkaK4qbIaQI9IJNMO2xsxukW6/aNoApNymN1D2FSi2la8Qbp/iPjNDKsG8suNPm9NtsWXQ==" - dependencies: - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/util-arn-parser@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.310.0.tgz#861ff8810851be52a320ec9e4786f15b5fc74fba" - integrity "sha1-hh/4gQhRvlKjIOyeR4bxW1/HT7o= sha512-jL8509owp/xB9+Or0pvn3Fe+b94qfklc2yPowZZIFAkFcCSIdkIglz18cPDWnYAcy9JGewpMS1COXKIUhZkJsA==" - dependencies: - tslib "^2.5.0" - -"@aws-sdk/util-endpoints@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.418.0.tgz#462c976f054fe260562d4d2844152a04dd883fd7" - integrity "sha1-RiyXbwVP4mBWLU0oRBUqBN2IP9c= sha512-sYSDwRTl7yE7LhHkPzemGzmIXFVHSsi3AQ1KeNEk84eBqxMHHcCc2kqklaBk2roXWe50QDgRMy1ikZUxvtzNHQ==" - dependencies: - "@aws-sdk/types" "3.418.0" - tslib "^2.5.0" - -"@aws-sdk/util-locate-window@^3.0.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz#b071baf050301adee89051032bd4139bba32cc40" - integrity "sha1-sHG68FAwGt7okFEDK9QTm7oyzEA= sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==" - dependencies: - tslib "^2.5.0" - -"@aws-sdk/util-user-agent-browser@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.418.0.tgz#dc76b8e7e5cae3f827d68cd4a3ee30c0d475a39c" - integrity "sha1-3Ha45+XK4/gn1ozUo+4wwNR1o5w= sha512-c4p4mc0VV/jIeNH0lsXzhJ1MpWRLuboGtNEpqE4s1Vl9ck2amv9VdUUZUmHbg+bVxlMgRQ4nmiovA4qIrqGuyg==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/types" "^2.3.3" - bowser "^2.11.0" - tslib "^2.5.0" - -"@aws-sdk/util-user-agent-node@3.418.0": - version "3.418.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.418.0.tgz#7d5a1c82ce3265ff0f70b13d58d08593113ab99a" - integrity "sha1-fVocgs4yZf8PcLE9WNCFkxE6uZo= sha512-BXMskXFtg+dmzSCgmnWOffokxIbPr1lFqa1D9kvM3l3IFRiFGx2IyDg+8MAhq11aPDLvoa/BDuQ0Yqma5izOhg==" - dependencies: - "@aws-sdk/types" "3.418.0" - "@smithy/node-config-provider" "^2.0.12" - "@smithy/types" "^2.3.3" - tslib "^2.5.0" - -"@aws-sdk/util-utf8-browser@^3.0.0": - version "3.259.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz#3275a6f5eb334f96ca76635b961d3c50259fd9ff" - integrity "sha1-MnWm9eszT5bKdmNblh08UCWf2f8= sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==" - dependencies: - tslib "^2.3.1" - -"@aws-sdk/xml-builder@3.310.0": - version "3.310.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.310.0.tgz#f0236f2103b438d16117e0939a6305ad69b7ff76" - integrity "sha1-8CNvIQO0ONFhF+CTmmMFrWm3/3Y= sha512-TqELu4mOuSIKQCqj63fGVs86Yh+vBx5nHRpWKNUNhB2nPTpfbziTs5c1X358be3peVWA4wPxW7Nt53KIg1tnNw==" - dependencies: - tslib "^2.5.0" - "@azure/abort-controller@^1.0.0", "@azure/abort-controller@^1.0.4": version "1.1.0" resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" @@ -774,23 +218,23 @@ tslib "^2.2.0" "@azure/msal-browser@^3.11.1": - version "3.27.0" - resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.27.0.tgz#b6f02f73c8e102d3f115009b4677539fb173fe2b" - integrity sha512-+b4ZKSD8+vslCtVRVetkegEhOFMLP3rxDWJY212ct+2r6jVg6OSQKc1Qz3kCoXo0FgwaXkb+76TMZfpHp8QtgA== + version "3.24.0" + resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.24.0.tgz#3208047672d0b0c943b0bef5f995d510d6582ae4" + integrity sha512-JGNV9hTYAa7lsum9IMIibn2kKczAojNihGo1hi7pG0kNrcKej530Fl6jxwM05A44/6I079CSn6WxYxbVhKUmWg== dependencies: - "@azure/msal-common" "14.16.0" + "@azure/msal-common" "14.15.0" -"@azure/msal-common@14.16.0": - version "14.16.0" - resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.16.0.tgz#f3470fcaec788dbe50859952cd499340bda23d7a" - integrity sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA== +"@azure/msal-common@14.15.0": + version "14.15.0" + resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.15.0.tgz#0e27ac0bb88fe100f4f8d1605b64d5c268636a55" + integrity sha512-ImAQHxmpMneJ/4S8BRFhjt1MZ3bppmpRPYYNyzeQPeFN288YKbb8TmmISQEbtfkQ1BPASvYZU5doIZOPBAqENQ== "@azure/msal-node@^2.9.2": - version "2.16.1" - resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.16.1.tgz#89828832e8e6c8a88cecc4ef6d8d4e4352116b77" - integrity sha512-1NEFpTmMMT2A7RnZuvRl/hUmJU+GLPjh+ShyIqPktG2PvSd2yvPnzGd/BxIBAAvJG5nr9lH4oYcQXepDbaE7fg== + version "2.14.0" + resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.14.0.tgz#7881895d41b03d8b9b38a29550ba3bbb15f73b3c" + integrity sha512-rrfzIpG3Q1rHjVYZmHAEDidWAZZ2cgkxlIcMQ8dHebRISaZ2KCV33Q8Vs+uaV6lxweROabNxKFlR2lIKagZqYg== dependencies: - "@azure/msal-common" "14.16.0" + "@azure/msal-common" "14.15.0" jsonwebtoken "^9.0.0" uuid "^8.3.0" @@ -2002,14 +1446,13 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@3.2.7": +"@budibase/backend-core@2.33.2": version "0.0.0" dependencies: "@budibase/nano" "10.1.5" "@budibase/pouchdb-replication-stream" "1.2.11" "@budibase/shared-core" "0.0.0" "@budibase/types" "0.0.0" - "@types/chance" "1.1.3" aws-cloudfront-sign "3.0.2" aws-sdk "2.1030.0" bcrypt "5.1.0" @@ -2083,16 +1526,16 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@npm:@budibase/pro@latest": - version "3.2.7" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.7.tgz#4dfc48f3e2ba3a3b235872e54c3de4de54ea7941" - integrity sha512-GRRaf1qSqQfoodjvKjBDvNOVHZrcSXF7so6Y9Xv/MiRTjDES5nmhIT5rL/PQ1+Mb+sPytYmMaJ2mlTtwqSQZgQ== +"@budibase/pro@0.0.0", "@budibase/pro@npm:@budibase/pro@latest": + version "2.33.2" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.33.2.tgz#5c2012f7b2bf0fd871cda1ad37ad7a0442c84658" + integrity sha512-lBB6Wfp6OIOHRlGq82WS9KxvEXRs/P2QlwJT0Aj9PhmkQFsnXm2r8d18f0xTGvcflD+iR7XGP/k56JlCanmhQg== dependencies: "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "3.2.7" - "@budibase/shared-core" "3.2.7" - "@budibase/string-templates" "3.2.7" - "@budibase/types" "3.2.7" + "@budibase/backend-core" "2.33.2" + "@budibase/shared-core" "2.33.2" + "@budibase/string-templates" "2.33.2" + "@budibase/types" "2.33.2" "@koa/router" "8.0.8" bull "4.10.1" dd-trace "5.2.0" @@ -2105,13 +1548,13 @@ scim-patch "^0.8.1" scim2-parse-filter "^0.2.8" -"@budibase/shared-core@3.2.7": +"@budibase/shared-core@2.33.2": version "0.0.0" dependencies: "@budibase/types" "0.0.0" cron-validate "1.4.5" -"@budibase/string-templates@3.2.7": +"@budibase/string-templates@2.33.2": version "0.0.0" dependencies: "@budibase/handlebars-helpers" "^0.13.2" @@ -2119,7 +1562,7 @@ handlebars "^4.7.8" lodash.clonedeep "^4.5.0" -"@budibase/types@3.2.7": +"@budibase/types@2.33.2": version "0.0.0" dependencies: scim-patch "^0.8.1" @@ -2536,48 +1979,6 @@ google-gax "^4.3.3" protobufjs "^7.2.6" -"@google-cloud/paginator@^3.0.7": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-3.0.7.tgz#fb6f8e24ec841f99defaebf62c75c2e744dd419b" - integrity "sha1-+2+OJOyEH5ne+uv2LHXC50TdQZs= sha512-jJNutk0arIQhmpUUQJPJErsojqo834KcyB6X7a1mxuic8i1tKXxde8E69IZxNZawRIlZdIK2QY4WALvlK5MzYQ==" - dependencies: - arrify "^2.0.0" - extend "^3.0.2" - -"@google-cloud/projectify@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-3.0.0.tgz#302b25f55f674854dce65c2532d98919b118a408" - integrity "sha1-MCsl9V9nSFTc5lwlMtmJGbEYpAg= sha512-HRkZsNmjScY6Li8/kb70wjGlDDyLkVk3KvoEo9uIoxSjYLJasGiCch9+PqRVDOCGUFvEIqyogl+BeqILL4OJHA==" - -"@google-cloud/promisify@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-3.0.1.tgz#8d724fb280f47d1ff99953aee0c1669b25238c2e" - integrity "sha1-jXJPsoD0fR/5mVOu4MFmmyUjjC4= sha512-z1CjRjtQyBOYL+5Qr9DdYIfrdLBe746jRTYfaYU6MeXkqp7UfYs/jX16lFFVzZ7PGEJvqZNqYUEtb1mvDww4pA==" - -"@google-cloud/storage@^6.9.3": - version "6.12.0" - resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-6.12.0.tgz#a5d3093cc075252dca5bd19a3cfda406ad3a9de1" - integrity "sha1-pdMJPMB1JS3KW9GaPP2kBq06neE= sha512-78nNAY7iiZ4O/BouWMWTD/oSF2YtYgYB3GZirn0To6eBOugjXVoK+GXgUXOl+HlqbAOyHxAVXOlsj3snfbQ1dw==" - dependencies: - "@google-cloud/paginator" "^3.0.7" - "@google-cloud/projectify" "^3.0.0" - "@google-cloud/promisify" "^3.0.0" - abort-controller "^3.0.0" - async-retry "^1.3.3" - compressible "^2.0.12" - duplexify "^4.0.0" - ent "^2.2.0" - extend "^3.0.2" - fast-xml-parser "^4.2.2" - gaxios "^5.0.0" - google-auth-library "^8.0.1" - mime "^3.0.0" - mime-types "^2.0.8" - p-limit "^3.0.1" - retry-request "^5.0.0" - teeny-request "^8.0.0" - uuid "^8.0.0" - "@grpc/grpc-js@^1.10.9": version "1.10.10" resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.10.10.tgz#476d315feeb9dbb0f2d6560008c92688c30f13e0" @@ -3226,6 +2627,25 @@ resolved "https://registry.yarnpkg.com/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" integrity sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg== +"@jsep-plugin/assignment@^1.2.1": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@jsep-plugin/assignment/-/assignment-1.3.0.tgz#fcfc5417a04933f7ceee786e8ab498aa3ce2b242" + integrity sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ== + +"@jsep-plugin/regex@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" + integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== + +"@koa/router@13.1.0", "@koa/router@^13.1.0": + version "13.1.0" + resolved "https://registry.yarnpkg.com/@koa/router/-/router-13.1.0.tgz#43f4c554444ea4f4a148a5735a9525c6d16fd1b5" + integrity sha512-mNVu1nvkpSd8Q8gMebGbCkDWJ51ODetrFvLKYusej+V0ByD4btqHYnPIzTBLXnQMVUlm/oxVwqmWBY3zQfZilw== + dependencies: + http-errors "^2.0.0" + koa-compose "^4.1.0" + path-to-regexp "^6.3.0" + "@koa/router@8.0.8": version "8.0.8" resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.8.tgz#95f32d11373d03d89dcb63fabe9ac6f471095236" @@ -3702,9 +3122,9 @@ integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== "@opentelemetry/api@^1.0.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" - integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== + version "1.7.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.7.0.tgz#b139c81999c23e3c8d3c0a7234480e945920fc40" + integrity sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw== "@opentelemetry/core@^1.14.0": version "1.19.0" @@ -3825,7 +3245,7 @@ dependencies: slash "^4.0.0" -"@rollup/plugin-commonjs@16.0.0", "@rollup/plugin-commonjs@^16.0.0": +"@rollup/plugin-commonjs@^16.0.0": version "16.0.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz#169004d56cd0f0a1d0f35915d31a036b0efe281f" integrity sha512-LuNyypCP3msCGVQJ7ki8PqYdpjfEkE/xtFa5DqlF+7IBD0JsfMZ87C58heSwIMint58sAUZbt3ITqOmdQv/dXw== @@ -3911,7 +3331,7 @@ is-module "^1.0.0" resolve "^1.22.1" -"@rollup/plugin-replace@^5.0.2", "@rollup/plugin-replace@^5.0.3": +"@rollup/plugin-replace@^5.0.3": version "5.0.7" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-5.0.7.tgz#150c9ee9db8031d9e4580a61a0edeaaed3d37687" integrity sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ== @@ -4493,18 +3913,7 @@ dependencies: defer-to-connect "^1.0.1" -"@techpass/passport-openidconnect@0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-0.3.3.tgz#6c01c78bd8da0ca8917378dfbe18024702620352" - integrity sha512-i2X/CofjnGBqpTmw6b+Ex3Co/NrR2xjnIHvnOJk62XIlJJHNSTwmhJ1PkXoA5RGKlxZWchADFGjLTJnebvRj7A== - dependencies: - base64url "^3.0.1" - oauth "^0.9.15" - passport-strategy "^1.0.0" - request "^2.88.0" - webfinger "^0.4.2" - -"@techteamer/ocsp@1.0.0": +"@techpass/passport-openidconnect@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-1.0.0.tgz#e79a70b2ccd54d04122b774a33469cb52858a6bd" integrity sha512-jcTny/3ZUlp1wN9xrUPjPQpVOfMtZ9ehSF/1T6AXse/FvgiWXDIVZUPW/QcoDsXXqYeI6huWPMGM4AwxtMe8bA== @@ -4956,10 +4365,10 @@ "@types/koa-compose" "*" "@types/node" "*" -"@types/koa__router@8.0.8": - version "8.0.8" - resolved "https://registry.yarnpkg.com/@types/koa__router/-/koa__router-8.0.8.tgz#b1e0e9a512498777d3366bbdf0e853df27ec831c" - integrity sha512-9pGCaDtzCsj4HJ8HmGuqzk8+s57sPj4njWd08GG5o92n5Xp9io2snc40CPpXFhoKcZ8OKhuu6ht4gNou9e1C2w== +"@types/koa__router@12.0.4": + version "12.0.4" + resolved "https://registry.yarnpkg.com/@types/koa__router/-/koa__router-12.0.4.tgz#a1f9afec9dc7e7d9fa1252d1938c44b403e19a28" + integrity sha512-Y7YBbSmfXZpa/m5UGGzb7XadJIRBRnwNY9cdAojZGp65Cpe5MAP3mOZE7e3bImt8dfKS4UFcR16SLH8L/z7PBw== dependencies: "@types/koa" "*" @@ -5455,18 +4864,6 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397" integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw== -"@types/triple-beam@^1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.2.tgz#38ecb64f01aa0d02b7c8f4222d7c38af6316fef8" - integrity sha512-txGIh+0eDFzKGC25zORnswy+br1Ha7hj5cMVwKIU7+s0U2AxxJru/jZSMU6OC9MJWP6+pc/hc6ZjyZShpsyY2g== - -"@types/tunnel@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.3.tgz#f109e730b072b3136347561fc558c9358bb8c6e9" - integrity sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA== - dependencies: - "@types/node" "*" - "@types/uuid@8.3.4": version "8.3.4" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" @@ -5916,6 +5313,11 @@ acorn-import-assertions@^1.9.0: resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -6405,14 +5807,7 @@ async-lock@^1.4.1: resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.4.1.tgz#56b8718915a9b68b10fce2f2a9a3dddf765ef53f" integrity sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ== -async-retry@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" - integrity "sha1-Dn82wE2EeOeli9vtgM7fl3eF8oA= sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==" - dependencies: - retry "0.13.1" - -async@^3.2.1, async@^3.2.3, async@^3.2.4: +async@^3.2.3, async@^3.2.4: version "3.2.5" resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg== @@ -6697,16 +6092,6 @@ before-after-hook@^2.2.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== -big-integer@^1.6.43: - version "1.6.51" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686" - integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg== - -bignumber.js@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.4.0.tgz#838a992da9f9d737e0f4b2db0be62bb09dd0c5e8" - integrity sha512-uw4ra6Cv483Op/ebM0GBKKfxZlSmn6NgFRby5L3yGTlunLj53KQgndDlqy2WVFOwgvurocApYkSud0aO+mvrpQ== - bignumber.js@^9.0.0: version "9.1.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" @@ -6717,11 +6102,6 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -binascii@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/binascii/-/binascii-0.0.2.tgz#a7f8a8801dbccf8b1756b743daa0fee9e2d9e0ee" - integrity sha512-rA2CrUl1+6yKrn+XgLs8Hdy18OER1UW146nM+ixzhQXDY+Bd3ySkyIJGwF2a4I45JwbvF1mDL/nWkqBwpOcdBA== - bl@^1.0.0: version "1.2.3" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" @@ -6786,11 +6166,6 @@ boolean@^3.0.1: resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b" integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw== -bowser@^2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" - integrity "sha1-XKPDV1enqldxUAxwpzqfke9CCo8= sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" - boxen@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" @@ -7584,11 +6959,6 @@ commander@^2.16.0, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, comm resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== -commander@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" - integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== - commander@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" @@ -8339,7 +7709,12 @@ dayjs@^1.10.8: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -dc-polyfill@^0.1.2, dc-polyfill@^0.1.4: +dc-polyfill@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.3.tgz#fe9eefc86813439dd46d6f9ad9582ec079c39720" + integrity sha512-Wyk5n/5KUj3GfVKV2jtDbtChC/Ff9fjKsBcg4ZtYW1yQe3DXNHcGURvmoxhqQdfOQ9TwyMjnfyv1lyYcOkFkFA== + +dc-polyfill@^0.1.4: version "0.1.6" resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== @@ -8381,6 +7756,43 @@ dd-trace@5.2.0: semver "^7.5.4" tlhunter-sorted-set "^0.1.0" +dd-trace@5.23.0: + version "5.23.0" + resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.23.0.tgz#a0c11863406de440a6675648caf06e1d07d67ba8" + integrity sha512-nLvwSGpTMIk6S3sMSge6yFqqgqI573VgZc8MF31vl6K0ouJoE7OkVx9cmSVjS4CbSi525tcKq9z7tApsNLpVLQ== + dependencies: + "@datadog/native-appsec" "8.1.1" + "@datadog/native-iast-rewriter" "2.4.1" + "@datadog/native-iast-taint-tracking" "3.1.0" + "@datadog/native-metrics" "^2.0.0" + "@datadog/pprof" "5.3.0" + "@datadog/sketches-js" "^2.1.0" + "@opentelemetry/api" ">=1.0.0 <1.9.0" + "@opentelemetry/core" "^1.14.0" + crypto-randomuuid "^1.0.0" + dc-polyfill "^0.1.4" + ignore "^5.2.4" + import-in-the-middle "1.11.2" + int64-buffer "^0.1.9" + istanbul-lib-coverage "3.2.0" + jest-docblock "^29.7.0" + jsonpath-plus "^9.0.0" + koalas "^1.0.2" + limiter "1.1.5" + lodash.sortby "^4.7.0" + lru-cache "^7.14.0" + module-details-from-path "^1.0.3" + msgpack-lite "^0.1.26" + opentracing ">=0.12.1" + path-to-regexp "^0.1.10" + pprof-format "^2.1.0" + protobufjs "^7.2.5" + retry "^0.13.1" + rfdc "^1.3.1" + semver "^7.5.4" + shell-quote "^1.8.1" + tlhunter-sorted-set "^0.1.0" + debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: version "4.3.6" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" @@ -9993,7 +9405,7 @@ fast-url-parser@^1.1.3: dependencies: punycode "^1.3.2" -fast-xml-parser@4.2.5, fast-xml-parser@4.4.1, fast-xml-parser@^4.2.2, fast-xml-parser@^4.2.5: +fast-xml-parser@4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== @@ -11233,15 +10645,6 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -11275,6 +10678,11 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +husky@^9.1.4: + version "9.1.7" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" + integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== + ical-generator@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ical-generator/-/ical-generator-4.1.0.tgz#2a336c951864c5583a2aa715d16f2edcdfd2d90b" @@ -11391,7 +10799,7 @@ import-from@^3.0.0: dependencies: resolve-from "^5.0.0" -import-in-the-middle@1.11.2, import-in-the-middle@^1.7.3: +import-in-the-middle@1.11.2: version "1.11.2" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz#dd848e72b63ca6cd7c34df8b8d97fc9baee6174f" integrity sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA== @@ -11401,6 +10809,16 @@ import-in-the-middle@1.11.2, import-in-the-middle@^1.7.3: cjs-module-lexer "^1.2.2" module-details-from-path "^1.0.3" +import-in-the-middle@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.7.3.tgz#ffa784cdd57a47d2b68d2e7dd33070ff06baee43" + integrity sha512-R2I11NRi0lI3jD2+qjqyVlVEahsejw7LDnYEbGb47QEFjczE3bZYsmWheCTQA+LFs2DzOQxR7Pms7naHW1V4bQ== + dependencies: + acorn "^8.8.2" + acorn-import-assertions "^1.9.0" + cjs-module-lexer "^1.2.2" + module-details-from-path "^1.0.3" + import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" @@ -11606,9 +11024,9 @@ ip@^2.0.0: integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== ipaddr.js@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" - integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== + version "2.1.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" + integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== is-arguments@^1.1.1: version "1.1.1" @@ -12843,7 +12261,7 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: +json-stringify-safe@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== @@ -13485,6 +12903,15 @@ leveldown@5.6.0, leveldown@^5.4.0: napi-macros "~2.0.0" node-gyp-build "~4.1.0" +leveldown@6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/leveldown/-/leveldown-6.1.1.tgz#0f0e480fa88fd807abf94c33cb7e40966ea4b5ce" + integrity sha512-88c+E+Eizn4CkQOBHwqlCJaTNEjGpaEIikn1S+cINc5E9HEvJ77bqY4JY/HxT5u0caWqsc3P3DcFIKBI1vHt+A== + dependencies: + abstract-leveldown "^7.2.0" + napi-macros "~2.0.0" + node-gyp-build "^4.3.0" + levelup@4.4.0, levelup@^4.3.2: version "4.4.0" resolved "https://registry.yarnpkg.com/levelup/-/levelup-4.4.0.tgz#f89da3a228c38deb49c48f88a70fb71f01cafed6" @@ -13814,6 +13241,11 @@ lookpath@1.1.0: resolved "https://registry.yarnpkg.com/lookpath/-/lookpath-1.1.0.tgz#932d68371a2f0b4a5644f03d6a2b4728edba96d2" integrity sha512-B9NM7XpVfkyWqfOBI/UW0kVhGw7pJztsduch+1wkbYDi90mYK6/InFul3lG0hYko/VEcVMARVBJ5daFRc5aKCw== +lossless-json@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lossless-json/-/lossless-json-4.0.2.tgz#f00c52815805d1421930a87e2670e27350958a3f" + integrity sha512-+z0EaLi2UcWi8MZRxA5iTb6m4Ys4E80uftGY+yG5KNFJb5EceQXOhdW/pWJZ8m97s26u7yZZAYMcKWNztSZssA== + loupe@^2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" @@ -14451,18 +13883,6 @@ module-lookup-amd@^7.0.1: requirejs "^2.3.5" requirejs-config-file "^4.0.0" -moment-timezone@^0.5.15: - version "0.5.41" - resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.41.tgz#a7ad3285fd24aaf5f93b8119a9d749c8039c64c5" - integrity sha512-e0jGNZDOHfBXJGz8vR/sIMXvBIGJJcqFjmlg9lmE+5KX1U7/RZNMswfD8nKnNCnQdKTIj50IaRKwl1fvMLyyRg== - dependencies: - moment "^2.29.4" - -moment@^2.29.4: - version "2.29.4" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108" - integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w== - mongodb-connection-string-url@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz#b4f87f92fd8593f3b9365f592515a06d304a1e9c" @@ -14715,11 +14135,6 @@ node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-f dependencies: whatwg-url "^5.0.0" -node-forge@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== - node-gyp-build-optional-packages@5.0.7: version "5.0.7" resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz#5d2632bbde0ab2f6e22f1bbac2199b07244ae0b3" @@ -14736,9 +14151,9 @@ node-gyp-build@^4.3.0, node-gyp-build@^4.5.0: integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== node-gyp-build@^4.8.0, node-gyp-build@^4.8.2: - version "4.8.2" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.2.tgz#4f802b71c1ab2ca16af830e6c1ea7dd1ad9496fa" - integrity sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw== + version "4.8.4" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" + integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== node-gyp-build@~4.1.0: version "4.1.1" @@ -15834,18 +15249,28 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-to-regexp@1.x: - version "1.9.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" - integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== + version "1.8.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== dependencies: isarray "0.0.1" -path-to-regexp@^0.1.10, path-to-regexp@^0.1.2: +path-to-regexp@^0.1.10: version "0.1.11" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.11.tgz#a527e662c89efc4646dbfa8100bf3e847e495761" integrity sha512-c0t+KCuUkO/YDLPG4WWzEwx3J5F/GHXsD1h/SNZfySqAIKe/BaP95x8fWtOfRJokpS5yYHRJjMtYlXD8jxnpbw== -path-to-regexp@^6.1.0, path-to-regexp@^6.3.0: +path-to-regexp@^0.1.2: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +path-to-regexp@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5" + integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== + +path-to-regexp@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== @@ -15963,11 +15388,6 @@ pgpass@1.x: dependencies: split2 "^4.1.0" -phin@^2.9.1: - version "2.9.3" - resolved "https://registry.yarnpkg.com/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c" - integrity sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA== - picocolors@^1.0.0, picocolors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" @@ -16746,7 +16166,12 @@ pouchdb@9.0.0: uuid "8.3.2" vuvuzela "1.0.3" -pprof-format@^2.0.7, pprof-format@^2.1.0: +pprof-format@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.0.7.tgz#526e4361f8b37d16b2ec4bb0696b5292de5046a4" + integrity sha512-1qWaGAzwMpaXJP9opRa23nPnt2Egi7RMNoNBptEE/XwHbcn4fC2b/4U4bKc5arkGkIh2ZabpF2bEb+c5GNHEKA== + +pprof-format@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.1.0.tgz#acc8d7773bcf4faf0a3d3df11bceefba7ac06664" integrity sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw== @@ -17608,14 +17033,6 @@ restore-cursor@^3.1.0: onetime "^5.1.0" signal-exit "^3.0.2" -retry-request@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-5.0.2.tgz#143d85f90c755af407fcc46b7166a4ba520e44da" - integrity sha512-wfI3pk7EE80lCIXprqh7ym48IHYdwmAAzESdbU8Q9l7pnRCk9LEhpbOTNKjz6FARLm/Bl5m+4F0ABxOkYUujSQ== - dependencies: - debug "^4.1.1" - extend "^3.0.2" - retry-request@^7.0.0: version "7.0.2" resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-7.0.2.tgz#60bf48cfb424ec01b03fca6665dee91d06dd95f3" @@ -17625,11 +17042,6 @@ retry-request@^7.0.0: extend "^3.0.2" teeny-request "^9.0.0" -retry@0.13.1, retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity "sha1-GFsVh6z2eRnWOzVzSeA1N7JIRlg= sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" - retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -18538,11 +17950,6 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== - stack-utils@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" @@ -18639,7 +18046,16 @@ string-range@~1.2, string-range@~1.2.1: resolved "https://registry.yarnpkg.com/string-range/-/string-range-1.2.2.tgz#a893ed347e72299bc83befbbf2a692a8d239d5dd" integrity sha512-tYft6IFi8SjplJpxCUxyqisD3b+R2CSkomrtJYCkvuf1KuCAWgz7YXt4O0jip7efpfCemwHEzTEAO8EuOYgh3w== -"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18722,7 +18138,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18736,6 +18152,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -18816,7 +18239,7 @@ striptags@^3.1.1: strnum@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" - integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + integrity "sha1-XE6Cn+Fa1P8NIMPbWsl7c8mwcts= sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" strong-log-transformer@2.1.0, strong-log-transformer@^2.1.0: version "2.1.0" @@ -19326,11 +18749,6 @@ timekeeper@2.2.0: resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.2.0.tgz#9645731fce9e3280a18614a57a9d1b72af3ca368" integrity sha512-W3AmPTJWZkRwu+iSNxPIsLZ2ByADsOLbbLxe46UJyWj3mlYLlwucKiq+/dPm0l9wTzqoF3/2PH0AGFCebjq23A== -timekeeper@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.3.1.tgz#2deb6e0b95d93625fda84c18d47f84a99e4eba01" - integrity sha512-LeQRS7/4JcC0PgdSFnfUiStQEdiuySlCj/5SJ18D+T1n9BoY7PxKFfCwLulpHXoLUFr67HxBddQdEX47lDGx1g== - tiny-glob@^0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2" @@ -19480,9 +18898,9 @@ tr46@~0.0.3: integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== tree-sitter-bash@^0.23.1: - version "0.23.2" - resolved "https://registry.yarnpkg.com/tree-sitter-bash/-/tree-sitter-bash-0.23.2.tgz#73286bca0ead777cd42b7d693ca7e1d3f8f7f411" - integrity sha512-pTe5u2c41joNINYWrp3ZmFJX9cqPF4og1k4JtKoG22377BA7SmD2THfwj1wF2n0tHAgYLOzHZ9m8nUjhEwX5Jw== + version "0.23.3" + resolved "https://registry.yarnpkg.com/tree-sitter-bash/-/tree-sitter-bash-0.23.3.tgz#c5f49f7ae70d719fe08af96059ccb83383eb3fc2" + integrity sha512-36cg/GQ2YmIbeiBeqeuh4fBJ6i4kgVouDaqTxqih5ysPag+zHufyIaxMOFeM8CeplwAK/Luj1o5XHqgdAfoCZg== dependencies: node-addon-api "^8.2.1" node-gyp-build "^4.8.2" @@ -19569,7 +18987,7 @@ tsconfig-paths@^3.10.1, tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tsconfig-paths@^4.1.2, tsconfig-paths@^4.2.0: +tsconfig-paths@^4.1.2: version "4.2.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== @@ -20437,32 +19855,6 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -winston-transport@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" - integrity sha512-YpZzcUzBedhlTAfJg6vJDlyEai/IFMIVcaEZZyl3UXIl4gmqRpU7AE89AHLkbzLUsv0NVmw7ts+iztqKxxPW1Q== - dependencies: - logform "^2.3.2" - readable-stream "^3.6.0" - triple-beam "^1.3.0" - -winston@^3.1.0: - version "3.8.2" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.8.2.tgz#56e16b34022eb4cff2638196d9646d7430fdad50" - integrity sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew== - dependencies: - "@colors/colors" "1.5.0" - "@dabh/diagnostics" "^2.0.2" - async "^3.2.3" - is-stream "^2.0.0" - logform "^2.4.0" - one-time "^1.0.0" - readable-stream "^3.4.0" - safe-stable-stringify "^2.3.1" - stack-trace "0.0.x" - triple-beam "^1.3.0" - winston-transport "^4.5.0" - word-wrap@~1.2.3: version "1.2.5" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" @@ -20480,7 +19872,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -20498,6 +19890,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From db5a29d74d97486b20928524179540c6fae1828b Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 17:54:17 +0000 Subject: [PATCH 18/40] remove top level deps --- package.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/package.json b/package.json index 0f1045c81d..ab3f4de455 100644 --- a/package.json +++ b/package.json @@ -122,9 +122,5 @@ }, "engines": { "node": ">=20.0.0 <21.0.0" - }, - "dependencies": { - "@azure/identity": "4.2.1", - "xml2js": "0.5.0" } } From 0ad7548e398e16dcecd921c42964a04d8e2a98a7 Mon Sep 17 00:00:00 2001 From: Adria Navarro Date: Tue, 19 Nov 2024 18:54:31 +0100 Subject: [PATCH 19/40] Dedup --- yarn.lock | 89 ++++++------------------------------------------------- 1 file changed, 9 insertions(+), 80 deletions(-) diff --git a/yarn.lock b/yarn.lock index ed39c04b94..bfd14f26fd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3116,16 +3116,11 @@ dependencies: "@octokit/openapi-types" "^18.0.0" -"@opentelemetry/api@>=1.0.0 <1.9.0": +"@opentelemetry/api@>=1.0.0 <1.9.0", "@opentelemetry/api@^1.0.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== -"@opentelemetry/api@^1.0.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.7.0.tgz#b139c81999c23e3c8d3c0a7234480e945920fc40" - integrity sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw== - "@opentelemetry/core@^1.14.0": version "1.19.0" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.19.0.tgz#6563bb65465bf232d8435553b9a122d9351c0fbb" @@ -4626,7 +4621,7 @@ "@types/pouchdb-core" "*" "@types/pouchdb-find" "*" -"@types/pouchdb@6.4.2": +"@types/pouchdb@6.4.2", "@types/pouchdb@^6.4.0": version "6.4.2" resolved "https://registry.yarnpkg.com/@types/pouchdb/-/pouchdb-6.4.2.tgz#54777533d86f4abd1a3989b272e085323623bbe1" integrity sha512-YsI47rASdtzR+3V3JE2UKY58snhm0AglHBpyckQBkRYoCbTvGagXHtV0x5n8nzN04jQmvTG+Sm85cIzKT3KXBA== @@ -4647,27 +4642,6 @@ "@types/pouchdb-node" "*" "@types/pouchdb-replication" "*" -"@types/pouchdb@^6.4.0": - version "6.4.0" - resolved "https://registry.yarnpkg.com/@types/pouchdb/-/pouchdb-6.4.0.tgz#f9c41ca64b23029f9bf2eb4bf6956e6431cb79f8" - integrity sha512-eGCpX+NXhd5VLJuJMzwe3L79fa9+IDTrAG3CPaf4s/31PD56hOrhDJTSmRELSXuiqXr6+OHzzP0PldSaWsFt7w== - dependencies: - "@types/pouchdb-adapter-cordova-sqlite" "*" - "@types/pouchdb-adapter-fruitdown" "*" - "@types/pouchdb-adapter-http" "*" - "@types/pouchdb-adapter-idb" "*" - "@types/pouchdb-adapter-leveldb" "*" - "@types/pouchdb-adapter-localstorage" "*" - "@types/pouchdb-adapter-memory" "*" - "@types/pouchdb-adapter-node-websql" "*" - "@types/pouchdb-adapter-websql" "*" - "@types/pouchdb-browser" "*" - "@types/pouchdb-core" "*" - "@types/pouchdb-http" "*" - "@types/pouchdb-mapreduce" "*" - "@types/pouchdb-node" "*" - "@types/pouchdb-replication" "*" - "@types/proper-lockfile@^4.1.4": version "4.1.4" resolved "https://registry.yarnpkg.com/@types/proper-lockfile/-/proper-lockfile-4.1.4.tgz#cd9fab92bdb04730c1ada542c356f03620f84008" @@ -5308,11 +5282,6 @@ acorn-globals@^7.0.0: acorn "^8.1.0" acorn-walk "^8.0.2" -acorn-import-assertions@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== - acorn-import-attributes@^1.9.5: version "1.9.5" resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" @@ -7709,12 +7678,7 @@ dayjs@^1.10.8: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -dc-polyfill@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.3.tgz#fe9eefc86813439dd46d6f9ad9582ec079c39720" - integrity sha512-Wyk5n/5KUj3GfVKV2jtDbtChC/Ff9fjKsBcg4ZtYW1yQe3DXNHcGURvmoxhqQdfOQ9TwyMjnfyv1lyYcOkFkFA== - -dc-polyfill@^0.1.4: +dc-polyfill@^0.1.2, dc-polyfill@^0.1.4: version "0.1.6" resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== @@ -10799,7 +10763,7 @@ import-from@^3.0.0: dependencies: resolve-from "^5.0.0" -import-in-the-middle@1.11.2: +import-in-the-middle@1.11.2, import-in-the-middle@^1.7.3: version "1.11.2" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz#dd848e72b63ca6cd7c34df8b8d97fc9baee6174f" integrity sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA== @@ -10809,16 +10773,6 @@ import-in-the-middle@1.11.2: cjs-module-lexer "^1.2.2" module-details-from-path "^1.0.3" -import-in-the-middle@^1.7.3: - version "1.7.3" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.7.3.tgz#ffa784cdd57a47d2b68d2e7dd33070ff06baee43" - integrity sha512-R2I11NRi0lI3jD2+qjqyVlVEahsejw7LDnYEbGb47QEFjczE3bZYsmWheCTQA+LFs2DzOQxR7Pms7naHW1V4bQ== - dependencies: - acorn "^8.8.2" - acorn-import-assertions "^1.9.0" - cjs-module-lexer "^1.2.2" - module-details-from-path "^1.0.3" - import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" @@ -14145,12 +14099,7 @@ node-gyp-build@<4.0, node-gyp-build@^3.9.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-3.9.0.tgz#53a350187dd4d5276750da21605d1cb681d09e25" integrity sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A== -node-gyp-build@^4.3.0, node-gyp-build@^4.5.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" - integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== - -node-gyp-build@^4.8.0, node-gyp-build@^4.8.2: +node-gyp-build@^4.3.0, node-gyp-build@^4.5.0, node-gyp-build@^4.8.0, node-gyp-build@^4.8.2: version "4.8.4" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== @@ -15255,22 +15204,12 @@ path-to-regexp@1.x: dependencies: isarray "0.0.1" -path-to-regexp@^0.1.10: +path-to-regexp@^0.1.10, path-to-regexp@^0.1.2: version "0.1.11" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.11.tgz#a527e662c89efc4646dbfa8100bf3e847e495761" integrity sha512-c0t+KCuUkO/YDLPG4WWzEwx3J5F/GHXsD1h/SNZfySqAIKe/BaP95x8fWtOfRJokpS5yYHRJjMtYlXD8jxnpbw== -path-to-regexp@^0.1.2: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - -path-to-regexp@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5" - integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== - -path-to-regexp@^6.3.0: +path-to-regexp@^6.1.0, path-to-regexp@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.3.0.tgz#2b6a26a337737a8e1416f9272ed0766b1c0389f4" integrity sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ== @@ -16166,12 +16105,7 @@ pouchdb@9.0.0: uuid "8.3.2" vuvuzela "1.0.3" -pprof-format@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.0.7.tgz#526e4361f8b37d16b2ec4bb0696b5292de5046a4" - integrity sha512-1qWaGAzwMpaXJP9opRa23nPnt2Egi7RMNoNBptEE/XwHbcn4fC2b/4U4bKc5arkGkIh2ZabpF2bEb+c5GNHEKA== - -pprof-format@^2.1.0: +pprof-format@^2.0.7, pprof-format@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.1.0.tgz#acc8d7773bcf4faf0a3d3df11bceefba7ac06664" integrity sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw== @@ -17057,12 +16991,7 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" - integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== - -rfdc@^1.3.1: +rfdc@^1.3.0, rfdc@^1.3.1: version "1.4.1" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== From 98795501c4b1b43feedde13cc78335878668456f Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 18:23:50 +0000 Subject: [PATCH 20/40] update mssql and aws sdk deps --- packages/backend-core/package.json | 2 +- packages/server/package.json | 7 +- packages/server/src/integrations/snowflake.ts | 3 +- packages/worker/package.json | 2 +- yarn.lock | 1937 +++++++++++++++-- 5 files changed, 1793 insertions(+), 158 deletions(-) diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index a970cbce78..977f7c5746 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -33,7 +33,7 @@ "@budibase/shared-core": "0.0.0", "@budibase/types": "0.0.0", "aws-cloudfront-sign": "3.0.2", - "aws-sdk": "2.1030.0", + "aws-sdk": "2.1692.0", "bcrypt": "5.1.0", "bcryptjs": "2.4.3", "bull": "4.10.1", diff --git a/packages/server/package.json b/packages/server/package.json index 71de972786..28a85fdb3e 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -66,7 +66,7 @@ "airtable": "0.12.2", "arangojs": "7.2.0", "archiver": "7.0.1", - "aws-sdk": "2.1030.0", + "aws-sdk": "2.1692.0", "bcrypt": "5.1.0", "bcryptjs": "2.4.3", "buffer": "6.0.3", @@ -97,7 +97,7 @@ "lodash": "4.17.21", "memorystream": "0.3.1", "mongodb": "6.7.0", - "mssql": "10.0.1", + "mssql": "11.0.1", "mysql2": "3.9.8", "node-fetch": "2.6.7", "object-sizeof": "2.6.1", @@ -111,6 +111,7 @@ "redis": "4", "serialize-error": "^7.0.1", "server-destroy": "1.0.1", + "snowflake-sdk": "^1.15.0", "socket.io": "4.8.1", "tar": "6.2.1", "tmp": "0.2.3", @@ -118,7 +119,7 @@ "uuid": "^8.3.2", "validate.js": "0.13.1", "worker-farm": "1.7.0", - "xml2js": "0.5.0" + "xml2js": "^0.6.2" }, "devDependencies": { "@babel/preset-env": "7.16.11", diff --git a/packages/server/src/integrations/snowflake.ts b/packages/server/src/integrations/snowflake.ts index bb77a19547..6b3c79ed52 100644 --- a/packages/server/src/integrations/snowflake.ts +++ b/packages/server/src/integrations/snowflake.ts @@ -18,7 +18,6 @@ interface SnowflakeConfig { schema: string } - const SCHEMA: Integration = { docs: "https://developers.snowflake.com/", description: @@ -93,7 +92,7 @@ class SnowflakePromise { return new Promise((resolve, reject) => { this.client.execute({ sqlText: sql, - complete: function(err: Error, statementExecuted: string, rows: any) { + complete: function (err: Error, statementExecuted: string, rows: any) { if (err) { return reject(err) } diff --git a/packages/worker/package.json b/packages/worker/package.json index cb33934bdc..1e1a984892 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -44,7 +44,7 @@ "@koa/router": "13.1.0", "@techpass/passport-openidconnect": "1.0.0", "@types/global-agent": "2.1.1", - "aws-sdk": "2.1030.0", + "aws-sdk": "2.1692.0", "bcrypt": "5.1.0", "bcryptjs": "2.4.3", "bull": "4.10.1", diff --git a/yarn.lock b/yarn.lock index bfd14f26fd..52fc595f31 100644 --- a/yarn.lock +++ b/yarn.lock @@ -82,6 +82,616 @@ call-me-maybe "^1.0.1" z-schema "^5.0.1" +"@aws-crypto/crc32@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-5.2.0.tgz#cfcc22570949c98c6689cfcbd2d693d36cdae2e1" + integrity sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/crc32c@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz#4e34aab7f419307821509a98b9b08e84e0c1917e" + integrity sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/sha1-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz#b0ee2d2821d3861f017e965ef3b4cb38e3b6a0f4" + integrity sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg== + dependencies: + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz#153895ef1dba6f9fce38af550e0ef58988eb649e" + integrity sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw== + dependencies: + "@aws-crypto/sha256-js" "^5.2.0" + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-js@5.2.0", "@aws-crypto/sha256-js@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz#c4fdb773fdbed9a664fc1a95724e206cf3860042" + integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/supports-web-crypto@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz#a1e399af29269be08e695109aa15da0a07b5b5fb" + integrity sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg== + dependencies: + tslib "^2.6.2" + +"@aws-crypto/util@5.2.0", "@aws-crypto/util@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-5.2.0.tgz#71284c9cffe7927ddadac793c14f14886d3876da" + integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-s3@^3.388.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.693.0.tgz#188b621498ffaeb7b1ea5794f61e3e8d9a4bcac2" + integrity sha512-vgGI2e0Q6pzyhqfrSysi+sk/i+Nl+lMon67oqj/57RcCw9daL1/inpS+ADuwHpiPWkrg+U0bOXnmHjkLeTslJg== + dependencies: + "@aws-crypto/sha1-browser" "5.2.0" + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.693.0" + "@aws-sdk/client-sts" "3.693.0" + "@aws-sdk/core" "3.693.0" + "@aws-sdk/credential-provider-node" "3.693.0" + "@aws-sdk/middleware-bucket-endpoint" "3.693.0" + "@aws-sdk/middleware-expect-continue" "3.693.0" + "@aws-sdk/middleware-flexible-checksums" "3.693.0" + "@aws-sdk/middleware-host-header" "3.693.0" + "@aws-sdk/middleware-location-constraint" "3.693.0" + "@aws-sdk/middleware-logger" "3.693.0" + "@aws-sdk/middleware-recursion-detection" "3.693.0" + "@aws-sdk/middleware-sdk-s3" "3.693.0" + "@aws-sdk/middleware-ssec" "3.693.0" + "@aws-sdk/middleware-user-agent" "3.693.0" + "@aws-sdk/region-config-resolver" "3.693.0" + "@aws-sdk/signature-v4-multi-region" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@aws-sdk/util-endpoints" "3.693.0" + "@aws-sdk/util-user-agent-browser" "3.693.0" + "@aws-sdk/util-user-agent-node" "3.693.0" + "@aws-sdk/xml-builder" "3.693.0" + "@smithy/config-resolver" "^3.0.11" + "@smithy/core" "^2.5.2" + "@smithy/eventstream-serde-browser" "^3.0.12" + "@smithy/eventstream-serde-config-resolver" "^3.0.9" + "@smithy/eventstream-serde-node" "^3.0.11" + "@smithy/fetch-http-handler" "^4.1.0" + "@smithy/hash-blob-browser" "^3.1.8" + "@smithy/hash-node" "^3.0.9" + "@smithy/hash-stream-node" "^3.1.8" + "@smithy/invalid-dependency" "^3.0.9" + "@smithy/md5-js" "^3.0.9" + "@smithy/middleware-content-length" "^3.0.11" + "@smithy/middleware-endpoint" "^3.2.2" + "@smithy/middleware-retry" "^3.0.26" + "@smithy/middleware-serde" "^3.0.9" + "@smithy/middleware-stack" "^3.0.9" + "@smithy/node-config-provider" "^3.1.10" + "@smithy/node-http-handler" "^3.3.0" + "@smithy/protocol-http" "^4.1.6" + "@smithy/smithy-client" "^3.4.3" + "@smithy/types" "^3.7.0" + "@smithy/url-parser" "^3.0.9" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.26" + "@smithy/util-defaults-mode-node" "^3.0.26" + "@smithy/util-endpoints" "^2.1.5" + "@smithy/util-middleware" "^3.0.9" + "@smithy/util-retry" "^3.0.9" + "@smithy/util-stream" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + "@smithy/util-waiter" "^3.1.8" + tslib "^2.6.2" + +"@aws-sdk/client-sso-oidc@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.693.0.tgz#2fd7f93bd81839f5cd08c5e6e9a578b80572d3c4" + integrity sha512-UEDbYlYtK/e86OOMyFR4zEPyenIxDzO2DRdz3fwVW7RzZ94wfmSwBh/8skzPTuY1G7sI064cjHW0b0QG01Sdtg== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.693.0" + "@aws-sdk/credential-provider-node" "3.693.0" + "@aws-sdk/middleware-host-header" "3.693.0" + "@aws-sdk/middleware-logger" "3.693.0" + "@aws-sdk/middleware-recursion-detection" "3.693.0" + "@aws-sdk/middleware-user-agent" "3.693.0" + "@aws-sdk/region-config-resolver" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@aws-sdk/util-endpoints" "3.693.0" + "@aws-sdk/util-user-agent-browser" "3.693.0" + "@aws-sdk/util-user-agent-node" "3.693.0" + "@smithy/config-resolver" "^3.0.11" + "@smithy/core" "^2.5.2" + "@smithy/fetch-http-handler" "^4.1.0" + "@smithy/hash-node" "^3.0.9" + "@smithy/invalid-dependency" "^3.0.9" + "@smithy/middleware-content-length" "^3.0.11" + "@smithy/middleware-endpoint" "^3.2.2" + "@smithy/middleware-retry" "^3.0.26" + "@smithy/middleware-serde" "^3.0.9" + "@smithy/middleware-stack" "^3.0.9" + "@smithy/node-config-provider" "^3.1.10" + "@smithy/node-http-handler" "^3.3.0" + "@smithy/protocol-http" "^4.1.6" + "@smithy/smithy-client" "^3.4.3" + "@smithy/types" "^3.7.0" + "@smithy/url-parser" "^3.0.9" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.26" + "@smithy/util-defaults-mode-node" "^3.0.26" + "@smithy/util-endpoints" "^2.1.5" + "@smithy/util-middleware" "^3.0.9" + "@smithy/util-retry" "^3.0.9" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sso@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.693.0.tgz#9cd5e07e57013b8c7980512810d775d7b6f67e36" + integrity sha512-QEynrBC26x6TG9ZMzApR/kZ3lmt4lEIs2D+cHuDxt6fDGzahBUsQFBwJqhizzsM97JJI5YvmJhmihoYjdSSaXA== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.693.0" + "@aws-sdk/middleware-host-header" "3.693.0" + "@aws-sdk/middleware-logger" "3.693.0" + "@aws-sdk/middleware-recursion-detection" "3.693.0" + "@aws-sdk/middleware-user-agent" "3.693.0" + "@aws-sdk/region-config-resolver" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@aws-sdk/util-endpoints" "3.693.0" + "@aws-sdk/util-user-agent-browser" "3.693.0" + "@aws-sdk/util-user-agent-node" "3.693.0" + "@smithy/config-resolver" "^3.0.11" + "@smithy/core" "^2.5.2" + "@smithy/fetch-http-handler" "^4.1.0" + "@smithy/hash-node" "^3.0.9" + "@smithy/invalid-dependency" "^3.0.9" + "@smithy/middleware-content-length" "^3.0.11" + "@smithy/middleware-endpoint" "^3.2.2" + "@smithy/middleware-retry" "^3.0.26" + "@smithy/middleware-serde" "^3.0.9" + "@smithy/middleware-stack" "^3.0.9" + "@smithy/node-config-provider" "^3.1.10" + "@smithy/node-http-handler" "^3.3.0" + "@smithy/protocol-http" "^4.1.6" + "@smithy/smithy-client" "^3.4.3" + "@smithy/types" "^3.7.0" + "@smithy/url-parser" "^3.0.9" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.26" + "@smithy/util-defaults-mode-node" "^3.0.26" + "@smithy/util-endpoints" "^2.1.5" + "@smithy/util-middleware" "^3.0.9" + "@smithy/util-retry" "^3.0.9" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sts@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.693.0.tgz#9e2c418f4850269635632bee4d1a31057c04bcc5" + integrity sha512-4S2y7VEtvdnjJX4JPl4kDQlslxXEZFnC50/UXVUYSt/AMc5A/GgspFNA5FVz4E3Gwpfobbf23hR2NBF8AGvYoQ== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.693.0" + "@aws-sdk/core" "3.693.0" + "@aws-sdk/credential-provider-node" "3.693.0" + "@aws-sdk/middleware-host-header" "3.693.0" + "@aws-sdk/middleware-logger" "3.693.0" + "@aws-sdk/middleware-recursion-detection" "3.693.0" + "@aws-sdk/middleware-user-agent" "3.693.0" + "@aws-sdk/region-config-resolver" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@aws-sdk/util-endpoints" "3.693.0" + "@aws-sdk/util-user-agent-browser" "3.693.0" + "@aws-sdk/util-user-agent-node" "3.693.0" + "@smithy/config-resolver" "^3.0.11" + "@smithy/core" "^2.5.2" + "@smithy/fetch-http-handler" "^4.1.0" + "@smithy/hash-node" "^3.0.9" + "@smithy/invalid-dependency" "^3.0.9" + "@smithy/middleware-content-length" "^3.0.11" + "@smithy/middleware-endpoint" "^3.2.2" + "@smithy/middleware-retry" "^3.0.26" + "@smithy/middleware-serde" "^3.0.9" + "@smithy/middleware-stack" "^3.0.9" + "@smithy/node-config-provider" "^3.1.10" + "@smithy/node-http-handler" "^3.3.0" + "@smithy/protocol-http" "^4.1.6" + "@smithy/smithy-client" "^3.4.3" + "@smithy/types" "^3.7.0" + "@smithy/url-parser" "^3.0.9" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.26" + "@smithy/util-defaults-mode-node" "^3.0.26" + "@smithy/util-endpoints" "^2.1.5" + "@smithy/util-middleware" "^3.0.9" + "@smithy/util-retry" "^3.0.9" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/core@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.693.0.tgz#437969dd740895a59863d737bad14646bc2e1725" + integrity sha512-v6Z/kWmLFqRLDPEwl9hJGhtTgIFHjZugSfF1Yqffdxf4n1AWgtHS7qSegakuMyN5pP4K2tvUD8qHJ+gGe2Bw2A== + dependencies: + "@aws-sdk/types" "3.692.0" + "@smithy/core" "^2.5.2" + "@smithy/node-config-provider" "^3.1.10" + "@smithy/property-provider" "^3.1.9" + "@smithy/protocol-http" "^4.1.6" + "@smithy/signature-v4" "^4.2.2" + "@smithy/smithy-client" "^3.4.3" + "@smithy/types" "^3.7.0" + "@smithy/util-middleware" "^3.0.9" + fast-xml-parser "4.4.1" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-env@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.693.0.tgz#f97feed9809fe2800216943470015fdaaba47c4f" + integrity sha512-hMUZaRSF7+iBKZfBHNLihFs9zvpM1CB8MBOTnTp5NGCVkRYF3SB2LH+Kcippe0ats4qCyB1eEoyQX99rERp2iQ== + dependencies: + "@aws-sdk/core" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@smithy/property-provider" "^3.1.9" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-http@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.693.0.tgz#5caad0ac47eded1edeb63f907280580ccfaadba3" + integrity sha512-sL8MvwNJU7ZpD7/d2VVb3by1GknIJUxzTIgYtVkDVA/ojo+KRQSSHxcj0EWWXF5DTSh2Tm+LrEug3y1ZyKHsDA== + dependencies: + "@aws-sdk/core" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@smithy/fetch-http-handler" "^4.1.0" + "@smithy/node-http-handler" "^3.3.0" + "@smithy/property-provider" "^3.1.9" + "@smithy/protocol-http" "^4.1.6" + "@smithy/smithy-client" "^3.4.3" + "@smithy/types" "^3.7.0" + "@smithy/util-stream" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-ini@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.693.0.tgz#b4557ac1092657660a15c9bd55e17c27f79ec621" + integrity sha512-kvaa4mXhCCOuW7UQnBhYqYfgWmwy7WSBSDClutwSLPZvgrhYj2l16SD2lN4IfYdxARYMJJ1lFYp3/jJG/9Yk4Q== + dependencies: + "@aws-sdk/core" "3.693.0" + "@aws-sdk/credential-provider-env" "3.693.0" + "@aws-sdk/credential-provider-http" "3.693.0" + "@aws-sdk/credential-provider-process" "3.693.0" + "@aws-sdk/credential-provider-sso" "3.693.0" + "@aws-sdk/credential-provider-web-identity" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@smithy/credential-provider-imds" "^3.2.6" + "@smithy/property-provider" "^3.1.9" + "@smithy/shared-ini-file-loader" "^3.1.10" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-node@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.693.0.tgz#c5ceac64a69304d5b4db3fd68473480cafddb4a9" + integrity sha512-42WMsBjTNnjYxYuM3qD/Nq+8b7UdMopUq5OduMDxoM3mFTV6PXMMnfI4Z1TNnR4tYRvPXAnuNltF6xmjKbSJRA== + dependencies: + "@aws-sdk/credential-provider-env" "3.693.0" + "@aws-sdk/credential-provider-http" "3.693.0" + "@aws-sdk/credential-provider-ini" "3.693.0" + "@aws-sdk/credential-provider-process" "3.693.0" + "@aws-sdk/credential-provider-sso" "3.693.0" + "@aws-sdk/credential-provider-web-identity" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@smithy/credential-provider-imds" "^3.2.6" + "@smithy/property-provider" "^3.1.9" + "@smithy/shared-ini-file-loader" "^3.1.10" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-process@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.693.0.tgz#e84e945f1a148f06ff697608d5309e73347e5aa9" + integrity sha512-cvxQkrTWHHjeHrPlj7EWXPnFSq8x7vMx+Zn1oTsMpCY445N9KuzjfJTkmNGwU2GT6rSZI9/0MM02aQvl5bBBTQ== + dependencies: + "@aws-sdk/core" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@smithy/property-provider" "^3.1.9" + "@smithy/shared-ini-file-loader" "^3.1.10" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-sso@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.693.0.tgz#72767389f533d9d17a14af63daaafcc8368ab43a" + integrity sha512-479UlJxY+BFjj3pJFYUNC0DCMrykuG7wBAXfsvZqQxKUa83DnH5Q1ID/N2hZLkxjGd4ZW0AC3lTOMxFelGzzpQ== + dependencies: + "@aws-sdk/client-sso" "3.693.0" + "@aws-sdk/core" "3.693.0" + "@aws-sdk/token-providers" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@smithy/property-provider" "^3.1.9" + "@smithy/shared-ini-file-loader" "^3.1.10" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-web-identity@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.693.0.tgz#b6133b5ef9d3582e36e02e9c66766714ff672a11" + integrity sha512-8LB210Pr6VeCiSb2hIra+sAH4KUBLyGaN50axHtIgufVK8jbKIctTZcVY5TO9Se+1107TsruzeXS7VeqVdJfFA== + dependencies: + "@aws-sdk/core" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@smithy/property-provider" "^3.1.9" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-bucket-endpoint@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.693.0.tgz#e4823a40935d34f5e58a4fbc830d8ff92e44fc99" + integrity sha512-cPIa+lxMYiFRHtxKfNIVSFGO6LSgZCk42pu3d7KGwD6hu6vXRD5B2/DD3rPcEH1zgl2j0Kx1oGAV7SRXKHSFag== + dependencies: + "@aws-sdk/types" "3.692.0" + "@aws-sdk/util-arn-parser" "3.693.0" + "@smithy/node-config-provider" "^3.1.10" + "@smithy/protocol-http" "^4.1.6" + "@smithy/types" "^3.7.0" + "@smithy/util-config-provider" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-expect-continue@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.693.0.tgz#d8696cee9ebea1d973d8daf872fd913b41d62cf0" + integrity sha512-MuK/gsJWpHz6Tv0CqTCS+QNOxLa2RfPh1biVCu/uO3l7kA0TjQ/C+tfgKvLXeH103tuDrOVINK+bt2ENmI3SWg== + dependencies: + "@aws-sdk/types" "3.692.0" + "@smithy/protocol-http" "^4.1.6" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-flexible-checksums@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.693.0.tgz#80f07802d98ff33a6899a09c59cf51aab426aaac" + integrity sha512-xkS6zjuE11ob93H9t65kHzphXcUMnN2SmIm2wycUPg+hi8Q6DJA6U2p//6oXkrr9oHy1QvwtllRd7SAd63sFKQ== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@aws-crypto/crc32c" "5.2.0" + "@aws-crypto/util" "5.2.0" + "@aws-sdk/core" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/node-config-provider" "^3.1.10" + "@smithy/protocol-http" "^4.1.6" + "@smithy/types" "^3.7.0" + "@smithy/util-middleware" "^3.0.9" + "@smithy/util-stream" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-host-header@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.693.0.tgz#69322909c0792df1e6be7c7fb5e2b6f76090a55c" + integrity sha512-BCki6sAZ5jYwIN/t3ElCiwerHad69ipHwPsDCxJQyeiOnJ8HG+lEpnVIfrnI8A0fLQNSF3Gtx6ahfBpKiv1Oug== + dependencies: + "@aws-sdk/types" "3.692.0" + "@smithy/protocol-http" "^4.1.6" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-location-constraint@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.693.0.tgz#1856eaaad64d41d1f8fa53ced58a6c7cf5eccc6e" + integrity sha512-eDAExTZ9uNIP7vs2JCVCOuWJauGueisBSn+Ovt7UvvuEUp6KOIJqn8oFxWmyUQu2GvbG4OcaTLgbqD95YHTB0Q== + dependencies: + "@aws-sdk/types" "3.692.0" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-logger@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.693.0.tgz#fc10294e6963f8e5d58ba1ededd891e999f544a9" + integrity sha512-dXnXDPr+wIiJ1TLADACI1g9pkSB21KkMIko2u4CJ2JCBoxi5IqeTnVoa6YcC8GdFNVRl+PorZ3Zqfmf1EOTC6w== + dependencies: + "@aws-sdk/types" "3.692.0" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-recursion-detection@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.693.0.tgz#88a8157293775e7116707da26501da4b5e042f51" + integrity sha512-0LDmM+VxXp0u3rG0xQRWD/q6Ubi7G8I44tBPahevD5CaiDZTkmNTrVUf0VEJgVe0iCKBppACMBDkLB0/ETqkFw== + dependencies: + "@aws-sdk/types" "3.692.0" + "@smithy/protocol-http" "^4.1.6" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-sdk-s3@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.693.0.tgz#e0850854d5079f372786b2ccfe85729caa7a49d8" + integrity sha512-5A++RBjJ3guyq5pbYs+Oq5hMlA8CK2OWaHx09cxVfhHWl/RoaY8DXrft4gnhoUEBrrubyMw7r9j7RIMLvS58kg== + dependencies: + "@aws-sdk/core" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@aws-sdk/util-arn-parser" "3.693.0" + "@smithy/core" "^2.5.2" + "@smithy/node-config-provider" "^3.1.10" + "@smithy/protocol-http" "^4.1.6" + "@smithy/signature-v4" "^4.2.2" + "@smithy/smithy-client" "^3.4.3" + "@smithy/types" "^3.7.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.9" + "@smithy/util-stream" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-ssec@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.693.0.tgz#2ff779147d188090b3a6cda3ed12ca4085220a73" + integrity sha512-Ro5vzI7SRgEeuoMk3fKqFjGv6mG4c7VsSCDwnkiasmafQFBTPvUIpgmu2FXMHqW/OthvoiOzpSrlJ9Bwlx2f8A== + dependencies: + "@aws-sdk/types" "3.692.0" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-user-agent@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.693.0.tgz#4b55cfab3fc7e671b08e1ea63a98e45a1e13e6a5" + integrity sha512-/KUq/KEpFFbQmNmpp7SpAtFAdViquDfD2W0QcG07zYBfz9MwE2ig48ALynXm5sMpRmnG7sJXjdvPtTsSVPfkiw== + dependencies: + "@aws-sdk/core" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@aws-sdk/util-endpoints" "3.693.0" + "@smithy/core" "^2.5.2" + "@smithy/protocol-http" "^4.1.6" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/node-http-handler@^3.374.0": + version "3.374.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/node-http-handler/-/node-http-handler-3.374.0.tgz#8cd58b4d9814713e26034c12eabc119c113a5bc4" + integrity sha512-v1Z6m0wwkf65/tKuhwrtPRqVoOtNkDTRn2MBMtxCwEw+8V8Q+YRFqVgGN+J1n53ktE0G5OYVBux/NHiAjJHReQ== + dependencies: + "@smithy/node-http-handler" "^1.0.2" + tslib "^2.5.0" + +"@aws-sdk/region-config-resolver@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.693.0.tgz#9cde5e99f654c788540acfb2a4218d444e8621c2" + integrity sha512-YLUkMsUY0GLW/nfwlZ69cy1u07EZRmsv8Z9m0qW317/EZaVx59hcvmcvb+W4bFqj5E8YImTjoGfE4cZ0F9mkyw== + dependencies: + "@aws-sdk/types" "3.692.0" + "@smithy/node-config-provider" "^3.1.10" + "@smithy/types" "^3.7.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.9" + tslib "^2.6.2" + +"@aws-sdk/signature-v4-multi-region@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.693.0.tgz#85bd90bb78be1a98d5a5ca41033cb0703146c2c4" + integrity sha512-s7zbbsoVIriTR4ZGaateKuTqz6ddpazAyHvjk7I9kd+NvGNPiuAI18UdbuiiRI6K5HuYKf1ah6mKWFGPG15/kQ== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@smithy/protocol-http" "^4.1.6" + "@smithy/signature-v4" "^4.2.2" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/token-providers@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.693.0.tgz#5ce7d6aa7a3437d4abdc0dca1be47f5158d15c85" + integrity sha512-nDBTJMk1l/YmFULGfRbToOA2wjf+FkQT4dMgYCv+V9uSYsMzQj8A7Tha2dz9yv4vnQgYaEiErQ8d7HVyXcVEoA== + dependencies: + "@aws-sdk/types" "3.692.0" + "@smithy/property-provider" "^3.1.9" + "@smithy/shared-ini-file-loader" "^3.1.10" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/types@3.692.0", "@aws-sdk/types@^3.222.0": + version "3.692.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.692.0.tgz#c8f6c75b6ad659865b72759796d4d92c1b72069b" + integrity sha512-RpNvzD7zMEhiKgmlxGzyXaEcg2khvM7wd5sSHVapOcrde1awQSOMGI4zKBQ+wy5TnDfrm170ROz/ERLYtrjPZA== + dependencies: + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/util-arn-parser@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.693.0.tgz#8dae27eb822ab4f88be28bb3c0fc11f1f13d3948" + integrity sha512-WC8x6ca+NRrtpAH64rWu+ryDZI3HuLwlEr8EU6/dbC/pt+r/zC0PBoC15VEygUaBA+isppCikQpGyEDu0Yj7gQ== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-endpoints@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.693.0.tgz#99f56f83fc25bdc3321f5871d6354abd56768891" + integrity sha512-eo4F6DRQ/kxS3gxJpLRv+aDNy76DxQJL5B3DPzpr9Vkq0ygVoi4GT5oIZLVaAVIJmi6k5qq9dLsYZfWLUxJJSg== + dependencies: + "@aws-sdk/types" "3.692.0" + "@smithy/types" "^3.7.0" + "@smithy/util-endpoints" "^2.1.5" + tslib "^2.6.2" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.693.0.tgz#1160f6d055cf074ca198eb8ecf89b6311537ad6c" + integrity sha512-ttrag6haJLWABhLqtg1Uf+4LgHWIMOVSYL+VYZmAp2v4PUGOwWmWQH0Zk8RM7YuQcLfH/EoR72/Yxz6A4FKcuw== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-browser@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.693.0.tgz#c6969be97e7cd0190b3b72a82a642b29ff4659c4" + integrity sha512-6EUfuKOujtddy18OLJUaXfKBgs+UcbZ6N/3QV4iOkubCUdeM1maIqs++B9bhCbWeaeF5ORizJw5FTwnyNjE/mw== + dependencies: + "@aws-sdk/types" "3.692.0" + "@smithy/types" "^3.7.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-node@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.693.0.tgz#b26c806faa2001d4fa1d515b146eeff411513dd9" + integrity sha512-td0OVX8m5ZKiXtecIDuzY3Y3UZIzvxEr57Hp21NOwieqKCG2UeyQWWeGPv0FQaU7dpTkvFmVNI+tx9iB8V/Nhg== + dependencies: + "@aws-sdk/middleware-user-agent" "3.693.0" + "@aws-sdk/types" "3.692.0" + "@smithy/node-config-provider" "^3.1.10" + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + +"@aws-sdk/xml-builder@3.693.0": + version "3.693.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.693.0.tgz#709a46a3335b71144d9f7917a7cb3033b5a04e82" + integrity sha512-C/rPwJcqnV8VDr2/VtcQnymSpcfEEgH1Jm6V0VmfXNZFv4Qzf1eCS8nsec0gipYgZB+cBBjfXw5dAk6pJ8ubpw== + dependencies: + "@smithy/types" "^3.7.0" + tslib "^2.6.2" + "@azure/abort-controller@^1.0.0", "@azure/abort-controller@^1.0.4": version "1.1.0" resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" @@ -96,7 +706,7 @@ dependencies: tslib "^2.6.2" -"@azure/core-auth@^1.3.0", "@azure/core-auth@^1.4.0", "@azure/core-auth@^1.5.0": +"@azure/core-auth@^1.3.0", "@azure/core-auth@^1.4.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.5.0.tgz#a41848c5c31cb3b7c84c409885267d55a2c92e44" integrity sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw== @@ -105,6 +715,15 @@ "@azure/core-util" "^1.1.0" tslib "^2.2.0" +"@azure/core-auth@^1.5.0", "@azure/core-auth@^1.7.2", "@azure/core-auth@^1.8.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.9.0.tgz#ac725b03fabe3c892371065ee9e2041bee0fd1ac" + integrity sha512-FPwHpZywuyasDSLMqJ6fhbOK3TqUdviZNF8OqRGA4W5Ewib2lEEZ+pBsYcBa88B2NGO/SEnYPGhyBqNlE8ilSw== + dependencies: + "@azure/abort-controller" "^2.0.0" + "@azure/core-util" "^1.11.0" + tslib "^2.6.2" + "@azure/core-client@^1.3.0", "@azure/core-client@^1.4.0", "@azure/core-client@^1.5.0": version "1.9.2" resolved "https://registry.yarnpkg.com/@azure/core-client/-/core-client-1.9.2.tgz#6fc69cee2816883ab6c5cdd653ee4f2ff9774f74" @@ -127,6 +746,26 @@ "@azure/core-client" "^1.3.0" "@azure/core-rest-pipeline" "^1.3.0" +"@azure/core-http@^3.0.0": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@azure/core-http/-/core-http-3.0.4.tgz#024b2909bbc0f2fce08c74f97a21312c4f42e922" + integrity sha512-Fok9VVhMdxAFOtqiiAtg74fL0UJkt0z3D+ouUUxcRLzZNBioPRAMJFVxiWoJljYpXsRi4GDQHzQHDc9AiYaIUQ== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-auth" "^1.3.0" + "@azure/core-tracing" "1.0.0-preview.13" + "@azure/core-util" "^1.1.1" + "@azure/logger" "^1.0.0" + "@types/node-fetch" "^2.5.0" + "@types/tunnel" "^0.0.3" + form-data "^4.0.0" + node-fetch "^2.6.7" + process "^0.11.10" + tslib "^2.2.0" + tunnel "^0.0.6" + uuid "^8.3.0" + xml2js "^0.5.0" + "@azure/core-lro@^2.2.0": version "2.5.1" resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-2.5.1.tgz#9c6be24b84f8a8c8e8ac376c5018460c5a585d0b" @@ -143,7 +782,21 @@ dependencies: tslib "^2.2.0" -"@azure/core-rest-pipeline@^1.1.0", "@azure/core-rest-pipeline@^1.3.0", "@azure/core-rest-pipeline@^1.8.0", "@azure/core-rest-pipeline@^1.9.1": +"@azure/core-rest-pipeline@^1.1.0": + version "1.18.0" + resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.18.0.tgz#165f1cd9bb1060be3b6895742db3d1f1106271d3" + integrity sha512-QSoGUp4Eq/gohEFNJaUOwTN7BCc2nHTjjbm75JT0aD7W65PWM1H/tItz0GsABn22uaKyGxiMhWQLt2r+FGU89Q== + dependencies: + "@azure/abort-controller" "^2.0.0" + "@azure/core-auth" "^1.8.0" + "@azure/core-tracing" "^1.0.1" + "@azure/core-util" "^1.11.0" + "@azure/logger" "^1.0.0" + http-proxy-agent "^7.0.0" + https-proxy-agent "^7.0.0" + tslib "^2.6.2" + +"@azure/core-rest-pipeline@^1.3.0", "@azure/core-rest-pipeline@^1.8.0", "@azure/core-rest-pipeline@^1.9.1": version "1.11.0" resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.11.0.tgz#fc0e8f56caac08a9d4ac91c07a6c5a360ea31c82" integrity sha512-nB4KXl6qAyJmBVLWA7SakT4tzpYZTCk4pvRBeI+Ye0WYSOrlTqlMhc4MSS/8atD3ufeYWdkN380LLoXlUUzThw== @@ -158,6 +811,14 @@ https-proxy-agent "^5.0.0" tslib "^2.2.0" +"@azure/core-tracing@1.0.0-preview.13": + version "1.0.0-preview.13" + resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz#55883d40ae2042f6f1e12b17dd0c0d34c536d644" + integrity sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ== + dependencies: + "@opentelemetry/api" "^1.0.1" + tslib "^2.2.0" + "@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" @@ -173,7 +834,15 @@ "@azure/abort-controller" "^1.0.0" tslib "^2.2.0" -"@azure/identity@4.2.1", "@azure/identity@^3.4.1": +"@azure/core-util@^1.1.1", "@azure/core-util@^1.11.0": + version "1.11.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.11.0.tgz#f530fc67e738aea872fbdd1cc8416e70219fada7" + integrity sha512-DxOSLua+NdpWoSqULhjDyAZTXFdP/LKkqtYuxxz1SCN289zk3OG8UOpnCQAz/tygyACBtWp/BoO72ptK7msY8g== + dependencies: + "@azure/abort-controller" "^2.0.0" + tslib "^2.6.2" + +"@azure/identity@4.2.1", "@azure/identity@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -218,26 +887,40 @@ tslib "^2.2.0" "@azure/msal-browser@^3.11.1": - version "3.24.0" - resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.24.0.tgz#3208047672d0b0c943b0bef5f995d510d6582ae4" - integrity sha512-JGNV9hTYAa7lsum9IMIibn2kKczAojNihGo1hi7pG0kNrcKej530Fl6jxwM05A44/6I079CSn6WxYxbVhKUmWg== + version "3.27.0" + resolved "https://registry.yarnpkg.com/@azure/msal-browser/-/msal-browser-3.27.0.tgz#b6f02f73c8e102d3f115009b4677539fb173fe2b" + integrity sha512-+b4ZKSD8+vslCtVRVetkegEhOFMLP3rxDWJY212ct+2r6jVg6OSQKc1Qz3kCoXo0FgwaXkb+76TMZfpHp8QtgA== dependencies: - "@azure/msal-common" "14.15.0" + "@azure/msal-common" "14.16.0" -"@azure/msal-common@14.15.0": - version "14.15.0" - resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.15.0.tgz#0e27ac0bb88fe100f4f8d1605b64d5c268636a55" - integrity sha512-ImAQHxmpMneJ/4S8BRFhjt1MZ3bppmpRPYYNyzeQPeFN288YKbb8TmmISQEbtfkQ1BPASvYZU5doIZOPBAqENQ== +"@azure/msal-common@14.16.0": + version "14.16.0" + resolved "https://registry.yarnpkg.com/@azure/msal-common/-/msal-common-14.16.0.tgz#f3470fcaec788dbe50859952cd499340bda23d7a" + integrity sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA== "@azure/msal-node@^2.9.2": - version "2.14.0" - resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.14.0.tgz#7881895d41b03d8b9b38a29550ba3bbb15f73b3c" - integrity sha512-rrfzIpG3Q1rHjVYZmHAEDidWAZZ2cgkxlIcMQ8dHebRISaZ2KCV33Q8Vs+uaV6lxweROabNxKFlR2lIKagZqYg== + version "2.16.2" + resolved "https://registry.yarnpkg.com/@azure/msal-node/-/msal-node-2.16.2.tgz#3eb768d36883ea6f9a939c0b5b467b518e78fffc" + integrity sha512-An7l1hEr0w1HMMh1LU+rtDtqL7/jw74ORlc9Wnh06v7TU/xpG39/Zdr1ZJu3QpjUfKJ+E0/OXMW8DRSWTlh7qQ== dependencies: - "@azure/msal-common" "14.15.0" + "@azure/msal-common" "14.16.0" jsonwebtoken "^9.0.0" uuid "^8.3.0" +"@azure/storage-blob@12.18.x": + version "12.18.0" + resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.18.0.tgz#9dd001c9aa5e972216f5af15131009086cfeb59e" + integrity sha512-BzBZJobMoDyjJsPRMLNHvqHycTGrT8R/dtcTx9qUFcqwSRfGVK9A/cZ7Nx38UQydT9usZGbaDCN75QRNjezSAA== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-http" "^3.0.0" + "@azure/core-lro" "^2.2.0" + "@azure/core-paging" "^1.1.1" + "@azure/core-tracing" "1.0.0-preview.13" + "@azure/logger" "^1.0.0" + events "^3.0.0" + tslib "^2.2.0" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.22.5", "@babel/code-frame@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" @@ -1446,7 +2129,7 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@2.33.2": +"@budibase/backend-core@3.2.7": version "0.0.0" dependencies: "@budibase/nano" "10.1.5" @@ -1454,7 +2137,7 @@ "@budibase/shared-core" "0.0.0" "@budibase/types" "0.0.0" aws-cloudfront-sign "3.0.2" - aws-sdk "2.1030.0" + aws-sdk "2.1692.0" bcrypt "5.1.0" bcryptjs "2.4.3" bull "4.10.1" @@ -1526,16 +2209,16 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@0.0.0", "@budibase/pro@npm:@budibase/pro@latest": - version "2.33.2" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.33.2.tgz#5c2012f7b2bf0fd871cda1ad37ad7a0442c84658" - integrity sha512-lBB6Wfp6OIOHRlGq82WS9KxvEXRs/P2QlwJT0Aj9PhmkQFsnXm2r8d18f0xTGvcflD+iR7XGP/k56JlCanmhQg== +"@budibase/pro@npm:@budibase/pro@latest": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.7.tgz#4dfc48f3e2ba3a3b235872e54c3de4de54ea7941" + integrity sha512-GRRaf1qSqQfoodjvKjBDvNOVHZrcSXF7so6Y9Xv/MiRTjDES5nmhIT5rL/PQ1+Mb+sPytYmMaJ2mlTtwqSQZgQ== dependencies: "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "2.33.2" - "@budibase/shared-core" "2.33.2" - "@budibase/string-templates" "2.33.2" - "@budibase/types" "2.33.2" + "@budibase/backend-core" "3.2.7" + "@budibase/shared-core" "3.2.7" + "@budibase/string-templates" "3.2.7" + "@budibase/types" "3.2.7" "@koa/router" "8.0.8" bull "4.10.1" dd-trace "5.2.0" @@ -1548,13 +2231,13 @@ scim-patch "^0.8.1" scim2-parse-filter "^0.2.8" -"@budibase/shared-core@2.33.2": +"@budibase/shared-core@3.2.7": version "0.0.0" dependencies: "@budibase/types" "0.0.0" cron-validate "1.4.5" -"@budibase/string-templates@2.33.2": +"@budibase/string-templates@3.2.7": version "0.0.0" dependencies: "@budibase/handlebars-helpers" "^0.13.2" @@ -1562,7 +2245,7 @@ handlebars "^4.7.8" lodash.clonedeep "^4.5.0" -"@budibase/types@2.33.2": +"@budibase/types@3.2.7": version "0.0.0" dependencies: scim-patch "^0.8.1" @@ -1673,6 +2356,11 @@ style-mod "^4.0.0" w3c-keyname "^2.2.4" +"@colors/colors@1.6.0", "@colors/colors@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0" + integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA== + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -1680,6 +2368,15 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@dabh/diagnostics@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" + integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== + dependencies: + colorspace "1.1.x" + enabled "2.0.x" + kuler "^2.0.0" + "@dagrejs/dagre@1.1.4": version "1.1.4" resolved "https://registry.yarnpkg.com/@dagrejs/dagre/-/dagre-1.1.4.tgz#66f9c0e2b558308f2c268f60e2c28f22ee17e339" @@ -1979,6 +2676,45 @@ google-gax "^4.3.3" protobufjs "^7.2.6" +"@google-cloud/paginator@^5.0.0": + version "5.0.2" + resolved "https://registry.yarnpkg.com/@google-cloud/paginator/-/paginator-5.0.2.tgz#86ad773266ce9f3b82955a8f75e22cd012ccc889" + integrity sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg== + dependencies: + arrify "^2.0.0" + extend "^3.0.2" + +"@google-cloud/projectify@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@google-cloud/projectify/-/projectify-4.0.0.tgz#d600e0433daf51b88c1fa95ac7f02e38e80a07be" + integrity sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA== + +"@google-cloud/promisify@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@google-cloud/promisify/-/promisify-4.0.0.tgz#a906e533ebdd0f754dca2509933334ce58b8c8b1" + integrity sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g== + +"@google-cloud/storage@^7.7.0": + version "7.14.0" + resolved "https://registry.yarnpkg.com/@google-cloud/storage/-/storage-7.14.0.tgz#eda9715f68507949214af804c906eba6d168a214" + integrity sha512-H41bPL2cMfSi4EEnFzKvg7XSb7T67ocSXrmF7MPjfgFB0L6CKGzfIYJheAZi1iqXjz6XaCT1OBf6HCG5vDBTOQ== + dependencies: + "@google-cloud/paginator" "^5.0.0" + "@google-cloud/projectify" "^4.0.0" + "@google-cloud/promisify" "^4.0.0" + abort-controller "^3.0.0" + async-retry "^1.3.3" + duplexify "^4.1.3" + fast-xml-parser "^4.4.1" + gaxios "^6.0.2" + google-auth-library "^9.6.3" + html-entities "^2.5.2" + mime "^3.0.0" + p-limit "^3.0.1" + retry-request "^7.0.0" + teeny-request "^9.0.0" + uuid "^8.0.0" + "@grpc/grpc-js@^1.10.9": version "1.10.10" resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.10.10.tgz#476d315feeb9dbb0f2d6560008c92688c30f13e0" @@ -2612,7 +3348,7 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@js-joda/core@^5.5.3": +"@js-joda/core@^5.6.1": version "5.6.3" resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-5.6.3.tgz#41ae1c07de1ebe0f6dde1abcbc9700a09b9c6056" integrity sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA== @@ -3116,11 +3852,16 @@ dependencies: "@octokit/openapi-types" "^18.0.0" -"@opentelemetry/api@>=1.0.0 <1.9.0", "@opentelemetry/api@^1.0.0": +"@opentelemetry/api@>=1.0.0 <1.9.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== +"@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.0.1": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" + integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== + "@opentelemetry/core@^1.14.0": version "1.19.0" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.19.0.tgz#6563bb65465bf232d8435553b9a122d9351c0fbb" @@ -3240,7 +3981,7 @@ dependencies: slash "^4.0.0" -"@rollup/plugin-commonjs@^16.0.0": +"@rollup/plugin-commonjs@16.0.0", "@rollup/plugin-commonjs@^16.0.0": version "16.0.0" resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-16.0.0.tgz#169004d56cd0f0a1d0f35915d31a036b0efe281f" integrity sha512-LuNyypCP3msCGVQJ7ki8PqYdpjfEkE/xtFa5DqlF+7IBD0JsfMZ87C58heSwIMint58sAUZbt3ITqOmdQv/dXw== @@ -3326,7 +4067,7 @@ is-module "^1.0.0" resolve "^1.22.1" -"@rollup/plugin-replace@^5.0.3": +"@rollup/plugin-replace@^5.0.2", "@rollup/plugin-replace@^5.0.3": version "5.0.7" resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-5.0.7.tgz#150c9ee9db8031d9e4580a61a0edeaaed3d37687" integrity sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ== @@ -3552,6 +4293,546 @@ dependencies: "@sinonjs/commons" "^2.0.0" +"@smithy/abort-controller@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-1.1.0.tgz#2da0d73c504b93ca8bb83bdc8d6b8208d73f418b" + integrity sha512-5imgGUlZL4dW4YWdMYAKLmal9ny/tlenM81QZY7xYyb76z9Z/QOg7oM5Ak9HQl8QfFTlGVWwcMXl+54jroRgEQ== + dependencies: + "@smithy/types" "^1.2.0" + tslib "^2.5.0" + +"@smithy/abort-controller@^3.1.8": + version "3.1.8" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-3.1.8.tgz#ce0c10ddb2b39107d70b06bbb8e4f6e368bc551d" + integrity sha512-+3DOBcUn5/rVjlxGvUPKc416SExarAQ+Qe0bqk30YSUjbepwpS7QN0cyKUSifvLJhdMZ0WPzPP5ymut0oonrpQ== + dependencies: + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader-native@^3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.1.tgz#39045ed278ee1b6f4c12715c7565678557274c29" + integrity sha512-VEYtPvh5rs/xlyqpm5NRnfYLZn+q0SRPELbvBV+C/G7IQ+ouTuo+NKKa3ShG5OaFR8NYVMXls9hPYLTvIKKDrQ== + dependencies: + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader/-/chunked-blob-reader-4.0.0.tgz#754099909957fb1986c16eb88afad75919d7129d" + integrity sha512-jSqRnZvkT4egkq/7b6/QRCNXmmYVcHwnJldqJ3IhVpQE2atObVJ137xmGeuGFhjFUr8gCEVAOKwSY79OvpbDaQ== + dependencies: + tslib "^2.6.2" + +"@smithy/config-resolver@^3.0.11", "@smithy/config-resolver@^3.0.12": + version "3.0.12" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-3.0.12.tgz#f355f95fcb5ee932a90871a488a4f2128e8ad3ac" + integrity sha512-YAJP9UJFZRZ8N+UruTeq78zkdjUHmzsY62J4qKWZ4SXB4QXJ/+680EfXXgkYA2xj77ooMqtUY9m406zGNqwivQ== + dependencies: + "@smithy/node-config-provider" "^3.1.11" + "@smithy/types" "^3.7.1" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.10" + tslib "^2.6.2" + +"@smithy/core@^2.5.2", "@smithy/core@^2.5.3": + version "2.5.3" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.5.3.tgz#1d5723f676b0d6ec08c515272f0ac03aa59fac72" + integrity sha512-96uW8maifUSmehaeW7uydWn7wBc98NEeNI3zN8vqakGpyCQgzyJaA64Z4FCOUmAdCJkhppd/7SZ798Fo4Xx37g== + dependencies: + "@smithy/middleware-serde" "^3.0.10" + "@smithy/protocol-http" "^4.1.7" + "@smithy/types" "^3.7.1" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-middleware" "^3.0.10" + "@smithy/util-stream" "^3.3.1" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/credential-provider-imds@^3.2.6", "@smithy/credential-provider-imds@^3.2.7": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.7.tgz#6eedf87ba0238723ec46d8ce0f18e276685a702d" + integrity sha512-cEfbau+rrWF8ylkmmVAObOmjbTIzKyUC5TkBL58SbLywD0RCBC4JAUKbmtSm2w5KUJNRPGgpGFMvE2FKnuNlWQ== + dependencies: + "@smithy/node-config-provider" "^3.1.11" + "@smithy/property-provider" "^3.1.10" + "@smithy/types" "^3.7.1" + "@smithy/url-parser" "^3.0.10" + tslib "^2.6.2" + +"@smithy/eventstream-codec@^3.1.9": + version "3.1.9" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-3.1.9.tgz#4271354e75e57d30771fca307da403896c657430" + integrity sha512-F574nX0hhlNOjBnP+noLtsPFqXnWh2L0+nZKCwcu7P7J8k+k+rdIDs+RMnrMwrzhUE4mwMgyN0cYnEn0G8yrnQ== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@smithy/types" "^3.7.1" + "@smithy/util-hex-encoding" "^3.0.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-browser@^3.0.12": + version "3.0.13" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.13.tgz#191dcf9181e7ab0914ec43d51518d471b9d466ae" + integrity sha512-Nee9m+97o9Qj6/XeLz2g2vANS2SZgAxV4rDBMKGHvFJHU/xz88x2RwCkwsvEwYjSX4BV1NG1JXmxEaDUzZTAtw== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.12" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/eventstream-serde-config-resolver@^3.0.9": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.10.tgz#5c0b2ae0bb8e11cfa77851098e46f7350047ec8d" + integrity sha512-K1M0x7P7qbBUKB0UWIL5KOcyi6zqV5mPJoL0/o01HPJr0CSq3A9FYuJC6e11EX6hR8QTIR++DBiGrYveOu6trw== + dependencies: + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/eventstream-serde-node@^3.0.11": + version "3.0.12" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.12.tgz#7312383e821b5807abf2fe12316c2a8967d022f0" + integrity sha512-kiZymxXvZ4tnuYsPSMUHe+MMfc4FTeFWJIc0Q5wygJoUQM4rVHNghvd48y7ppuulNMbuYt95ah71pYc2+o4JOA== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.12" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/eventstream-serde-universal@^3.0.12": + version "3.0.12" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.12.tgz#803d7beb29a3de4a64e91af97331a4654741c35f" + integrity sha512-1i8ifhLJrOZ+pEifTlF0EfZzMLUGQggYQ6WmZ4d5g77zEKf7oZ0kvh1yKWHPjofvOwqrkwRDVuxuYC8wVd662A== + dependencies: + "@smithy/eventstream-codec" "^3.1.9" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/fetch-http-handler@^4.1.0", "@smithy/fetch-http-handler@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.1.tgz#cead80762af4cdea11e7eeb627ea1c4835265dfa" + integrity sha512-bH7QW0+JdX0bPBadXt8GwMof/jz0H28I84hU1Uet9ISpzUqXqRQ3fEZJ+ANPOhzSEczYvANNl3uDQDYArSFDtA== + dependencies: + "@smithy/protocol-http" "^4.1.7" + "@smithy/querystring-builder" "^3.0.10" + "@smithy/types" "^3.7.1" + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-blob-browser@^3.1.8": + version "3.1.9" + resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.9.tgz#1f2c3ef6afbb0ce3e58a0129753850bb9267aae8" + integrity sha512-wOu78omaUuW5DE+PVWXiRKWRZLecARyP3xcq5SmkXUw9+utgN8HnSnBfrjL2B/4ZxgqPjaAJQkC/+JHf1ITVaQ== + dependencies: + "@smithy/chunked-blob-reader" "^4.0.0" + "@smithy/chunked-blob-reader-native" "^3.0.1" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/hash-node@^3.0.9": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.10.tgz#93c857b4bff3a48884886440fd9772924887e592" + integrity sha512-3zWGWCHI+FlJ5WJwx73Mw2llYR8aflVyZN5JhoqLxbdPZi6UyKSdCeXAWJw9ja22m6S6Tzz1KZ+kAaSwvydi0g== + dependencies: + "@smithy/types" "^3.7.1" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-stream-node@^3.1.8": + version "3.1.9" + resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-3.1.9.tgz#97eb416811b7e7b9d036f0271588151b619759e9" + integrity sha512-3XfHBjSP3oDWxLmlxnt+F+FqXpL3WlXs+XXaB6bV9Wo8BBu87fK1dSEsyH7Z4ZHRmwZ4g9lFMdf08m9hoX1iRA== + dependencies: + "@smithy/types" "^3.7.1" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/invalid-dependency@^3.0.9": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.10.tgz#8616dee555916c24dec3e33b1e046c525efbfee3" + integrity sha512-Lp2L65vFi+cj0vFMu2obpPW69DU+6O5g3086lmI4XcnRCG8PxvpWC7XyaVwJCxsZFzueHjXnrOH/E0pl0zikfA== + dependencies: + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/is-array-buffer@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz#f84f0d9f9a36601a9ca9381688bd1b726fd39111" + integrity sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA== + dependencies: + tslib "^2.6.2" + +"@smithy/is-array-buffer@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz#9a95c2d46b8768946a9eec7f935feaddcffa5e7a" + integrity sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ== + dependencies: + tslib "^2.6.2" + +"@smithy/md5-js@^3.0.9": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-3.0.10.tgz#52ab927cf03cd1d24fed82d8ba936faf5632436e" + integrity sha512-m3bv6dApflt3fS2Y1PyWPUtRP7iuBlvikEOGwu0HsCZ0vE7zcIX+dBoh3e+31/rddagw8nj92j0kJg2TfV+SJA== + dependencies: + "@smithy/types" "^3.7.1" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/middleware-content-length@^3.0.11": + version "3.0.12" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-3.0.12.tgz#3b248ed1e8f1e0ae67171abb8eae9da7ab7ca613" + integrity sha512-1mDEXqzM20yywaMDuf5o9ue8OkJ373lSPbaSjyEvkWdqELhFMyNNgKGWL/rCSf4KME8B+HlHKuR8u9kRj8HzEQ== + dependencies: + "@smithy/protocol-http" "^4.1.7" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/middleware-endpoint@^3.2.2", "@smithy/middleware-endpoint@^3.2.3": + version "3.2.3" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.3.tgz#7dd3df0052fc55891522631a7751e613b6efd68a" + integrity sha512-Hdl9296i/EMptaX7agrSzJZDiz5Y8XPUeBbctTmMtnCguGpqfU3jVsTUan0VLaOhsnquqWLL8Bl5HrlbVGT1og== + dependencies: + "@smithy/core" "^2.5.3" + "@smithy/middleware-serde" "^3.0.10" + "@smithy/node-config-provider" "^3.1.11" + "@smithy/shared-ini-file-loader" "^3.1.11" + "@smithy/types" "^3.7.1" + "@smithy/url-parser" "^3.0.10" + "@smithy/util-middleware" "^3.0.10" + tslib "^2.6.2" + +"@smithy/middleware-retry@^3.0.26": + version "3.0.27" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.27.tgz#2e4dda420178835cd2d416479505d313b601ba21" + integrity sha512-H3J/PjJpLL7Tt+fxDKiOD25sMc94YetlQhCnYeNmina2LZscAdu0ZEZPas/kwePHABaEtqp7hqa5S4UJgMs1Tg== + dependencies: + "@smithy/node-config-provider" "^3.1.11" + "@smithy/protocol-http" "^4.1.7" + "@smithy/service-error-classification" "^3.0.10" + "@smithy/smithy-client" "^3.4.4" + "@smithy/types" "^3.7.1" + "@smithy/util-middleware" "^3.0.10" + "@smithy/util-retry" "^3.0.10" + tslib "^2.6.2" + uuid "^9.0.1" + +"@smithy/middleware-serde@^3.0.10", "@smithy/middleware-serde@^3.0.9": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.10.tgz#5f6c0b57b10089a21d355bd95e9b7d40378454d7" + integrity sha512-MnAuhh+dD14F428ubSJuRnmRsfOpxSzvRhaGVTvd/lrUDE3kxzCCmH8lnVTvoNQnV2BbJ4c15QwZ3UdQBtFNZA== + dependencies: + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/middleware-stack@^3.0.10", "@smithy/middleware-stack@^3.0.9": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.10.tgz#73e2fde5d151440844161773a17ee13375502baf" + integrity sha512-grCHyoiARDBBGPyw2BeicpjgpsDFWZZxptbVKb3CRd/ZA15F/T6rZjCCuBUjJwdck1nwUuIxYtsS4H9DDpbP5w== + dependencies: + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/node-config-provider@^3.1.10", "@smithy/node-config-provider@^3.1.11": + version "3.1.11" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.11.tgz#95feba85a5cb3de3fe9adfff1060b35fd556d023" + integrity sha512-URq3gT3RpDikh/8MBJUB+QGZzfS7Bm6TQTqoh4CqE8NBuyPkWa5eUXj0XFcFfeZVgg3WMh1u19iaXn8FvvXxZw== + dependencies: + "@smithy/property-provider" "^3.1.10" + "@smithy/shared-ini-file-loader" "^3.1.11" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/node-http-handler@^1.0.2": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-1.1.0.tgz#887cee930b520e08043c9f41e463f8d8f5dae127" + integrity sha512-d3kRriEgaIiGXLziAM8bjnaLn1fthCJeTLZIwEIpzQqe6yPX0a+yQoLCTyjb2fvdLwkMoG4p7THIIB5cj5lkbg== + dependencies: + "@smithy/abort-controller" "^1.1.0" + "@smithy/protocol-http" "^1.2.0" + "@smithy/querystring-builder" "^1.1.0" + "@smithy/types" "^1.2.0" + tslib "^2.5.0" + +"@smithy/node-http-handler@^3.3.0", "@smithy/node-http-handler@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-3.3.1.tgz#788fc1c22c21a0cf982f4025ccf9f64217f3164f" + integrity sha512-fr+UAOMGWh6bn4YSEezBCpJn9Ukp9oR4D32sCjCo7U81evE11YePOQ58ogzyfgmjIO79YeOdfXXqr0jyhPQeMg== + dependencies: + "@smithy/abort-controller" "^3.1.8" + "@smithy/protocol-http" "^4.1.7" + "@smithy/querystring-builder" "^3.0.10" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/property-provider@^3.1.10", "@smithy/property-provider@^3.1.9": + version "3.1.10" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.10.tgz#ae00447c1060c194c3e1b9475f7c8548a70f8486" + integrity sha512-n1MJZGTorTH2DvyTVj+3wXnd4CzjJxyXeOgnTlgNVFxaaMeT4OteEp4QrzF8p9ee2yg42nvyVK6R/awLCakjeQ== + dependencies: + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/protocol-http@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-1.2.0.tgz#a554e4dabb14508f0bc2cdef9c3710e2b294be04" + integrity sha512-GfGfruksi3nXdFok5RhgtOnWe5f6BndzYfmEXISD+5gAGdayFGpjWu5pIqIweTudMtse20bGbc+7MFZXT1Tb8Q== + dependencies: + "@smithy/types" "^1.2.0" + tslib "^2.5.0" + +"@smithy/protocol-http@^4.1.6", "@smithy/protocol-http@^4.1.7": + version "4.1.7" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.1.7.tgz#5c67e62beb5deacdb94f2127f9a344bdf1b2ed6e" + integrity sha512-FP2LepWD0eJeOTm0SjssPcgqAlDFzOmRXqXmGhfIM52G7Lrox/pcpQf6RP4F21k0+O12zaqQt5fCDOeBtqY6Cg== + dependencies: + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/querystring-builder@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-1.1.0.tgz#de6306104640ade34e59be33949db6cc64aa9d7f" + integrity sha512-gDEi4LxIGLbdfjrjiY45QNbuDmpkwh9DX4xzrR2AzjjXpxwGyfSpbJaYhXARw9p17VH0h9UewnNQXNwaQyYMDA== + dependencies: + "@smithy/types" "^1.2.0" + "@smithy/util-uri-escape" "^1.1.0" + tslib "^2.5.0" + +"@smithy/querystring-builder@^3.0.10": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-3.0.10.tgz#db8773af85ee3977c82b8e35a5cdd178c621306d" + integrity sha512-nT9CQF3EIJtIUepXQuBFb8dxJi3WVZS3XfuDksxSCSn+/CzZowRLdhDn+2acbBv8R6eaJqPupoI/aRFIImNVPQ== + dependencies: + "@smithy/types" "^3.7.1" + "@smithy/util-uri-escape" "^3.0.0" + tslib "^2.6.2" + +"@smithy/querystring-parser@^3.0.10": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.10.tgz#62db744a1ed2cf90f4c08d2c73d365e033b4a11c" + integrity sha512-Oa0XDcpo9SmjhiDD9ua2UyM3uU01ZTuIrNdZvzwUTykW1PM8o2yJvMh1Do1rY5sUQg4NDV70dMi0JhDx4GyxuQ== + dependencies: + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/service-error-classification@^3.0.10": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.10.tgz#941c549daf0e9abb84d3def1d9e1e3f0f74f5ba6" + integrity sha512-zHe642KCqDxXLuhs6xmHVgRwy078RfqxP2wRDpIyiF8EmsWXptMwnMwbVa50lw+WOGNrYm9zbaEg0oDe3PTtvQ== + dependencies: + "@smithy/types" "^3.7.1" + +"@smithy/shared-ini-file-loader@^3.1.10", "@smithy/shared-ini-file-loader@^3.1.11": + version "3.1.11" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.11.tgz#0b4f98c4a66480956fbbefc4627c5dc09d891aea" + integrity sha512-AUdrIZHFtUgmfSN4Gq9nHu3IkHMa1YDcN+s061Nfm+6pQ0mJy85YQDB0tZBCmls0Vuj22pLwDPmL92+Hvfwwlg== + dependencies: + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/signature-v4@^4.2.2": + version "4.2.3" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-4.2.3.tgz#abbca5e5fe9158422b3125b2956791a325a27f22" + integrity sha512-pPSQQ2v2vu9vc8iew7sszLd0O09I5TRc5zhY71KA+Ao0xYazIG+uLeHbTJfIWGO3BGVLiXjUr3EEeCcEQLjpWQ== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/protocol-http" "^4.1.7" + "@smithy/types" "^3.7.1" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-middleware" "^3.0.10" + "@smithy/util-uri-escape" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/smithy-client@^3.4.3", "@smithy/smithy-client@^3.4.4": + version "3.4.4" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.4.4.tgz#460870dc97d945fa2f390890359cf09d01131e0f" + integrity sha512-dPGoJuSZqvirBq+yROapBcHHvFjChoAQT8YPWJ820aPHHiowBlB3RL1Q4kPT1hx0qKgJuf+HhyzKi5Gbof4fNA== + dependencies: + "@smithy/core" "^2.5.3" + "@smithy/middleware-endpoint" "^3.2.3" + "@smithy/middleware-stack" "^3.0.10" + "@smithy/protocol-http" "^4.1.7" + "@smithy/types" "^3.7.1" + "@smithy/util-stream" "^3.3.1" + tslib "^2.6.2" + +"@smithy/types@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-1.2.0.tgz#9dc65767b0ee3d6681704fcc67665d6fc9b6a34e" + integrity sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA== + dependencies: + tslib "^2.5.0" + +"@smithy/types@^3.7.0", "@smithy/types@^3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.7.1.tgz#4af54c4e28351e9101996785a33f2fdbf93debe7" + integrity sha512-XKLcLXZY7sUQgvvWyeaL/qwNPp6V3dWcUjqrQKjSb+tzYiCy340R/c64LV5j+Tnb2GhmunEX0eou+L+m2hJNYA== + dependencies: + tslib "^2.6.2" + +"@smithy/url-parser@^3.0.10", "@smithy/url-parser@^3.0.9": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.10.tgz#f389985a79766cff4a99af14979f01a17ce318da" + integrity sha512-j90NUalTSBR2NaZTuruEgavSdh8MLirf58LoGSk4AtQfyIymogIhgnGUU2Mga2bkMkpSoC9gxb74xBXL5afKAQ== + dependencies: + "@smithy/querystring-parser" "^3.0.10" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/util-base64@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-3.0.0.tgz#f7a9a82adf34e27a72d0719395713edf0e493017" + integrity sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ== + dependencies: + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-body-length-browser@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz#86ec2f6256310b4845a2f064e2f571c1ca164ded" + integrity sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-body-length-node@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz#99a291bae40d8932166907fe981d6a1f54298a6d" + integrity sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA== + dependencies: + tslib "^2.6.2" + +"@smithy/util-buffer-from@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz#6fc88585165ec73f8681d426d96de5d402021e4b" + integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA== + dependencies: + "@smithy/is-array-buffer" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-buffer-from@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz#559fc1c86138a89b2edaefc1e6677780c24594e3" + integrity sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-config-provider@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz#62c6b73b22a430e84888a8f8da4b6029dd5b8efe" + integrity sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-defaults-mode-browser@^3.0.26": + version "3.0.27" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.27.tgz#d5df39faee8ad4bb5a6920b208469caa9dda2ccb" + integrity sha512-GV8NvPy1vAGp7u5iD/xNKUxCorE4nQzlyl057qRac+KwpH5zq8wVq6rE3lPPeuFLyQXofPN6JwxL1N9ojGapiQ== + dependencies: + "@smithy/property-provider" "^3.1.10" + "@smithy/smithy-client" "^3.4.4" + "@smithy/types" "^3.7.1" + bowser "^2.11.0" + tslib "^2.6.2" + +"@smithy/util-defaults-mode-node@^3.0.26": + version "3.0.27" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.27.tgz#a7248c9d9cb620827ab57ef9d1867bfe8aef42d0" + integrity sha512-7+4wjWfZqZxZVJvDutO+i1GvL6bgOajEkop4FuR6wudFlqBiqwxw3HoH6M9NgeCd37km8ga8NPp2JacQEtAMPg== + dependencies: + "@smithy/config-resolver" "^3.0.12" + "@smithy/credential-provider-imds" "^3.2.7" + "@smithy/node-config-provider" "^3.1.11" + "@smithy/property-provider" "^3.1.10" + "@smithy/smithy-client" "^3.4.4" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/util-endpoints@^2.1.5": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.1.6.tgz#720cbd1a616ad7c099b77780f0cb0f1f9fc5d2df" + integrity sha512-mFV1t3ndBh0yZOJgWxO9J/4cHZVn5UG1D8DeCc6/echfNkeEJWu9LD7mgGH5fHrEdR7LDoWw7PQO6QiGpHXhgA== + dependencies: + "@smithy/node-config-provider" "^3.1.11" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/util-hex-encoding@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz#32938b33d5bf2a15796cd3f178a55b4155c535e6" + integrity sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-middleware@^3.0.10", "@smithy/util-middleware@^3.0.9": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-3.0.10.tgz#ab8be99f1aaafe5a5490c344f27a264b72b7592f" + integrity sha512-eJO+/+RsrG2RpmY68jZdwQtnfsxjmPxzMlQpnHKjFPwrYqvlcT+fHdT+ZVwcjlWSrByOhGr9Ff2GG17efc192A== + dependencies: + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/util-retry@^3.0.10", "@smithy/util-retry@^3.0.9": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.10.tgz#fc13e1b30e87af0cbecadf29ca83b171e2040440" + integrity sha512-1l4qatFp4PiU6j7UsbasUHL2VU023NRB/gfaa1M0rDqVrRN4g3mCArLRyH3OuktApA4ye+yjWQHjdziunw2eWA== + dependencies: + "@smithy/service-error-classification" "^3.0.10" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + +"@smithy/util-stream@^3.3.0", "@smithy/util-stream@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.3.1.tgz#a2636f435637ef90d64df2bb8e71cd63236be112" + integrity sha512-Ff68R5lJh2zj+AUTvbAU/4yx+6QPRzg7+pI7M1FbtQHcRIp7xvguxVsQBKyB3fwiOwhAKu0lnNyYBaQfSW6TNw== + dependencies: + "@smithy/fetch-http-handler" "^4.1.1" + "@smithy/node-http-handler" "^3.3.1" + "@smithy/types" "^3.7.1" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-uri-escape@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-1.1.0.tgz#a8c5edaf19c0efdb9b51661e840549cf600a1808" + integrity sha512-/jL/V1xdVRt5XppwiaEU8Etp5WHZj609n0xMTuehmCqdoOFbId1M+aEeDWZsQ+8JbEB/BJ6ynY2SlYmOaKtt8w== + dependencies: + tslib "^2.5.0" + +"@smithy/util-uri-escape@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz#e43358a78bf45d50bb736770077f0f09195b6f54" + integrity sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg== + dependencies: + tslib "^2.6.2" + +"@smithy/util-utf8@^2.0.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz#dd96d7640363259924a214313c3cf16e7dd329c5" + integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== + dependencies: + "@smithy/util-buffer-from" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-utf8@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-3.0.0.tgz#1a6a823d47cbec1fd6933e5fc87df975286d9d6a" + integrity sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA== + dependencies: + "@smithy/util-buffer-from" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-waiter@^3.1.8": + version "3.1.9" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-3.1.9.tgz#1330ce2e79b58419d67755d25bce7a226e32dc6d" + integrity sha512-/aMXPANhMOlMPjfPtSrDfPeVP8l56SJlz93xeiLmhLe5xvlXA5T3abZ2ilEsDEPeY9T/wnN/vNGn9wa1SbufWA== + dependencies: + "@smithy/abort-controller" "^3.1.8" + "@smithy/types" "^3.7.1" + tslib "^2.6.2" + "@socket.io/component-emitter@~3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" @@ -3916,6 +5197,17 @@ oauth "~0.9.0" passport-strategy "^1.0.0" +"@techteamer/ocsp@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@techteamer/ocsp/-/ocsp-1.0.1.tgz#420f80c64ff0f74a70b65c88e4031c03a9da6ded" + integrity sha512-q4pW5wAC6Pc3JI8UePwE37CkLQ5gDGZMgjSX4MEEm4D4Di59auDQ8UNIDzC4gRnPNmmcwjpPxozq8p5pjiOmOw== + dependencies: + asn1.js "^5.4.1" + asn1.js-rfc2560 "^5.0.1" + asn1.js-rfc5280 "^3.0.0" + async "^3.2.4" + simple-lru-cache "^0.0.2" + "@tediousjs/connection-string@^0.5.0": version "0.5.0" resolved "https://registry.yarnpkg.com/@tediousjs/connection-string/-/connection-string-0.5.0.tgz#9b3d858c040aac6bdf5584bf45370cef5b6522b4" @@ -4424,6 +5716,14 @@ "@types/node" "*" form-data "^3.0.0" +"@types/node-fetch@^2.5.0": + version "2.6.12" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.12.tgz#8ab5c3ef8330f13100a7479e2cd56d3386830a03" + integrity sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA== + dependencies: + "@types/node" "*" + form-data "^4.0.0" + "@types/node-fetch@^2.6.4": version "2.6.11" resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24" @@ -4451,6 +5751,13 @@ dependencies: undici-types "~5.26.4" +"@types/node@>=18": + version "22.9.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.1.tgz#bdf91c36e0e7ecfb7257b2d75bf1b206b308ca71" + integrity sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg== + dependencies: + undici-types "~6.19.8" + "@types/node@>=8.0.0 <15": version "14.18.37" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.37.tgz#0bfcd173e8e1e328337473a8317e37b3b14fd30d" @@ -4838,6 +6145,18 @@ resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397" integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw== +"@types/triple-beam@^1.3.2": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.5.tgz#74fef9ffbaa198eb8b588be029f38b00299caa2c" + integrity sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw== + +"@types/tunnel@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.3.tgz#f109e730b072b3136347561fc558c9358bb8c6e9" + integrity sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA== + dependencies: + "@types/node" "*" + "@types/uuid@8.3.4": version "8.3.4" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" @@ -5331,7 +6650,7 @@ agent-base@6, agent-base@^6.0.2: dependencies: debug "4" -agent-base@^7.0.2: +agent-base@^7.0.2, agent-base@^7.1.0: version "7.1.1" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== @@ -5725,7 +7044,7 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== -arrify@^2.0.1: +arrify@^2.0.0, arrify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== @@ -5735,6 +7054,20 @@ asap@^2.0.0: resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== +asn1.js-rfc2560@^5.0.0, asn1.js-rfc2560@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/asn1.js-rfc2560/-/asn1.js-rfc2560-5.0.1.tgz#cff99b903e714756b29503ad49de01c72f131e60" + integrity sha512-1PrVg6kuBziDN3PGFmRk3QrjpKvP9h/Hv5yMrFZvC1kpzP6dQRzf5BpKstANqHBkaOUmTpakJWhicTATOA/SbA== + dependencies: + asn1.js-rfc5280 "^3.0.0" + +asn1.js-rfc5280@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/asn1.js-rfc5280/-/asn1.js-rfc5280-3.0.0.tgz#94e60498d5d4984b842d1a825485837574ccc902" + integrity sha512-Y2LZPOWeZ6qehv698ZgOGGCZXBQShObWnGthTrIFlIQjuV1gg2B8QOhWFRExq/MR1VnPpIIe7P9vX2vElxv+Pg== + dependencies: + asn1.js "^5.0.0" + asn1.js@^4.10.1: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -5744,6 +7077,16 @@ asn1.js@^4.10.1: inherits "^2.0.1" minimalistic-assert "^1.0.0" +asn1.js@^5.0.0, asn1.js@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" + integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + safer-buffer "^2.1.0" + asn1@^0.2.6: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" @@ -5776,6 +7119,13 @@ async-lock@^1.4.1: resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.4.1.tgz#56b8718915a9b68b10fce2f2a9a3dddf765ef53f" integrity sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ== +async-retry@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" + integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== + dependencies: + retry "0.13.1" + async@^3.2.3, async@^3.2.4: version "3.2.5" resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" @@ -5825,22 +7175,23 @@ aws-cloudfront-sign@3.0.2: resolved "https://registry.yarnpkg.com/aws-cloudfront-sign/-/aws-cloudfront-sign-3.0.2.tgz#da5273b0301bcd70312c8c76293d5fec6d414f0a" integrity sha512-Z/yOGZ3Hd1rhYbY13mtRiLCbCDC1Xf/v+dQUyUwMLnyunD/nfDZd/2LMZ9MKxxOhVb2RzEmEwY0F9f+riPaSWQ== -aws-sdk@2.1030.0: - version "2.1030.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1030.0.tgz#24a856af3d2b8b37c14a8f59974993661c66fd82" - integrity sha512-to0STOb8DsSGuSsUb/WCbg/UFnMGfIYavnJH5ZlRCHzvCFjTyR+vfE8ku+qIZvfFM4+5MNTQC/Oxfun2X/TuyA== +aws-sdk@2.1692.0: + version "2.1692.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1692.0.tgz#9dac5f7bfcc5ab45825cc8591b12753aa7d2902c" + integrity sha512-x511uiJ/57FIsbgUe5csJ13k3uzu25uWQE+XqfBis/sB0SFoiElJWXRkgEAUh0U6n40eT3ay5Ue4oPkRMu1LYw== dependencies: buffer "4.9.2" events "1.1.1" ieee754 "1.1.13" - jmespath "0.15.0" + jmespath "0.16.0" querystring "0.2.0" sax "1.2.1" url "0.10.3" - uuid "3.3.2" - xml2js "0.4.19" + util "^0.12.4" + uuid "8.0.0" + xml2js "0.6.2" -axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2: +axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -6061,16 +7412,31 @@ before-after-hook@^2.2.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== +big-integer@^1.6.43: + version "1.6.52" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" + integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== + bignumber.js@^9.0.0: version "9.1.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.1.tgz#c4df7dc496bd849d4c9464344c1aa74228b4dac6" integrity sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig== +bignumber.js@^9.1.2: + version "9.1.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" + integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== +binascii@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/binascii/-/binascii-0.0.2.tgz#a7f8a8801dbccf8b1756b743daa0fee9e2d9e0ee" + integrity sha512-rA2CrUl1+6yKrn+XgLs8Hdy18OER1UW146nM+ixzhQXDY+Bd3ySkyIJGwF2a4I45JwbvF1mDL/nWkqBwpOcdBA== + bl@^1.0.0: version "1.2.3" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" @@ -6088,10 +7454,10 @@ bl@^4.0.3, bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" -bl@^6.0.3: - version "6.0.13" - resolved "https://registry.yarnpkg.com/bl/-/bl-6.0.13.tgz#dc5f288d3f849771bb6112b29477abee4c0a9d96" - integrity sha512-tMncAcpsyjZgAVbVFupVIaB2xud13xxT59fdHkuszY2jdZkqIWfpQdmII1fOe3kOGAz0mNLTIHEm+KxpYsQKKg== +bl@^6.0.11: + version "6.0.16" + resolved "https://registry.yarnpkg.com/bl/-/bl-6.0.16.tgz#29b190f1a754e2d168de3dc8c74ed8d12bf78e6e" + integrity sha512-V/kz+z2Mx5/6qDfRCilmrukUXcXuCoXKg3/3hDvzKKoSUx8CJKudfIoT29XZc3UE9xBvxs5qictiHdprwtteEg== dependencies: "@types/readable-stream" "^4.0.0" buffer "^6.0.3" @@ -6135,6 +7501,11 @@ boolean@^3.0.1: resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b" integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw== +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + boxen@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" @@ -6181,6 +7552,11 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== +browser-request@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/browser-request/-/browser-request-0.3.3.tgz#9ece5b5aca89a29932242e18bf933def9876cc17" + integrity sha512-YyNI4qJJ+piQG6MMEuo7J3Bzaqssufx04zpEKYfSrl/1Op59HWali9zMtBpXnkmqMcOuWJPZvudrm9wISmnCbg== + browserify-aes@^1.0.4, browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" @@ -6849,7 +8225,7 @@ collect-v8-coverage@^1.0.0: resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== -color-convert@^1.9.0: +color-convert@^1.9.0, color-convert@^1.9.3: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== @@ -6868,16 +8244,32 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== -color-name@^1.1.4, color-name@~1.1.4: +color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +color-string@^1.6.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" + integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + color-support@^1.1.2, color-support@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== +color@^3.1.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" + integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== + dependencies: + color-convert "^1.9.3" + color-string "^1.6.0" + colord@^2.9.1: version "2.9.3" resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" @@ -6888,6 +8280,14 @@ colorette@2.0.19, colorette@^2.0.7: resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== +colorspace@1.1.x: + version "1.1.4" + resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" + integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w== + dependencies: + color "^3.1.3" + text-hex "1.0.x" + columnify@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.6.0.tgz#6989531713c9008bb29735e61e37acf5bd553cf3" @@ -8492,6 +9892,16 @@ duplexify@^4.0.0, duplexify@^4.1.2: readable-stream "^3.1.1" stream-shift "^1.0.0" +duplexify@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.3.tgz#a07e1c0d0a2c001158563d32592ba58bddb0236f" + integrity sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.2" + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -8575,6 +9985,11 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== +enabled@2.0.x: + version "2.0.0" + resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" + integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== + encodeurl@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -8697,7 +10112,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2: +es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0: version "1.23.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== @@ -8749,20 +10164,6 @@ es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23 unbox-primitive "^1.0.2" which-typed-array "^1.1.15" -es-aggregate-error@^1.0.9: - version "1.0.13" - resolved "https://registry.yarnpkg.com/es-aggregate-error/-/es-aggregate-error-1.0.13.tgz#7f28b77c9d8d09bbcd3a466e4be9fe02fa985201" - integrity sha512-KkzhUUuD2CUMqEc8JEqsXEMDHzDPE8RCjZeUBitsnB1eNcAJWQPiciKsMXe3Yytj4Flw1XLl46Qcf9OxvZha7A== - dependencies: - define-data-property "^1.1.4" - define-properties "^1.2.1" - es-abstract "^1.23.2" - es-errors "^1.3.0" - function-bind "^1.1.2" - globalthis "^1.0.3" - has-property-descriptors "^1.0.2" - set-function-name "^2.0.2" - es-define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" @@ -9254,6 +10655,13 @@ expand-template@^2.0.3: resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== +expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw== + dependencies: + homedir-polyfill "^1.0.1" + expect@^29.0.0, expect@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" @@ -9369,13 +10777,18 @@ fast-url-parser@^1.1.3: dependencies: punycode "^1.3.2" -fast-xml-parser@4.4.1: +fast-xml-parser@4.4.1, fast-xml-parser@^4.2.5, fast-xml-parser@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== dependencies: strnum "^1.0.5" +fastest-levenshtein@^1.0.16: + version "1.0.16" + resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" + integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== + fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -9397,6 +10810,11 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" +fecha@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" + integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== + fengari-interop@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/fengari-interop/-/fengari-interop-0.1.3.tgz#3ad37a90e7430b69b365441e9fc0ba168942a146" @@ -9589,6 +11007,11 @@ flatten@^1.0.2: resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== +fn.name@1.x.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" + integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== + follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" @@ -9802,6 +11225,17 @@ gaxios@^6.0.0, gaxios@^6.1.1: node-fetch "^2.6.9" uuid "^10.0.0" +gaxios@^6.0.2: + version "6.7.1" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-6.7.1.tgz#ebd9f7093ede3ba502685e73390248bb5b7f71fb" + integrity sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ== + dependencies: + extend "^3.0.2" + https-proxy-agent "^7.0.1" + is-stream "^2.0.0" + node-fetch "^2.6.9" + uuid "^9.0.1" + gcp-metadata@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-6.1.0.tgz#9b0dd2b2445258e7597f2024332d20611cbd6b8c" @@ -9824,7 +11258,7 @@ generic-names@^4.0.0: dependencies: loader-utils "^3.2.0" -generic-pool@3.9.0: +generic-pool@3.9.0, generic-pool@^3.8.2: version "3.9.0" resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-3.9.0.tgz#36f4a678e963f4fdb8707eab050823abc4e8f5e4" integrity sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g== @@ -10215,6 +11649,18 @@ google-auth-library@^9.3.0: gtoken "^7.0.0" jws "^4.0.0" +google-auth-library@^9.6.3: + version "9.15.0" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-9.15.0.tgz#1b009c08557929c881d72f953f17e839e91b009b" + integrity sha512-7ccSEJFDFO7exFbO6NRyC+xH8/mZ1GZGG2xxx9iHxZWcjUjJpjWxIMw3cofAKcueZ6DATiukmmprD7yavQHOyQ== + dependencies: + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + gaxios "^6.1.1" + gcp-metadata "^6.1.0" + gtoken "^7.0.0" + jws "^4.0.0" + google-gax@^4.3.3: version "4.3.7" resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-4.3.7.tgz#f1870902d09c54c5d1735ef1ee7903d4458d6a49" @@ -10466,6 +11912,13 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -10511,6 +11964,11 @@ html-encoding-sniffer@^3.0.0: dependencies: whatwg-encoding "^2.0.0" +html-entities@^2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" + integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -10609,6 +12067,14 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" +http-proxy-agent@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" + integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig== + dependencies: + agent-base "^7.1.0" + debug "^4.3.4" + https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -10617,7 +12083,7 @@ https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: agent-base "6" debug "4" -https-proxy-agent@^7.0.1: +https-proxy-agent@^7.0.0, https-proxy-agent@^7.0.1, https-proxy-agent@^7.0.2: version "7.0.5" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz#9e8b5013873299e11fab6fd548405da2d6c602b2" integrity sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw== @@ -10642,11 +12108,6 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== -husky@^9.1.4: - version "9.1.7" - resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" - integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== - ical-generator@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ical-generator/-/ical-generator-4.1.0.tgz#2a336c951864c5583a2aa715d16f2edcdfd2d90b" @@ -10978,11 +12439,11 @@ ip@^2.0.0: integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== ipaddr.js@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f" - integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ== + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== -is-arguments@^1.1.1: +is-arguments@^1.0.4, is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== @@ -11003,6 +12464,11 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + is-bigint@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" @@ -11358,7 +12824,7 @@ is-type-of@^1.0.0: is-class-hotfix "~0.0.6" isstream "~0.1.2" -is-typed-array@^1.1.13: +is-typed-array@^1.1.13, is-typed-array@^1.1.3: version "1.1.13" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== @@ -11415,7 +12881,7 @@ is-whitespace@^0.3.0: resolved "https://registry.yarnpkg.com/is-whitespace/-/is-whitespace-0.3.0.tgz#1639ecb1be036aec69a54cbb401cfbed7114ab7f" integrity sha512-RydPhl4S6JwAyj0JJjshWJEFG6hNye3pZFBRZaTUfZFwGHxzppNaNOVgQuS/E/SlhrApuMXrpnK1EEIXfdo3Dg== -is-wsl@^2.2.0: +is-wsl@^2.1.1, is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== @@ -12017,10 +13483,10 @@ jimp@1.1.4: "@jimp/types" "1.1.4" "@jimp/utils" "1.1.4" -jmespath@0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" - integrity sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w== +jmespath@0.16.0: + version "0.16.0" + resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.16.0.tgz#b15b0a85dfd4d930d43e69ed605943c802785076" + integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== joi@17.6.0: version "17.6.0" @@ -12078,11 +13544,6 @@ js-yaml@^3.10.0, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -jsbi@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/jsbi/-/jsbi-4.3.0.tgz#b54ee074fb6fcbc00619559305c8f7e912b04741" - integrity sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g== - jsdom@^16.0.1: version "16.7.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" @@ -12588,6 +14049,11 @@ koalas@^1.0.2: resolved "https://registry.yarnpkg.com/koalas/-/koalas-1.0.2.tgz#318433f074235db78fae5661a02a8ca53ee295cd" integrity sha512-RYhBbYaTTTHId3l6fnMZc3eGQNW6FVCqMG6AMwA5I1Mafr6AflaXeoi6x3xQuATRotGYRLk6+1ELZH4dstFNOA== +kuler@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" + integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== + latest-version@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" @@ -13185,6 +14651,23 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" +logform@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.7.0.tgz#cfca97528ef290f2e125a08396805002b2d060d1" + integrity sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ== + dependencies: + "@colors/colors" "1.6.0" + "@types/triple-beam" "^1.3.2" + fecha "^4.2.0" + ms "^2.1.1" + safe-stable-stringify "^2.3.1" + triple-beam "^1.3.0" + +long@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" + integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== + long@^5.0.0, long@^5.2.1: version "5.2.3" resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" @@ -13565,7 +15048,7 @@ mime-kind@^3.0.0: file-type "^12.1.0" mime-types "^2.1.24" -mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.24, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.24, mime-types@^2.1.29, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -13837,6 +15320,18 @@ module-lookup-amd@^7.0.1: requirejs "^2.3.5" requirejs-config-file "^4.0.0" +moment-timezone@^0.5.15: + version "0.5.46" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.46.tgz#a21aa6392b3c6b3ed916cd5e95858a28d893704a" + integrity sha512-ZXm9b36esbe7OmdABqIWJuBBiLLwAjrN7CE+7sYdCCx82Nabt1wHDj8TVseS59QIlfFPbOoiBPm6ca9BioG4hw== + dependencies: + moment "^2.29.4" + +moment@^2.29.4: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + mongodb-connection-string-url@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.0.tgz#b4f87f92fd8593f3b9365f592515a06d304a1e9c" @@ -13895,17 +15390,17 @@ msgpackr@1.10.1, msgpackr@^1.5.2: optionalDependencies: msgpackr-extract "^3.0.2" -mssql@10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/mssql/-/mssql-10.0.1.tgz#96053ae91b96fdc0469b9d8ca34663d448075bdf" - integrity sha512-k0Xkav/3OppZs8Kj+FIo7k7ejbcsVNxp5/ePayxfXzuBZhxD/Y/RhIhrtfHyH6FmlJnBQPj7eDI2IN7B0BiSxQ== +mssql@11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/mssql/-/mssql-11.0.1.tgz#a32ab7763bfbb3f5d970e47563df3911fc04e21d" + integrity sha512-KlGNsugoT90enKlR8/G36H0kTxPthDhmtNUCwEHvgRza5Cjpjoj+P2X6eMpFUDN7pFrJZsKadL4x990G8RBE1w== dependencies: "@tediousjs/connection-string" "^0.5.0" commander "^11.0.0" debug "^4.3.3" rfdc "^1.3.0" tarn "^3.0.2" - tedious "^16.4.0" + tedious "^18.2.1" multi-part-lite@^1.0.0: version "1.0.0" @@ -14624,6 +16119,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +one-time@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45" + integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g== + dependencies: + fn.name "1.x.x" + onetime@^5.1.0, onetime@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -14636,6 +16138,14 @@ only@~0.0.2: resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" integrity sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ== +open@^7.3.1: + version "7.4.2" + resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" + integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== + dependencies: + is-docker "^2.0.0" + is-wsl "^2.1.1" + open@^8.0.0, open@^8.4.0, open@~8.4.0: version "8.4.2" resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9" @@ -14825,7 +16335,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.1, p-limit@^3.0.2, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -15047,6 +16557,11 @@ parse-ms@^2.1.0: resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-2.1.0.tgz#348565a753d4391fa524029956b172cb7753097d" integrity sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA== +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== + parse-path@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-7.0.0.tgz#605a2d58d0a749c8594405d8cc3a2bf76d16099b" @@ -15198,9 +16713,9 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-to-regexp@1.x: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== + version "1.9.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" + integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== dependencies: isarray "0.0.1" @@ -16445,6 +17960,13 @@ pure-rand@^6.0.0: resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.0.1.tgz#31207dddd15d43f299fdcdb2f572df65030c19af" integrity sha512-t+x1zEHDjBwkDGY5v5ApnZ/utcd4XYDiJsaQQoptTXgUXX95sDg1elCdJghzicm7n2mbCBJ3uYWr6M22SO19rg== +python-struct@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/python-struct/-/python-struct-1.1.3.tgz#f0ff1845ec520408e94dd8492bfd770aad26cae3" + integrity sha512-UsI/mNvk25jRpGKYI38Nfbv84z48oiIWwG67DLVvjRhy8B/0aIK+5Ju5WOHgw/o9rnEmbAS00v4rgKFQeC332Q== + dependencies: + long "^4.0.0" + q@^1.1.2: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -16656,6 +18178,15 @@ readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.2.2, readable string_decoder "~1.1.1" util-deprecate "~1.0.1" +readable-stream@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + readable-stream@^4.0.0, readable-stream@^4.2.0: version "4.5.1" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.1.tgz#3f2e4e66eab45606ac8f31597b9edb80c13b12ab" @@ -16976,16 +18507,16 @@ retry-request@^7.0.0: extend "^3.0.2" teeny-request "^9.0.0" +retry@0.13.1, retry@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity "sha1-GFsVh6z2eRnWOzVzSeA1N7JIRlg= sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" + retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== -retry@^0.13.1: - version "0.13.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" - integrity "sha1-GFsVh6z2eRnWOzVzSeA1N7JIRlg= sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==" - reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" @@ -17277,7 +18808,7 @@ safe-stable-stringify@^2.1.0, safe-stable-stringify@^2.3.1: resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -17443,7 +18974,7 @@ set-function-length@^1.2.1: gopd "^1.0.1" has-property-descriptors "^1.0.2" -set-function-name@^2.0.1, set-function-name@^2.0.2: +set-function-name@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== @@ -17580,6 +19111,18 @@ simple-get@^4.0.0: once "^1.3.1" simple-concat "^1.0.0" +simple-lru-cache@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/simple-lru-cache/-/simple-lru-cache-0.0.2.tgz#d59cc3a193c1a5d0320f84ee732f6e4713e511dd" + integrity sha512-uEv/AFO0ADI7d99OHDmh1QfYzQk/izT1vCmu/riQfh7qjBVUUgRT87E5s5h7CxWCA/+YoZerykpEthzVrW3LIw== + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== + dependencies: + is-arrayish "^0.3.1" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -17613,6 +19156,42 @@ smob@^1.0.0: resolved "https://registry.yarnpkg.com/smob/-/smob-1.5.0.tgz#85d79a1403abf128d24d3ebc1cdc5e1a9548d3ab" integrity sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig== +snowflake-sdk@^1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/snowflake-sdk/-/snowflake-sdk-1.15.0.tgz#cc32fa0f2869d9e5a026e293b50d387ddbd67aca" + integrity sha512-u7eNIT2JWkA8USJF6gTOCcReNrdh8V9LCazJi3F0XnX5ZJkgPz2gNSn67drT4ywqNaXdXfFM0i/yNSa58fi2Rg== + dependencies: + "@aws-sdk/client-s3" "^3.388.0" + "@aws-sdk/node-http-handler" "^3.374.0" + "@azure/storage-blob" "12.18.x" + "@google-cloud/storage" "^7.7.0" + "@techteamer/ocsp" "1.0.1" + asn1.js-rfc2560 "^5.0.0" + asn1.js-rfc5280 "^3.0.0" + axios "^1.6.8" + big-integer "^1.6.43" + bignumber.js "^9.1.2" + binascii "0.0.2" + bn.js "^5.2.1" + browser-request "^0.3.3" + expand-tilde "^2.0.2" + fast-xml-parser "^4.2.5" + fastest-levenshtein "^1.0.16" + generic-pool "^3.8.2" + glob "^10.0.0" + https-proxy-agent "^7.0.2" + jsonwebtoken "^9.0.0" + mime-types "^2.1.29" + mkdirp "^1.0.3" + moment "^2.29.4" + moment-timezone "^0.5.15" + open "^7.3.1" + python-struct "^1.1.3" + simple-lru-cache "^0.0.2" + toml "^3.0.0" + uuid "^8.3.2" + winston "^3.1.0" + socket.io-adapter@~2.5.2: version "2.5.5" resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz#c7a1f9c703d7756844751b6ff9abfc1780664082" @@ -17831,6 +19410,11 @@ sprintf-js@^1.1.1, sprintf-js@^1.1.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.2.tgz#da1765262bf8c0f571749f2ad6c26300207ae673" integrity sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug== +sprintf-js@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" + integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -17879,6 +19463,11 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== +stack-trace@0.0.x: + version "0.0.10" + resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" + integrity sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg== + stack-utils@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" @@ -17935,6 +19524,11 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== +stream-shift@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== + stream-to-array@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353" @@ -17975,16 +19569,7 @@ string-range@~1.2, string-range@~1.2.1: resolved "https://registry.yarnpkg.com/string-range/-/string-range-1.2.2.tgz#a893ed347e72299bc83befbbf2a692a8d239d5dd" integrity sha512-tYft6IFi8SjplJpxCUxyqisD3b+R2CSkomrtJYCkvuf1KuCAWgz7YXt4O0jip7efpfCemwHEzTEAO8EuOYgh3w== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -18067,7 +19652,7 @@ stringify-object@^3.2.1: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -18081,13 +19666,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -18531,22 +20109,21 @@ tarn@^3.0.1, tarn@^3.0.2: resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.2.tgz#73b6140fbb881b71559c4f8bfde3d9a4b3d27693" integrity sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ== -tedious@^16.4.0: - version "16.7.1" - resolved "https://registry.yarnpkg.com/tedious/-/tedious-16.7.1.tgz#1190f30fd99a413f1dc9250dee4835cf0788b650" - integrity sha512-NmedZS0NJiTv3CoYnf1FtjxIDUgVYzEmavrc8q2WHRb+lP4deI9BpQfmNnBZZaWusDbP5FVFZCcvzb3xOlNVlQ== +tedious@^18.2.1: + version "18.6.1" + resolved "https://registry.yarnpkg.com/tedious/-/tedious-18.6.1.tgz#1c4a3f06c891be67a032117e2e25193286d44496" + integrity sha512-9AvErXXQTd6l7TDd5EmM+nxbOGyhnmdbp/8c3pw+tjaiSXW9usME90ET/CRG1LN1Y9tPMtz/p83z4Q97B4DDpw== dependencies: - "@azure/identity" "^3.4.1" + "@azure/core-auth" "^1.7.2" + "@azure/identity" "^4.2.1" "@azure/keyvault-keys" "^4.4.0" - "@js-joda/core" "^5.5.3" - bl "^6.0.3" - es-aggregate-error "^1.0.9" + "@js-joda/core" "^5.6.1" + "@types/node" ">=18" + bl "^6.0.11" iconv-lite "^0.6.3" js-md4 "^0.3.2" - jsbi "^4.3.0" native-duplexpair "^1.0.0" - node-abort-controller "^3.1.1" - sprintf-js "^1.1.2" + sprintf-js "^1.1.3" teeny-request@^9.0.0: version "9.0.0" @@ -18609,6 +20186,11 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== +text-hex@1.0.x: + version "1.0.0" + resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" + integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -18678,6 +20260,11 @@ timekeeper@2.2.0: resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.2.0.tgz#9645731fce9e3280a18614a57a9d1b72af3ca368" integrity sha512-W3AmPTJWZkRwu+iSNxPIsLZ2ByADsOLbbLxe46UJyWj3mlYLlwucKiq+/dPm0l9wTzqoF3/2PH0AGFCebjq23A== +timekeeper@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/timekeeper/-/timekeeper-2.3.1.tgz#2deb6e0b95d93625fda84c18d47f84a99e4eba01" + integrity sha512-LeQRS7/4JcC0PgdSFnfUiStQEdiuySlCj/5SJ18D+T1n9BoY7PxKFfCwLulpHXoLUFr67HxBddQdEX47lDGx1g== + tiny-glob@^0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2" @@ -18785,6 +20372,11 @@ token-types@^4.1.1: "@tokenizer/token" "^0.3.0" ieee754 "^1.2.1" +toml@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" + integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== + toposort@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" @@ -18854,6 +20446,11 @@ trim-repeated@^1.0.0: dependencies: escape-string-regexp "^1.0.2" +triple-beam@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" + integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== + ts-api-utils@^1.0.1, ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" @@ -18916,7 +20513,7 @@ tsconfig-paths@^3.10.1, tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tsconfig-paths@^4.1.2: +tsconfig-paths@^4.1.2, tsconfig-paths@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== @@ -18935,6 +20532,11 @@ tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.4.1, tslib@^2.6 resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== +tslib@^2.5.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tsscmp@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" @@ -18963,6 +20565,11 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" +tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + tweetnacl@^0.14.3: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" @@ -19190,7 +20797,7 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== -undici-types@~6.19.2: +undici-types@~6.19.2, undici-types@~6.19.8: version "6.19.8" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== @@ -19393,6 +21000,17 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +util@^0.12.4: + version "0.12.5" + resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" + integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== + dependencies: + inherits "^2.0.3" + is-arguments "^1.0.4" + is-generator-function "^1.0.7" + is-typed-array "^1.1.3" + which-typed-array "^1.1.2" + utils-merge@1.x.x, utils-merge@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -19403,17 +21021,17 @@ uuid-random@^1.3.2: resolved "https://registry.yarnpkg.com/uuid-random/-/uuid-random-1.3.2.tgz#96715edbaef4e84b1dcf5024b00d16f30220e2d0" integrity sha512-UOzej0Le/UgkbWEO8flm+0y+G+ljUon1QWTEZOq1rnMAsxo2+SckbiZdKzAHHlVh6gJqI1TjC/xwgR50MuCrBQ== -uuid@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== +uuid@8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" + integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== uuid@8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.1.0.tgz#6f1536eb43249f473abc6bd58ff983da1ca30d8d" integrity sha512-CI18flHDznR0lq54xBycOVmphdCYnQLKn8abKn7PXUiKUGdEd+/l9LWNJmugXel4hXq7S+RMNl34ecyC9TntWg== -uuid@8.3.2, uuid@^8.3.0, uuid@^8.3.1, uuid@^8.3.2: +uuid@8.3.2, uuid@^8.0.0, uuid@^8.3.0, uuid@^8.3.1, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -19730,7 +21348,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== -which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15: +which-typed-array@^1.1.13, which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.2: version "1.1.15" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== @@ -19784,6 +21402,32 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" +winston-transport@^4.9.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.9.0.tgz#3bba345de10297654ea6f33519424560003b3bf9" + integrity sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A== + dependencies: + logform "^2.7.0" + readable-stream "^3.6.2" + triple-beam "^1.3.0" + +winston@^3.1.0: + version "3.17.0" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.17.0.tgz#74b8665ce9b4ea7b29d0922cfccf852a08a11423" + integrity sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw== + dependencies: + "@colors/colors" "^1.6.0" + "@dabh/diagnostics" "^2.0.2" + async "^3.2.3" + is-stream "^2.0.0" + logform "^2.7.0" + one-time "^1.0.0" + readable-stream "^3.4.0" + safe-stable-stringify "^2.3.1" + stack-trace "0.0.x" + triple-beam "^1.3.0" + winston-transport "^4.9.0" + word-wrap@~1.2.3: version "1.2.5" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" @@ -19801,7 +21445,7 @@ worker-farm@1.7.0: dependencies: errno "~0.1.7" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -19819,15 +21463,6 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" @@ -19955,7 +21590,7 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.4.19, xml2js@0.5.0, xml2js@0.6.2, xml2js@^0.5.0: +xml2js@0.6.2, xml2js@^0.5.0, xml2js@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== From 5093e1a84bfde73c447f9d804500ae54cc03fd45 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 18:28:19 +0000 Subject: [PATCH 21/40] more pins --- packages/server/package.json | 4 +- yarn.lock | 310 ++++++++++++----------------------- 2 files changed, 103 insertions(+), 211 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 28a85fdb3e..2727f17e60 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -60,7 +60,7 @@ "@bull-board/koa": "5.10.2", "@elastic/elasticsearch": "7.10.0", "@google-cloud/firestore": "7.8.0", - "@koa/router": "^13.1.0", + "@koa/router": "13.1.0", "@socket.io/redis-adapter": "^8.2.1", "@types/xml2js": "^0.4.14", "airtable": "0.12.2", @@ -119,7 +119,7 @@ "uuid": "^8.3.2", "validate.js": "0.13.1", "worker-farm": "1.7.0", - "xml2js": "^0.6.2" + "xml2js": "0.6.2" }, "devDependencies": { "@babel/preset-env": "7.16.11", diff --git a/yarn.lock b/yarn.lock index 52fc595f31..a7b13c751e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -842,7 +842,7 @@ "@azure/abort-controller" "^2.0.0" tslib "^2.6.2" -"@azure/identity@4.2.1", "@azure/identity@^4.2.1": +"@azure/identity@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -2129,44 +2129,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@3.2.7": - version "0.0.0" - dependencies: - "@budibase/nano" "10.1.5" - "@budibase/pouchdb-replication-stream" "1.2.11" - "@budibase/shared-core" "0.0.0" - "@budibase/types" "0.0.0" - aws-cloudfront-sign "3.0.2" - aws-sdk "2.1692.0" - bcrypt "5.1.0" - bcryptjs "2.4.3" - bull "4.10.1" - correlation-id "4.0.0" - dd-trace "5.23.0" - dotenv "16.0.1" - ioredis "5.3.2" - joi "17.6.0" - jsonwebtoken "9.0.2" - knex "2.4.2" - koa-passport "^6.0.0" - koa-pino-logger "4.0.0" - lodash "4.17.21" - node-fetch "2.6.7" - passport-google-oauth "2.0.0" - passport-local "1.0.0" - passport-oauth2-refresh "^2.1.0" - pino "8.11.0" - pino-http "8.3.3" - posthog-node "4.0.1" - pouchdb "9.0.0" - pouchdb-find "9.0.0" - redlock "4.2.0" - rotating-file-stream "3.1.0" - sanitize-s3-objectkey "0.0.1" - semver "^7.5.4" - tar-fs "2.1.1" - uuid "^8.3.2" - "@budibase/handlebars-helpers@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77" @@ -2209,47 +2171,6 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@npm:@budibase/pro@latest": - version "3.2.7" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.7.tgz#4dfc48f3e2ba3a3b235872e54c3de4de54ea7941" - integrity sha512-GRRaf1qSqQfoodjvKjBDvNOVHZrcSXF7so6Y9Xv/MiRTjDES5nmhIT5rL/PQ1+Mb+sPytYmMaJ2mlTtwqSQZgQ== - dependencies: - "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "3.2.7" - "@budibase/shared-core" "3.2.7" - "@budibase/string-templates" "3.2.7" - "@budibase/types" "3.2.7" - "@koa/router" "8.0.8" - bull "4.10.1" - dd-trace "5.2.0" - joi "17.6.0" - jsonwebtoken "9.0.2" - lru-cache "^7.14.1" - memorystream "^0.3.1" - node-fetch "2.6.7" - openai "4.59.0" - scim-patch "^0.8.1" - scim2-parse-filter "^0.2.8" - -"@budibase/shared-core@3.2.7": - version "0.0.0" - dependencies: - "@budibase/types" "0.0.0" - cron-validate "1.4.5" - -"@budibase/string-templates@3.2.7": - version "0.0.0" - dependencies: - "@budibase/handlebars-helpers" "^0.13.2" - dayjs "^1.10.8" - handlebars "^4.7.8" - lodash.clonedeep "^4.5.0" - -"@budibase/types@3.2.7": - version "0.0.0" - dependencies: - scim-patch "^0.8.1" - "@bull-board/api@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3" @@ -2389,13 +2310,6 @@ resolved "https://registry.yarnpkg.com/@dagrejs/graphlib/-/graphlib-2.2.4.tgz#d77bfa9ff49e2307c0c6e6b8b26b5dd3c05816c4" integrity sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw== -"@datadog/native-appsec@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-7.0.0.tgz#a380174dd49aef2d9bb613a0ec8ead6dc7822095" - integrity sha512-bywstWFW2hWxzPuS0+mFMVHHL0geulx5yQFtsjfszaH2LTAgk2D+Rt40MKbAoZ8q3tRw2dy6aYQ7svO3ca8jpA== - dependencies: - node-gyp-build "^3.9.0" - "@datadog/native-appsec@8.1.1": version "8.1.1" resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.1.1.tgz#76aa34697e6ecbd3d9ef7e6938d3cdcfa689b1f3" @@ -2403,14 +2317,6 @@ dependencies: node-gyp-build "^3.9.0" -"@datadog/native-iast-rewriter@2.2.2": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.2.2.tgz#3f7feaf6be1af4c83ad063065b8ed509bbaf11cb" - integrity sha512-13ZBhJpjZ/tiV6rYfyAf/ITye9cyd3x12M/2NKhD4Ivev4N4uKBREAjpArOtzKtPXZ5b6oXwVV4ofT1SHoYyzA== - dependencies: - lru-cache "^7.14.0" - node-gyp-build "^4.5.0" - "@datadog/native-iast-rewriter@2.4.1": version "2.4.1" resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.4.1.tgz#e8211f78c818906513fb96a549374da0382c7623" @@ -2419,13 +2325,6 @@ lru-cache "^7.14.0" node-gyp-build "^4.5.0" -"@datadog/native-iast-taint-tracking@1.6.4": - version "1.6.4" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-1.6.4.tgz#16c21ad7c36a53420c0d3c5a3720731809cc7e98" - integrity sha512-Owxk7hQ4Dxwv4zJAoMjRga0IvE6lhvxnNc8pJCHsemCWBXchjr/9bqg05Zy5JnMbKUWn4XuZeJD6RFZpRa8bfw== - dependencies: - node-gyp-build "^3.9.0" - "@datadog/native-iast-taint-tracking@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.1.0.tgz#7b2ed7f8fad212d65e5ab03bcdea8b42a3051b2e" @@ -2441,17 +2340,6 @@ node-addon-api "^6.1.0" node-gyp-build "^3.9.0" -"@datadog/pprof@5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.0.0.tgz#0c0aaf06def6d2bc4b2d353ec7b264dadbfbefab" - integrity sha512-vhNan4SBuNWLpexunDJQ+hNbRAgWdk2qy5Iyh7Nn94uSSHXigAJMAvu4jwMKKQKFfchtobOkWT8GQUWW3tgpFg== - dependencies: - delay "^5.0.0" - node-gyp-build "<4.0" - p-limit "^3.1.0" - pprof-format "^2.0.7" - source-map "^0.7.4" - "@datadog/pprof@5.3.0": version "5.3.0" resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.3.0.tgz#c2f58d328ecced7f99887f1a559d7fe3aecb9219" @@ -3373,7 +3261,7 @@ resolved "https://registry.yarnpkg.com/@jsep-plugin/regex/-/regex-1.0.4.tgz#cb2fc423220fa71c609323b9ba7f7d344a755fcc" integrity sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg== -"@koa/router@13.1.0", "@koa/router@^13.1.0": +"@koa/router@13.1.0": version "13.1.0" resolved "https://registry.yarnpkg.com/@koa/router/-/router-13.1.0.tgz#43f4c554444ea4f4a148a5735a9525c6d16fd1b5" integrity sha512-mNVu1nvkpSd8Q8gMebGbCkDWJ51ODetrFvLKYusej+V0ByD4btqHYnPIzTBLXnQMVUlm/oxVwqmWBY3zQfZilw== @@ -3382,18 +3270,6 @@ koa-compose "^4.1.0" path-to-regexp "^6.3.0" -"@koa/router@8.0.8": - version "8.0.8" - resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.8.tgz#95f32d11373d03d89dcb63fabe9ac6f471095236" - integrity sha512-FnT93N4NUehnXr+juupDmG2yfi0JnWdCmNEuIXpCG4TtG+9xvtrLambBH3RclycopVUOEYAim2lydiNBI7IRVg== - dependencies: - debug "^4.1.1" - http-errors "^1.7.3" - koa-compose "^4.1.0" - methods "^1.1.2" - path-to-regexp "1.x" - urijs "^1.19.2" - "@lerna/child-process@7.4.2": version "7.4.2" resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-7.4.2.tgz#a2fd013ac2150dc288270d3e0d0b850c06bec511" @@ -3857,7 +3733,7 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== -"@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.0.1": +"@opentelemetry/api@^1.0.1": version "1.9.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== @@ -7191,7 +7067,23 @@ aws-sdk@2.1692.0: uuid "8.0.0" xml2js "0.6.2" -axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: +axios@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" + integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + +axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -9078,48 +8970,11 @@ dayjs@^1.10.8: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -dc-polyfill@^0.1.2, dc-polyfill@^0.1.4: +dc-polyfill@^0.1.4: version "0.1.6" resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== -dd-trace@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.2.0.tgz#6ca2d76ece95f08d98468d7782c22f24192afa53" - integrity sha512-Z5ql3ZKzVW3DPstHPkTPcIPvKljHNtzTYY/WuZRlgT4XK7rMaN0j5nA8LlUh7m+tOPWs05IiKngbYVZjsqhRgA== - dependencies: - "@datadog/native-appsec" "7.0.0" - "@datadog/native-iast-rewriter" "2.2.2" - "@datadog/native-iast-taint-tracking" "1.6.4" - "@datadog/native-metrics" "^2.0.0" - "@datadog/pprof" "5.0.0" - "@datadog/sketches-js" "^2.1.0" - "@opentelemetry/api" "^1.0.0" - "@opentelemetry/core" "^1.14.0" - crypto-randomuuid "^1.0.0" - dc-polyfill "^0.1.2" - ignore "^5.2.4" - import-in-the-middle "^1.7.3" - int64-buffer "^0.1.9" - ipaddr.js "^2.1.0" - istanbul-lib-coverage "3.2.0" - jest-docblock "^29.7.0" - koalas "^1.0.2" - limiter "1.1.5" - lodash.sortby "^4.7.0" - lru-cache "^7.14.0" - methods "^1.1.2" - module-details-from-path "^1.0.3" - msgpack-lite "^0.1.26" - node-abort-controller "^3.1.1" - opentracing ">=0.12.1" - path-to-regexp "^0.1.2" - pprof-format "^2.0.7" - protobufjs "^7.2.5" - retry "^0.13.1" - semver "^7.5.4" - tlhunter-sorted-set "^0.1.0" - dd-trace@5.23.0: version "5.23.0" resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.23.0.tgz#a0c11863406de440a6675648caf06e1d07d67ba8" @@ -11012,7 +10867,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.15.6: +follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -12005,7 +11860,12 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -12224,7 +12084,7 @@ import-from@^3.0.0: dependencies: resolve-from "^5.0.0" -import-in-the-middle@1.11.2, import-in-the-middle@^1.7.3: +import-in-the-middle@1.11.2: version "1.11.2" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz#dd848e72b63ca6cd7c34df8b8d97fc9baee6174f" integrity sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA== @@ -12438,11 +12298,6 @@ ip@^2.0.0: resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== -ipaddr.js@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" - integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== - is-arguments@^1.0.4, is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -12491,6 +12346,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -12940,11 +12800,6 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isobject@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" - integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== - isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -13816,7 +13671,14 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@^3.0.2, kind-of@^3.1.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -15383,7 +15245,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@1.10.1, msgpackr@^1.5.2: +msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -15547,7 +15409,7 @@ node-abi@^3.3.0: dependencies: semver "^7.3.5" -node-abort-controller@^3.0.1, node-abort-controller@^3.1.1: +node-abort-controller@^3.0.1: version "3.1.1" resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== @@ -15577,13 +15439,27 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: +node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.9, node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-gyp-build-optional-packages@5.0.7: version "5.0.7" resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz#5d2632bbde0ab2f6e22f1bbac2199b07244ae0b3" @@ -16657,7 +16533,15 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@0.6.0, passport@^0.4.0, passport@^0.6.0: +passport@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" + integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + +passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -16712,14 +16596,7 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@1.x: - version "1.9.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" - integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== - dependencies: - isarray "0.0.1" - -path-to-regexp@^0.1.10, path-to-regexp@^0.1.2: +path-to-regexp@^0.1.10: version "0.1.11" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.11.tgz#a527e662c89efc4646dbfa8100bf3e847e495761" integrity sha512-c0t+KCuUkO/YDLPG4WWzEwx3J5F/GHXsD1h/SNZfySqAIKe/BaP95x8fWtOfRJokpS5yYHRJjMtYlXD8jxnpbw== @@ -17620,7 +17497,7 @@ pouchdb@9.0.0: uuid "8.3.2" vuvuzela "1.0.3" -pprof-format@^2.0.7, pprof-format@^2.1.0: +pprof-format@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.1.0.tgz#acc8d7773bcf4faf0a3d3df11bceefba7ac06664" integrity sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw== @@ -18914,13 +18791,33 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.4, semver@^7.6.0: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +semver@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" + integrity sha512-abLdIKCosKfpnmhS52NCTjO4RiLspDfsn37prjzGrp9im5DPJOgh82Os92vtwGh6XdQryKI/7SREZnV+aqiXrA== + seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -20389,7 +20286,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -20890,14 +20787,6 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unset-value@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" - integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== - dependencies: - has-value "^2.0.2" - isobject "^4.0.0" - untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -20948,11 +20837,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urijs@^1.19.2: - version "1.19.11" - resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" - integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== - url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -21590,7 +21474,7 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.6.2, xml2js@^0.5.0, xml2js@^0.6.2: +xml2js@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== @@ -21598,6 +21482,14 @@ xml2js@0.6.2, xml2js@^0.5.0, xml2js@^0.6.2: sax ">=0.6.0" xmlbuilder "~11.0.0" +xml2js@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + xmlbuilder@~11.0.0: version "11.0.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" From 235458ce5b215454899c096c3210f93b70bc75af Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 18:35:50 +0000 Subject: [PATCH 22/40] pro ref --- packages/pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pro b/packages/pro index a3fb5faa97..4facf6a44e 160000 --- a/packages/pro +++ b/packages/pro @@ -1 +1 @@ -Subproject commit a3fb5faa97ebee477e6f3d01116380e6409ab1e8 +Subproject commit 4facf6a44ee52a405794845f71584168b9db652c From 24f87e90d377835c369030f8aea75292d0c6a984 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 18:38:26 +0000 Subject: [PATCH 23/40] bump yarn lock --- yarn.lock | 308 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 208 insertions(+), 100 deletions(-) diff --git a/yarn.lock b/yarn.lock index a7b13c751e..49bb6cb357 100644 --- a/yarn.lock +++ b/yarn.lock @@ -842,7 +842,7 @@ "@azure/abort-controller" "^2.0.0" tslib "^2.6.2" -"@azure/identity@^4.2.1": +"@azure/identity@4.2.1", "@azure/identity@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -2129,6 +2129,44 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@budibase/backend-core@3.2.7": + version "0.0.0" + dependencies: + "@budibase/nano" "10.1.5" + "@budibase/pouchdb-replication-stream" "1.2.11" + "@budibase/shared-core" "0.0.0" + "@budibase/types" "0.0.0" + aws-cloudfront-sign "3.0.2" + aws-sdk "2.1692.0" + bcrypt "5.1.0" + bcryptjs "2.4.3" + bull "4.10.1" + correlation-id "4.0.0" + dd-trace "5.23.0" + dotenv "16.0.1" + ioredis "5.3.2" + joi "17.6.0" + jsonwebtoken "9.0.2" + knex "2.4.2" + koa-passport "^6.0.0" + koa-pino-logger "4.0.0" + lodash "4.17.21" + node-fetch "2.6.7" + passport-google-oauth "2.0.0" + passport-local "1.0.0" + passport-oauth2-refresh "^2.1.0" + pino "8.11.0" + pino-http "8.3.3" + posthog-node "4.0.1" + pouchdb "9.0.0" + pouchdb-find "9.0.0" + redlock "4.2.0" + rotating-file-stream "3.1.0" + sanitize-s3-objectkey "0.0.1" + semver "^7.5.4" + tar-fs "2.1.1" + uuid "^8.3.2" + "@budibase/handlebars-helpers@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77" @@ -2171,6 +2209,47 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" +"@budibase/pro@npm:@budibase/pro@latest": + version "3.2.7" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.7.tgz#4dfc48f3e2ba3a3b235872e54c3de4de54ea7941" + integrity sha512-GRRaf1qSqQfoodjvKjBDvNOVHZrcSXF7so6Y9Xv/MiRTjDES5nmhIT5rL/PQ1+Mb+sPytYmMaJ2mlTtwqSQZgQ== + dependencies: + "@anthropic-ai/sdk" "^0.27.3" + "@budibase/backend-core" "3.2.7" + "@budibase/shared-core" "3.2.7" + "@budibase/string-templates" "3.2.7" + "@budibase/types" "3.2.7" + "@koa/router" "8.0.8" + bull "4.10.1" + dd-trace "5.2.0" + joi "17.6.0" + jsonwebtoken "9.0.2" + lru-cache "^7.14.1" + memorystream "^0.3.1" + node-fetch "2.6.7" + openai "4.59.0" + scim-patch "^0.8.1" + scim2-parse-filter "^0.2.8" + +"@budibase/shared-core@3.2.7": + version "0.0.0" + dependencies: + "@budibase/types" "0.0.0" + cron-validate "1.4.5" + +"@budibase/string-templates@3.2.7": + version "0.0.0" + dependencies: + "@budibase/handlebars-helpers" "^0.13.2" + dayjs "^1.10.8" + handlebars "^4.7.8" + lodash.clonedeep "^4.5.0" + +"@budibase/types@3.2.7": + version "0.0.0" + dependencies: + scim-patch "^0.8.1" + "@bull-board/api@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3" @@ -2310,6 +2389,13 @@ resolved "https://registry.yarnpkg.com/@dagrejs/graphlib/-/graphlib-2.2.4.tgz#d77bfa9ff49e2307c0c6e6b8b26b5dd3c05816c4" integrity sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw== +"@datadog/native-appsec@7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-7.0.0.tgz#a380174dd49aef2d9bb613a0ec8ead6dc7822095" + integrity sha512-bywstWFW2hWxzPuS0+mFMVHHL0geulx5yQFtsjfszaH2LTAgk2D+Rt40MKbAoZ8q3tRw2dy6aYQ7svO3ca8jpA== + dependencies: + node-gyp-build "^3.9.0" + "@datadog/native-appsec@8.1.1": version "8.1.1" resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.1.1.tgz#76aa34697e6ecbd3d9ef7e6938d3cdcfa689b1f3" @@ -2317,6 +2403,14 @@ dependencies: node-gyp-build "^3.9.0" +"@datadog/native-iast-rewriter@2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.2.2.tgz#3f7feaf6be1af4c83ad063065b8ed509bbaf11cb" + integrity sha512-13ZBhJpjZ/tiV6rYfyAf/ITye9cyd3x12M/2NKhD4Ivev4N4uKBREAjpArOtzKtPXZ5b6oXwVV4ofT1SHoYyzA== + dependencies: + lru-cache "^7.14.0" + node-gyp-build "^4.5.0" + "@datadog/native-iast-rewriter@2.4.1": version "2.4.1" resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.4.1.tgz#e8211f78c818906513fb96a549374da0382c7623" @@ -2325,6 +2419,13 @@ lru-cache "^7.14.0" node-gyp-build "^4.5.0" +"@datadog/native-iast-taint-tracking@1.6.4": + version "1.6.4" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-1.6.4.tgz#16c21ad7c36a53420c0d3c5a3720731809cc7e98" + integrity sha512-Owxk7hQ4Dxwv4zJAoMjRga0IvE6lhvxnNc8pJCHsemCWBXchjr/9bqg05Zy5JnMbKUWn4XuZeJD6RFZpRa8bfw== + dependencies: + node-gyp-build "^3.9.0" + "@datadog/native-iast-taint-tracking@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.1.0.tgz#7b2ed7f8fad212d65e5ab03bcdea8b42a3051b2e" @@ -2340,6 +2441,17 @@ node-addon-api "^6.1.0" node-gyp-build "^3.9.0" +"@datadog/pprof@5.0.0": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.0.0.tgz#0c0aaf06def6d2bc4b2d353ec7b264dadbfbefab" + integrity sha512-vhNan4SBuNWLpexunDJQ+hNbRAgWdk2qy5Iyh7Nn94uSSHXigAJMAvu4jwMKKQKFfchtobOkWT8GQUWW3tgpFg== + dependencies: + delay "^5.0.0" + node-gyp-build "<4.0" + p-limit "^3.1.0" + pprof-format "^2.0.7" + source-map "^0.7.4" + "@datadog/pprof@5.3.0": version "5.3.0" resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.3.0.tgz#c2f58d328ecced7f99887f1a559d7fe3aecb9219" @@ -3270,6 +3382,18 @@ koa-compose "^4.1.0" path-to-regexp "^6.3.0" +"@koa/router@8.0.8": + version "8.0.8" + resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.8.tgz#95f32d11373d03d89dcb63fabe9ac6f471095236" + integrity sha512-FnT93N4NUehnXr+juupDmG2yfi0JnWdCmNEuIXpCG4TtG+9xvtrLambBH3RclycopVUOEYAim2lydiNBI7IRVg== + dependencies: + debug "^4.1.1" + http-errors "^1.7.3" + koa-compose "^4.1.0" + methods "^1.1.2" + path-to-regexp "1.x" + urijs "^1.19.2" + "@lerna/child-process@7.4.2": version "7.4.2" resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-7.4.2.tgz#a2fd013ac2150dc288270d3e0d0b850c06bec511" @@ -3733,7 +3857,7 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== -"@opentelemetry/api@^1.0.1": +"@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.0.1": version "1.9.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== @@ -7067,23 +7191,7 @@ aws-sdk@2.1692.0: uuid "8.0.0" xml2js "0.6.2" -axios@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" - integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== - dependencies: - follow-redirects "^1.15.0" - form-data "^4.0.0" - proxy-from-env "^1.1.0" - -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - -axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: +axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -8970,11 +9078,48 @@ dayjs@^1.10.8: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -dc-polyfill@^0.1.4: +dc-polyfill@^0.1.2, dc-polyfill@^0.1.4: version "0.1.6" resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== +dd-trace@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.2.0.tgz#6ca2d76ece95f08d98468d7782c22f24192afa53" + integrity sha512-Z5ql3ZKzVW3DPstHPkTPcIPvKljHNtzTYY/WuZRlgT4XK7rMaN0j5nA8LlUh7m+tOPWs05IiKngbYVZjsqhRgA== + dependencies: + "@datadog/native-appsec" "7.0.0" + "@datadog/native-iast-rewriter" "2.2.2" + "@datadog/native-iast-taint-tracking" "1.6.4" + "@datadog/native-metrics" "^2.0.0" + "@datadog/pprof" "5.0.0" + "@datadog/sketches-js" "^2.1.0" + "@opentelemetry/api" "^1.0.0" + "@opentelemetry/core" "^1.14.0" + crypto-randomuuid "^1.0.0" + dc-polyfill "^0.1.2" + ignore "^5.2.4" + import-in-the-middle "^1.7.3" + int64-buffer "^0.1.9" + ipaddr.js "^2.1.0" + istanbul-lib-coverage "3.2.0" + jest-docblock "^29.7.0" + koalas "^1.0.2" + limiter "1.1.5" + lodash.sortby "^4.7.0" + lru-cache "^7.14.0" + methods "^1.1.2" + module-details-from-path "^1.0.3" + msgpack-lite "^0.1.26" + node-abort-controller "^3.1.1" + opentracing ">=0.12.1" + path-to-regexp "^0.1.2" + pprof-format "^2.0.7" + protobufjs "^7.2.5" + retry "^0.13.1" + semver "^7.5.4" + tlhunter-sorted-set "^0.1.0" + dd-trace@5.23.0: version "5.23.0" resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.23.0.tgz#a0c11863406de440a6675648caf06e1d07d67ba8" @@ -10867,7 +11012,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: +follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -11860,12 +12005,7 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== - -http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -12084,7 +12224,7 @@ import-from@^3.0.0: dependencies: resolve-from "^5.0.0" -import-in-the-middle@1.11.2: +import-in-the-middle@1.11.2, import-in-the-middle@^1.7.3: version "1.11.2" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz#dd848e72b63ca6cd7c34df8b8d97fc9baee6174f" integrity sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA== @@ -12298,6 +12438,11 @@ ip@^2.0.0: resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== +ipaddr.js@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== + is-arguments@^1.0.4, is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -12346,11 +12491,6 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -12800,6 +12940,11 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -13671,14 +13816,7 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@^3.0.2, kind-of@^3.1.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== - dependencies: - is-buffer "^1.1.5" - -kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -15245,7 +15383,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@^1.5.2: +msgpackr@1.10.1, msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -15409,7 +15547,7 @@ node-abi@^3.3.0: dependencies: semver "^7.3.5" -node-abort-controller@^3.0.1: +node-abort-controller@^3.0.1, node-abort-controller@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== @@ -15439,27 +15577,13 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: +node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" -node-fetch@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" - integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== - dependencies: - whatwg-url "^5.0.0" - -node-fetch@^2.6.9, node-fetch@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - node-gyp-build-optional-packages@5.0.7: version "5.0.7" resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz#5d2632bbde0ab2f6e22f1bbac2199b07244ae0b3" @@ -16533,15 +16657,7 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" - integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - -passport@^0.6.0: +passport@0.6.0, passport@^0.4.0, passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -16596,7 +16712,14 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@^0.1.10: +path-to-regexp@1.x: + version "1.9.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" + integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== + dependencies: + isarray "0.0.1" + +path-to-regexp@^0.1.10, path-to-regexp@^0.1.2: version "0.1.11" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.11.tgz#a527e662c89efc4646dbfa8100bf3e847e495761" integrity sha512-c0t+KCuUkO/YDLPG4WWzEwx3J5F/GHXsD1h/SNZfySqAIKe/BaP95x8fWtOfRJokpS5yYHRJjMtYlXD8jxnpbw== @@ -17497,7 +17620,7 @@ pouchdb@9.0.0: uuid "8.3.2" vuvuzela "1.0.3" -pprof-format@^2.1.0: +pprof-format@^2.0.7, pprof-format@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.1.0.tgz#acc8d7773bcf4faf0a3d3df11bceefba7ac06664" integrity sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw== @@ -18791,33 +18914,13 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: - version "5.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" - integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== - -semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: +"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" - integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== - -semver@^7.5.4, semver@^7.6.0: - version "7.6.3" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" - integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== - -semver@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" - integrity sha512-abLdIKCosKfpnmhS52NCTjO4RiLspDfsn37prjzGrp9im5DPJOgh82Os92vtwGh6XdQryKI/7SREZnV+aqiXrA== - seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -20286,7 +20389,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: +tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -20787,6 +20890,14 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unset-value@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" + integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== + dependencies: + has-value "^2.0.2" + isobject "^4.0.0" + untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -20837,6 +20948,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +urijs@^1.19.2: + version "1.19.11" + resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" + integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== + url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -21474,7 +21590,7 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.6.2: +xml2js@0.6.2, xml2js@^0.5.0: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== @@ -21482,14 +21598,6 @@ xml2js@0.6.2: sax ">=0.6.0" xmlbuilder "~11.0.0" -xml2js@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" - integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - xmlbuilder@~11.0.0: version "11.0.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" From 795f20988a15ce58d435277aa4fd9d5deeba4a0c Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 18:40:51 +0000 Subject: [PATCH 24/40] cleaner lockfile --- yarn.lock | 308 ++++++++++++++++++------------------------------------ 1 file changed, 100 insertions(+), 208 deletions(-) diff --git a/yarn.lock b/yarn.lock index 49bb6cb357..a7b13c751e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -842,7 +842,7 @@ "@azure/abort-controller" "^2.0.0" tslib "^2.6.2" -"@azure/identity@4.2.1", "@azure/identity@^4.2.1": +"@azure/identity@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@azure/identity/-/identity-4.2.1.tgz#22b366201e989b7b41c0e1690e103bd579c31e4c" integrity sha512-U8hsyC9YPcEIzoaObJlRDvp7KiF0MGS7xcWbyJSVvXRkC/HXo1f0oYeBYmEvVgRfacw7GHf6D6yAoh9JHz6A5Q== @@ -2129,44 +2129,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@3.2.7": - version "0.0.0" - dependencies: - "@budibase/nano" "10.1.5" - "@budibase/pouchdb-replication-stream" "1.2.11" - "@budibase/shared-core" "0.0.0" - "@budibase/types" "0.0.0" - aws-cloudfront-sign "3.0.2" - aws-sdk "2.1692.0" - bcrypt "5.1.0" - bcryptjs "2.4.3" - bull "4.10.1" - correlation-id "4.0.0" - dd-trace "5.23.0" - dotenv "16.0.1" - ioredis "5.3.2" - joi "17.6.0" - jsonwebtoken "9.0.2" - knex "2.4.2" - koa-passport "^6.0.0" - koa-pino-logger "4.0.0" - lodash "4.17.21" - node-fetch "2.6.7" - passport-google-oauth "2.0.0" - passport-local "1.0.0" - passport-oauth2-refresh "^2.1.0" - pino "8.11.0" - pino-http "8.3.3" - posthog-node "4.0.1" - pouchdb "9.0.0" - pouchdb-find "9.0.0" - redlock "4.2.0" - rotating-file-stream "3.1.0" - sanitize-s3-objectkey "0.0.1" - semver "^7.5.4" - tar-fs "2.1.1" - uuid "^8.3.2" - "@budibase/handlebars-helpers@^0.13.2": version "0.13.2" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.2.tgz#73ab51c464e91fd955b429017648e0257060db77" @@ -2209,47 +2171,6 @@ pouchdb-promise "^6.0.4" through2 "^2.0.0" -"@budibase/pro@npm:@budibase/pro@latest": - version "3.2.7" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-3.2.7.tgz#4dfc48f3e2ba3a3b235872e54c3de4de54ea7941" - integrity sha512-GRRaf1qSqQfoodjvKjBDvNOVHZrcSXF7so6Y9Xv/MiRTjDES5nmhIT5rL/PQ1+Mb+sPytYmMaJ2mlTtwqSQZgQ== - dependencies: - "@anthropic-ai/sdk" "^0.27.3" - "@budibase/backend-core" "3.2.7" - "@budibase/shared-core" "3.2.7" - "@budibase/string-templates" "3.2.7" - "@budibase/types" "3.2.7" - "@koa/router" "8.0.8" - bull "4.10.1" - dd-trace "5.2.0" - joi "17.6.0" - jsonwebtoken "9.0.2" - lru-cache "^7.14.1" - memorystream "^0.3.1" - node-fetch "2.6.7" - openai "4.59.0" - scim-patch "^0.8.1" - scim2-parse-filter "^0.2.8" - -"@budibase/shared-core@3.2.7": - version "0.0.0" - dependencies: - "@budibase/types" "0.0.0" - cron-validate "1.4.5" - -"@budibase/string-templates@3.2.7": - version "0.0.0" - dependencies: - "@budibase/handlebars-helpers" "^0.13.2" - dayjs "^1.10.8" - handlebars "^4.7.8" - lodash.clonedeep "^4.5.0" - -"@budibase/types@3.2.7": - version "0.0.0" - dependencies: - scim-patch "^0.8.1" - "@bull-board/api@5.10.2": version "5.10.2" resolved "https://registry.yarnpkg.com/@bull-board/api/-/api-5.10.2.tgz#ae8ff6918b23897bf879a6ead3683f964374c4b3" @@ -2389,13 +2310,6 @@ resolved "https://registry.yarnpkg.com/@dagrejs/graphlib/-/graphlib-2.2.4.tgz#d77bfa9ff49e2307c0c6e6b8b26b5dd3c05816c4" integrity sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw== -"@datadog/native-appsec@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-7.0.0.tgz#a380174dd49aef2d9bb613a0ec8ead6dc7822095" - integrity sha512-bywstWFW2hWxzPuS0+mFMVHHL0geulx5yQFtsjfszaH2LTAgk2D+Rt40MKbAoZ8q3tRw2dy6aYQ7svO3ca8jpA== - dependencies: - node-gyp-build "^3.9.0" - "@datadog/native-appsec@8.1.1": version "8.1.1" resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-8.1.1.tgz#76aa34697e6ecbd3d9ef7e6938d3cdcfa689b1f3" @@ -2403,14 +2317,6 @@ dependencies: node-gyp-build "^3.9.0" -"@datadog/native-iast-rewriter@2.2.2": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.2.2.tgz#3f7feaf6be1af4c83ad063065b8ed509bbaf11cb" - integrity sha512-13ZBhJpjZ/tiV6rYfyAf/ITye9cyd3x12M/2NKhD4Ivev4N4uKBREAjpArOtzKtPXZ5b6oXwVV4ofT1SHoYyzA== - dependencies: - lru-cache "^7.14.0" - node-gyp-build "^4.5.0" - "@datadog/native-iast-rewriter@2.4.1": version "2.4.1" resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-2.4.1.tgz#e8211f78c818906513fb96a549374da0382c7623" @@ -2419,13 +2325,6 @@ lru-cache "^7.14.0" node-gyp-build "^4.5.0" -"@datadog/native-iast-taint-tracking@1.6.4": - version "1.6.4" - resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-1.6.4.tgz#16c21ad7c36a53420c0d3c5a3720731809cc7e98" - integrity sha512-Owxk7hQ4Dxwv4zJAoMjRga0IvE6lhvxnNc8pJCHsemCWBXchjr/9bqg05Zy5JnMbKUWn4XuZeJD6RFZpRa8bfw== - dependencies: - node-gyp-build "^3.9.0" - "@datadog/native-iast-taint-tracking@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-3.1.0.tgz#7b2ed7f8fad212d65e5ab03bcdea8b42a3051b2e" @@ -2441,17 +2340,6 @@ node-addon-api "^6.1.0" node-gyp-build "^3.9.0" -"@datadog/pprof@5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.0.0.tgz#0c0aaf06def6d2bc4b2d353ec7b264dadbfbefab" - integrity sha512-vhNan4SBuNWLpexunDJQ+hNbRAgWdk2qy5Iyh7Nn94uSSHXigAJMAvu4jwMKKQKFfchtobOkWT8GQUWW3tgpFg== - dependencies: - delay "^5.0.0" - node-gyp-build "<4.0" - p-limit "^3.1.0" - pprof-format "^2.0.7" - source-map "^0.7.4" - "@datadog/pprof@5.3.0": version "5.3.0" resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.3.0.tgz#c2f58d328ecced7f99887f1a559d7fe3aecb9219" @@ -3382,18 +3270,6 @@ koa-compose "^4.1.0" path-to-regexp "^6.3.0" -"@koa/router@8.0.8": - version "8.0.8" - resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.8.tgz#95f32d11373d03d89dcb63fabe9ac6f471095236" - integrity sha512-FnT93N4NUehnXr+juupDmG2yfi0JnWdCmNEuIXpCG4TtG+9xvtrLambBH3RclycopVUOEYAim2lydiNBI7IRVg== - dependencies: - debug "^4.1.1" - http-errors "^1.7.3" - koa-compose "^4.1.0" - methods "^1.1.2" - path-to-regexp "1.x" - urijs "^1.19.2" - "@lerna/child-process@7.4.2": version "7.4.2" resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-7.4.2.tgz#a2fd013ac2150dc288270d3e0d0b850c06bec511" @@ -3857,7 +3733,7 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.8.0.tgz#5aa7abb48f23f693068ed2999ae627d2f7d902ec" integrity sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w== -"@opentelemetry/api@^1.0.0", "@opentelemetry/api@^1.0.1": +"@opentelemetry/api@^1.0.1": version "1.9.0" resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== @@ -7191,7 +7067,23 @@ aws-sdk@2.1692.0: uuid "8.0.0" xml2js "0.6.2" -axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: +axios@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35" + integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA== + dependencies: + follow-redirects "^1.15.0" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +axios@^0.21.1: + version "0.21.4" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" + integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== + dependencies: + follow-redirects "^1.14.0" + +axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== @@ -9078,48 +8970,11 @@ dayjs@^1.10.8: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -dc-polyfill@^0.1.2, dc-polyfill@^0.1.4: +dc-polyfill@^0.1.4: version "0.1.6" resolved "https://registry.yarnpkg.com/dc-polyfill/-/dc-polyfill-0.1.6.tgz#c2940fa68ffb24a7bf127cc6cfdd15b39f0e7f02" integrity sha512-UV33cugmCC49a5uWAApM+6Ev9ZdvIUMTrtCO9fj96TPGOQiea54oeO3tiEVdVeo3J9N2UdJEmbS4zOkkEA35uQ== -dd-trace@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.2.0.tgz#6ca2d76ece95f08d98468d7782c22f24192afa53" - integrity sha512-Z5ql3ZKzVW3DPstHPkTPcIPvKljHNtzTYY/WuZRlgT4XK7rMaN0j5nA8LlUh7m+tOPWs05IiKngbYVZjsqhRgA== - dependencies: - "@datadog/native-appsec" "7.0.0" - "@datadog/native-iast-rewriter" "2.2.2" - "@datadog/native-iast-taint-tracking" "1.6.4" - "@datadog/native-metrics" "^2.0.0" - "@datadog/pprof" "5.0.0" - "@datadog/sketches-js" "^2.1.0" - "@opentelemetry/api" "^1.0.0" - "@opentelemetry/core" "^1.14.0" - crypto-randomuuid "^1.0.0" - dc-polyfill "^0.1.2" - ignore "^5.2.4" - import-in-the-middle "^1.7.3" - int64-buffer "^0.1.9" - ipaddr.js "^2.1.0" - istanbul-lib-coverage "3.2.0" - jest-docblock "^29.7.0" - koalas "^1.0.2" - limiter "1.1.5" - lodash.sortby "^4.7.0" - lru-cache "^7.14.0" - methods "^1.1.2" - module-details-from-path "^1.0.3" - msgpack-lite "^0.1.26" - node-abort-controller "^3.1.1" - opentracing ">=0.12.1" - path-to-regexp "^0.1.2" - pprof-format "^2.0.7" - protobufjs "^7.2.5" - retry "^0.13.1" - semver "^7.5.4" - tlhunter-sorted-set "^0.1.0" - dd-trace@5.23.0: version "5.23.0" resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-5.23.0.tgz#a0c11863406de440a6675648caf06e1d07d67ba8" @@ -11012,7 +10867,7 @@ fn.name@1.x.x: resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -follow-redirects@^1.15.6: +follow-redirects@^1.14.0, follow-redirects@^1.15.0, follow-redirects@^1.15.6: version "1.15.9" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== @@ -12005,7 +11860,12 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.8.0" -http-cache-semantics@3.8.1, http-cache-semantics@4.1.1, http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: +http-cache-semantics@3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + +http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0, http-cache-semantics@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== @@ -12224,7 +12084,7 @@ import-from@^3.0.0: dependencies: resolve-from "^5.0.0" -import-in-the-middle@1.11.2, import-in-the-middle@^1.7.3: +import-in-the-middle@1.11.2: version "1.11.2" resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.11.2.tgz#dd848e72b63ca6cd7c34df8b8d97fc9baee6174f" integrity sha512-gK6Rr6EykBcc6cVWRSBR5TWf8nn6hZMYSRYqCcHa0l0d1fPK7JSYo6+Mlmck76jIX9aL/IZ71c06U2VpFwl1zA== @@ -12438,11 +12298,6 @@ ip@^2.0.0: resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ== -ipaddr.js@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" - integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== - is-arguments@^1.0.4, is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -12491,6 +12346,11 @@ is-boolean-object@^1.1.0: call-bind "^1.0.2" has-tostringtag "^1.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-buffer@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" @@ -12940,11 +12800,6 @@ isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== -isobject@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" - integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== - isolated-vm@^4.7.2: version "4.7.2" resolved "https://registry.yarnpkg.com/isolated-vm/-/isolated-vm-4.7.2.tgz#5670d5cce1d92004f9b825bec5b0b11fc7501b65" @@ -13816,7 +13671,14 @@ kill-port@^1.6.1: get-them-args "1.3.2" shell-exec "1.0.2" -kind-of@6.0.3, kind-of@^3.0.2, kind-of@^3.1.0, kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: +kind-of@^3.0.2, kind-of@^3.1.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ== + dependencies: + is-buffer "^1.1.5" + +kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== @@ -15383,7 +15245,7 @@ msgpackr-extract@^3.0.2: "@msgpackr-extract/msgpackr-extract-linux-x64" "3.0.2" "@msgpackr-extract/msgpackr-extract-win32-x64" "3.0.2" -msgpackr@1.10.1, msgpackr@^1.5.2: +msgpackr@^1.5.2: version "1.10.1" resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.10.1.tgz#51953bb4ce4f3494f0c4af3f484f01cfbb306555" integrity sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ== @@ -15547,7 +15409,7 @@ node-abi@^3.3.0: dependencies: semver "^7.3.5" -node-abort-controller@^3.0.1, node-abort-controller@^3.1.1: +node-abort-controller@^3.0.1: version "3.1.1" resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== @@ -15577,13 +15439,27 @@ node-domexception@1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@2.6.7, node-fetch@2.6.9, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7, node-fetch@^2.6.9, node-fetch@^2.7.0: +node-fetch@2.6.7, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== dependencies: whatwg-url "^5.0.0" +node-fetch@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" + integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== + dependencies: + whatwg-url "^5.0.0" + +node-fetch@^2.6.9, node-fetch@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" + integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== + dependencies: + whatwg-url "^5.0.0" + node-gyp-build-optional-packages@5.0.7: version "5.0.7" resolved "https://registry.yarnpkg.com/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz#5d2632bbde0ab2f6e22f1bbac2199b07244ae0b3" @@ -16657,7 +16533,15 @@ passport-strategy@1.x.x, passport-strategy@^1.0.0: resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== -passport@0.6.0, passport@^0.4.0, passport@^0.6.0: +passport@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/passport/-/passport-0.4.1.tgz#941446a21cb92fc688d97a0861c38ce9f738f270" + integrity sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg== + dependencies: + passport-strategy "1.x.x" + pause "0.0.1" + +passport@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== @@ -16712,14 +16596,7 @@ path-scurry@^1.11.1, path-scurry@^1.6.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@1.x: - version "1.9.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" - integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== - dependencies: - isarray "0.0.1" - -path-to-regexp@^0.1.10, path-to-regexp@^0.1.2: +path-to-regexp@^0.1.10: version "0.1.11" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.11.tgz#a527e662c89efc4646dbfa8100bf3e847e495761" integrity sha512-c0t+KCuUkO/YDLPG4WWzEwx3J5F/GHXsD1h/SNZfySqAIKe/BaP95x8fWtOfRJokpS5yYHRJjMtYlXD8jxnpbw== @@ -17620,7 +17497,7 @@ pouchdb@9.0.0: uuid "8.3.2" vuvuzela "1.0.3" -pprof-format@^2.0.7, pprof-format@^2.1.0: +pprof-format@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/pprof-format/-/pprof-format-2.1.0.tgz#acc8d7773bcf4faf0a3d3df11bceefba7ac06664" integrity sha512-0+G5bHH0RNr8E5hoZo/zJYsL92MhkZjwrHp3O2IxmY8RJL9ooKeuZ8Tm0ZNBw5sGZ9TiM71sthTjWoR2Vf5/xw== @@ -18914,13 +18791,33 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -"semver@2 || 3 || 4 || 5", semver@7.5.3, semver@^5.5.0, semver@^5.6.0, semver@^5.7.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@~2.3.1: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + +semver@7.5.3, semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3: version "7.5.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" +semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.4, semver@^7.6.0: + version "7.6.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" + integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== + +semver@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" + integrity sha512-abLdIKCosKfpnmhS52NCTjO4RiLspDfsn37prjzGrp9im5DPJOgh82Os92vtwGh6XdQryKI/7SREZnV+aqiXrA== + seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -20389,7 +20286,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -20890,14 +20787,6 @@ unpipe@1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unset-value@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-2.0.1.tgz#57bed0c22d26f28d69acde5df9a11b77c74d2df3" - integrity sha512-2hvrBfjUE00PkqN+q0XP6yRAOGrR06uSiUoIQGZkc7GxvQ9H7v8quUPNtZjMg4uux69i8HWpIjLPUKwCuRGyNg== - dependencies: - has-value "^2.0.2" - isobject "^4.0.0" - untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" @@ -20948,11 +20837,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -urijs@^1.19.2: - version "1.19.11" - resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.11.tgz#204b0d6b605ae80bea54bea39280cdb7c9f923cc" - integrity sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ== - url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -21590,7 +21474,7 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.6.2, xml2js@^0.5.0: +xml2js@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== @@ -21598,6 +21482,14 @@ xml2js@0.6.2, xml2js@^0.5.0: sax ">=0.6.0" xmlbuilder "~11.0.0" +xml2js@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" + integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + xmlbuilder@~11.0.0: version "11.0.1" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" From 79c515e57d812892708a376d0fb6d12c6508d1ab Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 19:02:22 +0000 Subject: [PATCH 25/40] types --- packages/server/package.json | 2 +- .../src/api/controllers/query/import/sources/curl.ts | 2 +- packages/server/src/integrations/microsoftSqlServer.ts | 1 + packages/server/src/integrations/snowflake.ts | 8 ++++++-- packages/server/src/utilities/fileSystem/processor.ts | 6 +++--- yarn.lock | 8 ++++---- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 2727f17e60..8ff2c1f8c2 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -132,7 +132,7 @@ "@types/koa-send": "^4.1.6", "@types/koa__router": "12.0.4", "@types/lodash": "4.14.200", - "@types/mssql": "9.1.4", + "@types/mssql": "9.1.5", "@types/node-fetch": "2.6.4", "@types/oracledb": "6.5.1", "@types/pg": "8.6.6", diff --git a/packages/server/src/api/controllers/query/import/sources/curl.ts b/packages/server/src/api/controllers/query/import/sources/curl.ts index f1747c9fc7..3e0ea1bcd7 100644 --- a/packages/server/src/api/controllers/query/import/sources/curl.ts +++ b/packages/server/src/api/controllers/query/import/sources/curl.ts @@ -2,7 +2,7 @@ import { ImportSource, ImportInfo } from "./base" import { Query } from "../../../../../definitions/common" import { URL } from "url" -const parseCurl = async (data: string): any => { +const parseCurl = async (data: string): Promise => { const curlconverter = await import("curlconverter") const curlJson = curlconverter.toJsonString(data) return JSON.parse(curlJson) diff --git a/packages/server/src/integrations/microsoftSqlServer.ts b/packages/server/src/integrations/microsoftSqlServer.ts index 0a07371cd3..48d7c15f42 100644 --- a/packages/server/src/integrations/microsoftSqlServer.ts +++ b/packages/server/src/integrations/microsoftSqlServer.ts @@ -281,6 +281,7 @@ class SqlServerIntegration extends Sql implements DatasourcePlus { case MSSQLConfigAuthType.NTLM: { const { domain, trustServerCertificate } = this.config.ntlmConfig || {} + clientCfg.authentication = { type: "ntlm", options: { diff --git a/packages/server/src/integrations/snowflake.ts b/packages/server/src/integrations/snowflake.ts index 6b3c79ed52..00c5ec6d38 100644 --- a/packages/server/src/integrations/snowflake.ts +++ b/packages/server/src/integrations/snowflake.ts @@ -74,14 +74,14 @@ const SCHEMA: Integration = { class SnowflakePromise { config: SnowflakeConfig - client: snowflakeSdk + client?: snowflakeSdk.Connection constructor(config: SnowflakeConfig) { this.config = config } async connect() { - if (this.client?.isConnected()) return + if (this.client?.isUp()) return this.client = snowflakeSdk.createConnection(this.config) const connectAsync = promisify(this.client.connect.bind(this.client)) @@ -89,6 +89,10 @@ class SnowflakePromise { } async execute(sql: string) { + if (!this.client) { + throw Error("No snowflake client present to execute query. Run connect() first to initialise.") + } + return new Promise((resolve, reject) => { this.client.execute({ sqlText: sql, diff --git a/packages/server/src/utilities/fileSystem/processor.ts b/packages/server/src/utilities/fileSystem/processor.ts index a32a7568f4..03fbf4ad0a 100644 --- a/packages/server/src/utilities/fileSystem/processor.ts +++ b/packages/server/src/utilities/fileSystem/processor.ts @@ -1,4 +1,4 @@ -import jimp from "jimp" +import { Jimp } from "jimp" const FORMATS = { IMAGES: ["png", "jpg", "jpeg", "gif", "bmp", "tiff"], @@ -6,8 +6,8 @@ const FORMATS = { function processImage(file: { path: string }) { // this will overwrite the temp file - return jimp.read(file.path).then(img => { - return img.resize(300, jimp.AUTO).write(file.path) + return Jimp.read(file.path).then(img => { + return img.resize({ w: 256 }).write(file.path as `${string}.${string}`) }) } diff --git a/yarn.lock b/yarn.lock index a7b13c751e..b3cb15f423 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5575,10 +5575,10 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== -"@types/mssql@9.1.4": - version "9.1.4" - resolved "https://registry.yarnpkg.com/@types/mssql/-/mssql-9.1.4.tgz#d485b06494a76d15b957e0952305c55053bac366" - integrity sha512-st2ryK+viraRuptxcGs+66J0RrABytxhGxUlpWcOniNPzpnxIaeNhPJVM3lZn1r+s/6lQARYID6Z+MBoseSD8g== +"@types/mssql@9.1.5": + version "9.1.5" + resolved "https://registry.yarnpkg.com/@types/mssql/-/mssql-9.1.5.tgz#1574a5870aeb029c6d787861af101161b9b8d3b6" + integrity sha512-Q9EsgXwuRoX5wvUSu24YfbKMbFChv7pZ/jeCzPkj47ehcuXYsBcfogwrtVFosSjinD4Q/MY2YPGk9Yy1cM2Ywg== dependencies: "@types/node" "*" "@types/tedious" "*" From 70b9e4680f4324c95e22877bf1f1939d8dfbbcde Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 19:03:54 +0000 Subject: [PATCH 26/40] types and lint --- packages/server/src/integrations/snowflake.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/server/src/integrations/snowflake.ts b/packages/server/src/integrations/snowflake.ts index 00c5ec6d38..eacf3d0551 100644 --- a/packages/server/src/integrations/snowflake.ts +++ b/packages/server/src/integrations/snowflake.ts @@ -90,7 +90,9 @@ class SnowflakePromise { async execute(sql: string) { if (!this.client) { - throw Error("No snowflake client present to execute query. Run connect() first to initialise.") + throw Error( + "No snowflake client present to execute query. Run connect() first to initialise." + ) } return new Promise((resolve, reject) => { From 941aa181dd5ddedfe57bda3eaf04853090108b51 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 19 Nov 2024 19:16:10 +0000 Subject: [PATCH 27/40] more types --- .../src/integrations/microsoftSqlServer.ts | 5 +++++ packages/server/src/integrations/snowflake.ts | 20 +++++++++++-------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/packages/server/src/integrations/microsoftSqlServer.ts b/packages/server/src/integrations/microsoftSqlServer.ts index 48d7c15f42..1ad16bda49 100644 --- a/packages/server/src/integrations/microsoftSqlServer.ts +++ b/packages/server/src/integrations/microsoftSqlServer.ts @@ -282,8 +282,13 @@ class SqlServerIntegration extends Sql implements DatasourcePlus { const { domain, trustServerCertificate } = this.config.ntlmConfig || {} + if (!domain) { + throw Error("Domain must be provided for NTLM config") + } + clientCfg.authentication = { type: "ntlm", + // @ts-ignore options: { domain, }, diff --git a/packages/server/src/integrations/snowflake.ts b/packages/server/src/integrations/snowflake.ts index eacf3d0551..838cbb4106 100644 --- a/packages/server/src/integrations/snowflake.ts +++ b/packages/server/src/integrations/snowflake.ts @@ -6,7 +6,7 @@ import { QueryType, SqlQuery, } from "@budibase/types" -import snowflakeSdk from "snowflake-sdk" +import snowflakeSdk, { SnowflakeError } from "snowflake-sdk" import { promisify } from "util" interface SnowflakeConfig { @@ -89,16 +89,20 @@ class SnowflakePromise { } async execute(sql: string) { - if (!this.client) { - throw Error( - "No snowflake client present to execute query. Run connect() first to initialise." - ) - } - return new Promise((resolve, reject) => { + if (!this.client) { + throw Error( + "No snowflake client present to execute query. Run connect() first to initialise." + ) + } + this.client.execute({ sqlText: sql, - complete: function (err: Error, statementExecuted: string, rows: any) { + complete: function ( + err: SnowflakeError | undefined, + statementExecuted: any, + rows: any + ) { if (err) { return reject(err) } From 0bb6f691a80a6d90d8db243cf5dea07eb4a09d37 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 20 Nov 2024 10:05:55 +0000 Subject: [PATCH 28/40] adding crypto dep --- packages/worker/src/api/controllers/global/users.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/worker/src/api/controllers/global/users.ts b/packages/worker/src/api/controllers/global/users.ts index fa19948bf5..f415698fc0 100644 --- a/packages/worker/src/api/controllers/global/users.ts +++ b/packages/worker/src/api/controllers/global/users.ts @@ -40,6 +40,7 @@ import { import { checkAnyUserExists } from "../../../utilities/users" import { isEmailConfigured } from "../../../utilities/email" import { BpmStatusKey, BpmStatusValue, utils } from "@budibase/shared-core" +import crypto from "crypto" const MAX_USERS_UPLOAD_LIMIT = 1000 From d0ad87d504ab25f31b3f2f2fb4657301cfe6cf16 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 20 Nov 2024 11:40:53 +0000 Subject: [PATCH 29/40] revert curlconverter --- packages/server/package.json | 2 +- .../controllers/query/import/sources/curl.ts | 7 +- yarn.lock | 207 ++++++++++++++---- 3 files changed, 168 insertions(+), 48 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index 8ff2c1f8c2..75818db4df 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -75,7 +75,7 @@ "content-disposition": "^0.5.4", "cookies": "0.8.0", "csvtojson": "2.0.10", - "curlconverter": "4.11.0", + "curlconverter": "3.21.0", "dd-trace": "5.23.0", "dotenv": "8.2.0", "form-data": "4.0.0", diff --git a/packages/server/src/api/controllers/query/import/sources/curl.ts b/packages/server/src/api/controllers/query/import/sources/curl.ts index 3e0ea1bcd7..357047b2c7 100644 --- a/packages/server/src/api/controllers/query/import/sources/curl.ts +++ b/packages/server/src/api/controllers/query/import/sources/curl.ts @@ -1,9 +1,9 @@ import { ImportSource, ImportInfo } from "./base" import { Query } from "../../../../../definitions/common" import { URL } from "url" +const curlconverter = require("curlconverter") -const parseCurl = async (data: string): Promise => { - const curlconverter = await import("curlconverter") +const parseCurl = (data: string): Promise => { const curlJson = curlconverter.toJsonString(data) return JSON.parse(curlJson) } @@ -52,8 +52,7 @@ export class Curl extends ImportSource { isSupported = async (data: string): Promise => { try { - const curl = await parseCurl(data) - this.curl = curl + this.curl = parseCurl(data) } catch (err) { return false } diff --git a/yarn.lock b/yarn.lock index b3cb15f423..e3dbca7228 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2289,6 +2289,24 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@curlconverter/yargs-parser@^0.0.1": + version "0.0.1" + resolved "https://registry.yarnpkg.com/@curlconverter/yargs-parser/-/yargs-parser-0.0.1.tgz#62a360cea3d62b9b5805e61e8110cea98da8d140" + integrity sha512-DbEVRYqrorzwqc63MQ3RODflut1tNla8ZCKo1h83lF7+fbntgubZsDfRDBv5Lxj3vkKuvAolysNM2ekwJev8wA== + +"@curlconverter/yargs@^0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@curlconverter/yargs/-/yargs-0.0.2.tgz#a8ad4a2a2d0b0f897f8c117f664199165b59fd8a" + integrity sha512-Q1YEebpCY61kxme4wvU0/IN/uMBfG5pZOKCo9FU+w20ElPvN+eH2qEVbK1C12t3Tee3qeYLLEU6HkiUeO1gc4A== + dependencies: + "@curlconverter/yargs-parser" "^0.0.1" + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + "@dabh/diagnostics@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" @@ -6383,6 +6401,11 @@ JSONStream@^1.3.5: jsonparse "^1.2.0" through ">=2.2.7 <3" +a-sync-waterfall@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz#75b6b6aa72598b497a125e7a2770f14f4c8a1fa7" + integrity sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA== + abab@^2.0.3, abab@^2.0.5, abab@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" @@ -6925,7 +6948,7 @@ arrify@^2.0.0, arrify@^2.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== -asap@^2.0.0: +asap@^2.0.0, asap@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== @@ -8220,6 +8243,11 @@ commander@^2.16.0, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3, comm resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== +commander@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" + integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== + commander@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" @@ -8476,6 +8504,11 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +cookie@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" + integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== + cookie@~0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" @@ -8831,16 +8864,17 @@ csvtojson@2.0.10: lodash "^4.17.3" strip-bom "^2.0.0" -curlconverter@4.11.0: - version "4.11.0" - resolved "https://registry.yarnpkg.com/curlconverter/-/curlconverter-4.11.0.tgz#39a319675cf243278a488411c583c9ada5f74efe" - integrity sha512-jBSvfDN10L6rGWVlkAYgtkIG8lYprDvtBgos7mafxtv15keYeQWsxUgnzns3JmqEcGJMeaGlDNdRUszURPCUaw== +curlconverter@3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/curlconverter/-/curlconverter-3.21.0.tgz#50b9568b8d24967ef55a0fcd872e7a18eea4cbc2" + integrity sha512-DXCnp1A/Xa69FujksUfdvWQFAnIn/C+4Wuv8t+UVdZkF/lY5bzj98GGKOGme7V/ckSHDLxE29Xp76sJ5Cpsp5A== dependencies: + "@curlconverter/yargs" "^0.0.2" + cookie "^0.4.1" jsesc "^3.0.2" - lossless-json "^4.0.2" - tree-sitter "^0.21.1" - tree-sitter-bash "^0.23.1" - web-tree-sitter "^0.24.3" + nunjucks "^3.2.3" + query-string "^7.0.1" + string.prototype.startswith "^1.0.0" yamljs "^0.3.0" "d3-color@1 - 3": @@ -9056,7 +9090,7 @@ decimal.js@^10.2.1, decimal.js@^10.4.3: resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== -decode-uri-component@^0.2.0: +decode-uri-component@^0.2.0, decode-uri-component@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== @@ -10019,6 +10053,58 @@ es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0: unbox-primitive "^1.0.2" which-typed-array "^1.1.15" +es-abstract@^1.23.3: + version "1.23.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.5.tgz#f4599a4946d57ed467515ed10e4f157289cd52fb" + integrity sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + data-view-buffer "^1.0.1" + data-view-byte-length "^1.0.1" + data-view-byte-offset "^1.0.0" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-set-tostringtag "^2.0.3" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" + globalthis "^1.0.4" + gopd "^1.0.1" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + hasown "^2.0.2" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" + is-callable "^1.2.7" + is-data-view "^1.0.1" + is-negative-zero "^2.0.3" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.3" + is-string "^1.0.7" + is-typed-array "^1.1.13" + is-weakref "^1.0.2" + object-inspect "^1.13.3" + object-keys "^1.1.1" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.3" + safe-array-concat "^1.1.2" + safe-regex-test "^1.0.3" + string.prototype.trim "^1.2.9" + string.prototype.trimend "^1.0.8" + string.prototype.trimstart "^1.0.8" + typed-array-buffer "^1.0.2" + typed-array-byte-length "^1.0.1" + typed-array-byte-offset "^1.0.2" + typed-array-length "^1.0.6" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.15" + es-define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" @@ -10804,6 +10890,11 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" +filter-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/filter-obj/-/filter-obj-1.1.0.tgz#9b311112bc6c6127a16e016c6c5d7f19e0805c5b" + integrity sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ== + find-free-port@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/find-free-port/-/find-free-port-2.0.0.tgz#4b22e5f6579eb1a38c41ac6bcb3efed1b6da9b1b" @@ -11463,6 +11554,14 @@ globalthis@^1.0.1, globalthis@^1.0.3: dependencies: define-properties "^1.1.3" +globalthis@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" + integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== + dependencies: + define-properties "^1.2.1" + gopd "^1.0.1" + globalyzer@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465" @@ -14540,11 +14639,6 @@ lookpath@1.1.0: resolved "https://registry.yarnpkg.com/lookpath/-/lookpath-1.1.0.tgz#932d68371a2f0b4a5644f03d6a2b4728edba96d2" integrity sha512-B9NM7XpVfkyWqfOBI/UW0kVhGw7pJztsduch+1wkbYDi90mYK6/InFul3lG0hYko/VEcVMARVBJ5daFRc5aKCw== -lossless-json@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/lossless-json/-/lossless-json-4.0.2.tgz#f00c52815805d1421930a87e2670e27350958a3f" - integrity sha512-+z0EaLi2UcWi8MZRxA5iTb6m4Ys4E80uftGY+yG5KNFJb5EceQXOhdW/pWJZ8m97s26u7yZZAYMcKWNztSZssA== - loupe@^2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" @@ -15429,11 +15523,6 @@ node-addon-api@^6.1.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-6.1.0.tgz#ac8470034e58e67d0c6f1204a18ae6995d9c0d76" integrity sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA== -node-addon-api@^8.0.0, node-addon-api@^8.2.1: - version "8.2.2" - resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-8.2.2.tgz#3658f78d04d260aa95931d3bbc45f22ce433b821" - integrity sha512-9emqXAKhVoNrQ792nLI/wpzPpJ/bj/YXxW0CvAau1+RdGBcCRF1Dmz7719zgVsQNrzHl9Tzn3ImZ4qWFarWL0A== - node-domexception@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" @@ -15470,7 +15559,7 @@ node-gyp-build@<4.0, node-gyp-build@^3.9.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-3.9.0.tgz#53a350187dd4d5276750da21605d1cb681d09e25" integrity sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A== -node-gyp-build@^4.3.0, node-gyp-build@^4.5.0, node-gyp-build@^4.8.0, node-gyp-build@^4.8.2: +node-gyp-build@^4.3.0, node-gyp-build@^4.5.0: version "4.8.4" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.4.tgz#8a70ee85464ae52327772a90d66c6077a900cfc8" integrity sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ== @@ -15781,6 +15870,15 @@ nth-check@^2.0.1: dependencies: boolbase "^1.0.0" +nunjucks@^3.2.3: + version "3.2.4" + resolved "https://registry.yarnpkg.com/nunjucks/-/nunjucks-3.2.4.tgz#f0878eef528ce7b0aa35d67cc6898635fd74649e" + integrity sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ== + dependencies: + a-sync-waterfall "^1.0.0" + asap "^2.0.3" + commander "^5.1.0" + nwsapi@^2.2.0, nwsapi@^2.2.4: version "2.2.12" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.12.tgz#fb6af5c0ec35b27b4581eb3bbad34ec9e5c696f8" @@ -15880,6 +15978,11 @@ object-inspect@^1.13.1: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== +object-inspect@^1.13.3: + version "1.13.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a" + integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA== + object-is@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" @@ -17865,6 +17968,16 @@ query-string@^5.0.1: object-assign "^4.1.0" strict-uri-encode "^1.0.0" +query-string@^7.0.1: + version "7.1.3" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" + integrity sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg== + dependencies: + decode-uri-component "^0.2.2" + filter-obj "^1.1.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -18228,6 +18341,16 @@ regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2: es-errors "^1.3.0" set-function-name "^2.0.1" +regexp.prototype.flags@^1.5.3: + version "1.5.3" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" + integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-errors "^1.3.0" + set-function-name "^2.0.2" + regexparam@2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/regexparam/-/regexparam-2.0.2.tgz#a0f6aa057c67b1c9c09508c45823c0755b1f6e58" @@ -18871,7 +18994,7 @@ set-function-length@^1.2.1: gopd "^1.0.1" has-property-descriptors "^1.0.2" -set-function-name@^2.0.1: +set-function-name@^2.0.1, set-function-name@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== @@ -19276,6 +19399,11 @@ split-ca@^1.0.1: resolved "https://registry.yarnpkg.com/split-ca/-/split-ca-1.0.1.tgz#6c83aff3692fa61256e0cd197e05e9de157691a6" integrity sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ== +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + split2@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" @@ -19448,6 +19576,11 @@ strict-uri-encode@^1.0.0: resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" integrity sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ== +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== + string-hash@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" @@ -19493,6 +19626,15 @@ string-width@^5.0.0, string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" +string.prototype.startswith@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.startswith/-/string.prototype.startswith-1.0.1.tgz#623e2d013d93d3d2bbfbc9eed9e1010ba3f50ce8" + integrity sha512-7FoHkxvUevSBxSBXqsJgQy+IwuSPVl1jF31FEagFxkKnNKnmRLcHY6cJgxy074qrFq9T0OE36OU5aPw+z1v0yw== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + string.prototype.trim@^1.2.9: version "1.2.9" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" @@ -20315,22 +20457,6 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== -tree-sitter-bash@^0.23.1: - version "0.23.3" - resolved "https://registry.yarnpkg.com/tree-sitter-bash/-/tree-sitter-bash-0.23.3.tgz#c5f49f7ae70d719fe08af96059ccb83383eb3fc2" - integrity sha512-36cg/GQ2YmIbeiBeqeuh4fBJ6i4kgVouDaqTxqih5ysPag+zHufyIaxMOFeM8CeplwAK/Luj1o5XHqgdAfoCZg== - dependencies: - node-addon-api "^8.2.1" - node-gyp-build "^4.8.2" - -tree-sitter@^0.21.1: - version "0.21.1" - resolved "https://registry.yarnpkg.com/tree-sitter/-/tree-sitter-0.21.1.tgz#fbb34c09056700814af0e1e37688e06463ba04c4" - integrity sha512-7dxoA6kYvtgWw80265MyqJlkRl4yawIjO7S5MigytjELkX43fV2WsAXzsNfO7sBpPPCF5Gp0+XzHk0DwLCq3xQ== - dependencies: - node-addon-api "^8.0.0" - node-gyp-build "^4.8.0" - trim-newlines@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" @@ -21119,11 +21245,6 @@ web-streams-polyfill@4.0.0-beta.3: resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38" integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug== -web-tree-sitter@^0.24.3: - version "0.24.4" - resolved "https://registry.yarnpkg.com/web-tree-sitter/-/web-tree-sitter-0.24.4.tgz#c223df93a1284efbe871aa36c2c9de097a116ec1" - integrity sha512-sETP1Sf9OTd4LusrKBNznNgTt3fWoWhJnAFaKPiGSeVKXJbZ72qoMpxddKMdVI5BgXv32OI7tkKQre5PmF9reA== - web-vitals@^4.0.1: version "4.2.3" resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.3.tgz#270c4baecfbc6ec6fc15da1989e465e5f9b94fb7" From f96983184fab984bc2493e31ab23565c8741422c Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 20 Nov 2024 12:11:48 +0000 Subject: [PATCH 30/40] explain NTLM type ignore --- packages/server/src/integrations/microsoftSqlServer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/integrations/microsoftSqlServer.ts b/packages/server/src/integrations/microsoftSqlServer.ts index 1ad16bda49..1c74e6b1ff 100644 --- a/packages/server/src/integrations/microsoftSqlServer.ts +++ b/packages/server/src/integrations/microsoftSqlServer.ts @@ -288,7 +288,7 @@ class SqlServerIntegration extends Sql implements DatasourcePlus { clientCfg.authentication = { type: "ntlm", - // @ts-ignore + // @ts-expect-error - username and password not required for NTLM options: { domain, }, From 803247f87b2660aaeed040dd8b118574e94ce166 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 20 Nov 2024 12:15:23 +0000 Subject: [PATCH 31/40] lint --- packages/server/src/api/controllers/query/import/sources/curl.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/server/src/api/controllers/query/import/sources/curl.ts b/packages/server/src/api/controllers/query/import/sources/curl.ts index 357047b2c7..5742d254af 100644 --- a/packages/server/src/api/controllers/query/import/sources/curl.ts +++ b/packages/server/src/api/controllers/query/import/sources/curl.ts @@ -1,6 +1,7 @@ import { ImportSource, ImportInfo } from "./base" import { Query } from "../../../../../definitions/common" import { URL } from "url" + const curlconverter = require("curlconverter") const parseCurl = (data: string): Promise => { From 5d0f220882f4a3cb34efa3fe6a921c5e47c1356a Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 20 Nov 2024 15:49:17 +0000 Subject: [PATCH 32/40] fix oidc tests --- packages/backend-core/package.json | 8 +- packages/worker/package.json | 4 +- yarn.lock | 239 ++++++++++++++++++++++++++--- 3 files changed, 225 insertions(+), 26 deletions(-) diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 4b4bccebad..8f91d1e55d 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -33,6 +33,7 @@ "@budibase/pouchdb-replication-stream": "1.2.11", "@budibase/shared-core": "0.0.0", "@budibase/types": "0.0.0", + "@techpass/passport-openidconnect": "0.3.3", "aws-cloudfront-sign": "3.0.2", "aws-sdk": "2.1692.0", "bcrypt": "5.1.0", @@ -41,6 +42,8 @@ "correlation-id": "4.0.0", "dd-trace": "5.23.0", "dotenv": "16.0.1", + "google-auth-library": "^8.0.1", + "google-spreadsheet": "npm:@budibase/google-spreadsheet@4.1.5", "ioredis": "5.3.2", "joi": "17.6.0", "jsonwebtoken": "9.0.2", @@ -62,10 +65,7 @@ "sanitize-s3-objectkey": "0.0.1", "semver": "^7.5.4", "tar-fs": "2.1.1", - "uuid": "^8.3.2", - "@techpass/passport-openidconnect": "1.0.0", - "google-auth-library": "^8.0.1", - "google-spreadsheet": "npm:@budibase/google-spreadsheet@4.1.5" + "uuid": "^8.3.2" }, "devDependencies": { "@jest/types": "^29.6.3", diff --git a/packages/worker/package.json b/packages/worker/package.json index 4918036e0c..85eae6c88a 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -40,11 +40,11 @@ "dependencies": { "@budibase/backend-core": "0.0.0", "@budibase/pro": "0.0.0", + "@budibase/shared-core": "0.0.0", "@budibase/string-templates": "0.0.0", "@budibase/types": "0.0.0", - "@budibase/shared-core": "0.0.0", "@koa/router": "13.1.0", - "@techpass/passport-openidconnect": "1.0.0", + "@techpass/passport-openidconnect": "0.3.3", "@types/global-agent": "2.1.1", "aws-sdk": "2.1692.0", "bcrypt": "5.1.0", diff --git a/yarn.lock b/yarn.lock index 0844cc1890..28591e7be0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2203,7 +2203,7 @@ "@budibase/pouchdb-replication-stream" "1.2.11" "@budibase/shared-core" "0.0.0" "@budibase/types" "0.0.0" - "@techpass/passport-openidconnect" "1.0.0" + "@techpass/passport-openidconnect" "0.3.3" aws-cloudfront-sign "3.0.2" aws-sdk "2.1692.0" bcrypt "5.1.0" @@ -5277,13 +5277,16 @@ dependencies: defer-to-connect "^1.0.1" -"@techpass/passport-openidconnect@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-1.0.0.tgz#e79a70b2ccd54d04122b774a33469cb52858a6bd" - integrity sha512-jcTny/3ZUlp1wN9xrUPjPQpVOfMtZ9ehSF/1T6AXse/FvgiWXDIVZUPW/QcoDsXXqYeI6huWPMGM4AwxtMe8bA== +"@techpass/passport-openidconnect@0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@techpass/passport-openidconnect/-/passport-openidconnect-0.3.3.tgz#6c01c78bd8da0ca8917378dfbe18024702620352" + integrity sha512-i2X/CofjnGBqpTmw6b+Ex3Co/NrR2xjnIHvnOJk62XIlJJHNSTwmhJ1PkXoA5RGKlxZWchADFGjLTJnebvRj7A== dependencies: - oauth "~0.9.0" + base64url "^3.0.1" + oauth "^0.9.15" passport-strategy "^1.0.0" + request "^2.88.0" + webfinger "^0.4.2" "@techteamer/ocsp@1.0.1": version "1.0.1" @@ -6835,7 +6838,7 @@ ajv-formats@^2.0.2: dependencies: ajv "^8.0.0" -ajv@^6.12.4: +ajv@^6.12.3, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -7232,13 +7235,18 @@ asn1.js@^5.0.0, asn1.js@^5.4.1: minimalistic-assert "^1.0.0" safer-buffer "^2.1.0" -asn1@^0.2.6: +asn1@^0.2.6, asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== dependencies: safer-buffer "~2.1.0" +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== + assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" @@ -7336,6 +7344,16 @@ aws-sdk@2.1692.0: uuid "8.0.0" xml2js "0.6.2" +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== + +aws4@^1.8.0: + version "1.13.2" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.13.2.tgz#0aa167216965ac9474ccfa83892cfb6b3e1e52ef" + integrity sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw== + axios@1.1.3, axios@1.7.7, axios@^0.21.1, axios@^1.0.0, axios@^1.1.3, axios@^1.4.0, axios@^1.6.2, axios@^1.6.8: version "1.7.7" resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" @@ -7527,12 +7545,12 @@ base64id@2.0.0, base64id@~2.0.0: resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== -base64url@3.x.x: +base64url@3.x.x, base64url@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== -bcrypt-pbkdf@^1.0.2: +bcrypt-pbkdf@^1.0.0, bcrypt-pbkdf@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w== @@ -8084,6 +8102,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001449: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001460.tgz#31d2e26f0a2309860ed3eff154e03890d9d851a7" integrity sha512-Bud7abqjvEjipUkpLs4D7gR0l8hBYBHoa+tGtKJHvT2AYzLp1z7EmVkUT4ERpVUfca8S2HGIVs883D8pUH1ZzQ== +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== + catering@^2.0.0, catering@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510" @@ -8456,7 +8479,7 @@ columnify@1.6.0: strip-ansi "^6.0.1" wcwidth "^1.0.0" -combined-stream@^1.0.6, combined-stream@^1.0.8: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -8792,6 +8815,11 @@ core-js-compat@^3.20.2, core-js-compat@^3.21.0, core-js-compat@^3.25.1, core-js- dependencies: browserslist "^4.21.5" +core-util-is@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ== + core-util-is@^1.0.2, core-util-is@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" @@ -9200,6 +9228,13 @@ dargs@^7.0.0: resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g== + dependencies: + assert-plus "^1.0.0" + data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -10139,6 +10174,14 @@ easymde@^2.16.1: codemirror-spell-checker "1.1.2" marked "^4.1.0" +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw== + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" @@ -10973,7 +11016,7 @@ extend-shallow@^2.0.1: dependencies: is-extendable "^0.1.0" -extend@^3.0.2: +extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -10987,6 +11030,16 @@ external-editor@^3.0.3: iconv-lite "^0.4.24" tmp "^0.0.33" +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g== + +extsprintf@^1.2.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" + integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== + fast-copy@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.1.tgz#9e89ef498b8c04c1cd76b33b8e14271658a732aa" @@ -11330,6 +11383,11 @@ foreground-child@^3.1.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== + form-data-encoder@1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040" @@ -11362,6 +11420,15 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + formdata-node@^4.3.2: version "4.4.1" resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2" @@ -11728,6 +11795,13 @@ getopts@2.3.0: resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.3.0.tgz#71e5593284807e03e2427449d4f6712a268666f4" integrity sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA== +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng== + dependencies: + assert-plus "^1.0.0" + gifwrap@^0.10.1: version "0.10.1" resolved "https://registry.yarnpkg.com/gifwrap/-/gifwrap-0.10.1.tgz#9ed46a5d51913b482d4221ce9c727080260b681e" @@ -12151,6 +12225,19 @@ handlebars@^4.7.7, handlebars@^4.7.8: optionalDependencies: uglify-js "^3.1.4" +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q== + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + hard-rejection@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" @@ -12459,6 +12546,15 @@ http-proxy-agent@^7.0.0: agent-base "^7.1.0" debug "^4.3.4" +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ== + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + https-proxy-agent@^5.0.0, https-proxy-agent@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" @@ -12492,6 +12588,11 @@ husky@^8.0.3: resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.3.tgz#4936d7212e46d1dea28fef29bb3a108872cd9184" integrity sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg== +husky@^9.1.4: + version "9.1.7" + resolved "https://registry.yarnpkg.com/husky/-/husky-9.1.7.tgz#d46a38035d101b46a70456a850ff4201344c0b2d" + integrity sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA== + ical-generator@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ical-generator/-/ical-generator-4.1.0.tgz#2a336c951864c5583a2aa715d16f2edcdfd2d90b" @@ -13222,7 +13323,7 @@ is-typed-array@^1.1.13, is-typed-array@^1.1.3: dependencies: which-typed-array "^1.1.14" -is-typedarray@^1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== @@ -13940,6 +14041,11 @@ js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.14.1: argparse "^1.0.7" esprima "^4.0.0" +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== + jsdom@^16.0.1: version "16.7.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710" @@ -14067,12 +14173,17 @@ json-schema-traverse@^1.0.0: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== +json-schema@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5" + integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json-stringify-safe@^5.0.1: +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== @@ -14138,6 +14249,16 @@ jsonwebtoken@9.0.2, jsonwebtoken@^9.0.0: ms "^2.1.1" semver "^7.5.4" +jsprim@^1.2.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb" + integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.4.0" + verror "1.10.0" + jstransform@~11.0.0: version "11.0.3" resolved "https://registry.yarnpkg.com/jstransform/-/jstransform-11.0.3.tgz#09a78993e0ae4d4ef4487f6155a91f6190cb4223" @@ -15446,7 +15567,7 @@ mime-kind@^3.0.0: file-type "^12.1.0" mime-types "^2.1.24" -mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.24, mime-types@^2.1.29, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.18, mime-types@^2.1.24, mime-types@^2.1.29, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -16395,7 +16516,12 @@ nx@16.10.0, "nx@>=16.5.1 < 17": "@nx/nx-win32-arm64-msvc" "16.10.0" "@nx/nx-win32-x64-msvc" "16.10.0" -oauth@0.9.x, oauth@~0.9.0: +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +oauth@0.9.x, oauth@^0.9.15: version "0.9.15" resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" integrity sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA== @@ -17198,6 +17324,11 @@ pend@~1.2.0: resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg== +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow== + periscopic@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/periscopic/-/periscopic-3.1.0.tgz#7e9037bf51c5855bd33b48928828db4afa79d97a" @@ -18421,6 +18552,11 @@ qs@^6.10.3, qs@^6.11.0, qs@^6.4.0: dependencies: side-channel "^1.0.6" +qs@~6.5.2: + version "6.5.3" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" + integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== + query-string@^5.0.1: version "5.1.1" resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" @@ -18863,6 +18999,32 @@ remixicon@2.5.0: resolved "https://registry.yarnpkg.com/remixicon/-/remixicon-2.5.0.tgz#b5e245894a1550aa23793f95daceadbf96ad1a41" integrity sha512-q54ra2QutYDZpuSnFjmeagmEiN9IMo56/zz5dDNitzKD23oFRw77cWo4TsrAdmdkPiEn8mxlrTqxnkujDbEGww== +request@^2.88.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -19283,7 +19445,7 @@ safe-stable-stringify@^2.1.0, safe-stable-stringify@^2.3.1: resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -19929,6 +20091,21 @@ ssh2@^1.11.0, ssh2@^1.4.0: cpu-features "~0.0.9" nan "^2.18.0" +sshpk@^1.7.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028" + integrity sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + ssri@^10.0.0, ssri@^10.0.1: version "10.0.3" resolved "https://registry.yarnpkg.com/ssri/-/ssri-10.0.3.tgz#7f83da39058ca1d599d174e9eee4237659710bf4" @@ -19985,6 +20162,11 @@ std-env@^3.3.1: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== +step@0.0.x: + version "0.0.6" + resolved "https://registry.yarnpkg.com/step/-/step-0.0.6.tgz#143e7849a5d7d3f4a088fe29af94915216eeede2" + integrity sha512-qSSeQinUJk2w38vUFobjFoE307GqsozMC8VisOCkJLpklvKPT0ptPHwWOrENoag8rgLudvTkfP3bancwP93/Jw== + stop-iteration-iterator@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" @@ -20903,7 +21085,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2: +tough-cookie@4.1.3, "tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0, tough-cookie@^4.1.2, tough-cookie@~2.5.0: version "4.1.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf" integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw== @@ -21068,7 +21250,7 @@ tunnel@^0.0.6: resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== -tweetnacl@^0.14.3: +tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== @@ -21605,6 +21787,15 @@ vary@^1, vary@^1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + vite-node@0.29.8: version "0.29.8" resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.29.8.tgz#6a1c9d4fb31e7b4e0f825d3a37abe3404e52bd8e" @@ -21738,6 +21929,14 @@ web-vitals@^4.0.1: resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.3.tgz#270c4baecfbc6ec6fc15da1989e465e5f9b94fb7" integrity sha512-/CFAm1mNxSmOj6i0Co+iGFJ58OS4NRGVP+AWS/l509uIK5a1bSoIVaHz/ZumpHTfHSZBpgrJ+wjfpAOrTHok5Q== +webfinger@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/webfinger/-/webfinger-0.4.2.tgz#3477a6d97799461896039fcffc650b73468ee76d" + integrity sha512-PvvQ/k74HkC3q5G7bGu4VYeKDt3ePZMzT5qFPtEnOL8eyIU1/06OtDn9X5vlkQ23BlegA3eN89rDLiYUife3xQ== + dependencies: + step "0.0.x" + xml2js "0.1.x" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -22083,7 +22282,7 @@ xml-parse-from-string@^1.0.0: resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28" integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g== -xml2js@0.6.2, xml2js@^0.5.0: +xml2js@0.1.x, xml2js@0.6.2, xml2js@^0.5.0: version "0.6.2" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499" integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA== From e50b12e79e709d195707217d7971b998db0fb721 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 20 Nov 2024 15:51:21 +0000 Subject: [PATCH 33/40] Fix test-libraries yarn invocation. --- .github/workflows/budibase_ci.yml | 6 ++++-- packages/builder/src/helpers/tests/nameHelpers.spec.js | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index f1ed6eb87e..af286a1237 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -114,9 +114,11 @@ jobs: - name: Test run: | if ${{ env.ONLY_AFFECTED_TASKS }}; then - yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --no-prefix --since=${{ env.NX_BASE_BRANCH }} -- --verbose --reporters=default --reporters=github-actions + yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/builder --no-prefix --since=${{ env.NX_BASE_BRANCH }} -- --verbose --reporters=default --reporters=github-actions + yarn test -- --scope=@budibase/builder --since=${{ env.NX_BASE_BRANCH }} else - yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --no-prefix -- --verbose --reporters=default --reporters=github-actions + yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/builder --no-prefix -- --verbose --reporters=default --reporters=github-actions + yarn test -- --scope=@budibase/builder fi test-worker: diff --git a/packages/builder/src/helpers/tests/nameHelpers.spec.js b/packages/builder/src/helpers/tests/nameHelpers.spec.js index 1ce2d1987a..167d9c29ae 100644 --- a/packages/builder/src/helpers/tests/nameHelpers.spec.js +++ b/packages/builder/src/helpers/tests/nameHelpers.spec.js @@ -90,7 +90,7 @@ describe("Automation Binding Update Functions", () => { 1 ) - expect(result[1].name).toBe("Second Step") + expect(result[1].name).toBe("Second Step fail") expect(result[2].inputs.branches[0].condition.equal).toEqual({ "stepsByName.Renamed Step.success": true, From d2241b0ffae1236135a2d9163902f03ce693bcfa Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 20 Nov 2024 15:53:26 +0000 Subject: [PATCH 34/40] Enable github annotations for vitest. --- .github/workflows/budibase_ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index af286a1237..e02caa816a 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -112,6 +112,9 @@ jobs: - run: yarn --frozen-lockfile - name: Test + env: + # This enables github annotations for vitest + GITHUB_ACTIONS: true run: | if ${{ env.ONLY_AFFECTED_TASKS }}; then yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/builder --no-prefix --since=${{ env.NX_BASE_BRANCH }} -- --verbose --reporters=default --reporters=github-actions From edee1c2a740a8ac250353ebcf640c2f509061d1e Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 20 Nov 2024 15:56:17 +0000 Subject: [PATCH 35/40] Forgot the no-prefix flag. --- .github/workflows/budibase_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index e02caa816a..83b6720e62 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -118,10 +118,10 @@ jobs: run: | if ${{ env.ONLY_AFFECTED_TASKS }}; then yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/builder --no-prefix --since=${{ env.NX_BASE_BRANCH }} -- --verbose --reporters=default --reporters=github-actions - yarn test -- --scope=@budibase/builder --since=${{ env.NX_BASE_BRANCH }} + yarn test -- --scope=@budibase/builder --since=${{ env.NX_BASE_BRANCH }} --no-prefix else yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/builder --no-prefix -- --verbose --reporters=default --reporters=github-actions - yarn test -- --scope=@budibase/builder + yarn test -- --scope=@budibase/builder --no-prefix fi test-worker: From 900dfc165288b4b0e34d6b08dbbaa7afb6bc132a Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 20 Nov 2024 16:03:45 +0000 Subject: [PATCH 36/40] Try a different method for enabling GHA annotations in vitest. --- .github/workflows/budibase_ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index 83b6720e62..413f62cb37 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -113,15 +113,13 @@ jobs: - run: yarn --frozen-lockfile - name: Test env: - # This enables github annotations for vitest - GITHUB_ACTIONS: true run: | if ${{ env.ONLY_AFFECTED_TASKS }}; then yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/builder --no-prefix --since=${{ env.NX_BASE_BRANCH }} -- --verbose --reporters=default --reporters=github-actions - yarn test -- --scope=@budibase/builder --since=${{ env.NX_BASE_BRANCH }} --no-prefix + yarn test -- --scope=@budibase/builder --since=${{ env.NX_BASE_BRANCH }} --no-prefix -- --reporter=default --reporter=github-actions else yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/builder --no-prefix -- --verbose --reporters=default --reporters=github-actions - yarn test -- --scope=@budibase/builder --no-prefix + yarn test -- --scope=@budibase/builder --no-prefix -- --reporter=default --reporter=github-actions fi test-worker: From a97d56149b14f392b2d729ef6b9c236c98f541a3 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 20 Nov 2024 16:04:41 +0000 Subject: [PATCH 37/40] Rename empty env. --- .github/workflows/budibase_ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index 413f62cb37..d30ef8f2fa 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -112,7 +112,6 @@ jobs: - run: yarn --frozen-lockfile - name: Test - env: run: | if ${{ env.ONLY_AFFECTED_TASKS }}; then yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/builder --no-prefix --since=${{ env.NX_BASE_BRANCH }} -- --verbose --reporters=default --reporters=github-actions From a7b51c8d08ae95afc8db29001c7d0ea7949ad994 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 20 Nov 2024 16:09:09 +0000 Subject: [PATCH 38/40] Give up on annotations for packages/builder for now. --- .github/workflows/budibase_ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/budibase_ci.yml b/.github/workflows/budibase_ci.yml index d30ef8f2fa..1258bddcca 100644 --- a/.github/workflows/budibase_ci.yml +++ b/.github/workflows/budibase_ci.yml @@ -115,10 +115,10 @@ jobs: run: | if ${{ env.ONLY_AFFECTED_TASKS }}; then yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/builder --no-prefix --since=${{ env.NX_BASE_BRANCH }} -- --verbose --reporters=default --reporters=github-actions - yarn test -- --scope=@budibase/builder --since=${{ env.NX_BASE_BRANCH }} --no-prefix -- --reporter=default --reporter=github-actions + yarn test -- --scope=@budibase/builder --since=${{ env.NX_BASE_BRANCH }} else yarn test -- --ignore=@budibase/worker --ignore=@budibase/server --ignore=@budibase/builder --no-prefix -- --verbose --reporters=default --reporters=github-actions - yarn test -- --scope=@budibase/builder --no-prefix -- --reporter=default --reporter=github-actions + yarn test -- --scope=@budibase/builder --no-prefix fi test-worker: From b2e18ba9086ee45bf5ced187aff9950a40eba77c Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 20 Nov 2024 16:09:22 +0000 Subject: [PATCH 39/40] Fix test. --- packages/builder/src/helpers/tests/nameHelpers.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/helpers/tests/nameHelpers.spec.js b/packages/builder/src/helpers/tests/nameHelpers.spec.js index 167d9c29ae..1ce2d1987a 100644 --- a/packages/builder/src/helpers/tests/nameHelpers.spec.js +++ b/packages/builder/src/helpers/tests/nameHelpers.spec.js @@ -90,7 +90,7 @@ describe("Automation Binding Update Functions", () => { 1 ) - expect(result[1].name).toBe("Second Step fail") + expect(result[1].name).toBe("Second Step") expect(result[2].inputs.branches[0].condition.equal).toEqual({ "stepsByName.Renamed Step.success": true, From a031e16c56cd79654e5de9ede5a57d2185327062 Mon Sep 17 00:00:00 2001 From: Budibase Staging Release Bot <> Date: Wed, 20 Nov 2024 16:41:35 +0000 Subject: [PATCH 40/40] Bump version to 3.2.10 --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 1abfec7d7c..df1d75bc05 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "3.2.9", + "version": "3.2.10", "npmClient": "yarn", "concurrency": 20, "command": {