diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index f004e0acc5..6ace2303d9 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -6,7 +6,7 @@ labels: bug assignees: '' --- -## Checklist +**Checklist** - [ ] I have searched budibase discussions and github issues to check if my issue already exists **Hosting** diff --git a/lerna.json b/lerna.json index 830d65b92f..0606169dd3 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index f65c40dea0..ca87d6daa4 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "description": "Budibase backend core libraries used in server and worker", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -23,7 +23,7 @@ }, "dependencies": { "@budibase/nano": "10.1.1", - "@budibase/types": "2.2.12-alpha.16", + "@budibase/types": "2.2.12-alpha.32", "@shopify/jest-koa-mocks": "5.0.1", "@techpass/passport-openidconnect": "0.3.2", "aws-cloudfront-sign": "2.2.0", diff --git a/packages/backend-core/src/events/publishers/rows.ts b/packages/backend-core/src/events/publishers/rows.ts index b1180fd936..9608613e89 100644 --- a/packages/backend-core/src/events/publishers/rows.ts +++ b/packages/backend-core/src/events/publishers/rows.ts @@ -3,7 +3,6 @@ import { Event, RowsImportedEvent, RowsCreatedEvent, - RowImportFormat, Table, } from "@budibase/types" @@ -16,14 +15,9 @@ const created = async (count: number, timestamp?: string | number) => { await publishEvent(Event.ROWS_CREATED, properties, timestamp) } -const imported = async ( - table: Table, - format: RowImportFormat, - count: number -) => { +const imported = async (table: Table, count: number) => { const properties: RowsImportedEvent = { tableId: table._id as string, - format, count, } await publishEvent(Event.ROWS_IMPORTED, properties) diff --git a/packages/backend-core/src/events/publishers/table.ts b/packages/backend-core/src/events/publishers/table.ts index 878885c33b..d50f4df0e1 100644 --- a/packages/backend-core/src/events/publishers/table.ts +++ b/packages/backend-core/src/events/publishers/table.ts @@ -2,7 +2,6 @@ import { publishEvent } from "../events" import { Event, TableExportFormat, - TableImportFormat, Table, TableCreatedEvent, TableUpdatedEvent, @@ -40,10 +39,9 @@ async function exported(table: Table, format: TableExportFormat) { await publishEvent(Event.TABLE_EXPORTED, properties) } -async function imported(table: Table, format: TableImportFormat) { +async function imported(table: Table) { const properties: TableImportedEvent = { tableId: table._id as string, - format, } await publishEvent(Event.TABLE_IMPORTED, properties) } diff --git a/packages/backend-core/yarn.lock b/packages/backend-core/yarn.lock index d8dd7886f3..b288cc521b 100644 --- a/packages/backend-core/yarn.lock +++ b/packages/backend-core/yarn.lock @@ -10,128 +10,64 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" - integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== - dependencies: - "@babel/highlight" "^7.16.7" - -"@babel/code-frame@^7.18.6": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: "@babel/highlight" "^7.18.6" -"@babel/compat-data@^7.17.10": - version "7.17.10" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.10.tgz#711dc726a492dfc8be8220028b1b92482362baab" - integrity sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw== +"@babel/compat-data@^7.20.5": + version "7.20.10" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.10.tgz#9d92fa81b87542fff50e848ed585b4212c1d34ec" + integrity sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg== -"@babel/compat-data@^7.20.0": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30" - integrity sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ== - -"@babel/core@^7.11.6": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.2.tgz#8dc9b1620a673f92d3624bd926dc49a52cf25b92" - integrity sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g== +"@babel/core@^7.11.6", "@babel/core@^7.12.3": + version "7.20.12" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.12.tgz#7930db57443c6714ad216953d1356dac0eb8496d" + integrity sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg== dependencies: "@ampproject/remapping" "^2.1.0" "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.2" - "@babel/helper-compilation-targets" "^7.20.0" - "@babel/helper-module-transforms" "^7.20.2" - "@babel/helpers" "^7.20.1" - "@babel/parser" "^7.20.2" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.1" - "@babel/types" "^7.20.2" + "@babel/generator" "^7.20.7" + "@babel/helper-compilation-targets" "^7.20.7" + "@babel/helper-module-transforms" "^7.20.11" + "@babel/helpers" "^7.20.7" + "@babel/parser" "^7.20.7" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.12" + "@babel/types" "^7.20.7" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.2.1" + json5 "^2.2.2" semver "^6.3.0" -"@babel/core@^7.12.3": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.2.tgz#87b2fcd7cce9becaa7f5acebdc4f09f3dd19d876" - integrity sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ== +"@babel/generator@^7.20.7", "@babel/generator@^7.7.2": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.7.tgz#f8ef57c8242665c5929fe2e8d82ba75460187b4a" + integrity sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw== dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.18.2" - "@babel/helper-compilation-targets" "^7.18.2" - "@babel/helper-module-transforms" "^7.18.0" - "@babel/helpers" "^7.18.2" - "@babel/parser" "^7.18.0" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.2" - "@babel/types" "^7.18.2" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.1" - semver "^6.3.0" - -"@babel/generator@^7.18.2", "@babel/generator@^7.7.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d" - integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw== - dependencies: - "@babel/types" "^7.18.2" - "@jridgewell/gen-mapping" "^0.3.0" - jsesc "^2.5.1" - -"@babel/generator@^7.20.1", "@babel/generator@^7.20.2": - version "7.20.4" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.4.tgz#4d9f8f0c30be75fd90a0562099a26e5839602ab8" - integrity sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA== - dependencies: - "@babel/types" "^7.20.2" + "@babel/types" "^7.20.7" "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" -"@babel/helper-compilation-targets@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz#67a85a10cbd5fc7f1457fec2e7f45441dc6c754b" - integrity sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ== +"@babel/helper-compilation-targets@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz#a6cd33e93629f5eb473b021aac05df62c4cd09bb" + integrity sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ== dependencies: - "@babel/compat-data" "^7.17.10" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.20.2" - semver "^6.3.0" - -"@babel/helper-compilation-targets@^7.20.0": - version "7.20.0" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" - integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== - dependencies: - "@babel/compat-data" "^7.20.0" + "@babel/compat-data" "^7.20.5" "@babel/helper-validator-option" "^7.18.6" browserslist "^4.21.3" + lru-cache "^5.1.1" semver "^6.3.0" -"@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz#8a6d2dedb53f6bf248e31b4baf38739ee4a637bd" - integrity sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ== - "@babel/helper-environment-visitor@^7.18.9": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== -"@babel/helper-function-name@^7.17.9": - version "7.17.9" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12" - integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg== - dependencies: - "@babel/template" "^7.16.7" - "@babel/types" "^7.17.0" - "@babel/helper-function-name@^7.19.0": version "7.19.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" @@ -140,13 +76,6 @@ "@babel/template" "^7.18.10" "@babel/types" "^7.19.0" -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" - "@babel/helper-hoist-variables@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" @@ -154,13 +83,6 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== - dependencies: - "@babel/types" "^7.16.7" - "@babel/helper-module-imports@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" @@ -168,45 +90,24 @@ dependencies: "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.18.0": - version "7.18.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz#baf05dec7a5875fb9235bd34ca18bad4e21221cd" - integrity sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.17.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.0" - "@babel/types" "^7.18.0" - -"@babel/helper-module-transforms@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" - integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== +"@babel/helper-module-transforms@^7.20.11": + version "7.20.11" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz#df4c7af713c557938c50ea3ad0117a7944b2f1b0" + integrity sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg== dependencies: "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-module-imports" "^7.18.6" "@babel/helper-simple-access" "^7.20.2" "@babel/helper-split-export-declaration" "^7.18.6" "@babel/helper-validator-identifier" "^7.19.1" - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.1" - "@babel/types" "^7.20.2" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.10" + "@babel/types" "^7.20.7" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.17.12", "@babel/helper-plugin-utils@^7.8.0": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz#86c2347da5acbf5583ba0a10aed4c9bf9da9cf96" - integrity sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA== - -"@babel/helper-simple-access@^7.17.7": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz#4dc473c2169ac3a1c9f4a51cfcd091d1c36fcff9" - integrity sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ== - dependencies: - "@babel/types" "^7.18.2" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.8.0": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== "@babel/helper-simple-access@^7.20.2": version "7.20.2" @@ -215,13 +116,6 @@ dependencies: "@babel/types" "^7.20.2" -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - "@babel/helper-split-export-declaration@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" @@ -234,52 +128,24 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== -"@babel/helper-validator-identifier@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" - integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== - "@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": version "7.19.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== - "@babel/helper-validator-option@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== -"@babel/helpers@^7.18.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.2.tgz#970d74f0deadc3f5a938bfa250738eb4ac889384" - integrity sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg== +"@babel/helpers@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.7.tgz#04502ff0feecc9f20ecfaad120a18f011a8e6dce" + integrity sha512-PBPjs5BppzsGaxHQCDKnZ6Gd9s6xl8bBCluz3vEInLGRJmnZan4F6BYCeqtyXqkk4W5IlPmjK4JlOuZkpJ3xZA== dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.18.2" - "@babel/types" "^7.18.2" - -"@babel/helpers@^7.20.1": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.1.tgz#2ab7a0fcb0a03b5bf76629196ed63c2d7311f4c9" - integrity sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg== - dependencies: - "@babel/template" "^7.18.10" - "@babel/traverse" "^7.20.1" - "@babel/types" "^7.20.0" - -"@babel/highlight@^7.16.7": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351" - integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - chalk "^2.0.0" - js-tokens "^4.0.0" + "@babel/template" "^7.20.7" + "@babel/traverse" "^7.20.7" + "@babel/types" "^7.20.7" "@babel/highlight@^7.18.6": version "7.18.6" @@ -290,15 +156,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.18.0": - version "7.18.4" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.4.tgz#6774231779dd700e0af29f6ad8d479582d7ce5ef" - integrity sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow== - -"@babel/parser@^7.18.10", "@babel/parser@^7.20.1", "@babel/parser@^7.20.2": - version "7.20.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.3.tgz#5358cf62e380cf69efcb87a7bb922ff88bfac6e2" - integrity sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg== +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.7.tgz#66fe23b3c8569220817d5feb8b9dcdc95bb4f71b" + integrity sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg== "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -385,81 +246,48 @@ "@babel/helper-plugin-utils" "^7.14.5" "@babel/plugin-syntax-typescript@^7.7.2": - version "7.17.12" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz#b54fc3be6de734a56b87508f99d6428b5b605a7b" - integrity sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw== + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== dependencies: - "@babel/helper-plugin-utils" "^7.17.12" + "@babel/helper-plugin-utils" "^7.19.0" "@babel/runtime@^7.15.4": - version "7.18.3" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4" - integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug== + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.7.tgz#fcb41a5a70550e04a7b708037c7c32f7f356d8fd" + integrity sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ== dependencies: - regenerator-runtime "^0.13.4" + regenerator-runtime "^0.13.11" -"@babel/template@^7.16.7", "@babel/template@^7.3.3": - version "7.16.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/template@^7.18.10": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" - integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== +"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.3.3": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8" + integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/parser" "^7.18.10" - "@babel/types" "^7.18.10" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" -"@babel/traverse@^7.18.0", "@babel/traverse@^7.18.2", "@babel/traverse@^7.7.2": - version "7.18.2" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.2.tgz#b77a52604b5cc836a9e1e08dca01cba67a12d2e8" - integrity sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.18.2" - "@babel/helper-environment-visitor" "^7.18.2" - "@babel/helper-function-name" "^7.17.9" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.18.0" - "@babel/types" "^7.18.2" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.20.1": - version "7.20.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8" - integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA== +"@babel/traverse@^7.20.10", "@babel/traverse@^7.20.12", "@babel/traverse@^7.20.7", "@babel/traverse@^7.7.2": + version "7.20.12" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.12.tgz#7f0f787b3a67ca4475adef1f56cb94f6abd4a4b5" + integrity sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ== dependencies: "@babel/code-frame" "^7.18.6" - "@babel/generator" "^7.20.1" + "@babel/generator" "^7.20.7" "@babel/helper-environment-visitor" "^7.18.9" "@babel/helper-function-name" "^7.19.0" "@babel/helper-hoist-variables" "^7.18.6" "@babel/helper-split-export-declaration" "^7.18.6" - "@babel/parser" "^7.20.1" - "@babel/types" "^7.20.0" + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.18.0", "@babel/types@^7.18.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3": - version "7.18.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.4.tgz#27eae9b9fd18e9dccc3f9d6ad051336f307be354" - integrity sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2": - version "7.20.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.2.tgz#67ac09266606190f496322dbaff360fdaa5e7842" - integrity sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog== +"@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.20.2", "@babel/types@^7.20.7", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.7.tgz#54ec75e252318423fc07fb644dc6a58a64c09b7f" + integrity sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg== dependencies: "@babel/helper-string-parser" "^7.19.4" "@babel/helper-validator-identifier" "^7.19.1" @@ -736,15 +564,6 @@ "@jridgewell/set-array" "^1.0.0" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/gen-mapping@^0.3.0": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9" - integrity sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg== - dependencies: - "@jridgewell/set-array" "^1.0.0" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" - "@jridgewell/gen-mapping@^0.3.2": version "0.3.2" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" @@ -754,36 +573,21 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" -"@jridgewell/resolve-uri@3.1.0": +"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe" - integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA== - -"@jridgewell/set-array@^1.0.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea" - integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ== - -"@jridgewell/set-array@^1.0.1": +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== -"@jridgewell/sourcemap-codec@1.4.14": +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.13" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c" - integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w== - "@jridgewell/trace-mapping@0.3.9": version "0.3.9" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" @@ -792,7 +596,7 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" -"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13": +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.13", "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== @@ -800,18 +604,10 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@jridgewell/trace-mapping@^0.3.9": - version "0.3.13" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea" - integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@mapbox/node-pre-gyp@^1.0.0": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz#09a8781a3a036151cdebbe8719d6f8b25d4058bc" - integrity sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw== + version "1.0.10" + resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c" + integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA== dependencies: detect-libc "^2.0.0" https-proxy-agent "^5.0.0" @@ -823,35 +619,35 @@ semver "^7.3.5" tar "^6.1.11" -"@msgpackr-extract/msgpackr-extract-darwin-arm64@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.1.2.tgz#9571b87be3a3f2c46de05585470bc4f3af2f6f00" - integrity sha512-TyVLn3S/+ikMDsh0gbKv2YydKClN8HaJDDpONlaZR+LVJmsxLFUgA+O7zu59h9+f9gX1aj/ahw9wqa6rosmrYQ== +"@msgpackr-extract/msgpackr-extract-darwin-arm64@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-2.2.0.tgz#901c5937e1441572ea23e631fe6deca68482fe76" + integrity sha512-Z9LFPzfoJi4mflGWV+rv7o7ZbMU5oAU9VmzCgL240KnqDW65Y2HFCT3MW06/ITJSnbVLacmcEJA8phywK7JinQ== -"@msgpackr-extract/msgpackr-extract-darwin-x64@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.1.2.tgz#bfbc6936ede2955218f5621a675679a5fe8e6f4c" - integrity sha512-YPXtcVkhmVNoMGlqp81ZHW4dMxK09msWgnxtsDpSiZwTzUBG2N+No2bsr7WMtBKCVJMSD6mbAl7YhKUqkp/Few== +"@msgpackr-extract/msgpackr-extract-darwin-x64@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-2.2.0.tgz#fb877fe6bae3c4d3cea29786737840e2ae689066" + integrity sha512-vq0tT8sjZsy4JdSqmadWVw6f66UXqUCabLmUVHZwUFzMgtgoIIQjT4VVRHKvlof3P/dMCkbMJ5hB1oJ9OWHaaw== -"@msgpackr-extract/msgpackr-extract-linux-arm64@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.1.2.tgz#22555e28382af2922e7450634c8a2f240bb9eb82" - integrity sha512-vHZ2JiOWF2+DN9lzltGbhtQNzDo8fKFGrf37UJrgqxU0yvtERrzUugnfnX1wmVfFhSsF8OxrfqiNOUc5hko1Zg== +"@msgpackr-extract/msgpackr-extract-linux-arm64@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-2.2.0.tgz#986179c38b10ac41fbdaf7d036c825cbc72855d9" + integrity sha512-hlxxLdRmPyq16QCutUtP8Tm6RDWcyaLsRssaHROatgnkOxdleMTgetf9JsdncL8vLh7FVy/RN9i3XR5dnb9cRA== -"@msgpackr-extract/msgpackr-extract-linux-arm@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.1.2.tgz#ffb6ae1beea7ac572b6be6bf2a8e8162ebdd8be7" - integrity sha512-42R4MAFeIeNn+L98qwxAt360bwzX2Kf0ZQkBBucJ2Ircza3asoY4CDbgiu9VWklq8gWJVSJSJBwDI+c/THiWkA== +"@msgpackr-extract/msgpackr-extract-linux-arm@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-2.2.0.tgz#15f2c6fe9e0adc06c21af7e95f484ff4880d79ce" + integrity sha512-SaJ3Qq4lX9Syd2xEo9u3qPxi/OB+5JO/ngJKK97XDpa1C587H9EWYO6KD8995DAjSinWvdHKRrCOXVUC5fvGOg== -"@msgpackr-extract/msgpackr-extract-linux-x64@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.1.2.tgz#7caf62eebbfb1345de40f75e89666b3d4194755f" - integrity sha512-RjRoRxg7Q3kPAdUSC5EUUPlwfMkIVhmaRTIe+cqHbKrGZ4M6TyCA/b5qMaukQ/1CHWrqYY2FbKOAU8Hg0pQFzg== +"@msgpackr-extract/msgpackr-extract-linux-x64@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-2.2.0.tgz#30cae5c9a202f3e1fa1deb3191b18ffcb2f239a2" + integrity sha512-94y5PJrSOqUNcFKmOl7z319FelCLAE0rz/jPCWS+UtdMZvpa4jrQd+cJPQCLp2Fes1yAW/YUQj/Di6YVT3c3Iw== -"@msgpackr-extract/msgpackr-extract-win32-x64@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.1.2.tgz#f2d8b9ddd8d191205ed26ce54aba3dfc5ae3e7c9" - integrity sha512-rIZVR48zA8hGkHIK7ED6+ZiXsjRCcAVBJbm8o89OKAMTmEAQ2QvoOxoiu3w2isAaWwzgtQIOFIqHwvZDyLKCvw== +"@msgpackr-extract/msgpackr-extract-win32-x64@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-2.2.0.tgz#016d855b6bc459fd908095811f6826e45dd4ba64" + integrity sha512-XrC0JzsqQSvOyM3t04FMLO6z5gCuhPE6k4FXuLK5xf52ZbdvcFe1yBmo7meCew9B8G2f0T9iu9t3kfTYRYROgA== "@shopify/jest-koa-mocks@5.0.1": version "5.0.1" @@ -869,9 +665,9 @@ "@hapi/hoek" "^9.0.0" "@sideway/formula@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c" - integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f" + integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg== "@sideway/pinpoint@^2.0.0": version "2.0.0" @@ -889,9 +685,9 @@ integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== "@sinonjs/commons@^1.7.0": - version "1.8.3" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" - integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + version "1.8.6" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9" + integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ== dependencies: type-detect "4.0.8" @@ -1022,9 +818,9 @@ "@types/node" "*" "@types/babel__core@^7.1.14": - version "7.1.19" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460" - integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw== + version "7.1.20" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.20.tgz#e168cdd612c92a2d335029ed62ac94c95b362359" + integrity sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -1048,16 +844,16 @@ "@babel/types" "^7.0.0" "@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.17.1" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.17.1.tgz#1a0e73e8c28c7e832656db372b779bfd2ef37314" - integrity sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA== + version "7.18.3" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.3.tgz#dfc508a85781e5698d5b33443416b6268c4b3e8d" + integrity sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w== dependencies: "@babel/types" "^7.3.0" "@types/bluebird@*": - version "3.5.36" - resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.36.tgz#00d9301d4dc35c2f6465a8aec634bb533674c652" - integrity sha512-HBNx4lhkxN7bx6P0++W8E289foSu8kO8GCk2unhuVggO+cE7rh9DhZUyPhUxNRG9m+5B5BTKxZQ5ZP92x/mx9Q== + version "3.5.38" + resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.38.tgz#7a671e66750ccd21c9fc9d264d0e1e5330bc9908" + integrity sha512-yR/Kxc0dd4FfwtEoLZMoqJbM/VE/W7hXn/MIjb+axcwag0iFmSPK7OBUZq1YWLynJUoWQkfUrI7T0HDqGApNSg== "@types/body-parser@*": version "1.19.2" @@ -1101,29 +897,29 @@ dependencies: "@types/ms" "*" -"@types/express-serve-static-core@^4.17.18": - version "4.17.28" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8" - integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig== +"@types/express-serve-static-core@^4.17.31": + version "4.17.32" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.32.tgz#93dda387f5516af616d8d3f05f2c4c79d81e1b82" + integrity sha512-aI5h/VOkxOF2Z1saPy0Zsxs5avets/iaiAJYznQFm5By/pamU31xWKL//epiF4OfUA2qTOc9PV6tCUjhO8wlZA== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" "@types/express@*": - version "4.17.13" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034" - integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA== + version "4.17.15" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.15.tgz#9290e983ec8b054b65a5abccb610411953d417ff" + integrity sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ== dependencies: "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.18" + "@types/express-serve-static-core" "^4.17.31" "@types/qs" "*" "@types/serve-static" "*" "@types/graceful-fs@^4.1.3": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" - integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + version "4.1.6" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.6.tgz#e14b2576a1c25026b7f02ede1de3b84c3a1efeae" + integrity sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw== dependencies: "@types/node" "*" @@ -1133,9 +929,9 @@ integrity sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA== "@types/http-errors@*": - version "1.8.2" - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-1.8.2.tgz#7315b4c4c54f82d13fa61c228ec5c2ea5cc9e0e1" - integrity sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w== + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.1.tgz#20172f9578b225f6c7da63446f56d4ce108d5a65" + integrity sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ== "@types/ioredis@4.28.0": version "4.28.0" @@ -1192,7 +988,21 @@ "@types/pino" "*" "@types/pino-http" "*" -"@types/koa@*", "@types/koa@2.13.4": +"@types/koa@*": + version "2.13.5" + resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.5.tgz#64b3ca4d54e08c0062e89ec666c9f45443b21a61" + integrity sha512-HSUOdzKz3by4fnqagwthW/1w/yJspTgppyyalPVbgZf8jQWvdIXcVW5h2DGtw4zYntOaeRGx49r1hxoPWrD4aA== + dependencies: + "@types/accepts" "*" + "@types/content-disposition" "*" + "@types/cookies" "*" + "@types/http-assert" "*" + "@types/http-errors" "*" + "@types/keygrip" "*" + "@types/koa-compose" "*" + "@types/node" "*" + +"@types/koa@2.13.4": version "2.13.4" resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.4.tgz#10620b3f24a8027ef5cbae88b393d1b31205726b" integrity sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw== @@ -1211,10 +1021,10 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.180.tgz#4ab7c9ddfc92ec4a887886483bc14c79fb380670" integrity sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g== -"@types/mime@^1": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" - integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/mime@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== "@types/ms@*": version "0.7.31" @@ -1230,9 +1040,9 @@ form-data "^3.0.0" "@types/node@*": - version "17.0.41" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.41.tgz#1607b2fd3da014ae5d4d1b31bc792a39348dfb9b" - integrity sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw== + version "18.11.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" + integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== "@types/node@14.18.20": version "14.18.20" @@ -1362,9 +1172,9 @@ "@types/pouchdb-find" "*" "@types/pouchdb-find@*": - version "6.3.7" - resolved "https://registry.yarnpkg.com/@types/pouchdb-find/-/pouchdb-find-6.3.7.tgz#f713534a53c1a7f3fd8fbbfb74131a1b04711ddc" - integrity sha512-b2dr9xoZRK5Mwl8UiRA9l5j9mmCxNfqXuu63H1KZHwJLILjoIIz7BntCvM0hnlnl7Q8P8wORq0IskuaMq5Nnnw== + version "7.3.0" + resolved "https://registry.yarnpkg.com/@types/pouchdb-find/-/pouchdb-find-7.3.0.tgz#b917030e9f4bf6e56bf8c3b9fe4b2a25e989009a" + integrity sha512-sFPli5tBjGX9UfXioik1jUzPdcN84eV82n0lmEFuoPepWqkLjQcyri0eOa++HYOaNPyMDhKFBqEALEZivK2dRg== dependencies: "@types/pouchdb-core" "*" @@ -1424,9 +1234,9 @@ "@types/pouchdb-replication" "*" "@types/prettier@^2.1.5": - version "2.6.3" - resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.3.tgz#68ada76827b0010d0db071f739314fa429943d0a" - integrity sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg== + version "2.7.2" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0" + integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg== "@types/qs@*": version "6.9.7" @@ -1459,11 +1269,11 @@ integrity sha512-4g1jrL98mdOIwSOUh6LTlB0Cs9I0dQPwINUhBg7C6pN4HLr8GS8xsksJxilW6S6dQHVi2K/o+lQuQcg7LroCnw== "@types/serve-static@*": - version "1.13.10" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9" - integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ== + version "1.15.0" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155" + integrity sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg== dependencies: - "@types/mime" "^1" + "@types/mime" "*" "@types/node" "*" "@types/stack-utils@^2.0.0": @@ -1509,9 +1319,9 @@ "@types/yargs-parser" "*" "@types/yargs@^17.0.8": - version "17.0.13" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.13.tgz#34cced675ca1b1d51fcf4d34c3c6f0fa142a5c76" - integrity sha512-9sWaruZk2JGxIQU+IhI1fhPYRcQ0UuTNuKuCW9bR5fp7qi2Llf7WDzNa17Cy7TKnh3cdxDOiyTu6gaLS0eDatg== + version "17.0.19" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.19.tgz#8dbecdc9ab48bee0cb74f6e3327de3fa0d0c98ae" + integrity sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ== dependencies: "@types/yargs-parser" "*" @@ -1630,9 +1440,9 @@ ansi-styles@^5.0.0: integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== anymatch@^3.0.3, anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" @@ -1717,14 +1527,14 @@ aws-sign2@~0.7.0: integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA== 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== + version "1.12.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3" + integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== axios-retry@^3.1.9: - version "3.2.5" - resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.2.5.tgz#64952992837c7d9a12eec156a2694a7945f60895" - integrity sha512-a8umkKbfIkTiYJQLx3v3TzKM85TGKB8ZQYz4zwykt2fpO64TsRlUhjaPaAb3fqMWCXFm2YhWcd8V5FHDKO9bSA== + version "3.3.1" + resolved "https://registry.yarnpkg.com/axios-retry/-/axios-retry-3.3.1.tgz#47624646138aedefbad2ac32f226f4ee94b6dcab" + integrity sha512-RohAUQTDxBSWLFEnoIG/6bvmy8l3TfpkclgStjl5MDCMBDgapAWCmr1r/9harQfWC8bzLC8job6UcL1A1Yc+/Q== dependencies: "@babel/runtime" "^7.15.4" is-retry-allowed "^2.2.0" @@ -1737,9 +1547,9 @@ axios@0.24.0: follow-redirects "^1.14.4" 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== + version "1.2.2" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.2.tgz#72681724c6e6a43a9fea860fc558127dbe32f9f1" + integrity sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q== dependencies: follow-redirects "^1.15.0" form-data "^4.0.0" @@ -1895,17 +1705,6 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -browserslist@^4.20.2: - version "4.20.4" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.4.tgz#98096c9042af689ee1e0271333dbc564b8ce4477" - integrity sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw== - dependencies: - caniuse-lite "^1.0.30001349" - electron-to-chromium "^1.4.147" - escalade "^3.1.1" - node-releases "^2.0.5" - picocolors "^1.0.0" - browserslist@^4.21.3: version "4.21.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" @@ -2029,15 +1828,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001349: - version "1.0.30001352" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001352.tgz#cc6f5da3f983979ad1e2cdbae0505dccaa7c6a12" - integrity sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA== - caniuse-lite@^1.0.30001400: - version "1.0.30001431" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz#e7c59bd1bc518fae03a4656be442ce6c4887a795" - integrity sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ== + version "1.0.30001442" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001442.tgz#40337f1cf3be7c637b061e2f78582dc1daec0614" + integrity sha512-239m03Pqy0hwxYPYR5JwOIxRJfLTWtle9FV8zosfV5pHg+/51uD4nxcUlM8+mWWGfwKtt8lJNHnD3cWw9VZ6ow== caseless@~0.12.0: version "0.12.0" @@ -2107,9 +1901,9 @@ ci-info@^2.0.0: integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== ci-info@^3.2.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.1.tgz#58331f6f472a25fe3a50a351ae3052936c2c7f32" - integrity sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg== + version "3.7.1" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.1.tgz#708a6cdae38915d597afdf3b145f2f8e1ff55f3f" + integrity sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w== cjs-module-lexer@^1.0.0: version "1.2.2" @@ -2136,16 +1930,16 @@ clone-buffer@1.0.0: integrity sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g== clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q== + version "1.0.3" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.3.tgz#af2032aa47816399cf5f0a1d0db902f517abb8c3" + integrity sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA== dependencies: mimic-response "^1.0.0" cluster-key-slot@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz#30474b2a981fb12172695833052bc0d01336d10d" - integrity sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw== + version "1.1.2" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" + integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== co@^4.6.0: version "4.6.0" @@ -2238,11 +2032,9 @@ content-type@^1.0.4: integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== cookies@~0.8.0: version "0.8.0" @@ -2275,11 +2067,11 @@ create-require@^1.1.0: integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cron-parser@^4.2.1: - version "4.6.0" - resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.6.0.tgz#404c3fdbff10ae80eef6b709555d577ef2fd2e0d" - integrity sha512-guZNLMGUgg6z4+eGhmHGw7ft+v6OQeuHzd1gcLxCo9Yg/qoxmG3nindp2/uwGCLizEisf2H0ptqeVXeoCpP6FA== + version "4.7.1" + resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-4.7.1.tgz#1e325a6a18e797a634ada1e2599ece0b6b5ed177" + integrity sha512-WguFaoQ0hQ61SgsCZLHUcNbAvlK0lypKXu62ARguefYmjzaOXIVRNrAmyXzabTwUn4sQvQLkk6bjH+ipGfw8bA== dependencies: - luxon "^3.0.1" + luxon "^3.2.1" cross-spawn@^7.0.3: version "7.0.3" @@ -2444,9 +2236,9 @@ double-ended-queue@2.1.0-0: integrity sha512-+BNfZ+deCo8hMNpDqDnvT+c0XpJ5cUa6mqYq89bho2Ifze4URTqRkcwR399hWoTrTkbZ/XJYDgP6rc7pRgffEQ== duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha512-CEj8FwwNA4cVH2uFCoHUrmojhYh1vmCdOaneKJXwkeY1i9jnlslVo9dx+hQ5Hl9GnH/Bwy/IjxAyOePyPKYnzA== + version "0.1.5" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.5.tgz#0b5e4d7bad5de8901ea4440624c8e1d20099217e" + integrity sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA== ecc-jsbn@~0.1.1: version "0.1.2" @@ -2468,11 +2260,6 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.4.147: - version "1.4.150" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.150.tgz#89f0e12505462d5df7e56c5b91aff7e1dfdd33ec" - integrity sha512-MP3oBer0X7ZeS9GJ0H6lmkn561UxiwOIY9TTkdxVY7lI9G6GVCKfgJaHaDcakwdKxBXA4T3ybeswH/WBIN/KTA== - electron-to-chromium@^1.4.251: version "1.4.284" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" @@ -2655,9 +2442,9 @@ fast-safe-stringify@^2.1.1: integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== fb-watchman@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" - integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" + integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA== dependencies: bser "2.1.1" @@ -2704,12 +2491,7 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" -follow-redirects@^1.14.4: - version "1.15.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" - integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== - -follow-redirects@^1.15.0: +follow-redirects@^1.14.4, follow-redirects@^1.15.0: version "1.15.2" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== @@ -2884,9 +2666,9 @@ glob@^8.0.0: once "^1.3.0" global-dirs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" - integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" + integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA== dependencies: ini "2.0.0" @@ -3169,10 +2951,10 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.8.1: - version "2.9.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" - integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== dependencies: has "^1.0.3" @@ -3279,9 +3061,9 @@ istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz#31d18bdd127f825dd02ea7bfdfd906f8ab840e9f" - integrity sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A== + version "5.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" + integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== dependencies: "@babel/core" "^7.12.3" "@babel/parser" "^7.14.7" @@ -3308,9 +3090,9 @@ istanbul-lib-source-maps@^4.0.0: source-map "^0.6.1" istanbul-reports@^3.1.3: - version "3.1.4" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c" - integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== dependencies: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" @@ -3525,9 +3307,9 @@ jest-mock@^28.1.3: "@types/node" "*" jest-pnp-resolver@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" - integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== + version "1.2.3" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e" + integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w== jest-regex-util@^28.0.2: version "28.0.2" @@ -3772,10 +3554,10 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== -json5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" - integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== +json5@^2.2.1, json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonc-parser@^3.2.0: version "3.2.0" @@ -3874,7 +3656,7 @@ koa-passport@4.1.4: dependencies: passport "^0.4.0" -koa@2.13.4, koa@^2.13.4: +koa@2.13.4: version "2.13.4" resolved "https://registry.yarnpkg.com/koa/-/koa-2.13.4.tgz#ee5b0cb39e0b8069c38d115139c774833d32462e" integrity sha512-43zkIKubNbnrULWlHdN5h1g3SEKXOEzoAlRsHOTFpnlDu8JlAOZSMJBLULusuXRequboiwJcj5vtYXKB3k7+2g== @@ -3903,6 +3685,35 @@ koa@2.13.4, koa@^2.13.4: type-is "^1.6.16" vary "^1.1.2" +koa@^2.13.4: + version "2.14.1" + resolved "https://registry.yarnpkg.com/koa/-/koa-2.14.1.tgz#defb9589297d8eb1859936e777f3feecfc26925c" + integrity sha512-USJFyZgi2l0wDgqkfD27gL4YGno7TfUkcmOe6UOLFOVuN+J7FwnNu4Dydl4CUQzraM1lBAiGed0M9OVJoT0Kqw== + dependencies: + accepts "^1.3.5" + cache-content-type "^1.0.0" + content-disposition "~0.5.2" + content-type "^1.0.4" + cookies "~0.8.0" + debug "^4.3.2" + delegates "^1.0.0" + depd "^2.0.0" + destroy "^1.0.4" + encodeurl "^1.0.2" + escape-html "^1.0.3" + fresh "~0.5.2" + http-assert "^1.3.0" + http-errors "^1.6.3" + is-generator-function "^1.0.7" + koa-compose "^4.1.0" + koa-convert "^2.0.0" + on-finished "^2.3.0" + only "~0.0.2" + parseurl "^1.3.2" + statuses "^1.5.0" + type-is "^1.6.16" + vary "^1.1.2" + latest-version@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" @@ -4103,6 +3914,13 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -4115,10 +3933,10 @@ ltgt@2.2.1, ltgt@^2.1.2, ltgt@~2.2.0: resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" integrity sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA== -luxon@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.0.4.tgz#d179e4e9f05e092241e7044f64aaa54796b03929" - integrity sha512-aV48rGUwP/Vydn8HT+5cdr26YYQiUZ42NM6ToMoaGKwYfWbfLeRkEu1wXWMHBZT6+KyLfcbbtVcoQFCbbPjKlw== +luxon@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.2.1.tgz#14f1af209188ad61212578ea7e3d518d18cee45f" + integrity sha512-QrwPArQCNLAKGO/C+ZIilgIuDnEnKx5QYODdDtbFaxzsbZcc/a7WFq7MhsVYgRlwawLtvOUESTlfJ+hc/USqPg== make-dir@^3.0.0, make-dir@^3.1.0: version "3.1.0" @@ -4229,20 +4047,22 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimist@^1.2.0: - version "1.2.6" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" - integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== - -minimist@^1.2.6: +minimist@^1.2.0, minimist@^1.2.6: version "1.2.7" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== minipass@^3.0.0: - version "3.1.6" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee" - integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ== + version "3.3.6" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a" + integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw== + dependencies: + yallist "^4.0.0" + +minipass@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-4.0.0.tgz#7cebb0f9fa7d56f0c5b17853cbe28838a8dbbd3b" + integrity sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw== dependencies: yallist "^4.0.0" @@ -4274,26 +4094,26 @@ ms@^2.1.1, ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -msgpackr-extract@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-2.1.2.tgz#56272030f3e163e1b51964ef8b1cd5e7240c03ed" - integrity sha512-cmrmERQFb19NX2JABOGtrKdHMyI6RUyceaPBQ2iRz9GnDkjBWFjNJC0jyyoOfZl2U/LZE3tQCCQc4dlRyA8mcA== +msgpackr-extract@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-2.2.0.tgz#4bb749b58d9764cfdc0d91c7977a007b08e8f262" + integrity sha512-0YcvWSv7ZOGl9Od6Y5iJ3XnPww8O7WLcpYMDwX+PAA/uXLDtyw94PJv9GLQV/nnp3cWlDhMoyKZIQLrx33sWog== dependencies: node-gyp-build-optional-packages "5.0.3" optionalDependencies: - "@msgpackr-extract/msgpackr-extract-darwin-arm64" "2.1.2" - "@msgpackr-extract/msgpackr-extract-darwin-x64" "2.1.2" - "@msgpackr-extract/msgpackr-extract-linux-arm" "2.1.2" - "@msgpackr-extract/msgpackr-extract-linux-arm64" "2.1.2" - "@msgpackr-extract/msgpackr-extract-linux-x64" "2.1.2" - "@msgpackr-extract/msgpackr-extract-win32-x64" "2.1.2" + "@msgpackr-extract/msgpackr-extract-darwin-arm64" "2.2.0" + "@msgpackr-extract/msgpackr-extract-darwin-x64" "2.2.0" + "@msgpackr-extract/msgpackr-extract-linux-arm" "2.2.0" + "@msgpackr-extract/msgpackr-extract-linux-arm64" "2.2.0" + "@msgpackr-extract/msgpackr-extract-linux-x64" "2.2.0" + "@msgpackr-extract/msgpackr-extract-win32-x64" "2.2.0" msgpackr@^1.5.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.7.2.tgz#68d6debf5999d6b61abb6e7046a689991ebf7261" - integrity sha512-mWScyHTtG6TjivXX9vfIy2nBtRupaiAj0HQ2mtmpmYujAmqZmaaEVPaSZ1NKLMvicaMLFzEaMk0ManxMRg8rMQ== + version "1.8.1" + resolved "https://registry.yarnpkg.com/msgpackr/-/msgpackr-1.8.1.tgz#2298aed8a14f83e99df77d344cbda3e436f29b5b" + integrity sha512-05fT4J8ZqjYlR4QcRDIhLCYKUOHXk7C/xa62GzMKj74l3up9k2QZ3LgFc6qWdsPHl91QA2WLWqWc8b8t7GLNNw== optionalDependencies: - msgpackr-extract "^2.1.2" + msgpackr-extract "^2.2.0" napi-macros@~2.0.0: version "2.0.0" @@ -4358,9 +4178,9 @@ node-int64@^0.4.0: integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== node-mocks-http@^1.11.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/node-mocks-http/-/node-mocks-http-1.11.0.tgz#defc0febf6b935f08245397d47534a8de592996e" - integrity sha512-jS/WzSOcKbOeGrcgKbenZeNhxUNnP36Yw11+hL4TTxQXErGfqYZ+MaYNNvhaTiGIJlzNSqgQkk9j8dSu1YWSuw== + version "1.12.1" + resolved "https://registry.yarnpkg.com/node-mocks-http/-/node-mocks-http-1.12.1.tgz#838e176019daf177caff6bb8534e3a32646e7531" + integrity sha512-jrA7Sn3qI6GsHgWtUW3gMj0vO6Yz0nJjzg3jRZYjcfj4tzi8oWPauDK1qHVJoAxTbwuDHF1JiM9GISZ/ocI/ig== dependencies: accepts "^1.3.7" content-disposition "^0.5.3" @@ -4373,15 +4193,10 @@ node-mocks-http@^1.11.0: range-parser "^1.2.0" type-is "^1.6.18" -node-releases@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" - integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q== - node-releases@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" - integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== + version "2.0.8" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.8.tgz#0f349cdc8fcfa39a92ac0be9bc48b7706292b9ae" + integrity sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A== nodemon@2.0.16: version "2.0.16" @@ -5025,9 +4840,9 @@ prr@~1.0.1: integrity sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw== psl@^1.1.28, psl@^1.1.33: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== pstree.remy@^1.1.8: version "1.1.8" @@ -5091,7 +4906,7 @@ range-parser@^1.2.0: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -rc@^1.2.8: +rc@1.2.8, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -5199,17 +5014,17 @@ redlock@4.2.0: dependencies: bluebird "^3.7.2" -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regenerator-runtime@^0.13.11: + 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== registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + version "4.2.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" + integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== dependencies: - rc "^1.2.8" + rc "1.2.8" registry-url@^5.0.0: version "5.1.0" @@ -5277,11 +5092,11 @@ resolve.exports@^1.1.0: integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== resolve@^1.20.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" - integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: - is-core-module "^2.8.1" + is-core-module "^2.9.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -5496,9 +5311,9 @@ sshpk@^1.7.0: tweetnacl "~0.14.0" stack-utils@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" - integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA== + version "2.0.6" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" + integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== dependencies: escape-string-regexp "^2.0.0" @@ -5617,9 +5432,9 @@ supports-color@^8.0.0: has-flag "^4.0.0" supports-hyperlinks@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" - integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== + version "2.3.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624" + integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA== dependencies: has-flag "^4.0.0" supports-color "^7.0.0" @@ -5651,13 +5466,13 @@ tar-stream@^2.1.4: readable-stream "^3.1.1" tar@^6.1.11: - version "6.1.11" - resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" - integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== + version "6.1.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.13.tgz#46e22529000f612180601a6fe0680e7da508847b" + integrity sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw== dependencies: chownr "^2.0.0" fs-minipass "^2.0.0" - minipass "^3.0.0" + minipass "^4.0.0" minizlib "^2.1.1" mkdirp "^1.0.3" yallist "^4.0.0" @@ -5722,7 +5537,7 @@ tmpl@1.0.5: to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-readable-stream@^1.0.0: version "1.0.0" @@ -5748,16 +5563,7 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" - integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.1.2" - -tough-cookie@^4.1.2: +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== @@ -5778,7 +5584,7 @@ tough-cookie@~2.5.0: tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== ts-jest@28.0.4: version "28.0.4" @@ -5830,14 +5636,14 @@ tsscmp@1.0.6: tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== dependencies: safe-buffer "^5.0.1" 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 sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA== type-detect@4.0.8: version "4.0.8" @@ -5891,11 +5697,6 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" -universalify@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - universalify@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" @@ -5939,7 +5740,7 @@ uri-js@^4.2.2: 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" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= + integrity sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ== dependencies: prepend-http "^2.0.0" @@ -5954,7 +5755,7 @@ url-parse@^1.5.3: url@0.10.3: version "0.10.3" resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - integrity sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ= + integrity sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ== dependencies: punycode "1.3.2" querystring "0.2.0" @@ -5962,12 +5763,12 @@ url@0.10.3: util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== utils-merge@1.x.x: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== uuid@3.3.2: version "3.3.2" @@ -6006,12 +5807,12 @@ v8-to-istanbul@^9.0.1: vary@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + 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 sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw== dependencies: assert-plus "^1.0.0" core-util-is "1.0.2" @@ -6020,7 +5821,7 @@ verror@1.10.0: vuvuzela@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/vuvuzela/-/vuvuzela-1.0.3.tgz#3be145e58271c73ca55279dd851f12a682114b0b" - integrity sha1-O+FF5YJxxzylUnndhR8SpoIRSws= + integrity sha512-Tm7jR1xTzBbPW+6y1tknKiEhz04Wf/1iZkcTJjSFcpNko43+dFW6+OOeQe9taJIug3NdfUAjFKgUSyQrIKaDvQ== walker@^1.0.8: version "1.0.8" @@ -6032,7 +5833,7 @@ walker@^1.0.8: webfinger@^0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/webfinger/-/webfinger-0.4.2.tgz#3477a6d97799461896039fcffc650b73468ee76d" - integrity sha1-NHem2XeZRhiWA5/P/GULc0aO520= + integrity sha512-PvvQ/k74HkC3q5G7bGu4VYeKDt3ePZMzT5qFPtEnOL8eyIU1/06OtDn9X5vlkQ23BlegA3eN89rDLiYUife3xQ== dependencies: step "0.0.x" xml2js "0.1.x" @@ -6040,12 +5841,12 @@ webfinger@^0.4.2: webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: tr46 "~0.0.3" webidl-conversions "^3.0.0" @@ -6083,7 +5884,7 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^3.0.0: version "3.0.3" @@ -6106,7 +5907,7 @@ write-file-atomic@^4.0.1: write-stream@~0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/write-stream/-/write-stream-0.4.3.tgz#83cc8c0347d0af6057a93862b4e3ae01de5c81c1" - integrity sha1-g8yMA0fQr2BXqThitOOuAd5cgcE= + integrity sha512-IJrvkhbAnj89W/GAVdVgbnPiVw5Ntg/B4tc/MUCIEwj/g6JIww1DWJyB/yBMT3yw2/TkT6IUZ0+IYef3flEw8A== dependencies: readable-stream "~0.0.2" @@ -6118,7 +5919,7 @@ xdg-basedir@^4.0.0: xml2js@0.1.x: version "0.1.14" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.1.14.tgz#5274e67f5a64c5f92974cd85139e0332adc6b90c" - integrity sha1-UnTmf1pkxfkpdM2FE54DMq3GuQw= + integrity sha512-pbdws4PPPNc1HPluSUKamY4GWMk592K7qwcj6BExbVOhhubub8+pMda/ql68b6L3luZs/OGjGSB5goV7SnmgnA== dependencies: sax ">=0.1.1" @@ -6133,7 +5934,7 @@ xml2js@0.4.19: xmlbuilder@~9.0.1: version "9.0.7" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" - integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= + integrity sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ== xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1: version "4.0.2" @@ -6145,6 +5946,11 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" @@ -6191,4 +5997,4 @@ yocto-queue@^0.1.0: zlib@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/zlib/-/zlib-1.0.5.tgz#6e7c972fc371c645a6afb03ab14769def114fcc0" - integrity sha1-bnyXL8NxxkWmr7A6sUdp3vEU/MA= + integrity sha512-40fpE2II+Cd3k8HWTWONfeKE2jL+P42iWJ1zzps5W51qcTsOUKM5Q5m2PFb0CLxlmFAaUuUdJGc3OfZy947v0w== diff --git a/packages/bbui/package.json b/packages/bbui/package.json index fb936c8c2a..6b67ca77d0 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/bbui", "description": "A UI solution used in the different Budibase projects.", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", @@ -38,7 +38,7 @@ ], "dependencies": { "@adobe/spectrum-css-workflow-icons": "1.2.1", - "@budibase/string-templates": "2.2.12-alpha.16", + "@budibase/string-templates": "2.2.12-alpha.32", "@spectrum-css/actionbutton": "1.0.1", "@spectrum-css/actiongroup": "1.0.1", "@spectrum-css/avatar": "3.0.2", diff --git a/packages/bbui/src/Form/Core/Picker.svelte b/packages/bbui/src/Form/Core/Picker.svelte index 81348452c7..f0b22e5cca 100644 --- a/packages/bbui/src/Form/Core/Picker.svelte +++ b/packages/bbui/src/Form/Core/Picker.svelte @@ -45,7 +45,9 @@ getOptionLabel ) - const onClick = () => { + const onClick = e => { + e.preventDefault() + e.stopPropagation() dispatch("click") if (readonly) { return @@ -88,7 +90,6 @@ class:is-open={open} aria-haspopup="listbox" on:click={onClick} - use:clickOutside={() => (open = false)} bind:this={button} > {#if fieldIcon} @@ -130,14 +131,25 @@ >>>>>> origin/develop bind:this={popover} {open} on:close={() => (open = false)} useAnchorWidth={!autoWidth} maxWidth={autoWidth ? 400 : null} > +<<<<<<< HEAD
+======= +
(open = false)} + > +>>>>>>> origin/develop {#if autocomplete} { dispatch("open") @@ -62,7 +65,7 @@ {#if open} - +
{ - context("Auth Configuration", () => { + xcontext("Auth Configuration", () => { before(() => { cy.login() }) @@ -21,7 +21,7 @@ filterTests(["smoke", "all"], () => { cy.get("[data-cy=oidc-active]").should('not.be.checked') cy.intercept("POST", "/api/global/configs").as("updateAuth") - cy.get("button[data-cy=oidc-save]").contains("Save").click({force: true}) + cy.get("button[data-cy=oidc-save]").contains("Save").click({ force: true }) cy.wait("@updateAuth") cy.get("@updateAuth").its("response.statusCode").should("eq", 200) @@ -45,7 +45,7 @@ filterTests(["smoke", "all"], () => { cy.get("button[data-cy=oidc-save]").should("not.be.disabled"); cy.intercept("POST", "/api/global/configs").as("updateAuth") - cy.get("button[data-cy=oidc-save]").contains("Save").click({force: true}) + cy.get("button[data-cy=oidc-save]").contains("Save").click({ force: true }) cy.wait("@updateAuth") cy.get("@updateAuth").its("response.statusCode").should("eq", 200) @@ -85,11 +85,11 @@ filterTests(["smoke", "all"], () => { cy.get(".auth-form input.spectrum-Textfield-input").type("Another ") cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 6) cy.get(".spectrum-Tags-item").contains("Another") - + cy.get("button[data-cy=oidc-save]").should("not.be.disabled"); cy.intercept("POST", "/api/global/configs").as("updateAuth") - cy.get("button[data-cy=oidc-save]").contains("Save").click({force: true}) + cy.get("button[data-cy=oidc-save]").contains("Save").click({ force: true }) cy.wait("@updateAuth") cy.get("@updateAuth").its("response.statusCode").should("eq", 200) @@ -123,7 +123,7 @@ filterTests(["smoke", "all"], () => { cy.get("button[data-cy=oidc-save]").should("not.be.disabled"); cy.intercept("POST", "/api/global/configs").as("updateAuth") - cy.get("button[data-cy=oidc-save]").contains("Save").click({force: true}) + cy.get("button[data-cy=oidc-save]").contains("Save").click({ force: true }) cy.wait("@updateAuth") cy.get("@updateAuth").its("response.statusCode").should("eq", 200) @@ -144,7 +144,7 @@ filterTests(["smoke", "all"], () => { cy.get("div.content").scrollTo("bottom") - cy.get("[data-cy=restore-oidc-default-scopes]").click({force: true}) + cy.get("[data-cy=restore-oidc-default-scopes]").click({ force: true }) cy.get(".spectrum-Tags").find(".spectrum-Tags-item").its("length").should("eq", 4) diff --git a/packages/builder/cypress/integration/adminAndManagement/userSettings.spec.js b/packages/builder/cypress/integration/adminAndManagement/userSettings.spec.js index a2b0d32d02..18362031c9 100644 --- a/packages/builder/cypress/integration/adminAndManagement/userSettings.spec.js +++ b/packages/builder/cypress/integration/adminAndManagement/userSettings.spec.js @@ -3,107 +3,112 @@ const interact = require('../../support/interact') filterTests(["smoke", "all"], () => { context("User Settings Menu", () => { - + before(() => { cy.login() }) - + it("should update user information via user settings menu", () => { - const fname = "test" - const lname = "user" + const fname = "test" + const lname = "user" - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.updateUserInformation(fname, lname) + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.updateUserInformation(fname, lname) - // Go to user info and confirm name update - cy.contains("Users").click() - cy.contains("test@test.com").click() + // Go to user info and confirm name update + cy.contains("Users").click() + cy.contains("test@test.com").click() - cy.get(interact.FIELD, { timeout: 1000 }).eq(1).within(() => { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', fname) - }) - cy.get(interact.FIELD).eq(2).within(() => { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', lname) - }) + cy.get(interact.FIELD, { timeout: 1000 }).eq(1).within(() => { + cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', fname) + }) + cy.get(interact.FIELD).eq(2).within(() => { + cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).should('have.value', lname) + }) }) - it("should allow copying of the users API key", () => { - cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true }) - cy.get(interact.SPECTRUM_MENU_ITEM).contains("View API key").click({ force: true }) - cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => { - cy.get(interact.SPECTRUM_ICON).click({force: true}) - }) - // There may be timing issues with this on the smoke build - cy.wait(500) - cy.get(".spectrum-Toast-content") + xit("should allow copying of the users API key", () => { + cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true }) + cy.get(interact.SPECTRUM_MENU_ITEM).contains("View API key").click({ force: true }) + cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => { + cy.get(interact.SPECTRUM_ICON).click({ force: true }) + }) + // There may be timing issues with this on the smoke build + cy.wait(500) + cy.get(".spectrum-Toast-content") .contains("URL copied to clipboard") .should("be.visible") }) it("should allow API key regeneration", () => { - // Get initial API key value - cy.get(interact.SPECTRUM_DIALOG_CONTENT) + cy.get(".user-dropdown .icon", { timeout: 2000 }).click({ force: true }) + cy.get(interact.SPECTRUM_MENU_ITEM).contains("View API key").click({ force: true }) + cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => { + cy.get(interact.SPECTRUM_ICON).click({ force: true }) + }) + // Get initial API key value + cy.get(interact.SPECTRUM_DIALOG_CONTENT) .find(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').as('keyOne') - // Click re-generate key button - cy.get("button").contains("Re-generate key").click({ force: true }) + // Click re-generate key button + cy.get("button").contains("Regenerate key").click({ force: true }) - // Verify API key was changed - cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => { - cy.get('@keyOne').then((keyOne) => { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').should('not.eq', keyOne) - }) + // Verify API key was changed + cy.get(interact.SPECTRUM_DIALOG_CONTENT).within(() => { + cy.get('@keyOne').then((keyOne) => { + cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).invoke('val').should('not.eq', keyOne) }) - cy.closeModal() + }) + cy.closeModal() }) it("should update password", () => { - // Access Update password modal - cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true }) - cy.get(interact.SPECTRUM_MENU_ITEM).contains("Update password").click({ force: true }) + // Access Update password modal + cy.get(".user-dropdown .icon", { timeout: 2000 }).click({ force: true }) + cy.get(interact.SPECTRUM_MENU_ITEM).contains("Update password").click({ force: true }) - // Enter new password and update - cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => { - for (let i = 0; i < 2; i++) { - // password set to 'newpwd' - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("newpwd") - } - cy.get("button").contains("Update password").click({ force: true }) - }) + // Enter new password and update + cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => { + for (let i = 0; i < 2; i++) { + // password set to 'newpwd' + cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("newpwd") + } + cy.get("button").contains("Update password").click({ force: true }) + }) - // Logout & in with new password - //cy.logOut() - cy.login("test@test.com", "newpwd") + // Logout & in with new password + //cy.logOut() + cy.login("test@test.com", "newpwd") }) - it("should open and close developer mode", () => { - cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true }) - - // Close developer mode & verify - cy.get(interact.SPECTRUM_MENU_ITEM).contains("Close developer mode").click({ force: true }) - cy.get(interact.SPECTRUM_SIDENAV).should('not.exist') // No config sections - cy.get(interact.CREATE_APP_BUTTON).should('not.exist') // No create app button - cy.get(".app").should('not.exist') // At least one app should be available + xit("should open and close developer mode", () => { + cy.get(".user-dropdown .icon", { timeout: 2000 }).click({ force: true }) - // Open developer mode & verify - cy.get(".avatar > .icon").click({ force: true }) - cy.get(interact.SPECTRUM_MENU_ITEM).contains("Open developer mode").click({ force: true }) - cy.get(interact.SPECTRUM_SIDENAV).should('exist') // config sections available - cy.get(interact.CREATE_APP_BUTTON).should('exist') // create app button available + // Close developer mode & verify + cy.get(interact.SPECTRUM_MENU_ITEM).contains("Close developer mode").click({ force: true }) + cy.get(interact.SPECTRUM_SIDENAV).should('not.exist') // No config sections + cy.get(interact.CREATE_APP_BUTTON).should('not.exist') // No create app button + cy.get(".app").should('not.exist') // At least one app should be available + + // Open developer mode & verify + cy.get(".avatar > .icon").click({ force: true }) + cy.get(interact.SPECTRUM_MENU_ITEM).contains("Open developer mode").click({ force: true }) + cy.get(".app-table").should('exist') // config sections available + cy.get(interact.CREATE_APP_BUTTON).should('exist') // create app button available }) after(() => { - // Change password back to original value - cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ force: true }) - cy.get(interact.SPECTRUM_MENU_ITEM).contains("Update password").click({ force: true }) - cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => { - for (let i = 0; i < 2; i++) { - cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("test") - } - cy.get("button").contains("Update password").click({ force: true }) - }) - // Remove users name - cy.updateUserInformation() + // Change password back to original value + cy.get(".user-dropdown .icon", { timeout: 2000 }).click({ force: true }) + cy.get(interact.SPECTRUM_MENU_ITEM).contains("Update password").click({ force: true }) + cy.get(interact.SPECTRUM_DIALOG_GRID).within(() => { + for (let i = 0; i < 2; i++) { + cy.get(interact.SPECTRUM_TEXTFIELD_INPUT).eq(i).type("test") + } + cy.get("button").contains("Update password").click({ force: true }) }) + // Remove users name + cy.updateUserInformation() + }) }) }) diff --git a/packages/builder/cypress/integration/appOverview.spec.js b/packages/builder/cypress/integration/appOverview.spec.js index 2afc0af277..60d0f2a06d 100644 --- a/packages/builder/cypress/integration/appOverview.spec.js +++ b/packages/builder/cypress/integration/appOverview.spec.js @@ -2,7 +2,7 @@ import filterTests from "../support/filterTests" import clientPackage from "@budibase/client/package.json" filterTests(["all"], () => { - context("Application Overview screen", () => { + xcontext("Application Overview screen", () => { before(() => { cy.login() cy.deleteAllApps() diff --git a/packages/builder/cypress/integration/createApp.spec.js b/packages/builder/cypress/integration/createApp.spec.js index d37b0806c4..897c7f8b91 100644 --- a/packages/builder/cypress/integration/createApp.spec.js +++ b/packages/builder/cypress/integration/createApp.spec.js @@ -14,15 +14,15 @@ filterTests(['smoke', 'all'], () => { cy.visit(`${Cypress.config().baseUrl}/builder/portal/apps/create`, { timeout: 5000 }) //added /portal/apps/create cy.wait(1000) cy.get(interact.CREATE_APP_BUTTON, { timeout: 10000 }).contains('Start from scratch').should("exist") - + cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist") cy.get(interact.TEMPLATE_CATEGORY).should("exist") - + cy.get(interact.APP_TABLE).should("not.exist") }) } - it("should provide filterable templates", () => { + xit("should provide filterable templates", () => { cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) cy.wait(500) @@ -30,16 +30,16 @@ filterTests(['smoke', 'all'], () => { .its("body") .then(val => { if (val.length > 0) { - cy.get(interact.SPECTRUM_BUTTON).contains("Templates").click({force: true}) + cy.get(interact.SPECTRUM_BUTTON).contains("View Templates").click({ force: true }) } }) cy.get(interact.TEMPLATE_CATEGORY_FILTER).should("exist") cy.get(interact.TEMPLATE_CATEGORY).should("exist") - + cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).its('length').should('be.gt', 1) cy.get(interact.TEMPLATE_CATEGORY_FILTER_ACTIONBUTTON).its('length').should('be.gt', 2) - + cy.get(interact.TEMPLATE_CATEGORY_FILTER_ACTIONBUTTON).eq(1).click() cy.get(interact.TEMPLATE_CATEGORY_ACTIONGROUP).should('have.length', 1) @@ -104,14 +104,14 @@ filterTests(['smoke', 'all'], () => { cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 5000 }) cy.updateUserInformation("Ted", "Userman") - + cy.createApp("", false) cy.applicationInAppTable("Teds app") cy.deleteApp("Teds app") // Accomodate names that end in 'S' cy.updateUserInformation("Chris", "Userman") - + cy.createApp("", false) cy.applicationInAppTable("Chris app") cy.deleteApp("Chris app") @@ -123,35 +123,49 @@ filterTests(['smoke', 'all'], () => { const exportedApp = 'cypress/fixtures/exported-app.txt' cy.importApp(exportedApp, "") - cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 2000 }) - cy.applicationInAppTable("My app") - - cy.get(".appTable .name").eq(0).click() - - cy.deleteApp("My app") + cy.get(".app-table .name").eq(0).click() + cy.closeModal() + cy.get(`[aria-label="ShowMenu"]`).click() + cy.get(".spectrum-Menu").within(() => { + cy.contains("Overview").click() + }) + cy.get(".app-overview-actions-icon").within(() => { + cy.get(".spectrum-Icon").click({ force: true }) + }) + cy.get(".spectrum-Menu").contains("Delete").click({ force: true }) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get("input").type("My app") + }) + cy.get(".spectrum-Button--warning").click() }) it("should create an application from an export, using the users first name as the default app name", () => { const exportedApp = 'cypress/fixtures/exported-app.txt' cy.updateUserInformation("Ted", "Userman") - cy.importApp(exportedApp, "") - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.applicationInAppTable("Teds app") - - cy.get(".appTable .name").eq(0).click() - - cy.deleteApp("Teds app") - + cy.get(".app-table .name").eq(0).click() + cy.closeModal() + cy.get(`[aria-label="ShowMenu"]`).click() + cy.get(".spectrum-Menu").within(() => { + cy.contains("Overview").click() + }) + cy.get(".app-overview-actions-icon").within(() => { + cy.get(".spectrum-Icon").click({ force: true }) + }) + cy.get(".spectrum-Menu").contains("Delete").click({ force: true }) + cy.get(".spectrum-Dialog-grid").within(() => { + cy.get("input").type("Teds app") + }) + cy.get(".spectrum-Button--warning").click() cy.updateUserInformation("", "") }) - it("should generate the first application from a template", () => { + xit("should generate the first application from a template", () => { cy.visit(`${Cypress.config().baseUrl}/builder`) cy.wait(500) @@ -172,28 +186,28 @@ filterTests(['smoke', 'all'], () => { const card = cy.get('.template-card').eq(0).should("exist"); const cardOverlay = card.get('.template-thumbnail-action-overlay').should("exist") cardOverlay.invoke("show") - cardOverlay.get("button").contains("Use template").should("exist").click({force: true}) + cardOverlay.get("button").contains("Use template").should("exist").click({ force: true }) }) // CMD Create app from theme card cy.get(".spectrum-Modal").should('be.visible') - + const templateName = cy.get(".spectrum-Modal .template-thumbnail-text") templateName.invoke('text') - .then(templateNameText => { - const templateNameParsed = "/"+templateNameText.toLowerCase().replace(/\s+/g, "-") - cy.get(interact.SPECTRUM_MODAL_INPUT).eq(0).should("have.value", templateNameText) - cy.get(interact.SPECTRUM_MODAL_INPUT).eq(1).should("have.value", templateNameParsed) + .then(templateNameText => { + const templateNameParsed = "/" + templateNameText.toLowerCase().replace(/\s+/g, "-") + cy.get(interact.SPECTRUM_MODAL_INPUT).eq(0).should("have.value", templateNameText) + cy.get(interact.SPECTRUM_MODAL_INPUT).eq(1).should("have.value", templateNameParsed) - cy.get(".spectrum-Modal .spectrum-ButtonGroup").contains("Create app").click() - cy.wait(5000) - - cy.visit(`${Cypress.config().baseUrl}/builder`) - cy.wait(2000) + cy.get(".spectrum-Modal .spectrum-ButtonGroup").contains("Create app").click() + cy.wait(5000) - cy.applicationInAppTable(templateNameText) - cy.deleteApp(templateNameText) - }); + cy.visit(`${Cypress.config().baseUrl}/builder`) + cy.wait(2000) + + cy.applicationInAppTable(templateNameText) + cy.deleteApp(templateNameText) + }); }) @@ -217,5 +231,5 @@ filterTests(['smoke', 'all'], () => { cy.deleteApp(secondAppName) }) - }) + }) }) diff --git a/packages/builder/cypress/integration/createScreen.spec.js b/packages/builder/cypress/integration/createScreen.spec.js index c4b237279d..09d8485386 100644 --- a/packages/builder/cypress/integration/createScreen.spec.js +++ b/packages/builder/cypress/integration/createScreen.spec.js @@ -2,7 +2,7 @@ import filterTests from "../support/filterTests" const interact = require('../support/interact') filterTests(["smoke", "all"], () => { - context("Screen Tests", () => { + xcontext("Screen Tests", () => { before(() => { cy.login() cy.createTestApp() @@ -25,7 +25,7 @@ filterTests(["smoke", "all"], () => { it.skip("should delete all screens then create first screen via button", () => { cy.deleteAllScreens() - + cy.contains("Create first screen").click() cy.get(interact.BODY, { timeout: 2000 }).should('contain', '/home') }) @@ -33,7 +33,7 @@ filterTests(["smoke", "all"], () => { it("Should create and filter screens by access level", () => { const accessLevels = ["Basic", "Admin", "Public", "Power"] - for (const access of accessLevels){ + for (const access of accessLevels) { // Create screen with specified access level cy.createScreen(access, access) // Filter by access level and confirm screen visible @@ -46,9 +46,9 @@ filterTests(["smoke", "all"], () => { // Filter by All screens - Confirm all screens visible cy.filterScreensAccessLevel("All screens") cy.get(interact.BODY).should('contain', accessLevels[0]) - .and('contain', accessLevels[1]) - .and('contain', accessLevels[2]) - .and('contain', accessLevels[3]) + .and('contain', accessLevels[1]) + .and('contain', accessLevels[2]) + .and('contain', accessLevels[3]) }) }) }) diff --git a/packages/builder/cypress/support/commands.js b/packages/builder/cypress/support/commands.js index 4c44fd6672..e63fd41591 100644 --- a/packages/builder/cypress/support/commands.js +++ b/packages/builder/cypress/support/commands.js @@ -101,7 +101,7 @@ Cypress.Commands.add("deleteUser", email => { }) Cypress.Commands.add("updateUserInformation", (firstName, lastName) => { - cy.get(".user-dropdown .avatar > .icon", { timeout: 2000 }).click({ + cy.get(".user-dropdown .icon", { timeout: 2000 }).click({ force: true, }) @@ -132,7 +132,7 @@ Cypress.Commands.add("updateUserInformation", (firstName, lastName) => { .blur() } cy.get(".confirm-wrap").within(() => { - cy.get("button").contains("Update information").click({ force: true }) + cy.get("button").contains("Save").click({ force: true }) }) cy.get(".spectrum-Dialog-grid").should("not.exist") }) @@ -222,9 +222,12 @@ Cypress.Commands.add("deleteApp", name => { // Go to app overview const appIdParsed = appId.split("_").pop() const actionEleId = `[data-cy=row_actions_${appIdParsed}]` - cy.get(actionEleId).within(() => { - cy.contains("Manage").click({ force: true }) + cy.get(actionEleId).click() + cy.get(`[aria-label="ShowMenu"]`).click() + cy.get(".spectrum-Menu").within(() => { + cy.contains("Overview").click() }) + cy.wait(500) // Unpublish first if needed @@ -400,7 +403,7 @@ Cypress.Commands.add("searchForApplication", appName => { return } else { // Searches for the app - cy.get(".filter").then(() => { + cy.get(".spectrum-Search").then(() => { cy.get(".spectrum-Textfield").within(() => { cy.get("input").eq(0).clear({ force: true }) cy.get("input").eq(0).type(appName, { force: true }) @@ -413,7 +416,7 @@ Cypress.Commands.add("searchForApplication", appName => { // Assumes there are no others Cypress.Commands.add("applicationInAppTable", appName => { cy.visit(`${Cypress.config().baseUrl}/builder`, { timeout: 30000 }) - cy.get(".appTable", { timeout: 30000 }).within(() => { + cy.get(".app-table", { timeout: 30000 }).within(() => { cy.get(".title").contains(appName).should("exist") }) }) diff --git a/packages/builder/package.json b/packages/builder/package.json index a0f3052005..82c939d1f4 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "license": "GPL-3.0", "private": true, "scripts": { @@ -71,10 +71,10 @@ } }, "dependencies": { - "@budibase/bbui": "2.2.12-alpha.16", - "@budibase/client": "2.2.12-alpha.16", - "@budibase/frontend-core": "2.2.12-alpha.16", - "@budibase/string-templates": "2.2.12-alpha.16", + "@budibase/bbui": "2.2.12-alpha.32", + "@budibase/client": "2.2.12-alpha.32", + "@budibase/frontend-core": "2.2.12-alpha.32", + "@budibase/string-templates": "2.2.12-alpha.32", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index d188073b95..6de73d487c 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -378,6 +378,7 @@ const getProviderContextBindings = (asset, dataProviders) => { providerId, // Table ID is used by JSON fields to know what table the field is in tableId: table?._id, + component: component._component, category: component._instanceName, icon: def.icon, display: { diff --git a/packages/builder/src/components/backend/DataTable/modals/ExportModal.svelte b/packages/builder/src/components/backend/DataTable/modals/ExportModal.svelte index f55e413a36..aae825928f 100644 --- a/packages/builder/src/components/backend/DataTable/modals/ExportModal.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/ExportModal.svelte @@ -12,6 +12,10 @@ name: "JSON", key: "json", }, + { + name: "JSON with Schema", + key: "jsonWithSchema", + }, ] export let view @@ -24,7 +28,7 @@ viewName: view, format: exportFormat, }) - download(data, `export.${exportFormat}`) + download(data, `export.${exportFormat === "csv" ? "csv" : "json"}`) } catch (error) { notifications.error(`Unable to export ${exportFormat.toUpperCase()} data`) } diff --git a/packages/builder/src/components/backend/DataTable/modals/ImportModal.svelte b/packages/builder/src/components/backend/DataTable/modals/ImportModal.svelte index bf44653e3d..173fb88829 100644 --- a/packages/builder/src/components/backend/DataTable/modals/ImportModal.svelte +++ b/packages/builder/src/components/backend/DataTable/modals/ImportModal.svelte @@ -6,22 +6,22 @@ Body, Layout, } from "@budibase/bbui" - import TableDataImport from "../../TableNavigator/TableDataImport.svelte" + import TableDataImport from "../../TableNavigator/ExistingTableDataImport.svelte" import { API } from "api" import { createEventDispatcher } from "svelte" const dispatch = createEventDispatcher() export let tableId - let dataImport - - $: valid = dataImport?.csvString != null && dataImport?.valid + let rows = [] + let allValid = false + let displayColumn = null async function importData() { try { await API.importTableData({ tableId, - data: dataImport, + rows, }) notifications.success("Rows successfully imported") } catch (error) { @@ -37,14 +37,14 @@ title="Import Data" confirmText="Import" onConfirm={importData} - disabled={!valid} + disabled={!allValid} > - Import rows to an existing table from a CSV. Only columns from the CSV which - exist in the table will be imported. + Import rows to an existing table from a CSV or JSON file. Only columns from + the file which exist in the table will be imported. - - + + diff --git a/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte b/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte index 4defcbafab..e4cbbfc7aa 100644 --- a/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte +++ b/packages/builder/src/components/backend/Datasources/CreateEditRelationship.svelte @@ -10,7 +10,6 @@ } from "@budibase/bbui" import { tables } from "stores/backend" import { Helpers } from "@budibase/bbui" - import { writable } from "svelte/store" export let save export let datasource @@ -18,41 +17,95 @@ export let fromRelationship = {} export let toRelationship = {} export let close - export let selectedFromTable - let originalFromName = fromRelationship.name, - originalToName = toRelationship.name - let fromTable, toTable, through, linkTable, tableOptions - let isManyToMany, isManyToOne, relationshipTypes - let errors, valid - let currentTables = {} + const colNotSet = "Please specify a column name" + const relationshipTypes = [ + { + label: "One to Many", + value: RelationshipTypes.MANY_TO_ONE, + }, + { + label: "Many to Many", + value: RelationshipTypes.MANY_TO_MANY, + }, + ] - if (fromRelationship && !fromRelationship.relationshipType) { - fromRelationship.relationshipType = RelationshipTypes.MANY_TO_ONE - } + let originalFromColumnName = toRelationship.name, + originalToColumnName = fromRelationship.name + let originalFromTable = plusTables.find( + table => table._id === toRelationship?.tableId + ) + let originalToTable = plusTables.find( + table => table._id === fromRelationship?.tableId + ) - if (toRelationship && selectedFromTable) { - toRelationship.tableId = selectedFromTable._id - } + let tableOptions + let errors = {} + let hasClickedSave = !!fromRelationship.relationshipType + let fromPrimary, + fromForeign, + fromTable, + toTable, + throughTable, + fromColumn, + toColumn + let fromId, toId, throughId, throughToKey, throughFromKey + let isManyToMany, isManyToOne, relationshipType - function inSchema(table, prop, ogName) { - if (!table || !prop || prop === ogName) { - return false + $: { + if (!fromPrimary) { + fromPrimary = fromRelationship.foreignKey + fromForeign = toRelationship.foreignKey + } + if (!fromColumn && !errors.fromColumn) { + fromColumn = toRelationship.name + } + if (!toColumn && !errors.toColumn) { + toColumn = fromRelationship.name + } + if (!fromId) { + fromId = toRelationship.tableId + } + if (!toId) { + toId = fromRelationship.tableId + } + if (!throughId) { + throughId = fromRelationship.through + throughFromKey = fromRelationship.throughFrom + throughToKey = fromRelationship.throughTo + } + if (!relationshipType) { + relationshipType = fromRelationship.relationshipType } - const keys = Object.keys(table.schema).map(key => key.toLowerCase()) - return keys.indexOf(prop.toLowerCase()) !== -1 } - const touched = writable({}) + $: tableOptions = plusTables.map(table => ({ + label: table.name, + value: table._id, + })) + $: valid = getErrorCount(errors) === 0 || !hasClickedSave - function invalidThroughTable({ through, throughTo, throughFrom }) { + $: isManyToMany = relationshipType === RelationshipTypes.MANY_TO_MANY + $: isManyToOne = relationshipType === RelationshipTypes.MANY_TO_ONE + $: fromTable = plusTables.find(table => table._id === fromId) + $: toTable = plusTables.find(table => table._id === toId) + $: throughTable = plusTables.find(table => table._id === throughId) + + $: toRelationship.relationshipType = fromRelationship?.relationshipType + + const getErrorCount = errors => + Object.entries(errors) + .filter(entry => !!entry[1]) + .map(entry => entry[0]).length + + function invalidThroughTable() { // need to know the foreign key columns to check error - if (!through || !throughTo || !throughFrom) { + if (!throughId || !throughToKey || !throughFromKey) { return false } - const throughTable = plusTables.find(tbl => tbl._id === through) - const otherColumns = Object.values(throughTable.schema).filter( - col => col.name !== throughFrom && col.name !== throughTo + const throughTbl = plusTables.find(tbl => tbl._id === throughId) + const otherColumns = Object.values(throughTbl.schema).filter( + col => col.name !== throughFromKey && col.name !== throughToKey ) for (let col of otherColumns) { if (col.constraints?.presence && !col.autocolumn) { @@ -62,142 +115,134 @@ return false } - function checkForErrors(fromRelate, toRelate) { - const isMany = - fromRelate.relationshipType === RelationshipTypes.MANY_TO_MANY + function validate() { + const isMany = relationshipType === RelationshipTypes.MANY_TO_MANY const tableNotSet = "Please specify a table" + const foreignKeyNotSet = "Please pick a foreign key" const errObj = {} - if ($touched.from && !fromTable) { - errObj.from = tableNotSet + if (!relationshipType) { + errObj.relationshipType = "Please specify a relationship type" } - if ($touched.to && !toTable) { - errObj.to = tableNotSet + if (!fromTable) { + errObj.fromTable = tableNotSet } - if ($touched.through && isMany && !fromRelate.through) { - errObj.through = tableNotSet + if (!toTable) { + errObj.toTable = tableNotSet } - if ($touched.through && invalidThroughTable(fromRelate)) { - errObj.through = - "Ensure all columns in table are nullable or auto generated" + if (isMany && !throughTable) { + errObj.throughTable = tableNotSet } - if ($touched.foreign && !isMany && !fromRelate.fieldName) { - errObj.foreign = "Please pick the foreign key" + if (isMany && !throughFromKey) { + errObj.throughFromKey = foreignKeyNotSet } - const colNotSet = "Please specify a column name" - if ($touched.fromCol && !fromRelate.name) { - errObj.fromCol = colNotSet + if (isMany && !throughToKey) { + errObj.throughToKey = foreignKeyNotSet } - if ($touched.toCol && !toRelate.name) { - errObj.toCol = colNotSet + if (invalidThroughTable()) { + errObj.throughTable = + "Ensure non-key columns are nullable or auto-generated" } - if ($touched.primary && !fromPrimary) { - errObj.primary = "Please pick the primary key" + if (!isMany && !fromForeign) { + errObj.fromForeign = foreignKeyNotSet } + if (!fromColumn) { + errObj.fromColumn = colNotSet + } + if (!toColumn) { + errObj.toColumn = colNotSet + } + if (!isMany && !fromPrimary) { + errObj.fromPrimary = "Please pick the primary key" + } + // currently don't support relationships back onto the table itself, needs to relate out const tableError = "From/to/through tables must be different" - if (fromTable && (fromTable === toTable || fromTable === through)) { - errObj.from = tableError + if (fromTable && (fromTable === toTable || fromTable === throughTable)) { + errObj.fromTable = tableError } - if (toTable && (toTable === fromTable || toTable === through)) { - errObj.to = tableError + if (toTable && (toTable === fromTable || toTable === throughTable)) { + errObj.toTable = tableError } - if (through && (through === fromTable || through === toTable)) { - errObj.through = tableError + if ( + throughTable && + (throughTable === fromTable || throughTable === toTable) + ) { + errObj.throughTable = tableError } const colError = "Column name cannot be an existing column" - if (inSchema(fromTable, fromRelate.name, originalFromName)) { - errObj.fromCol = colError + if (isColumnNameBeingUsed(toTable, fromColumn, originalFromColumnName)) { + errObj.fromColumn = colError } - if (inSchema(toTable, toRelate.name, originalToName)) { - errObj.toCol = colError + if (isColumnNameBeingUsed(fromTable, toColumn, originalToColumnName)) { + errObj.toColumn = colError } let fromType, toType - if (fromPrimary && fromRelate.fieldName) { + if (fromPrimary && fromForeign) { fromType = fromTable?.schema[fromPrimary]?.type - toType = toTable?.schema[fromRelate.fieldName]?.type + toType = toTable?.schema[fromForeign]?.type } if (fromType && toType && fromType !== toType) { - errObj.foreign = + errObj.fromForeign = "Column type of the foreign key must match the primary key" } + errors = errObj + return getErrorCount(errors) === 0 } - let fromPrimary - $: { - if (!fromPrimary && fromTable) { - fromPrimary = fromTable.primary[0] - } - } - $: isManyToMany = - fromRelationship?.relationshipType === RelationshipTypes.MANY_TO_MANY - $: isManyToOne = - fromRelationship?.relationshipType === RelationshipTypes.MANY_TO_ONE - $: tableOptions = plusTables.map(table => ({ - label: table.name, - value: table._id, - })) - $: fromTable = plusTables.find(table => table._id === toRelationship?.tableId) - $: toTable = plusTables.find(table => table._id === fromRelationship?.tableId) - $: through = plusTables.find(table => table._id === fromRelationship?.through) - $: checkForErrors(fromRelationship, toRelationship) - $: valid = - Object.keys(errors).length === 0 && Object.keys($touched).length !== 0 - $: linkTable = through || toTable - $: relationshipTypes = [ - { - label: "Many", - value: RelationshipTypes.MANY_TO_MANY, - }, - { - label: "One", - value: RelationshipTypes.MANY_TO_ONE, - }, - ] - $: updateRelationshipType(fromRelationship?.relationshipType) - $: tableChanged(fromTable, toTable) - - function updateRelationshipType(fromType) { - if (fromType === RelationshipTypes.MANY_TO_MANY) { - toRelationship.relationshipType = RelationshipTypes.MANY_TO_MANY - } else { - toRelationship.relationshipType = RelationshipTypes.MANY_TO_ONE + function isColumnNameBeingUsed(table, columnName, originalName) { + if (!table || !columnName || columnName === originalName) { + return false } + const keys = Object.keys(table.schema).map(key => key.toLowerCase()) + return keys.indexOf(columnName.toLowerCase()) !== -1 } function buildRelationships() { - // if any to many only need to check from - const manyToMany = - fromRelationship.relationshipType === RelationshipTypes.MANY_TO_MANY - // main is simply used to know this is the side the user configured it from const id = Helpers.uuid() - if (!manyToMany) { - delete fromRelationship.through - delete toRelationship.through - } + //Map temporary variables let relateFrom = { ...fromRelationship, + tableId: toId, + name: toColumn, + relationshipType, + fieldName: fromForeign, + through: throughId, + throughFrom: throughFromKey, + throughTo: throughToKey, type: "link", main: true, _id: id, } - let relateTo = { + let relateTo = (toRelationship = { ...toRelationship, + tableId: fromId, + name: fromColumn, + through: throughId, type: "link", _id: id, + }) + + // if any to many only need to check from + const manyToMany = + relateFrom.relationshipType === RelationshipTypes.MANY_TO_MANY + + if (!manyToMany) { + delete relateFrom.through + delete relateTo.through } // [0] is because we don't support composite keys for relationships right now if (manyToMany) { relateFrom = { ...relateFrom, - through: through._id, + through: throughTable._id, fieldName: toTable.primary[0], } relateTo = { ...relateTo, - through: through._id, + through: throughTable._id, fieldName: fromTable.primary[0], throughFrom: relateFrom.throughTo, throughTo: relateFrom.throughFrom, @@ -226,9 +271,27 @@ toRelationship = relateTo } - // save the relationship on to the datasource + function removeExistingRelationship() { + if (originalFromTable && originalFromColumnName) { + delete datasource.entities[originalFromTable.name].schema[ + originalToColumnName + ] + } + if (originalToTable && originalToColumnName) { + delete datasource.entities[originalToTable.name].schema[ + originalFromColumnName + ] + } + } + async function saveRelationship() { + hasClickedSave = true + if (!validate()) { + return false + } buildRelationships() + removeExistingRelationship() + // source of relationship datasource.entities[fromTable.name].schema[fromRelationship.name] = fromRelationship @@ -236,43 +299,14 @@ datasource.entities[toTable.name].schema[toRelationship.name] = toRelationship - // If relationship has been renamed - if (originalFromName !== fromRelationship.name) { - delete datasource.entities[fromTable.name].schema[originalFromName] - } - if (originalToName !== toRelationship.name) { - delete datasource.entities[toTable.name].schema[originalToName] - } - - // store the original names so it won't cause an error - originalToName = toRelationship.name - originalFromName = fromRelationship.name await save() } - async function deleteRelationship() { - delete datasource.entities[fromTable.name].schema[fromRelationship.name] - delete datasource.entities[toTable.name].schema[toRelationship.name] + removeExistingRelationship() await save() await tables.fetch() close() } - - function tableChanged(fromTbl, toTbl) { - if ( - (currentTables?.from?._id === fromTbl?._id && - currentTables?.to?._id === toTbl?._id) || - originalFromName || - originalToName - ) { - return - } - fromRelationship.name = toTbl?.name || "" - errors.fromCol = "" - toRelationship.name = fromTbl?.name || "" - errors.toCol = "" - currentTables = { from: fromTbl, to: toTbl } - } (errors.relationshipType = null)} />
Tables @@ -292,60 +328,74 @@ ($touched.primary = true)} - bind:error={errors.primary} + label={`Primary Key (${fromTable.name})`} + options={Object.keys(fromTable.schema)} bind:value={fromPrimary} + bind:error={errors.fromPrimary} + on:change={() => (errors.fromPrimary = null)} /> {/if} ($touched.through = true)} - bind:error={errors.through} - bind:value={fromRelationship.through} + bind:value={throughId} + bind:error={errors.throughTable} /> - {#if fromTable && toTable && through} + {#if fromTable && toTable && throughTable} ($touched.toForeign = true)} - bind:error={errors.toForeign} - bind:value={fromRelationship.throughFrom} + options={Object.keys(throughTable?.schema)} + bind:value={throughFromKey} + bind:error={errors.throughFromKey} + on:change={e => { + if (throughToKey === e.detail) { + throughToKey = null + } + errors.throughFromKey = null + }} /> {/if} {:else if isManyToOne && toTable} ($touched.fromCol = true)} - bind:error={errors.fromCol} label="From table column" - bind:value={fromRelationship.name} + bind:value={fromColumn} + bind:error={errors.fromColumn} + on:change={e => { + errors.fromColumn = e.detail?.length > 0 ? null : colNotSet + }} /> ($touched.toCol = true)} - bind:error={errors.toCol} label="To table column" - bind:value={toRelationship.name} + bind:value={toColumn} + bind:error={errors.toColumn} + on:change={e => (errors.toColumn = e.detail?.length > 0 ? null : colNotSet)} />
- {#if originalFromName != null} + {#if originalFromColumnName != null} {/if}
diff --git a/packages/builder/src/components/backend/TableNavigator/ExistingTableDataImport.svelte b/packages/builder/src/components/backend/TableNavigator/ExistingTableDataImport.svelte new file mode 100644 index 0000000000..cb150f71fc --- /dev/null +++ b/packages/builder/src/components/backend/TableNavigator/ExistingTableDataImport.svelte @@ -0,0 +1,251 @@ + + +
+ + +
+{#if fileName && Object.keys(validation).length === 0} +

No valid fields, try another file

+{:else if rows.length > 0 && !error} +
+ {#each Object.keys(validation) as name} +
+ {name} + -
-{#if fields.length} +{#if rows.length > 0 && !error}
- {#each fields as columnName} + {#each Object.values(schema) as column}
- {columnName} + {column.name} -
- {/if} -{:else if hasValidated} -
- +
- - + +
diff --git a/packages/builder/src/components/backend/TableNavigator/utils.js b/packages/builder/src/components/backend/TableNavigator/utils.js new file mode 100644 index 0000000000..658f037912 --- /dev/null +++ b/packages/builder/src/components/backend/TableNavigator/utils.js @@ -0,0 +1,71 @@ +import { API } from "api" +import { FIELDS } from "constants/backend" + +const BYTES_IN_MB = 1000000 +const FILE_SIZE_LIMIT = BYTES_IN_MB * 5 + +const getDefaultSchema = rows => { + const newSchema = {} + + rows.forEach(row => { + Object.keys(row).forEach(column => { + newSchema[column] = { + name: column, + type: "string", + constraints: FIELDS["STRING"].constraints, + } + }) + }) + + return newSchema +} + +export const parseFile = e => { + return new Promise((resolve, reject) => { + const file = Array.from(e.target.files)[0] + + if (file.size >= FILE_SIZE_LIMIT) { + reject("file too large") + return + } + + let reader = new FileReader() + + const resolveRows = (rows, schema = null) => { + resolve({ + rows, + schema: schema ?? getDefaultSchema(rows), + fileName: file.name, + fileType: file.type, + }) + } + + reader.addEventListener("load", function (e) { + const fileData = e.target.result + + if (file.type === "text/csv") { + API.csvToJson(fileData) + .then(rows => { + resolveRows(rows) + }) + .catch(() => { + reject("can't convert csv to json") + }) + } else if (file.type === "application/json") { + const parsedFileData = JSON.parse(fileData) + + if (Array.isArray(parsedFileData)) { + resolveRows(parsedFileData) + } else if (typeof parsedFileData === "object") { + resolveRows(parsedFileData.rows, parsedFileData.schema) + } else { + reject("invalid json format") + } + } else { + reject("invalid file type") + } + }) + + reader.readAsText(file) + }) +} diff --git a/packages/builder/src/components/design/settings/controls/DataSourceSelect.svelte b/packages/builder/src/components/design/settings/controls/DataSourceSelect.svelte index 6269599f40..49151a09b0 100644 --- a/packages/builder/src/components/design/settings/controls/DataSourceSelect.svelte +++ b/packages/builder/src/components/design/settings/controls/DataSourceSelect.svelte @@ -70,7 +70,10 @@ type: "provider", })) $: links = bindings + // Get only link bindings .filter(x => x.fieldSchema?.type === "link") + // Filter out bindings provided by forms + .filter(x => !x.component?.endsWith("/form")) .map(binding => { const { providerId, readableBinding, fieldSchema } = binding || {} const { name, tableId } = fieldSchema || {} diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/NewComponentPanel.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/NewComponentPanel.svelte index 98e04a262a..6b3f302264 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/NewComponentPanel.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/NewComponentPanel.svelte @@ -176,7 +176,6 @@ const addComponent = async component => { try { await store.actions.components.create(component) - $goto("../") } catch (error) { notifications.error(error || "Error creating component") } diff --git a/packages/builder/src/pages/builder/portal/_components/UpgradeButton.svelte b/packages/builder/src/pages/builder/portal/_components/UpgradeButton.svelte index 3e095dce21..7de6205a31 100644 --- a/packages/builder/src/pages/builder/portal/_components/UpgradeButton.svelte +++ b/packages/builder/src/pages/builder/portal/_components/UpgradeButton.svelte @@ -7,6 +7,7 @@ {#if $admin.cloud && $auth?.user?.accountPortalAccess}
- themeModal.show()} dataCy="theme"> - Theme - profileModal.show()} @@ -36,6 +33,9 @@ > My profile + themeModal.show()} dataCy="theme"> + Theme + updatePasswordModal.show()}> Update password diff --git a/packages/builder/src/pages/builder/portal/settings/auth/index.svelte b/packages/builder/src/pages/builder/portal/settings/auth/index.svelte index 412a75ec0a..f0ca5c9797 100644 --- a/packages/builder/src/pages/builder/portal/settings/auth/index.svelte +++ b/packages/builder/src/pages/builder/portal/settings/auth/index.svelte @@ -172,6 +172,8 @@ delete element.createdAt delete element.updatedAt + const { activated } = element.config + if (element.type === ConfigTypes.OIDC) { // Add a UUID here so each config is distinguishable when it arrives at the login page for (let config of element.config.configs) { @@ -181,30 +183,26 @@ // Callback urls shouldn't be included delete config.callbackURL } - if (partialOidc) { - if (!oidcComplete) { - notifications.error( - `Please fill in all required ${ConfigTypes.OIDC} fields` - ) - } else { - calls.push(API.saveConfig(element)) - // Turn the save button grey when clicked - oidcSaveButtonDisabled = true - originalOidcDoc = cloneDeep(providers.oidc) - } + if ((partialOidc || activated) && !oidcComplete) { + notifications.error( + `Please fill in all required ${ConfigTypes.OIDC} fields` + ) + } else if (oidcComplete || !activated) { + calls.push(API.saveConfig(element)) + // Turn the save button grey when clicked + oidcSaveButtonDisabled = true + originalOidcDoc = cloneDeep(providers.oidc) } } if (element.type === ConfigTypes.Google) { - if (partialGoogle) { - if (!googleComplete) { - notifications.error( - `Please fill in all required ${ConfigTypes.Google} fields` - ) - } else { - calls.push(API.saveConfig(element)) - googleSaveButtonDisabled = true - originalGoogleDoc = cloneDeep(providers.google) - } + if ((partialGoogle || activated) && !googleComplete) { + notifications.error( + `Please fill in all required ${ConfigTypes.Google} fields` + ) + } else if (googleComplete || !activated) { + calls.push(API.saveConfig(element)) + googleSaveButtonDisabled = true + originalGoogleDoc = cloneDeep(providers.google) } } }) diff --git a/packages/cli/package.json b/packages/cli/package.json index a823c00526..fd514d6917 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "description": "Budibase CLI, for developers, self hosting and migrations.", "main": "src/index.js", "bin": { @@ -26,9 +26,9 @@ "outputPath": "build" }, "dependencies": { - "@budibase/backend-core": "2.2.12-alpha.16", - "@budibase/string-templates": "2.2.12-alpha.16", - "@budibase/types": "2.2.12-alpha.16", + "@budibase/backend-core": "2.2.12-alpha.32", + "@budibase/string-templates": "2.2.12-alpha.32", + "@budibase/types": "2.2.12-alpha.32", "axios": "0.21.2", "chalk": "4.1.0", "cli-progress": "3.11.2", diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 9d50c13bb6..d1898a82c1 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -4019,7 +4019,8 @@ { "type": "filter", "label": "Filtering", - "key": "filter" + "key": "filter", + "nested": true }, { "type": "field", @@ -4535,7 +4536,8 @@ { "type": "filter", "label": "Filtering", - "key": "filter" + "key": "filter", + "nested": true }, { "type": "searchfield", @@ -4665,7 +4667,8 @@ { "type": "filter", "label": "Filtering", - "key": "filter" + "key": "filter", + "nested": true }, { "type": "field/sortable", @@ -4831,7 +4834,8 @@ { "type": "filter", "label": "Filtering", - "key": "filter" + "key": "filter", + "nested": true }, { "type": "field/sortable", diff --git a/packages/client/package.json b/packages/client/package.json index 3586b3c453..6f6422c236 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -19,9 +19,9 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "2.2.12-alpha.16", - "@budibase/frontend-core": "2.2.12-alpha.16", - "@budibase/string-templates": "2.2.12-alpha.16", + "@budibase/bbui": "2.2.12-alpha.32", + "@budibase/frontend-core": "2.2.12-alpha.32", + "@budibase/string-templates": "2.2.12-alpha.32", "@spectrum-css/button": "^3.0.3", "@spectrum-css/card": "^3.0.3", "@spectrum-css/divider": "^1.0.3", diff --git a/packages/client/src/components/Block.svelte b/packages/client/src/components/Block.svelte index 8258912e52..b72ff81b49 100644 --- a/packages/client/src/components/Block.svelte +++ b/packages/client/src/components/Block.svelte @@ -38,7 +38,7 @@ ...$component.styles?.normal, }, custom: - definition._styles?.custom || "" + $component.styles?.custom || "", + (definition._styles?.custom || "") + ($component.styles?.custom || ""), } // Create component tree diff --git a/packages/client/src/components/CustomThemeWrapper.svelte b/packages/client/src/components/CustomThemeWrapper.svelte index 20dae01ce0..c9ab9c9dc1 100644 --- a/packages/client/src/components/CustomThemeWrapper.svelte +++ b/packages/client/src/components/CustomThemeWrapper.svelte @@ -1,5 +1,9 @@
diff --git a/packages/client/src/components/app/blocks/CardsBlock.svelte b/packages/client/src/components/app/blocks/CardsBlock.svelte index 5098a3acf4..795e62eb31 100644 --- a/packages/client/src/components/app/blocks/CardsBlock.svelte +++ b/packages/client/src/components/app/blocks/CardsBlock.svelte @@ -36,9 +36,12 @@ let dataProviderId let repeaterId let schema + let enrichedSearchColumns $: fetchSchema(dataSource) - $: enrichedSearchColumns = enrichSearchColumns(searchColumns, schema) + $: enrichSearchColumns(searchColumns, schema).then( + val => (enrichedSearchColumns = val) + ) $: enrichedFilter = enrichFilter(filter, enrichedSearchColumns, formId) $: cardWidth = cardHorizontal ? 420 : 300 $: fullCardURL = buildFullCardUrl( diff --git a/packages/client/src/components/app/blocks/TableBlock.svelte b/packages/client/src/components/app/blocks/TableBlock.svelte index 0984c901a3..91c266b434 100644 --- a/packages/client/src/components/app/blocks/TableBlock.svelte +++ b/packages/client/src/components/app/blocks/TableBlock.svelte @@ -36,9 +36,12 @@ let newRowSidePanelId let schema let primaryDisplay + let enrichedSearchColumns $: fetchSchema(dataSource) - $: enrichedSearchColumns = enrichSearchColumns(searchColumns, schema) + $: enrichSearchColumns(searchColumns, schema).then( + val => (enrichedSearchColumns = val) + ) $: enrichedFilter = enrichFilter(filter, enrichedSearchColumns, formId) $: editTitle = getEditTitle(detailsFormBlockId, primaryDisplay) $: normalFields = getNormalFields(schema) diff --git a/packages/client/src/components/app/forms/Form.svelte b/packages/client/src/components/app/forms/Form.svelte index 977b940d1f..0b4502b962 100644 --- a/packages/client/src/components/app/forms/Form.svelte +++ b/packages/client/src/components/app/forms/Form.svelte @@ -24,6 +24,11 @@ let table $: fetchSchema(dataSource) + $: schemaKey = generateSchemaKey(schema) + $: initialValues = getInitialValues(actionType, dataSource, $context) + $: resetKey = Helpers.hashString( + schemaKey + JSON.stringify(initialValues) + disabled + ) // Returns the closes data context which isn't a built in context const getInitialValues = (type, dataSource, context) => { @@ -57,13 +62,17 @@ schema = res || {} } - $: initialValues = getInitialValues(actionType, dataSource, $context) - $: resetKey = Helpers.hashString( - !!schema + - JSON.stringify(initialValues) + - JSON.stringify(dataSource) + - disabled - ) + // Generates a predictable string that uniquely identifies a schema. We can't + // simply stringify the whole schema as there are array fields which have + // random order. + const generateSchemaKey = schema => { + if (!schema) { + return null + } + const fields = Object.keys(schema) + fields.sort() + return fields.map(field => `${field}:${schema[field].type}`).join("-") + } {#key resetKey} diff --git a/packages/client/src/utils/blocks.js b/packages/client/src/utils/blocks.js index 61cd640bbc..214b48a4d2 100644 --- a/packages/client/src/utils/blocks.js +++ b/packages/client/src/utils/blocks.js @@ -1,4 +1,5 @@ import { makePropSafe as safe } from "@budibase/string-templates" +import { API } from "../api/index.js" // Map of data types to component types for search fields inside blocks const schemaComponentMap = { @@ -15,10 +16,28 @@ const schemaComponentMap = { * @param searchColumns the search columns to use * @param schema the datasource schema */ -export const enrichSearchColumns = (searchColumns, schema) => { +export const enrichSearchColumns = async (searchColumns, schema) => { + if (!searchColumns?.length || !schema) { + return [] + } let enrichedColumns = [] - searchColumns?.forEach(column => { - const schemaType = schema?.[column]?.type + for (let column of searchColumns) { + let schemaType = schema[column]?.type + + // Check if this is a field in another related table. The only way we can + // check this is checking for a "." inside the column, then checking if we + // have a link field named the same as that field prefix. + if (column.includes(".")) { + const split = column.split(".") + const sourceField = split[0] + const linkField = split.slice(1).join(".") + const linkSchema = schema[sourceField] + if (linkSchema?.type === "link") { + const linkedDef = await API.fetchTableDefinition(linkSchema.tableId) + schemaType = linkedDef?.schema?.[linkField]?.type + } + } + const componentType = schemaComponentMap[schemaType] if (componentType) { enrichedColumns.push({ @@ -27,7 +46,7 @@ export const enrichSearchColumns = (searchColumns, schema) => { type: schemaType, }) } - }) + } return enrichedColumns.slice(0, 5) } @@ -57,12 +76,14 @@ export const enrichFilter = (filter, columns, formId) => { value: `{{ ${binding} }}`, }) const format = "YYYY-MM-DDTHH:mm:ss.SSSZ" + let hbs = `{{ date (add (date ${binding} "x") 86399999) "${format}" }}` + hbs = `{{#if ${binding} }}${hbs}{{/if}}` enrichedFilter.push({ field: column.name, type: column.type, operator: "rangeHigh", valueType: "Binding", - value: `{{ date (add (date ${binding} "x") 86399999) "${format}" }}`, + value: hbs, }) } diff --git a/packages/frontend-core/package.json b/packages/frontend-core/package.json index 09e8863229..321d95a284 100644 --- a/packages/frontend-core/package.json +++ b/packages/frontend-core/package.json @@ -1,12 +1,12 @@ { "name": "@budibase/frontend-core", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "description": "Budibase frontend core libraries used in builder and client", "author": "Budibase", "license": "MPL-2.0", "svelte": "src/index.js", "dependencies": { - "@budibase/bbui": "2.2.12-alpha.16", + "@budibase/bbui": "2.2.12-alpha.32", "lodash": "^4.17.21", "svelte": "^3.46.2" } diff --git a/packages/frontend-core/src/api/tables.js b/packages/frontend-core/src/api/tables.js index 279d3ba6fb..00f0e9ff2e 100644 --- a/packages/frontend-core/src/api/tables.js +++ b/packages/frontend-core/src/api/tables.js @@ -64,32 +64,22 @@ export const buildTableEndpoints = API => ({ * @param tableId the table ID to import to * @param data the data import object */ - importTableData: async ({ tableId, data }) => { + importTableData: async ({ tableId, rows }) => { return await API.post({ url: `/api/tables/${tableId}/import`, body: { - dataImport: data, + rows, }, }) }, - - /** - * Validates a candidate CSV to be imported for a certain table. - * @param tableId the table ID to import to - * @param csvString the CSV contents as a string - * @param schema the proposed schema - */ - validateTableCSV: async ({ tableId, csvString, schema }) => { + csvToJson: async csvString => { return await API.post({ - url: "/api/tables/csv/validate", + url: "/api/convert/csvToJson", body: { csvString, - schema, - tableId, }, }) }, - /** * Gets a list o tables. */ @@ -120,4 +110,22 @@ export const buildTableEndpoints = API => ({ url: `/api/tables/${tableId}/${tableRev}`, }) }, + validateNewTableImport: async ({ rows, schema }) => { + return await API.post({ + url: "/api/tables/validateNewTableImport", + body: { + rows, + schema, + }, + }) + }, + validateExistingTableImport: async ({ rows, tableId }) => { + return await API.post({ + url: "/api/tables/validateExistingTableImport", + body: { + rows, + tableId, + }, + }) + }, }) diff --git a/packages/sdk/package.json b/packages/sdk/package.json index bff35735ad..ad4f5615f1 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/sdk", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "description": "Budibase Public API SDK", "author": "Budibase", "license": "MPL-2.0", diff --git a/packages/server/package.json b/packages/server/package.json index fe1ecdecc7..0ba9468623 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "description": "Budibase Web Server", "main": "src/index.ts", "repository": { @@ -43,11 +43,11 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/swagger-parser": "10.0.3", - "@budibase/backend-core": "2.2.12-alpha.16", - "@budibase/client": "2.2.12-alpha.16", - "@budibase/pro": "2.2.12-alpha.16", - "@budibase/string-templates": "2.2.12-alpha.16", - "@budibase/types": "2.2.12-alpha.16", + "@budibase/backend-core": "2.2.12-alpha.32", + "@budibase/client": "2.2.12-alpha.32", + "@budibase/pro": "2.2.12-alpha.32", + "@budibase/string-templates": "2.2.12-alpha.32", + "@budibase/types": "2.2.12-alpha.32", "@bull-board/api": "3.7.0", "@bull-board/koa": "3.9.4", "@elastic/elasticsearch": "7.10.0", @@ -77,7 +77,7 @@ "joi": "17.6.0", "js-yaml": "4.1.0", "jsonschema": "1.4.0", - "knex": "0.95.15", + "knex": "2.4.0", "koa": "2.13.4", "koa-body": "4.2.0", "koa-compress": "4.0.1", diff --git a/packages/server/src/api/controllers/row/ExternalRequest.ts b/packages/server/src/api/controllers/row/ExternalRequest.ts index 80ba4fd808..6085921423 100644 --- a/packages/server/src/api/controllers/row/ExternalRequest.ts +++ b/packages/server/src/api/controllers/row/ExternalRequest.ts @@ -681,6 +681,12 @@ export class ExternalRequest { config, table ) + //if the sort column is a formula, remove it + for (let sortColumn of Object.keys(sort || {})) { + if (table.schema[sortColumn]?.type === "formula") { + delete sort?.[sortColumn] + } + } filters = buildFilters(id, filters || {}, table) const relationships = this.buildRelationships(table) // clean up row on ingress using schema diff --git a/packages/server/src/api/controllers/row/internal.ts b/packages/server/src/api/controllers/row/internal.ts index 9bfdff24ea..963eb6b954 100644 --- a/packages/server/src/api/controllers/row/internal.ts +++ b/packages/server/src/api/controllers/row/internal.ts @@ -27,7 +27,7 @@ import { import { cloneDeep } from "lodash/fp" import { context, db as dbCore } from "@budibase/backend-core" import { finaliseRow, updateRelatedFormula } from "./staticFormula" -import * as exporters from "../view/exporters" +import { csv, json, jsonWithSchema, Format, isFormat } from "../view/exporters" import { apiFileReturn } from "../../../utilities/fileSystem" import { Ctx, @@ -412,14 +412,15 @@ export async function exportRows(ctx: Ctx) { rows = result } - let headers = Object.keys(rows[0]) - // @ts-ignore - const exporter = exporters[format] - const filename = `export.${format}` - - // send down the file - ctx.attachment(filename) - return apiFileReturn(exporter(headers, rows)) + if (format === Format.CSV) { + ctx.attachment("export.csv") + return apiFileReturn(csv(Object.keys(rows[0]), rows)) + } else if (format === Format.JSON) { + ctx.attachment("export.json") + return apiFileReturn(json(rows)) + } else { + throw "Format not recognised" + } } export async function fetchEnrichedRow(ctx: Ctx) { diff --git a/packages/server/src/api/controllers/table/external.ts b/packages/server/src/api/controllers/table/external.ts index 8bb8886479..dbe09f59c1 100644 --- a/packages/server/src/api/controllers/table/external.ts +++ b/packages/server/src/api/controllers/table/external.ts @@ -10,9 +10,9 @@ import { } from "./utils" import { FieldTypes, RelationshipTypes } from "../../../constants" import { makeExternalQuery } from "../../../integrations/base/query" -import * as csvParser from "../../../utilities/csvParser" import { handleRequest } from "../row/external" import { events, context } from "@budibase/backend-core" +import { parse, isRows, isSchema } from "../../../utilities/schema" import { Datasource, Table, @@ -197,7 +197,7 @@ export async function save(ctx: BBContext) { const table: TableRequest = ctx.request.body const renamed = table?._rename // can't do this right now - delete table.dataImport + delete table.rows const datasourceId = getDatasourceId(ctx.request.body)! // table doesn't exist already, note that it is created if (!table._id) { @@ -338,17 +338,17 @@ export async function destroy(ctx: BBContext) { export async function bulkImport(ctx: BBContext) { const table = await sdk.tables.getTable(ctx.params.tableId) - const { dataImport } = ctx.request.body - if (!dataImport || !dataImport.schema || !dataImport.csvString) { + const { rows }: { rows: unknown } = ctx.request.body + const schema: unknown = table.schema + + if (!rows || !isRows(rows) || !isSchema(schema)) { ctx.throw(400, "Provided data import information is invalid.") } - const rows = await csvParser.transform({ - ...dataImport, - existingTable: table, - }) + + const parsedRows = await parse(rows, schema) await handleRequest(Operation.BULK_CREATE, table._id!, { - rows, + rows: parsedRows, }) - await events.rows.imported(table, "csv", rows.length) + await events.rows.imported(table, parsedRows.length) return table } diff --git a/packages/server/src/api/controllers/table/index.ts b/packages/server/src/api/controllers/table/index.ts index 0df974adc4..aa6dfde536 100644 --- a/packages/server/src/api/controllers/table/index.ts +++ b/packages/server/src/api/controllers/table/index.ts @@ -1,11 +1,16 @@ import * as internal from "./internal" import * as external from "./external" -import * as csvParser from "../../../utilities/csvParser" +import { + validate as validateSchema, + isSchema, + isRows, +} from "../../../utilities/schema" import { isExternalTable, isSQL } from "../../../integrations/utils" import { getDatasourceParams } from "../../../db/utils" import { context, events } from "@budibase/backend-core" import { Table, BBContext } from "@budibase/types" import sdk from "../../../sdk" +import csv from "csvtojson" function pickApi({ tableId, table }: { tableId?: string; table?: Table }) { if (table && !tableId) { @@ -56,16 +61,16 @@ export async function find(ctx: BBContext) { export async function save(ctx: BBContext) { const appId = ctx.appId const table = ctx.request.body - const importFormat = - table.dataImport && table.dataImport.csvString ? "csv" : undefined + const isImport = table.rows + const savedTable = await pickApi({ table }).save(ctx) if (!table._id) { await events.table.created(savedTable) } else { await events.table.updated(savedTable) } - if (importFormat) { - await events.table.imported(savedTable, importFormat) + if (isImport) { + await events.table.imported(savedTable) } ctx.status = 200 ctx.message = `Table ${table.name} saved successfully.` @@ -96,19 +101,43 @@ export async function bulkImport(ctx: BBContext) { ctx.body = { message: `Bulk rows created.` } } -export async function validateCSVSchema(ctx: BBContext) { - // tableId being specified means its an import to an existing table - const { csvString, schema = {}, tableId } = ctx.request.body - let existingTable - if (tableId) { - existingTable = await sdk.tables.getTable(tableId) - } - let result: Record | undefined = await csvParser.parse( - csvString, - schema - ) - if (existingTable) { - result = csvParser.updateSchema({ schema: result, existingTable }) - } - ctx.body = { schema: result } +export async function csvToJson(ctx: BBContext) { + const { csvString } = ctx.request.body + + const result = await csv().fromString(csvString) + + ctx.status = 200 + ctx.body = result +} + +export async function validateNewTableImport(ctx: BBContext) { + const { rows, schema }: { rows: unknown; schema: unknown } = ctx.request.body + + if (isRows(rows) && isSchema(schema)) { + ctx.status = 200 + ctx.body = validateSchema(rows, schema) + } else { + ctx.status = 422 + } +} + +export async function validateExistingTableImport(ctx: BBContext) { + const { rows, tableId }: { rows: unknown; tableId: unknown } = + ctx.request.body + + let schema = null + if (tableId) { + const table = await sdk.tables.getTable(tableId) + schema = table.schema + } else { + ctx.status = 422 + return + } + + if (tableId && isRows(rows) && isSchema(schema)) { + ctx.status = 200 + ctx.body = validateSchema(rows, schema) + } else { + ctx.status = 422 + } } diff --git a/packages/server/src/api/controllers/table/internal.ts b/packages/server/src/api/controllers/table/internal.ts index 3229134bf0..628932bba1 100644 --- a/packages/server/src/api/controllers/table/internal.ts +++ b/packages/server/src/api/controllers/table/internal.ts @@ -35,7 +35,7 @@ function checkAutoColumns(table: Table, oldTable: Table) { export async function save(ctx: any) { const db = context.getAppDB() - const { dataImport, ...rest } = ctx.request.body + const { rows, ...rest } = ctx.request.body let tableToSave = { type: "table", _id: generateTableID(), @@ -61,7 +61,7 @@ export async function save(ctx: any) { const tableSaveFunctions = new TableSaveFunctions({ user: ctx.user, oldTable, - dataImport, + importRows: rows, }) tableToSave = await tableSaveFunctions.before(tableToSave) @@ -185,7 +185,7 @@ export async function destroy(ctx: any) { export async function bulkImport(ctx: any) { const table = await sdk.tables.getTable(ctx.params.tableId) - const { dataImport } = ctx.request.body - await handleDataImport(ctx.user, table, dataImport) + const { rows } = ctx.request.body + await handleDataImport(ctx.user, table, rows) return table } diff --git a/packages/server/src/api/controllers/table/utils.ts b/packages/server/src/api/controllers/table/utils.ts index b672561325..30e79f6ee4 100644 --- a/packages/server/src/api/controllers/table/utils.ts +++ b/packages/server/src/api/controllers/table/utils.ts @@ -1,4 +1,4 @@ -import { transform } from "../../../utilities/csvParser" +import { parse, isSchema, isRows } from "../../../utilities/schema" import { getRowParams, generateRowID, InternalTables } from "../../../db/utils" import { isEqual } from "lodash" import { AutoFieldSubTypes, FieldTypes } from "../../../constants" @@ -128,24 +128,23 @@ export function importToRows(data: any, table: any, user: any = {}) { return finalData } -export async function handleDataImport(user: any, table: any, dataImport: any) { - if (!dataImport || !dataImport.csvString) { +export async function handleDataImport(user: any, table: any, rows: any) { + const schema: unknown = table.schema + + if (!rows || !isRows(rows) || !isSchema(schema)) { return table } const db = context.getAppDB() - // Populate the table with rows imported from CSV in a bulk update - const data = await transform({ - ...dataImport, - existingTable: table, - }) + const data = parse(rows, schema) let finalData: any = importToRows(data, table, user) await quotas.addRows(finalData.length, () => db.bulkDocs(finalData), { tableId: table._id, }) - await events.rows.imported(table, "csv", finalData.length) + + await events.rows.imported(table, finalData.length) return table } @@ -210,14 +209,14 @@ class TableSaveFunctions { db: any user: any oldTable: any - dataImport: any + importRows: any rows: any - constructor({ user, oldTable, dataImport }: any) { + constructor({ user, oldTable, importRows }: any) { this.db = context.getAppDB() this.user = user this.oldTable = oldTable - this.dataImport = dataImport + this.importRows = importRows // any rows that need updated this.rows = [] } @@ -241,7 +240,7 @@ class TableSaveFunctions { // after saving async after(table: any) { table = await handleSearchIndexes(table) - table = await handleDataImport(this.user, table, this.dataImport) + table = await handleDataImport(this.user, table, this.importRows) return table } diff --git a/packages/server/src/api/controllers/user.ts b/packages/server/src/api/controllers/user.ts index df64ffc7d0..1ae1a68824 100644 --- a/packages/server/src/api/controllers/user.ts +++ b/packages/server/src/api/controllers/user.ts @@ -4,19 +4,21 @@ import { getGlobalUsers, getRawGlobalUser } from "../../utilities/global" import { getFullUser } from "../../utilities/users" import { context, - constants, roles as rolesCore, db as dbCore, } from "@budibase/backend-core" -import { BBContext, User } from "@budibase/types" +import { BBContext, Ctx, SyncUserRequest, User } from "@budibase/types" import sdk from "../../sdk" -export async function syncUser(ctx: BBContext) { +export async function syncUser(ctx: Ctx) { let deleting = false, user: User | any const userId = ctx.params.id + + const previousUser = ctx.request.body?.previousUser + try { - user = await getRawGlobalUser(userId) + user = (await getRawGlobalUser(userId)) as User } catch (err: any) { if (err && err.status === 404) { user = {} @@ -25,6 +27,11 @@ export async function syncUser(ctx: BBContext) { throw err } } + + let previousApps = previousUser + ? Object.keys(previousUser.roles).map(appId => appId) + : [] + const roles = deleting ? {} : user.roles // remove props which aren't useful to metadata delete user.password @@ -40,8 +47,9 @@ export async function syncUser(ctx: BBContext) { .filter(entry => entry[1] !== rolesCore.BUILTIN_ROLE_IDS.PUBLIC) .map(([appId]) => appId) } - for (let prodAppId of prodAppIds) { + for (let prodAppId of new Set([...prodAppIds, ...previousApps])) { const roleId = roles[prodAppId] + const deleteFromApp = !roleId const devAppId = dbCore.getDevelopmentAppID(prodAppId) for (let appId of [prodAppId, devAppId]) { if (!(await dbCore.dbExists(appId))) { @@ -54,24 +62,24 @@ export async function syncUser(ctx: BBContext) { try { metadata = await db.get(metadataId) } catch (err) { - if (deleting) { + if (deleteFromApp) { return } metadata = { tableId: InternalTables.USER_METADATA, } } + + if (deleteFromApp) { + await db.remove(metadata) + return + } + // assign the roleId for the metadata doc if (roleId) { metadata.roleId = roleId } - let combined = !deleting - ? sdk.users.combineMetadataAndUser(user, metadata) - : { - ...metadata, - status: constants.UserStatus.INACTIVE, - metadata: rolesCore.BUILTIN_ROLE_IDS.PUBLIC, - } + let combined = sdk.users.combineMetadataAndUser(user, metadata) // if its null then there was no updates required if (combined) { await db.put(combined) diff --git a/packages/server/src/api/controllers/view/exporters.ts b/packages/server/src/api/controllers/view/exporters.ts index eec6e69641..4d927bca27 100644 --- a/packages/server/src/api/controllers/view/exporters.ts +++ b/packages/server/src/api/controllers/view/exporters.ts @@ -1,4 +1,4 @@ -import { Row } from "@budibase/types" +import { Row, TableSchema } from "@budibase/types" export function csv(headers: string[], rows: Row[]) { let csv = headers.map(key => `"${key}"`).join(",") @@ -18,11 +18,26 @@ export function csv(headers: string[], rows: Row[]) { return csv } -export function json(headers: string[], rows: Row[]) { +export function json(rows: Row[]) { return JSON.stringify(rows, undefined, 2) } -export const ExportFormats = { - CSV: "csv", - JSON: "json", +export function jsonWithSchema(schema: TableSchema, rows: Row[]) { + const newSchema: TableSchema = {} + Object.values(schema).forEach(column => { + if (!column.autocolumn) { + newSchema[column.name] = column + } + }) + return JSON.stringify({ schema: newSchema, rows }, undefined, 2) +} + +export enum Format { + CSV = "csv", + JSON = "json", + JSON_WITH_SCHEMA = "jsonWithSchema", +} + +export function isFormat(format: any): format is Format { + return Object.values(Format).includes(format as Format) } diff --git a/packages/server/src/api/controllers/view/index.ts b/packages/server/src/api/controllers/view/index.ts index 932823d172..7bb803d035 100644 --- a/packages/server/src/api/controllers/view/index.ts +++ b/packages/server/src/api/controllers/view/index.ts @@ -1,6 +1,6 @@ import viewTemplate from "./viewBuilder" import { apiFileReturn } from "../../../utilities/fileSystem" -import * as exporters from "./exporters" +import { csv, json, jsonWithSchema, Format, isFormat } from "./exporters" import { deleteView, getView, getViews, saveView } from "./utils" import { fetchView } from "../row" import { FieldTypes } from "../../../constants" @@ -127,9 +127,13 @@ export async function exportView(ctx: BBContext) { const viewName = decodeURIComponent(ctx.query.view as string) const view = await getView(viewName) - const format = ctx.query.format as string - if (!format || !Object.values(exporters.ExportFormats).includes(format)) { - ctx.throw(400, "Format must be specified, either csv or json") + const format = ctx.query.format as unknown + + if (!isFormat(format)) { + ctx.throw( + 400, + "Format must be specified, either csv, json or jsonWithSchema" + ) } if (view) { @@ -171,7 +175,7 @@ export async function exportView(ctx: BBContext) { }) // make sure no "undefined" entries appear in the CSV - if (format === exporters.ExportFormats.CSV) { + if (format === Format.CSV) { const schemaKeys = Object.keys(schema) for (let key of schemaKeys) { for (let row of rows) { @@ -182,13 +186,18 @@ export async function exportView(ctx: BBContext) { } } - // Export part - let headers = Object.keys(schema) - const exporter = format === "csv" ? exporters.csv : exporters.json - const filename = `${viewName}.${format}` - // send down the file - ctx.attachment(filename) - ctx.body = apiFileReturn(exporter(headers, rows)) + if (format === Format.CSV) { + ctx.attachment(`${viewName}.csv`) + ctx.body = apiFileReturn(csv(Object.keys(schema), rows)) + } else if (format === Format.JSON) { + ctx.attachment(`${viewName}.json`) + ctx.body = apiFileReturn(json(rows)) + } else if (format === Format.JSON_WITH_SCHEMA) { + ctx.attachment(`${viewName}.json`) + ctx.body = apiFileReturn(jsonWithSchema(schema, rows)) + } else { + throw "Format not recognised" + } if (viewName.startsWith(DocumentType.TABLE)) { await events.table.exported(table, format as TableExportFormat) diff --git a/packages/server/src/api/routes/table.ts b/packages/server/src/api/routes/table.ts index 23b1f4e988..7ffa5acb3e 100644 --- a/packages/server/src/api/routes/table.ts +++ b/packages/server/src/api/routes/table.ts @@ -67,10 +67,7 @@ router * structure, and the "updated", new column name should also be supplied. The schema should also be updated, this field * lets the server know that a field hasn't just been deleted, that the data has moved to a new name, this will fix * the rows in the table. This functionality is only available for internal tables. - * @apiParam (Body) {object} [dataImport] When creating an internal table it can be built from a CSV, by using the - * CSV validation endpoint. Send the CSV data to the validation endpoint, then put the results of that call - * into this property, along with the CSV and a table/rows will be built from it. This is not supported when updating - * or for external tables. + * @apiParam (Body) {object[]} [rows] When creating a table using a compatible data source, an array of objects to be imported into the new table can be provided. * * @apiParamExample {json} Example: * { @@ -99,15 +96,7 @@ router * "old": "columnName", * "updated": "newColumnName", * }, - * "dataImport": { - * "csvString": "column\nvalue", - * "primaryDisplay": "column", - * "schema": { - * "column": { - * "type": "string" - * } - * } - * } + * "rows": [] * } * * @apiSuccess {object} table The response body will contain the table structure after being cleaned up and @@ -121,30 +110,20 @@ router tableValidator(), tableController.save ) - /** - * @api {post} /api/tables/csv/validate Validate a CSV for a table - * @apiName Validate a CSV for a table - * @apiGroup tables - * @apiPermission builder - * @apiDescription When creating a new table, or importing a CSV to an existing table the CSV must be validated and - * converted into a Budibase schema; this endpoint does this. - * - * @apiParam (Body) {string} csvString The CSV which is to be validated as a string. - * @apiParam (Body) {object} [schema] When a CSV has been validated it is possible to re-validate after changing the - * type of a field, by default everything will be strings as there is no way to infer types. The returned schema can - * be updated and then returned to the endpoint to re-validate and check if the type will work for the CSV, e.g. - * using a number instead of strings. - * @apiParam (Body) {string} [tableId] If importing data to an existing table this will pull the current table and - * remove any fields from the CSV schema which do not exist on the table/don't match the type of the table. When - * importing a CSV to an existing table only fields that are present on the table can be imported. - * - * @apiSuccess {object} schema The response body will contain a "schema" object that represents the schema found for - * the CSV - this will be in the same format used for table schema.s - */ .post( - "/api/tables/csv/validate", + "/api/convert/csvToJson", authorized(BUILDER), - tableController.validateCSVSchema + tableController.csvToJson + ) + .post( + "/api/tables/validateNewTableImport", + authorized(BUILDER), + tableController.validateNewTableImport + ) + .post( + "/api/tables/validateExistingTableImport", + authorized(BUILDER), + tableController.validateExistingTableImport ) /** * @api {post} /api/tables/:tableId/:revId Delete a table @@ -177,9 +156,7 @@ router * * @apiParam {string} tableId The ID of the table which the data should be imported to. * - * @apiParam (Body) {object} dataImport This is the same as the structure used when creating an internal table with - * a CSV, it will have the "schema" returned from the CSV validation endpoint and the "csvString" which is to be - * turned into rows. + * @apiParam (Body) {object[]} rows An array of objects representing the rows to be imported, key-value pairs not matching the table schema will be ignored. * * @apiSuccess {string} message A message stating that the data was imported successfully. */ diff --git a/packages/server/src/api/routes/tests/misc.spec.js b/packages/server/src/api/routes/tests/misc.spec.js index 21dba8f085..2451953df1 100644 --- a/packages/server/src/api/routes/tests/misc.spec.js +++ b/packages/server/src/api/routes/tests/misc.spec.js @@ -42,7 +42,7 @@ describe("run misc tests", () => { }) describe("test table utilities", () => { - it("should be able to import a CSV", async () => { + it("should be able to import data", async () => { return config.doInContext(null, async () => { const table = await config.createTable({ name: "table", @@ -75,17 +75,11 @@ describe("run misc tests", () => { }, }, }) - const dataImport = { - csvString: "a,b,c,d\n1,2,3,4", - schema: {}, - } - for (let col of ["a", "b", "c", "d"]) { - dataImport.schema[col] = { type: "string" } - } + await tableUtils.handleDataImport( { userId: "test" }, table, - dataImport + [{ a: '1', b: '2', c: '3', d: '4'}] ) const rows = await config.getRows() expect(rows[0].a).toEqual("1") @@ -94,4 +88,4 @@ describe("run misc tests", () => { }) }) }) -}) \ No newline at end of file +}) diff --git a/packages/server/src/api/routes/tests/table.spec.js b/packages/server/src/api/routes/tests/table.spec.js index b4fd354b9d..521b64e0c0 100644 --- a/packages/server/src/api/routes/tests/table.spec.js +++ b/packages/server/src/api/routes/tests/table.spec.js @@ -43,21 +43,18 @@ describe("/tables", () => { expect(events.table.created).toBeCalledWith(res.body) }) - it("creates a table via data import CSV", async () => { + it("creates a table via data import", async () => { const table = basicTable() - table.dataImport = { - csvString: "\"name\",\"description\"\n\"test-name\",\"test-desc\"", - } - table.dataImport.schema = table.schema + table.rows = [{ name: 'test-name', description: 'test-desc' }] const res = await createTable(table) expect(events.table.created).toBeCalledTimes(1) expect(events.table.created).toBeCalledWith(res.body) expect(events.table.imported).toBeCalledTimes(1) - expect(events.table.imported).toBeCalledWith(res.body, "csv") + expect(events.table.imported).toBeCalledWith(res.body) expect(events.rows.imported).toBeCalledTimes(1) - expect(events.rows.imported).toBeCalledWith(res.body, "csv", 1) + expect(events.rows.imported).toBeCalledWith(res.body, 1) }) it("should apply authorization to endpoint", async () => { @@ -155,11 +152,10 @@ describe("/tables", () => { it("imports rows successfully", async () => { const table = await config.createTable() const importRequest = { - dataImport: { - csvString: "\"name\",\"description\"\n\"test-name\",\"test-desc\"", - schema: table.schema - } + schema: table.schema, + rows: [{ name: 'test-name', description: 'test-desc' }] } + jest.clearAllMocks() await request @@ -171,7 +167,7 @@ describe("/tables", () => { expect(events.table.created).not.toHaveBeenCalled() expect(events.rows.imported).toBeCalledTimes(1) - expect(events.rows.imported).toBeCalledWith(table, "csv", 1) + expect(events.rows.imported).toBeCalledWith(table, 1) }) }) @@ -206,24 +202,6 @@ describe("/tables", () => { }) }) - describe("validate csv", () => { - it("should be able to validate a CSV layout", async () => { - const res = await request - .post(`/api/tables/csv/validate`) - .send({ - csvString: "a,b,c,d\n1,2,3,4" - }) - .set(config.defaultHeaders()) - .expect('Content-Type', /json/) - .expect(200) - expect(res.body.schema).toBeDefined() - expect(res.body.schema.a).toEqual({ - type: "string", - success: true, - }) - }) - }) - describe("indexing", () => { it("should be able to create a table with indexes", async () => { await context.doInAppContext(appId, async () => { diff --git a/packages/server/src/api/routes/tests/user.spec.js b/packages/server/src/api/routes/tests/user.spec.js index 56f1923cb0..8f4f44d4c5 100644 --- a/packages/server/src/api/routes/tests/user.spec.js +++ b/packages/server/src/api/routes/tests/user.spec.js @@ -171,9 +171,28 @@ describe("/users", () => { .expect("Content-Type", /json/) expect(res.body.message).toEqual('User synced.') }) + + + it("should sync the user when a previous user is specified", async () => { + const app1 = await config.createApp('App 1') + const app2 = await config.createApp('App 2') + + let user = await config.createUser( + undefined, + undefined, + undefined, + undefined, + false, + true, + { [app1.appId]: 'ADMIN' }) + let res = await request + .post(`/api/users/metadata/sync/${user._id}`) + .set(config.defaultHeaders()) + .send({ previousUser: { ...user, roles: { ...user.roles, [app2.appId]: 'BASIC' } } }) + .expect(200) + .expect("Content-Type", /json/) + + expect(res.body.message).toEqual('User synced.') + }) }) - - - - }) diff --git a/packages/server/src/api/routes/utils/validators.ts b/packages/server/src/api/routes/utils/validators.ts index b6def14d70..4da680edd1 100644 --- a/packages/server/src/api/routes/utils/validators.ts +++ b/packages/server/src/api/routes/utils/validators.ts @@ -18,7 +18,7 @@ export function tableValidator() { schema: Joi.object().required(), name: Joi.string().required(), views: Joi.object(), - dataImport: Joi.object(), + rows: Joi.array(), }).unknown(true)) } diff --git a/packages/server/src/middleware/currentapp.ts b/packages/server/src/middleware/currentapp.ts index 2cd11aa438..593e96adcb 100644 --- a/packages/server/src/middleware/currentapp.ts +++ b/packages/server/src/middleware/currentapp.ts @@ -25,6 +25,7 @@ export default async (ctx: BBContext, next: any) => { if (!appCookie && !requestAppId) { return next() } + // check the app exists referenced in cookie if (appCookie) { const appId = appCookie.appId @@ -51,7 +52,7 @@ export default async (ctx: BBContext, next: any) => { let appId: string | undefined, roleId = roles.BUILTIN_ROLE_IDS.PUBLIC - if (!ctx.user) { + if (!ctx.user?._id) { // not logged in, try to set a cookie for public apps appId = requestAppId } else if (requestAppId != null) { @@ -96,7 +97,7 @@ export default async (ctx: BBContext, next: any) => { // need to judge this only based on the request app ID, if ( env.MULTI_TENANCY && - ctx.user && + ctx.user?._id && requestAppId && !tenancy.isUserInAppTenant(requestAppId, ctx.user) ) { diff --git a/packages/server/src/utilities/csvParser.ts b/packages/server/src/utilities/csvParser.ts deleted file mode 100644 index 0c138abc3e..0000000000 --- a/packages/server/src/utilities/csvParser.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { FieldSchema, Table } from "@budibase/types" -import csv from "csvtojson" -import { FieldTypes } from "../constants" - -type CsvParseOpts = { - schema?: { [key: string]: any } - existingTable: Table - csvString?: string -} - -const VALIDATORS: any = { - [FieldTypes.STRING]: () => true, - [FieldTypes.OPTIONS]: () => true, - [FieldTypes.BARCODEQR]: () => true, - [FieldTypes.NUMBER]: (attribute?: string) => { - // allow not to be present - if (!attribute) { - return true - } - return !isNaN(Number(attribute)) - }, - [FieldTypes.DATETIME]: (attribute?: string) => { - // allow not to be present - if (!attribute) { - return true - } - return !isNaN(new Date(attribute).getTime()) - }, -} - -const PARSERS: any = { - [FieldTypes.NUMBER]: (attribute?: string) => { - if (!attribute) { - return attribute - } - return Number(attribute) - }, - [FieldTypes.DATETIME]: (attribute?: string) => { - if (!attribute) { - return attribute - } - return new Date(attribute).toISOString() - }, -} - -export function parse(csvString: string, parsers: any): Record { - const result = csv().fromString(csvString) - - const schema: Record = {} - - return new Promise((resolve, reject) => { - result.on("header", headers => { - for (let header of headers) { - schema[header] = { - type: parsers[header] ? parsers[header].type : "string", - success: true, - } - } - }) - result.subscribe(row => { - // For each CSV row parse all the columns that need parsed - for (let key of Object.keys(parsers)) { - if (!schema[key] || schema[key].success) { - // get the validator for the column type - const validator = VALIDATORS[parsers[key].type] - - try { - // allow null/undefined values - schema[key].success = !row[key] || validator(row[key]) - } catch (err) { - schema[key].success = false - } - } - } - }) - result.on("done", error => { - if (error) { - console.error(error) - reject(error) - } - - resolve(schema) - }) - }) -} - -export function updateSchema({ - schema, - existingTable, -}: { - schema?: Record - existingTable?: Table -}) { - if (!schema) { - return schema - } - const finalSchema: Record = {} - const schemaKeyMap: Record = {} - Object.keys(schema).forEach(key => (schemaKeyMap[key.toLowerCase()] = key)) - for (let [key, field] of Object.entries(existingTable?.schema || {})) { - const lcKey = key.toLowerCase() - const foundKey: string = schemaKeyMap[lcKey] - if (foundKey) { - finalSchema[key] = schema[foundKey] - finalSchema[key].type = field.type - } - } - return finalSchema -} - -export async function transform({ - schema, - csvString, - existingTable, -}: CsvParseOpts) { - if (!schema || !csvString) { - throw new Error("Unable to transform CSV without schema") - } - const colParser: any = {} - - // make sure the table has all the columns required for import - if (existingTable) { - schema = updateSchema({ schema, existingTable }) - } - - for (let [key, field] of Object.entries(schema || {})) { - // don't import data to auto columns - if (!field.autocolumn) { - colParser[key] = PARSERS[field.type] || field.type - } - } - - try { - const data = await csv({ colParser }).fromString(csvString) - const schemaKeyMap: any = {} - Object.keys(schema || {}).forEach( - key => (schemaKeyMap[key.toLowerCase()] = key) - ) - for (let element of data) { - if (!data) { - continue - } - for (let key of Object.keys(element)) { - const mappedKey = schemaKeyMap[key.toLowerCase()] - // isn't a column in the table, remove it - if (mappedKey == null) { - delete element[key] - } - // casing is different, fix it in row - else if (key !== mappedKey) { - element[mappedKey] = element[key] - delete element[key] - } - } - } - return data - } catch (err) { - console.error(`Error transforming CSV to JSON for data import`, err) - throw err - } -} diff --git a/packages/server/src/utilities/schema.ts b/packages/server/src/utilities/schema.ts new file mode 100644 index 0000000000..f3d98d35c9 --- /dev/null +++ b/packages/server/src/utilities/schema.ts @@ -0,0 +1,141 @@ +import { FieldTypes } from "../constants" + +interface SchemaColumn { + readonly name: string + readonly type: FieldTypes + readonly autocolumn?: boolean +} + +interface Schema { + readonly [index: string]: SchemaColumn +} + +interface Row { + [index: string]: any +} + +type Rows = Array + +interface SchemaValidation { + [index: string]: boolean +} + +interface ValidationResults { + schemaValidation: SchemaValidation + allValid: boolean + invalidColumns: Array +} + +const PARSERS: any = { + [FieldTypes.NUMBER]: (attribute?: string) => { + if (!attribute) { + return attribute + } + return Number(attribute) + }, + [FieldTypes.DATETIME]: (attribute?: string) => { + if (!attribute) { + return attribute + } + return new Date(attribute).toISOString() + }, +} + +export function isSchema(schema: any): schema is Schema { + return ( + typeof schema === "object" && + Object.values(schema).every(rawColumn => { + const column = rawColumn as SchemaColumn + + return ( + column !== null && + typeof column === "object" && + typeof column.type === "string" && + Object.values(FieldTypes).includes(column.type as FieldTypes) + ) + }) + ) +} + +export function isRows(rows: any): rows is Rows { + return Array.isArray(rows) && rows.every(row => typeof row === "object") +} + +export function validate(rows: Rows, schema: Schema): ValidationResults { + const results: ValidationResults = { + schemaValidation: {}, + allValid: false, + invalidColumns: [], + } + + rows.forEach(row => { + Object.entries(row).forEach(([columnName, columnData]) => { + const columnType = schema[columnName]?.type + const isAutoColumn = schema[columnName]?.autocolumn + + // If the columnType is not a string, then it's not present in the schema, and should be added to the invalid columns array + if (typeof columnType !== "string") { + results.invalidColumns.push(columnName) + } else if ( + // If there's no data for this field don't bother with further checks + // If the field is already marked as invalid there's no need for further checks + results.schemaValidation[columnName] === false || + columnData == null || + isAutoColumn + ) { + return + } else if ( + columnType === FieldTypes.NUMBER && + isNaN(Number(columnData)) + ) { + // If provided must be a valid number + results.schemaValidation[columnName] = false + } else if ( + // If provided must be a valid date + columnType === FieldTypes.DATETIME && + isNaN(new Date(columnData).getTime()) + ) { + results.schemaValidation[columnName] = false + } else { + results.schemaValidation[columnName] = true + } + }) + }) + + results.allValid = + Object.values(results.schemaValidation).length > 0 && + Object.values(results.schemaValidation).every(column => column) + + // Select unique values + results.invalidColumns = [...new Set(results.invalidColumns)] + return results +} + +export function parse(rows: Rows, schema: Schema): Rows { + return rows.map(row => { + const parsedRow: Row = {} + + Object.entries(row).forEach(([columnName, columnData]) => { + if (!(columnName in schema) || schema[columnName]?.autocolumn) { + // Objects can be present in the row data but not in the schema, so make sure we don't proceed in such a case + return + } + + const columnType = schema[columnName].type + + if (columnType === FieldTypes.NUMBER) { + // If provided must be a valid number + parsedRow[columnName] = columnData ? Number(columnData) : columnData + } else if (columnType === FieldTypes.DATETIME) { + // If provided must be a valid date + parsedRow[columnName] = columnData + ? new Date(columnData).toISOString() + : columnData + } else { + parsedRow[columnName] = columnData + } + }) + + return parsedRow + }) +} diff --git a/packages/server/src/utilities/tests/__snapshots__/csvParser.spec.js.snap b/packages/server/src/utilities/tests/__snapshots__/csvParser.spec.js.snap deleted file mode 100644 index 07f73ba2ef..0000000000 --- a/packages/server/src/utilities/tests/__snapshots__/csvParser.spec.js.snap +++ /dev/null @@ -1,15 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`CSV Parser transformation transforms a CSV file into JSON 1`] = ` -Array [ - Object { - "Age": 4324, - }, - Object { - "Age": 34, - }, - Object { - "Age": 23423, - }, -] -`; diff --git a/packages/server/src/utilities/tests/csvParser.spec.js b/packages/server/src/utilities/tests/csvParser.spec.js deleted file mode 100644 index 2a997e6f3a..0000000000 --- a/packages/server/src/utilities/tests/csvParser.spec.js +++ /dev/null @@ -1,112 +0,0 @@ -const { readFileSync } = require("../fileSystem") -const csvParser = require("../csvParser") - -const CSV_PATH = __dirname + "/test.csv" - -const SCHEMAS = { - VALID: { - Age: { - type: "number", - }, - }, - INVALID: { - Address: { - type: "number", - }, - Age: { - type: "number", - }, - }, - IGNORE: { - Address: { - type: "omit", - }, - Age: { - type: "omit", - }, - Name: { - type: "string", - }, - }, - BROKEN: { - Address: { - type: "datetime", - }, - }, -} - -describe("CSV Parser", () => { - const csvString = readFileSync(CSV_PATH, "utf8") - - describe("parsing", () => { - it("returns status and types for a valid CSV transformation", async () => { - expect(await csvParser.parse(csvString, SCHEMAS.VALID)).toEqual({ - Address: { - success: true, - type: "string", - }, - Age: { - success: true, - type: "number", - }, - Name: { - success: true, - type: "string", - }, - }) - }) - - it("returns status and types for an invalid CSV transformation", async () => { - expect(await csvParser.parse(csvString, SCHEMAS.INVALID)).toEqual({ - Address: { - success: false, - type: "number", - }, - Age: { - success: true, - type: "number", - }, - Name: { - success: true, - type: "string", - }, - }) - }) - }) - - describe("transformation", () => { - it("transforms a CSV file into JSON", async () => { - expect( - await csvParser.transform({ - schema: SCHEMAS.VALID, - csvString, - }) - ).toMatchSnapshot() - }) - - it("transforms a CSV file into JSON ignoring certain fields", async () => { - expect( - await csvParser.transform({ - schema: SCHEMAS.IGNORE, - csvString, - }) - ).toEqual([ - { - Name: "Bertå", - }, - { - Name: "Ernie", - }, - { - Name: "Big Bird", - }, - ]) - }) - - it("throws an error on invalid schema", async () => { - await expect( - csvParser.transform({ schema: SCHEMAS.BROKEN, csvString }) - ).rejects.toThrow() - }) - }) -}) diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index 6720d6ce58..0514fed5d6 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -1273,13 +1273,13 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@2.2.12-alpha.16": - version "2.2.12-alpha.16" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.16.tgz#9ebfa7308fc97b34d6a076e4300fbcf996160d66" - integrity sha512-rHMryIOb71U7W5jZtn39vuBI7xSZ6XA4l6P7lc2bBT1lI10G/zQRoQWjsWaUWo+RVBQ5zki3Ok05tFS9Yx/7fA== +"@budibase/backend-core@2.2.12-alpha.32": + version "2.2.12-alpha.32" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.32.tgz#5d53fdde38e80fdade73c59cb81623041984a5fc" + integrity sha512-XoaqGrttx01wlblI0+O23R9uS5FTMgK07juY6mUkdReCK46IvmG7FFnuYu0euKVRbhChSf5X8S+fvKIAEi1ZFw== dependencies: "@budibase/nano" "10.1.1" - "@budibase/types" "2.2.12-alpha.16" + "@budibase/types" "2.2.12-alpha.32" "@shopify/jest-koa-mocks" "5.0.1" "@techpass/passport-openidconnect" "0.3.2" aws-cloudfront-sign "2.2.0" @@ -1374,13 +1374,13 @@ qs "^6.11.0" tough-cookie "^4.1.2" -"@budibase/pro@2.2.12-alpha.16": - version "2.2.12-alpha.16" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.16.tgz#db5a345b072e725765cd01edcad4a930ae875eba" - integrity sha512-GBXdOQMIbxU0TGgGQ4+npNGtuFvanNVFrZBqwB7+3x6rIku313WkbgJJji5uemtU6B8XFh/QqS6AA0R0PS2Kmg== +"@budibase/pro@2.2.12-alpha.32": + version "2.2.12-alpha.32" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.32.tgz#4f35b0ada97458cc69ee41ebb40d56b361518065" + integrity sha512-Kn/IahgIb9Ydzmasv4Bhlh3rvyAC2tBVSoI33OZ/6PKF0vPYJNJkFds3iGELNV7SyWoLbVWb2z5SQ4SSaOYsJw== dependencies: - "@budibase/backend-core" "2.2.12-alpha.16" - "@budibase/types" "2.2.12-alpha.16" + "@budibase/backend-core" "2.2.12-alpha.32" + "@budibase/types" "2.2.12-alpha.32" "@koa/router" "8.0.8" bull "4.10.1" joi "17.6.0" @@ -1405,10 +1405,10 @@ svelte-apexcharts "^1.0.2" svelte-flatpickr "^3.1.0" -"@budibase/types@2.2.12-alpha.16": - version "2.2.12-alpha.16" - resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.16.tgz#6fb42d4be88fbd8054a0a3264cf9c4b4a7248893" - integrity sha512-pXn/r3tA0A30f2dJVJfzldMGXAEhpObBfqbONn8AStiD6Qm8Hu9H6aFaCPqS8DDaWBuwY/tMqSry2E0saRaSwg== +"@budibase/types@2.2.12-alpha.32": + version "2.2.12-alpha.32" + resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.32.tgz#71af8e8cff66acbfd65aa87e66183dd95d76ce6f" + integrity sha512-ZZwmO+0ORGEFbU/EQvtnjo1VonUbBdsciFkTOiopVupU5iNY2oCKgbYTQiTZZisQrRuiKdPV6P17uV+YTkjQSQ== "@bull-board/api@3.7.0": version "3.7.0" @@ -5301,15 +5301,10 @@ color@^3.1.3: color-convert "^1.9.3" color-string "^1.6.0" -colorette@2.0.16: - version "2.0.16" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" - integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== - -colorette@^2.0.14: - version "2.0.17" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.17.tgz#5dd4c0d15e2984b7433cb4a9f2ead45063b80c47" - integrity sha512-hJo+3Bkn0NCHybn9Tu35fIeoOKGOk5OCC32y4Hz2It+qlCO2Q3DeQ1hRn/tDDMQKRYUEzqsl7jbF6dYKjlE60g== +colorette@2.0.19, colorette@^2.0.14: + version "2.0.19" + 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" @@ -5346,7 +5341,7 @@ commander@^5.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== -commander@^7.0.0, commander@^7.1.0: +commander@^7.0.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== @@ -5356,6 +5351,11 @@ commander@^8.3.0: resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +commander@^9.1.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + commoner@^0.10.1: version "0.10.8" resolved "https://registry.yarnpkg.com/commoner/-/commoner-0.10.8.tgz#34fc3672cd24393e8bb47e70caa0293811f4f2c5" @@ -5659,20 +5659,13 @@ dayjs@^1.10.4, dayjs@^1.10.5: resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.3.tgz#4754eb694a624057b9ad2224b67b15d552589258" integrity sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A== -debug@4, debug@^4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: +debug@4, debug@4.3.4, debug@^4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== - dependencies: - ms "2.1.2" - debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -7441,10 +7434,10 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA== -getopts@2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.5.tgz#67a0fe471cacb9c687d817cab6450b96dde8313b" - integrity sha512-9jb7AW5p3in+IiJWhQiZmmwkpLaR/ccTWdWQCtZM66HJcHHLegowh4q4tSD7gouUyeNvFWRavfK9GXosQHDpFA== +getopts@2.3.0: + version "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" @@ -9825,23 +9818,24 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -knex@0.95.15: - version "0.95.15" - resolved "https://registry.yarnpkg.com/knex/-/knex-0.95.15.tgz#39d7e7110a6e2ad7de5d673d2dea94143015e0e7" - integrity sha512-Loq6WgHaWlmL2bfZGWPsy4l8xw4pOE+tmLGkPG0auBppxpI0UcK+GYCycJcqz9W54f2LiGewkCVLBm3Wq4ur/w== +knex@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/knex/-/knex-2.4.0.tgz#7d33cc36f320cdac98741010544b4c6a98b8b19e" + integrity sha512-i0GWwqYp1Hs2yvc2rlDO6nzzkLhwdyOZKRdsMTB8ZxOs2IXQyL5rBjSbS1krowCh6V65T4X9CJaKtuIfkaPGSA== dependencies: - colorette "2.0.16" - commander "^7.1.0" - debug "4.3.2" + colorette "2.0.19" + commander "^9.1.0" + debug "4.3.4" escalade "^3.1.1" esm "^3.2.25" - getopts "2.2.5" + get-package-type "^0.1.0" + getopts "2.3.0" interpret "^2.2.0" lodash "^4.17.21" pg-connection-string "2.5.0" - rechoir "0.7.0" + rechoir "^0.8.0" resolve-from "^5.0.0" - tarn "^3.0.1" + tarn "^3.0.2" tildify "2.0.0" koa-body@4.2.0: @@ -12561,13 +12555,6 @@ recast@^0.11.17: private "~0.1.5" source-map "~0.5.0" -rechoir@0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.0.tgz#32650fd52c21ab252aa5d65b19310441c7e03aca" - integrity sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q== - dependencies: - resolve "^1.9.0" - rechoir@^0.7.0: version "0.7.1" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" @@ -12575,6 +12562,13 @@ rechoir@^0.7.0: dependencies: resolve "^1.9.0" +rechoir@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.8.0.tgz#49f866e0d32146142da3ad8f0eff352b3215ff22" + integrity sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ== + dependencies: + resolve "^1.20.0" + redis-commands@1.7.0, redis-commands@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89" @@ -14051,7 +14045,7 @@ tarn@^1.1.5: resolved "https://registry.yarnpkg.com/tarn/-/tarn-1.1.5.tgz#7be88622e951738b9fa3fb77477309242cdddc2d" integrity sha512-PMtJ3HCLAZeedWjJPgGnCvcphbCOMbtZpjKgLq3qM5Qq9aQud+XHrL0WlrlgnTyS8U+jrjGbEXprFcQrxPy52g== -tarn@^3.0.1: +tarn@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.2.tgz#73b6140fbb881b71559c4f8bfde3d9a4b3d27693" integrity sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ== diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json index b7ee8e54d9..b523f2cd0e 100644 --- a/packages/string-templates/package.json +++ b/packages/string-templates/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/string-templates", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "description": "Handlebars wrapper for Budibase templating.", "main": "src/index.cjs", "module": "dist/bundle.mjs", diff --git a/packages/types/package.json b/packages/types/package.json index d46658ab1f..8a27829c47 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/types", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "description": "Budibase types", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/types/src/api/web/user.ts b/packages/types/src/api/web/user.ts index 0ebe4ccce8..6acaf6912d 100644 --- a/packages/types/src/api/web/user.ts +++ b/packages/types/src/api/web/user.ts @@ -57,3 +57,7 @@ export interface CreateAdminUserRequest { password: string tenantId: string } + +export interface SyncUserRequest { + previousUser?: User +} diff --git a/packages/types/src/documents/app/table.ts b/packages/types/src/documents/app/table.ts index 23d77c5ad5..8223ce29c6 100644 --- a/packages/types/src/documents/app/table.ts +++ b/packages/types/src/documents/app/table.ts @@ -69,7 +69,7 @@ export interface Table extends Document { constrained?: string[] sql?: boolean indexes?: { [key: string]: any } - dataImport?: { [key: string]: any } + rows?: { [key: string]: any } } export interface TableRequest extends Table { diff --git a/packages/types/src/documents/global/user.ts b/packages/types/src/documents/global/user.ts index 2f2f13d0ca..aef36c3469 100644 --- a/packages/types/src/documents/global/user.ts +++ b/packages/types/src/documents/global/user.ts @@ -70,3 +70,7 @@ export interface AdminUser extends User { global: boolean } } + +export function isUser(user: object): user is User { + return !!(user as User).roles +} diff --git a/packages/types/src/sdk/events/event.ts b/packages/types/src/sdk/events/event.ts index e623ec59aa..0f668f0712 100644 --- a/packages/types/src/sdk/events/event.ts +++ b/packages/types/src/sdk/events/event.ts @@ -188,6 +188,4 @@ export interface BaseEvent { hosting?: Hosting } -export type RowImportFormat = "csv" export type TableExportFormat = "json" | "csv" -export type TableImportFormat = "csv" diff --git a/packages/types/src/sdk/events/rows.ts b/packages/types/src/sdk/events/rows.ts index 871658e6c9..c5736fec4e 100644 --- a/packages/types/src/sdk/events/rows.ts +++ b/packages/types/src/sdk/events/rows.ts @@ -1,8 +1,7 @@ -import { BaseEvent, RowImportFormat } from "./event" +import { BaseEvent } from "./event" export interface RowsImportedEvent extends BaseEvent { tableId: string - format: RowImportFormat count: number } diff --git a/packages/types/src/sdk/events/table.ts b/packages/types/src/sdk/events/table.ts index 2f9ca1c93e..da3c7edf47 100644 --- a/packages/types/src/sdk/events/table.ts +++ b/packages/types/src/sdk/events/table.ts @@ -1,4 +1,4 @@ -import { BaseEvent, TableExportFormat, TableImportFormat } from "./event" +import { BaseEvent, TableExportFormat } from "./event" export interface TableCreatedEvent extends BaseEvent { tableId: string @@ -19,5 +19,4 @@ export interface TableExportedEvent extends BaseEvent { export interface TableImportedEvent extends BaseEvent { tableId: string - format: TableImportFormat } diff --git a/packages/types/src/sdk/koa.ts b/packages/types/src/sdk/koa.ts index 302d1aeb67..f824b73458 100644 --- a/packages/types/src/sdk/koa.ts +++ b/packages/types/src/sdk/koa.ts @@ -41,7 +41,7 @@ export interface UserCtx } /** - * Deprecated: Use UserCtx / Ctx appropriately + * @deprecated: Use UserCtx / Ctx appropriately * Authenticated context. */ export interface BBContext extends Ctx { diff --git a/packages/worker/package.json b/packages/worker/package.json index 99f0ee1e9a..3cef4d12f6 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/worker", "email": "hi@budibase.com", - "version": "2.2.12-alpha.16", + "version": "2.2.12-alpha.32", "description": "Budibase background service", "main": "src/index.ts", "repository": { @@ -36,10 +36,10 @@ "author": "Budibase", "license": "GPL-3.0", "dependencies": { - "@budibase/backend-core": "2.2.12-alpha.16", - "@budibase/pro": "2.2.12-alpha.16", - "@budibase/string-templates": "2.2.12-alpha.16", - "@budibase/types": "2.2.12-alpha.16", + "@budibase/backend-core": "2.2.12-alpha.32", + "@budibase/pro": "2.2.12-alpha.32", + "@budibase/string-templates": "2.2.12-alpha.32", + "@budibase/types": "2.2.12-alpha.32", "@koa/router": "8.0.8", "@sentry/node": "6.17.7", "@techpass/passport-openidconnect": "0.3.2", diff --git a/packages/worker/src/api/routes/global/configs.ts b/packages/worker/src/api/routes/global/configs.ts index 7420d749c2..38a31a28e6 100644 --- a/packages/worker/src/api/routes/global/configs.ts +++ b/packages/worker/src/api/routes/global/configs.ts @@ -34,8 +34,8 @@ function settingValidation() { function googleValidation() { // prettier-ignore return Joi.object({ - clientID: Joi.string().required(), - clientSecret: Joi.string().required(), + clientID: Joi.when('activated', { is: true, then: Joi.string().required() }), + clientSecret: Joi.when('activated', { is: true, then: Joi.string().required() }), activated: Joi.boolean().required(), }).unknown(true) } @@ -45,12 +45,12 @@ function oidcValidation() { return Joi.object({ configs: Joi.array().items( Joi.object({ - clientID: Joi.string().required(), - clientSecret: Joi.string().required(), - configUrl: Joi.string().required(), + clientID: Joi.when('activated', { is: true, then: Joi.string().required() }), + clientSecret: Joi.when('activated', { is: true, then: Joi.string().required() }), + configUrl: Joi.when('activated', { is: true, then: Joi.string().required() }), logo: Joi.string().allow("", null), name: Joi.string().allow("", null), - uuid: Joi.string().required(), + uuid: Joi.when('activated', { is: true, then: Joi.string().required() }), activated: Joi.boolean().required(), scopes: Joi.array().optional() }) diff --git a/packages/worker/src/sdk/users/users.ts b/packages/worker/src/sdk/users/users.ts index f3117b63ab..5124a5c5b1 100644 --- a/packages/worker/src/sdk/users/users.ts +++ b/packages/worker/src/sdk/users/users.ts @@ -31,6 +31,7 @@ import { SearchUsersRequest, User, ThirdPartyUser, + isUser, } from "@budibase/types" import { sendEmail } from "../../utilities/email" import { EmailTemplatePurpose } from "../../constants" @@ -265,8 +266,9 @@ export const save = async ( await eventHelpers.handleSaveEvents(builtUser, dbUser) await addTenant(tenantId, _id, email) await cache.user.invalidateUser(response.id) + // let server know to sync user - await apps.syncUserInApps(_id) + await apps.syncUserInApps(_id, dbUser) await Promise.all(groupPromises) @@ -572,7 +574,7 @@ export const destroy = async (id: string, currentUser: any) => { await cache.user.invalidateUser(userId) await sessions.invalidateSessions(userId, { reason: "deletion" }) // let server know to sync user - await apps.syncUserInApps(userId) + await apps.syncUserInApps(userId, dbUser) } const bulkDeleteProcessing = async (dbUser: User) => { @@ -582,7 +584,7 @@ const bulkDeleteProcessing = async (dbUser: User) => { await cache.user.invalidateUser(userId) await sessions.invalidateSessions(userId, { reason: "bulk-deletion" }) // let server know to sync user - await apps.syncUserInApps(userId) + await apps.syncUserInApps(userId, dbUser) } export const invite = async ( diff --git a/packages/worker/src/utilities/appService.ts b/packages/worker/src/utilities/appService.ts index 244f10336f..478e986fe8 100644 --- a/packages/worker/src/utilities/appService.ts +++ b/packages/worker/src/utilities/appService.ts @@ -2,6 +2,7 @@ import fetch from "node-fetch" import { constants, tenancy, logging } from "@budibase/backend-core" import { checkSlashesInUrl } from "../utilities" import env from "../environment" +import { SyncUserRequest, User } from "@budibase/types" async function makeAppRequest(url: string, method: string, body: any) { if (env.isTest()) { @@ -24,11 +25,15 @@ async function makeAppRequest(url: string, method: string, body: any) { return fetch(checkSlashesInUrl(env.APPS_URL + url), request) } -export async function syncUserInApps(userId: string) { +export async function syncUserInApps(userId: string, previousUser?: User) { + const body: SyncUserRequest = { + previousUser, + } + const response = await makeAppRequest( `/api/users/metadata/sync/${userId}`, "POST", - {} + body ) if (response && response.status !== 200) { throw "Unable to sync user." diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index 9942d48aad..052edf0197 100644 --- a/packages/worker/yarn.lock +++ b/packages/worker/yarn.lock @@ -470,13 +470,13 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@budibase/backend-core@2.2.12-alpha.16": - version "2.2.12-alpha.16" - resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.16.tgz#9ebfa7308fc97b34d6a076e4300fbcf996160d66" - integrity sha512-rHMryIOb71U7W5jZtn39vuBI7xSZ6XA4l6P7lc2bBT1lI10G/zQRoQWjsWaUWo+RVBQ5zki3Ok05tFS9Yx/7fA== +"@budibase/backend-core@2.2.12-alpha.32": + version "2.2.12-alpha.32" + resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.2.12-alpha.32.tgz#5d53fdde38e80fdade73c59cb81623041984a5fc" + integrity sha512-XoaqGrttx01wlblI0+O23R9uS5FTMgK07juY6mUkdReCK46IvmG7FFnuYu0euKVRbhChSf5X8S+fvKIAEi1ZFw== dependencies: "@budibase/nano" "10.1.1" - "@budibase/types" "2.2.12-alpha.16" + "@budibase/types" "2.2.12-alpha.32" "@shopify/jest-koa-mocks" "5.0.1" "@techpass/passport-openidconnect" "0.3.2" aws-cloudfront-sign "2.2.0" @@ -521,23 +521,23 @@ qs "^6.11.0" tough-cookie "^4.1.2" -"@budibase/pro@2.2.12-alpha.16": - version "2.2.12-alpha.16" - resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.16.tgz#db5a345b072e725765cd01edcad4a930ae875eba" - integrity sha512-GBXdOQMIbxU0TGgGQ4+npNGtuFvanNVFrZBqwB7+3x6rIku313WkbgJJji5uemtU6B8XFh/QqS6AA0R0PS2Kmg== +"@budibase/pro@2.2.12-alpha.32": + version "2.2.12-alpha.32" + resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.2.12-alpha.32.tgz#4f35b0ada97458cc69ee41ebb40d56b361518065" + integrity sha512-Kn/IahgIb9Ydzmasv4Bhlh3rvyAC2tBVSoI33OZ/6PKF0vPYJNJkFds3iGELNV7SyWoLbVWb2z5SQ4SSaOYsJw== dependencies: - "@budibase/backend-core" "2.2.12-alpha.16" - "@budibase/types" "2.2.12-alpha.16" + "@budibase/backend-core" "2.2.12-alpha.32" + "@budibase/types" "2.2.12-alpha.32" "@koa/router" "8.0.8" bull "4.10.1" joi "17.6.0" jsonwebtoken "8.5.1" node-fetch "^2.6.1" -"@budibase/types@2.2.12-alpha.16": - version "2.2.12-alpha.16" - resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.16.tgz#6fb42d4be88fbd8054a0a3264cf9c4b4a7248893" - integrity sha512-pXn/r3tA0A30f2dJVJfzldMGXAEhpObBfqbONn8AStiD6Qm8Hu9H6aFaCPqS8DDaWBuwY/tMqSry2E0saRaSwg== +"@budibase/types@2.2.12-alpha.32": + version "2.2.12-alpha.32" + resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.2.12-alpha.32.tgz#71af8e8cff66acbfd65aa87e66183dd95d76ce6f" + integrity sha512-ZZwmO+0ORGEFbU/EQvtnjo1VonUbBdsciFkTOiopVupU5iNY2oCKgbYTQiTZZisQrRuiKdPV6P17uV+YTkjQSQ== "@cspotcode/source-map-support@^0.8.0": version "0.8.1" diff --git a/qa-core/src/config/internal-api/TestConfiguration/applications.ts b/qa-core/src/config/internal-api/TestConfiguration/applications.ts index 1cfd025974..aac82df013 100644 --- a/qa-core/src/config/internal-api/TestConfiguration/applications.ts +++ b/qa-core/src/config/internal-api/TestConfiguration/applications.ts @@ -117,7 +117,7 @@ export default class AppApi { return [response, json] } - async update( + async rename( appId: string, oldName: string, body: any @@ -153,4 +153,27 @@ export default class AppApi { expect(response).toHaveStatusCode(204) return [response] } + + async unlock(appId: string): Promise<[Response, responseMessage]> { + const response = await this.api.del(`/dev/${appId}/lock`) + const json = await response.json() + expect(response).toHaveStatusCode(200) + expect(json.message).toEqual("Lock released successfully.") + return [response, json] + } + + async updateIcon(appId: string): Promise<[Response, Application]> { + const body = { + icon: { + name: "ConversionFunnel", + color: "var(--spectrum-global-color-red-400)", + }, + } + const response = await this.api.put(`/applications/${appId}`, { body }) + const json = await response.json() + expect(response).toHaveStatusCode(200) + expect(json.icon.name).toEqual(body.icon.name) + expect(json.icon.color).toEqual(body.icon.color) + return [response, json] + } } diff --git a/qa-core/src/config/internal-api/TestConfiguration/rows.ts b/qa-core/src/config/internal-api/TestConfiguration/rows.ts index 39ba01f467..7269807f56 100644 --- a/qa-core/src/config/internal-api/TestConfiguration/rows.ts +++ b/qa-core/src/config/internal-api/TestConfiguration/rows.ts @@ -15,7 +15,7 @@ export default class RowsApi { const json = await response.json() if (this.rowAdded) { expect(response).toHaveStatusCode(200) - expect(json.length).toEqual(1) + expect(json.length).toBeGreaterThanOrEqual(1) } return [response, json] } @@ -36,4 +36,27 @@ export default class RowsApi { expect(response).toHaveStatusCode(200) return [response, json] } + + async searchNoPagination( + tableId: string, + body: any + ): Promise<[Response, Row[]]> { + const response = await this.api.post(`/${tableId}/search`, { body }) + const json = await response.json() + expect(response).toHaveStatusCode(200) + expect(json.hasNextPage).toEqual(false) + return [response, json.rows] + } + + async searchWithPagination( + tableId: string, + body: any + ): Promise<[Response, Row[]]> { + const response = await this.api.post(`/${tableId}/search`, { body }) + const json = await response.json() + expect(response).toHaveStatusCode(200) + expect(json.hasNextPage).toEqual(true) + expect(json.rows.length).toEqual(10) + return [response, json.rows] + } } diff --git a/qa-core/src/config/internal-api/fixtures/rows.ts b/qa-core/src/config/internal-api/fixtures/rows.ts index 90f6350dcf..f1f1c00493 100644 --- a/qa-core/src/config/internal-api/fixtures/rows.ts +++ b/qa-core/src/config/internal-api/fixtures/rows.ts @@ -6,3 +6,27 @@ export const generateNewRowForTable = (tableId: string): Row => { tableId: tableId, } } + +export const searchBody = (primaryDisplay: string): any => { + return { + bookmark: null, + limit: 10, + paginate: true, + query: { + contains: {}, + containsAny: {}, + empty: {}, + equal: {}, + fuzzy: {}, + notContains: {}, + notEmpty: {}, + notEqual: {}, + oneOf: {}, + range: {}, + string: {}, + }, + sort: primaryDisplay, + sortOrder: "ascending", + sortType: "string", + } +} diff --git a/qa-core/src/config/internal-api/fixtures/table.ts b/qa-core/src/config/internal-api/fixtures/table.ts index 5060a405bb..3de950fd9f 100644 --- a/qa-core/src/config/internal-api/fixtures/table.ts +++ b/qa-core/src/config/internal-api/fixtures/table.ts @@ -6,10 +6,6 @@ export const generateTable = (): Table => { schema: {}, sourceId: "bb_internal", type: "internal", - dataImport: { - valid: true, - schema: {}, - }, } } diff --git a/qa-core/src/tests/internal-api/applications/applications.spec.ts b/qa-core/src/tests/internal-api/applications/applications.spec.ts index 70724232bb..e7692740b8 100644 --- a/qa-core/src/tests/internal-api/applications/applications.spec.ts +++ b/qa-core/src/tests/internal-api/applications/applications.spec.ts @@ -69,7 +69,7 @@ describe("Internal API - Application creation, update, publish and delete", () = await config.applications.unpublish(app.appId) }) - it("POST - Sync application before deployment", async () => { + it("Sync application before deployment", async () => { const app = await config.applications.create(generateApp()) config.applications.api.appId = app.appId @@ -81,7 +81,7 @@ describe("Internal API - Application creation, update, publish and delete", () = }) }) - it("POST - Sync application after deployment", async () => { + it("Sync application after deployment", async () => { const app = await config.applications.create(generateApp()) config.applications.api.appId = app.appId @@ -96,24 +96,32 @@ describe("Internal API - Application creation, update, publish and delete", () = }) }) - it("PUT - Update an application", async () => { + it("Rename an application", async () => { const app = await config.applications.create(generateApp()) config.applications.api.appId = app.appId - await config.applications.update(app.appId, app.name, { + await config.applications.rename(app.appId, app.name, { name: generator.word(), }) }) - it("POST - Revert Changes without changes", async () => { + it("Update the icon and color of an application", async () => { + const app = await config.applications.create(generateApp()) + + config.applications.api.appId = app.appId + + await config.applications.updateIcon(app.appId) + }) + + it("Revert Changes without changes", async () => { const app = await config.applications.create(generateApp()) config.applications.api.appId = app.appId await config.applications.revertUnpublished(app.appId) }) - it("POST - Revert Changes", async () => { + it("Revert Changes", async () => { const app = await config.applications.create(generateApp()) config.applications.api.appId = app.appId @@ -126,11 +134,12 @@ describe("Internal API - Application creation, update, publish and delete", () = // // Revert the app to published state await config.applications.revertPublished(app.appId) + await config.applications.unlock(app.appId) // Check screen is removed await config.applications.getRoutes() }) - it("DELETE - Delete an application", async () => { + it("Delete an application", async () => { const app = await config.applications.create(generateApp()) await config.applications.delete(app.appId) diff --git a/qa-core/src/tests/internal-api/screens/screens.spec.ts b/qa-core/src/tests/internal-api/screens/screens.spec.ts index 06d2115af4..ee3e97afc6 100644 --- a/qa-core/src/tests/internal-api/screens/screens.spec.ts +++ b/qa-core/src/tests/internal-api/screens/screens.spec.ts @@ -21,7 +21,7 @@ describe("Internal API - /screens endpoints", () => { await config.afterAll() }) - it("POST - Create a screen with each role type", async () => { + it("Create a screen with each role type", async () => { // Create app const app = await appConfig.applications.create(generateApp()) @@ -35,7 +35,7 @@ describe("Internal API - /screens endpoints", () => { } }) - it("GET - Fetch screens", async () => { + it("Get screens", async () => { // Create app const app = await appConfig.applications.create(generateApp()) @@ -47,7 +47,7 @@ describe("Internal API - /screens endpoints", () => { await appConfig.applications.getRoutes(true) }) - it("DELETE - Delete a screen", async () => { + it("Delete a screen", async () => { // Create app const app = await appConfig.applications.create(generateApp()) diff --git a/qa-core/src/tests/internal-api/tables/tables.spec.ts b/qa-core/src/tests/internal-api/tables/tables.spec.ts index 6b2d2240e5..7d79330304 100644 --- a/qa-core/src/tests/internal-api/tables/tables.spec.ts +++ b/qa-core/src/tests/internal-api/tables/tables.spec.ts @@ -6,9 +6,12 @@ import { generateTable, generateNewColumnForTable, } from "../../../config/internal-api/fixtures/table" -import { generateNewRowForTable } from "../../../config/internal-api/fixtures/rows" +import { + generateNewRowForTable, + searchBody, +} from "../../../config/internal-api/fixtures/rows" -describe("Internal API - Application creation, update, publish and delete", () => { +describe("Internal API - Table Operations", () => { const api = new InternalAPIClient() const config = new TestConfiguration(api) @@ -31,7 +34,7 @@ describe("Internal API - Application creation, update, publish and delete", () = }) } - it("Operations on Tables", async () => { + it("Create and delete table, columns and rows", async () => { // create the app const appName = generator.word() const app = await createAppFromTemplate() @@ -86,4 +89,70 @@ describe("Internal API - Application creation, update, publish and delete", () = //Table was deleted await config.tables.getAll(2) }) + + it("Search and pagination", async () => { + // create the app + const appName = generator.word() + const app = await createAppFromTemplate() + config.applications.api.appId = app.appId + + // Get current tables: expect 2 in this template + await config.tables.getAll(2) + + // Add new table + const [createdTableResponse, createdTableData] = await config.tables.save( + generateTable() + ) + + //Table was added + await config.tables.getAll(3) + + //Get information about the table + await config.tables.getTableById(createdTableData._id) + + //Add Column to table + const newColumn = generateNewColumnForTable(createdTableData) + const [addColumnResponse, addColumnData] = await config.tables.save( + newColumn, + true + ) + + //Add Row to table + let newRow = generateNewRowForTable(addColumnData._id) + await config.rows.add(addColumnData._id, newRow) + + //Search single row + await config.rows.searchNoPagination( + createdTableData._id, + searchBody(createdTableData.primaryDisplay) + ) + + //Add 10 more rows + for (let i = 0; i < 10; i++) { + let newRow = generateNewRowForTable(addColumnData._id) + await config.rows.add(addColumnData._id, newRow) + } + + //Search rows with pagination + const [allRowsResponse, allRowsJson] = + await config.rows.searchWithPagination( + createdTableData._id, + searchBody(createdTableData.primaryDisplay) + ) + + //Delete Rows from table + const rowToDelete = { + rows: [allRowsJson], + } + const [deleteRowResponse, deleteRowData] = await config.rows.delete( + createdTableData._id, + rowToDelete + ) + + //Search single row + await config.rows.searchWithPagination( + createdTableData._id, + searchBody(createdTableData.primaryDisplay) + ) + }) }) diff --git a/qa-core/src/tests/internal-api/userManagement/appSpecificRoles.spec.ts b/qa-core/src/tests/internal-api/userManagement/appSpecificRoles.spec.ts index 502ce3d767..53ae78f42d 100644 --- a/qa-core/src/tests/internal-api/userManagement/appSpecificRoles.spec.ts +++ b/qa-core/src/tests/internal-api/userManagement/appSpecificRoles.spec.ts @@ -28,9 +28,12 @@ describe("Internal API - App Specific Roles & Permissions", () => { }) it("Add BASIC user to app", async () => { + // Create a user with BASIC role and check if it was created successfully const appUser = generateUser() expect(appUser[0].builder?.global).toEqual(false) expect(appUser[0].admin?.global).toEqual(false) + + // Add the user to the tenant. const [createUserResponse, createUserJson] = await config.users.addMultiple( appUser ) @@ -38,9 +41,12 @@ describe("Internal API - App Specific Roles & Permissions", () => { const app = await config.applications.create(appFromTemplate()) config.applications.api.appId = app.appId + // Get all the information from the create user const [userInfoResponse, userInfoJson] = await config.users.getInfo( createUserJson.created.successful[0]._id ) + + // Create the body with the information from the user and add the role to the app const body: User = { ...userInfoJson, roles: { @@ -49,6 +55,7 @@ describe("Internal API - App Specific Roles & Permissions", () => { } await config.users.updateInfo(body) + // Get the user information again and check if the role was added const [changedUserInfoResponse, changedUserInfoJson] = await config.users.getInfo(createUserJson.created.successful[0]._id) expect(changedUserInfoJson.roles[app.appId]).toBeDefined() @@ -56,6 +63,7 @@ describe("Internal API - App Specific Roles & Permissions", () => { }) it("Add ADMIN user to app", async () => { + // Create a user with ADMIN role and check if it was created successfully const adminUser = generateUser(1, "admin") expect(adminUser[0].builder?.global).toEqual(true) expect(adminUser[0].admin?.global).toEqual(true) @@ -63,15 +71,15 @@ describe("Internal API - App Specific Roles & Permissions", () => { adminUser ) - //const app = await config.applications.create(generateApp()) - //config.applications.api.appId = app.appId - const app = await config.applications.create(appFromTemplate()) config.applications.api.appId = app.appId + // Get all the information from the create user const [userInfoResponse, userInfoJson] = await config.users.getInfo( createUserJson.created.successful[0]._id ) + + // Create the body with the information from the user and add the role to the app const body: User = { ...userInfoJson, roles: { @@ -80,6 +88,7 @@ describe("Internal API - App Specific Roles & Permissions", () => { } await config.users.updateInfo(body) + // Get the user information again and check if the role was added const [changedUserInfoResponse, changedUserInfoJson] = await config.users.getInfo(createUserJson.created.successful[0]._id) expect(changedUserInfoJson.roles[app.appId]).toBeDefined() @@ -93,9 +102,9 @@ describe("Internal API - App Specific Roles & Permissions", () => { }) it("Add POWER user to app", async () => { + // Create a user with POWER role and check if it was created successfully const powerUser = generateUser(1, "developer") expect(powerUser[0].builder?.global).toEqual(true) - const [createUserResponse, createUserJson] = await config.users.addMultiple( powerUser ) @@ -103,9 +112,12 @@ describe("Internal API - App Specific Roles & Permissions", () => { const app = await config.applications.create(generateApp()) config.applications.api.appId = app.appId + // Get all the information from the create user const [userInfoResponse, userInfoJson] = await config.users.getInfo( createUserJson.created.successful[0]._id ) + + // Create the body with the information from the user and add the role to the app const body: User = { ...userInfoJson, roles: { @@ -114,6 +126,7 @@ describe("Internal API - App Specific Roles & Permissions", () => { } await config.users.updateInfo(body) + // Get the user information again and check if the role was added const [changedUserInfoResponse, changedUserInfoJson] = await config.users.getInfo(createUserJson.created.successful[0]._id) expect(changedUserInfoJson.roles[app.appId]).toBeDefined() @@ -122,6 +135,7 @@ describe("Internal API - App Specific Roles & Permissions", () => { describe("Check Access for default roles", () => { it("Check Table access for app user", async () => { + // Create a user with BASIC role and check if it was created successfully const appUser = generateUser() expect(appUser[0].builder?.global).toEqual(false) expect(appUser[0].admin?.global).toEqual(false) @@ -131,9 +145,12 @@ describe("Internal API - App Specific Roles & Permissions", () => { const app = await config.applications.create(generateApp()) config.applications.api.appId = app.appId + // Get all the information from the create user const [userInfoResponse, userInfoJson] = await config.users.getInfo( createUserJson.created.successful[0]._id ) + + // Create the body with the information from the user and add the role to the app const body: User = { ...userInfoJson, roles: { @@ -142,14 +159,18 @@ describe("Internal API - App Specific Roles & Permissions", () => { } await config.users.updateInfo(body) + // Get the user information again and check if the role was added const [changedUserInfoResponse, changedUserInfoJson] = await config.users.getInfo(createUserJson.created.successful[0]._id) expect(changedUserInfoJson.roles[app.appId]).toBeDefined() expect(changedUserInfoJson.roles[app.appId]).toEqual("BASIC") + // Create a table const [createdTableResponse, createdTableData] = await config.tables.save( generateTable() ) + + // Login with the user created and try to create a column await config.login(appUser[0].email, appUser[0].password) const newColumn = generateNewColumnForTable(createdTableData) await config.tables.forbiddenSave(newColumn) @@ -157,6 +178,7 @@ describe("Internal API - App Specific Roles & Permissions", () => { }) it("Check Table access for developer", async () => { + // Create a user with POWER role and check if it was created successfully const developer = generateUser(1, "developer") expect(developer[0].builder?.global).toEqual(true) @@ -166,9 +188,12 @@ describe("Internal API - App Specific Roles & Permissions", () => { const app = await config.applications.create(generateApp()) config.applications.api.appId = app.appId + // Get all the information from the create user const [userInfoResponse, userInfoJson] = await config.users.getInfo( createUserJson.created.successful[0]._id ) + + // Create the body with the information from the user and add the role to the app const body: User = { ...userInfoJson, roles: { @@ -177,14 +202,18 @@ describe("Internal API - App Specific Roles & Permissions", () => { } await config.users.updateInfo(body) + // Get the user information again and check if the role was added const [changedUserInfoResponse, changedUserInfoJson] = await config.users.getInfo(createUserJson.created.successful[0]._id) expect(changedUserInfoJson.roles[app.appId]).toBeDefined() expect(changedUserInfoJson.roles[app.appId]).toEqual("POWER") + // Create a table const [createdTableResponse, createdTableData] = await config.tables.save( generateTable() ) + + // Login with the user created and try to create a column await config.login( developer[0].email, developer[0].password @@ -197,6 +226,7 @@ describe("Internal API - App Specific Roles & Permissions", () => { }) it("Check Table access for admin", async () => { + // Create a user with ADMIN role and check if it was created successfully const adminUser = generateUser(1, "admin") expect(adminUser[0].builder?.global).toEqual(true) expect(adminUser[0].admin?.global).toEqual(true) @@ -206,9 +236,12 @@ describe("Internal API - App Specific Roles & Permissions", () => { const app = await config.applications.create(generateApp()) config.applications.api.appId = app.appId + // Get all the information from the create user const [userInfoResponse, userInfoJson] = await config.users.getInfo( createUserJson.created.successful[0]._id ) + + // Create the body with the information from the user and add the role to the app const body: User = { ...userInfoJson, roles: { @@ -217,11 +250,13 @@ describe("Internal API - App Specific Roles & Permissions", () => { } await config.users.updateInfo(body) + // Get the user information again and check if the role was added const [changedUserInfoResponse, changedUserInfoJson] = await config.users.getInfo(createUserJson.created.successful[0]._id) expect(changedUserInfoJson.roles[app.appId]).toBeDefined() expect(changedUserInfoJson.roles[app.appId]).toEqual("ADMIN") + // Login with the created user and create a table await config.login( adminUser[0].email, adminUser[0].password diff --git a/qa-core/src/tests/internal-api/userManagement/userManagement.spec.ts b/qa-core/src/tests/internal-api/userManagement/userManagement.spec.ts index ea235d7cc7..fb61d5070f 100644 --- a/qa-core/src/tests/internal-api/userManagement/userManagement.spec.ts +++ b/qa-core/src/tests/internal-api/userManagement/userManagement.spec.ts @@ -18,9 +18,13 @@ describe("Internal API - User Management & Permissions", () => { }) it("Add Users with different roles", async () => { + // Get all users await config.users.search() + + // Get all roles await config.users.getRoles() + // Add users with each role const admin = generateUser(1, "admin") expect(admin[0].builder?.global).toEqual(true) expect(admin[0].admin?.global).toEqual(true) @@ -34,6 +38,7 @@ describe("Internal API - User Management & Permissions", () => { await config.users.addMultiple(userList) + // Check users are added const [allUsersResponse, allUsersJson] = await config.users.getAll() expect(allUsersJson.length).toBeGreaterThan(0) })