diff --git a/Dockerfile b/Dockerfile index 59677c69b7ffce60fcccbea4501d5a1e92c4cc0b..19606527adbac48def6672dd4f1518ac96526048 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # build stage -FROM gitlab.ub.uni-bielefeld.de/cmg/clowm/dependency_proxy/containers/node:18 as build-stage +FROM node:18 as build-stage WORKDIR /app COPY package.json ./ COPY package-lock.json ./ @@ -8,10 +8,11 @@ COPY . . RUN npm run build-only # production stage -FROM gitlab.ub.uni-bielefeld.de/cmg/clowm/dependency_proxy/containers/nginx:stable-alpine as production-stage +FROM nginx:stable-alpine as production-stage +EXPOSE 80 HEALTHCHECK --interval=30s --timeout=4s CMD curl --head -f http://localhost || exit 1 COPY --from=build-stage /app/dist /usr/share/nginx/html COPY --from=build-stage /app/src/assets/env.template.js /tmp COPY nginx.conf /etc/nginx/conf.d/default.conf -EXPOSE 80 + CMD ["/bin/sh", "-c", "envsubst < /tmp/env.template.js > /usr/share/nginx/html/env.js && exec nginx -g 'daemon off;'"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..d645695673349e3947e8e5ae42332d0ac3164cd7 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 4733d826e19f1495e86207bb7bd713ed97185739..66b63f03ea3738f5ca76a22b139670937c781c34 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,11 @@ When accessing the website, these variables will be loaded dynamically into the |-------------------------|---------|----------|--------------------------------------------------| | `AUTH_API_BASE_URL` | unset | HTTP URL | Base URL for the Auth Service API | | `WORKFLOW_API_BASE_URL` | unset | HTTP URL | Base URL for the Workflow Service API | +| `RESOURCE_API_BASE_URL` | unset | HTTP URL | Base URL for the Resource Service API | | `S3PROXY_API_BASE_URL` | unset | HTTP URL | Base URL for the S3Proxy Service API | | `S3_URL` | unset | HTTP URL | URL of the S3 storage to interact with | | `DEV_SYSTEM` | `false` | boolean | Flag if the service is installed on a Dev system | + +## License + +The API is licensed under the [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) license. See the [License](LICENSE) file for more information diff --git a/index.html b/index.html index 61088270988b1c5c2bd89e8457bf83bc02b0d28b..9723102fbf222a41d7425880bad64e75952b7018 100644 --- a/index.html +++ b/index.html @@ -1,14 +1,15 @@ <!DOCTYPE html> <html lang="en" data-bs-theme="light"> - <head> - <meta charset="UTF-8" /> - <link rel="icon" href="/favicon.ico" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <title>CloWM</title> +<head> + <meta charset="UTF-8"/> + <link rel="icon" href="/favicon.ico"/> + <meta name="viewport" content="width=device-width, initial-scale=1.0"/> + <title>CloWM - Cloud-based Workflow Manager</title> + <meta name="description" content="The Cloud-based Workflow Manager (CloWM) is a service hosted at Bielefeld University that can transform your Nextflow workflow into a public webservice and provide compute and storage resources for executing your registered workflow"/> <script src="/env.js"></script> - </head> - <body> - <div id="app" class="d-flex flex-column justify-content-between" style="min-height: 100vh"></div> - <script type="module" src="/src/main.ts"></script> - </body> +</head> +<body> +<div id="app" class="d-flex flex-column justify-content-between" style="min-height: 100vh"></div> +<script type="module" src="/src/main.ts"></script> +</body> </html> diff --git a/package-lock.json b/package-lock.json index 526ec7500ee19be500f24e93b3b264b18cc526e8..b30b02ddd8e043765e363950f1e7880fc4c9d451 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "clowm-ui", "version": "2.0.0", + "license": "Apache-2.0", "dependencies": { "@aws-sdk/client-s3": "^3.440.0", "@aws-sdk/lib-storage": "^3.440.0", @@ -14,45 +15,46 @@ "@fortawesome/fontawesome-free": "~6.4.2", "@popperjs/core": "~2.11.8", "ajv": "~8.12.0", - "bootstrap": "~5.3.1", - "chart.js": "~4.3.3", + "bootstrap": "~5.3.0", + "chart.js": "~4.4.0", "chartjs-plugin-zoom": "~2.0.1", - "dayjs": "~1.11.9", + "dayjs": "~1.11.0", "dompurify": "~3.0.5", "filesize": "~10.0.12", "idb-keyval": "^6.2.1", - "pinia": "~2.1.6", - "semver": "~7.5.4", + "pinia": "~2.1.0", + "semver": "~7.5.0", "showdown": "~2.1.0", - "vue": "~3.3.4", - "vue-router": "~4.2.4", - "vue3-cookies": "~1.0.6" + "vue": "~3.4.0", + "vue-router": "~4.2.0", + "vue3-cookies": "~1.0.0" }, "devDependencies": { "@esbuild-plugins/node-globals-polyfill": "~0.2.3", "@esbuild-plugins/node-modules-polyfill": "~0.2.2", "@rushstack/eslint-patch": "~1.2.0", "@tsconfig/node18": "^18.2.1", - "@types/bootstrap": "~5.2.6", - "@types/dompurify": "~3.0.2", - "@types/node": "^16.18.48", + "@types/bootstrap": "~5.2.0", + "@types/dompurify": "~3.0.0", + "@types/node": "^18.19.5", "@types/semver": "~7.5.1", "@types/showdown": "~2.0.1", - "@vitejs/plugin-vue": "~4.3.4", + "@vitejs/plugin-vue": "~5.0.0", "@vue/eslint-config-prettier": "~8.0.0", "@vue/eslint-config-typescript": "~11.0.3", - "@vue/tsconfig": "~0.4.0", + "@vue/tsconfig": "~0.5.0", "axios": "~1.6.0", "eslint": "~8.48.0", - "eslint-plugin-vue": "~9.17.0", + "eslint-plugin-vue": "~9.19.0", + "highlight.js": "^11.9.0", "npm-run-all": "~4.1.5", - "openapi-typescript-codegen": "^0.25.0", + "openapi-typescript-codegen": "^0.26.0", "prettier": "~3.0.3", "rollup-plugin-node-polyfills": "~0.2.1", "sass": "~1.66.1", "typescript": "~5.1.6", - "vite": "~4.4.9", - "vue-tsc": "~1.8.10" + "vite": "~5.0.0", + "vue-tsc": "~1.8.0" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -65,15 +67,22 @@ } }, "node_modules/@apidevtools/json-schema-ref-parser": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", - "integrity": "sha512-GBD2Le9w2+lVFoc4vswGI/TjkNIZSVp7+9xPf+X3uidBfWnAeUWmquteSyt0+VCrhNMWj/FTABISQrD3Z/YA+w==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.1.0.tgz", + "integrity": "sha512-g/VW9ZQEFJAOwAyUb8JFf7MLiLy2uEB4rU270rGzDwICxnxMlPy0O11KVePSgS36K1NI29gSlK84n5INGhd4Ag==", "dev": true, "dependencies": { "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" + "@types/json-schema": "^7.0.13", + "@types/lodash.clonedeep": "^4.5.7", + "js-yaml": "^4.1.0", + "lodash.clonedeep": "^4.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" } }, "node_modules/@aws-crypto/crc32": { @@ -202,65 +211,66 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@aws-sdk/client-s3": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.468.0.tgz", - "integrity": "sha512-j0MnSYKu7KRAPXXn5egmJBzzPAgM/Hb0UUr0CHRrj8eMV7Ni/cZQpbU8tqgFel7BrsS4YINB5W/Q3FShHpI/8w==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.495.0.tgz", + "integrity": "sha512-Lr08ygmesFScyF7TK70uS4O9YLTaKHH4O/FGNKw17DpI5XyyS/Aje9yVqn6Yi3OUrsKChxGK1n0gc6ipyUGsjQ==", "dependencies": { "@aws-crypto/sha1-browser": "3.0.0", "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.468.0", - "@aws-sdk/core": "3.468.0", - "@aws-sdk/credential-provider-node": "3.468.0", - "@aws-sdk/middleware-bucket-endpoint": "3.468.0", - "@aws-sdk/middleware-expect-continue": "3.468.0", - "@aws-sdk/middleware-flexible-checksums": "3.468.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-location-constraint": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-sdk-s3": "3.468.0", - "@aws-sdk/middleware-signing": "3.468.0", - "@aws-sdk/middleware-ssec": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.468.0", - "@aws-sdk/region-config-resolver": "3.468.0", - "@aws-sdk/signature-v4-multi-region": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.468.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.468.0", - "@aws-sdk/xml-builder": "3.465.0", - "@smithy/config-resolver": "^2.0.20", - "@smithy/eventstream-serde-browser": "^2.0.15", - "@smithy/eventstream-serde-config-resolver": "^2.0.15", - "@smithy/eventstream-serde-node": "^2.0.15", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-blob-browser": "^2.0.16", - "@smithy/hash-node": "^2.0.17", - "@smithy/hash-stream-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/md5-js": "^2.0.17", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.2", - "@smithy/middleware-retry": "^2.0.23", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/protocol-http": "^3.0.11", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.28", - "@smithy/util-endpoints": "^1.0.6", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-stream": "^2.0.23", - "@smithy/util-utf8": "^2.0.2", - "@smithy/util-waiter": "^2.0.15", + "@aws-sdk/client-sts": "3.495.0", + "@aws-sdk/core": "3.495.0", + "@aws-sdk/credential-provider-node": "3.495.0", + "@aws-sdk/middleware-bucket-endpoint": "3.495.0", + "@aws-sdk/middleware-expect-continue": "3.495.0", + "@aws-sdk/middleware-flexible-checksums": "3.495.0", + "@aws-sdk/middleware-host-header": "3.495.0", + "@aws-sdk/middleware-location-constraint": "3.495.0", + "@aws-sdk/middleware-logger": "3.495.0", + "@aws-sdk/middleware-recursion-detection": "3.495.0", + "@aws-sdk/middleware-sdk-s3": "3.495.0", + "@aws-sdk/middleware-signing": "3.495.0", + "@aws-sdk/middleware-ssec": "3.495.0", + "@aws-sdk/middleware-user-agent": "3.495.0", + "@aws-sdk/region-config-resolver": "3.495.0", + "@aws-sdk/signature-v4-multi-region": "3.495.0", + "@aws-sdk/types": "3.495.0", + "@aws-sdk/util-endpoints": "3.495.0", + "@aws-sdk/util-user-agent-browser": "3.495.0", + "@aws-sdk/util-user-agent-node": "3.495.0", + "@aws-sdk/xml-builder": "3.495.0", + "@smithy/config-resolver": "^2.1.0", + "@smithy/core": "^1.3.0", + "@smithy/eventstream-serde-browser": "^2.1.0", + "@smithy/eventstream-serde-config-resolver": "^2.1.0", + "@smithy/eventstream-serde-node": "^2.1.0", + "@smithy/fetch-http-handler": "^2.4.0", + "@smithy/hash-blob-browser": "^2.1.0", + "@smithy/hash-node": "^2.1.0", + "@smithy/hash-stream-node": "^2.1.0", + "@smithy/invalid-dependency": "^2.1.0", + "@smithy/md5-js": "^2.1.0", + "@smithy/middleware-content-length": "^2.1.0", + "@smithy/middleware-endpoint": "^2.4.0", + "@smithy/middleware-retry": "^2.1.0", + "@smithy/middleware-serde": "^2.1.0", + "@smithy/middleware-stack": "^2.1.0", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/node-http-handler": "^2.3.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/smithy-client": "^2.3.0", + "@smithy/types": "^2.9.0", + "@smithy/url-parser": "^2.1.0", + "@smithy/util-base64": "^2.1.0", + "@smithy/util-body-length-browser": "^2.1.0", + "@smithy/util-body-length-node": "^2.2.0", + "@smithy/util-defaults-mode-browser": "^2.1.0", + "@smithy/util-defaults-mode-node": "^2.1.0", + "@smithy/util-endpoints": "^1.1.0", + "@smithy/util-retry": "^2.1.0", + "@smithy/util-stream": "^2.1.0", + "@smithy/util-utf8": "^2.1.0", + "@smithy/util-waiter": "^2.1.0", "fast-xml-parser": "4.2.5", "tslib": "^2.5.0" }, @@ -269,45 +279,46 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.468.0.tgz", - "integrity": "sha512-NabkDaiFsMP8lBR3+JzdtOVarH8kCJst30fQyBIs2PI0uMfajFJ+SK9JTg1J1YZY6aNJBxo2Bxu3dl0fjZ5N/g==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.495.0.tgz", + "integrity": "sha512-Uerh3aDe/JeQNjcyXKI+8VuKPOAB6mCUKlScD0AIca1Kdyk8PsQTq4rDzFCYAQsNS5/BuPN+Ak0NqwsJM0agYA==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.468.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.468.0", - "@aws-sdk/region-config-resolver": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.468.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.468.0", - "@smithy/config-resolver": "^2.0.20", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.2", - "@smithy/middleware-retry": "^2.0.23", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/protocol-http": "^3.0.11", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.28", - "@smithy/util-endpoints": "^1.0.6", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-utf8": "^2.0.2", + "@aws-sdk/core": "3.495.0", + "@aws-sdk/middleware-host-header": "3.495.0", + "@aws-sdk/middleware-logger": "3.495.0", + "@aws-sdk/middleware-recursion-detection": "3.495.0", + "@aws-sdk/middleware-user-agent": "3.495.0", + "@aws-sdk/region-config-resolver": "3.495.0", + "@aws-sdk/types": "3.495.0", + "@aws-sdk/util-endpoints": "3.495.0", + "@aws-sdk/util-user-agent-browser": "3.495.0", + "@aws-sdk/util-user-agent-node": "3.495.0", + "@smithy/config-resolver": "^2.1.0", + "@smithy/core": "^1.3.0", + "@smithy/fetch-http-handler": "^2.4.0", + "@smithy/hash-node": "^2.1.0", + "@smithy/invalid-dependency": "^2.1.0", + "@smithy/middleware-content-length": "^2.1.0", + "@smithy/middleware-endpoint": "^2.4.0", + "@smithy/middleware-retry": "^2.1.0", + "@smithy/middleware-serde": "^2.1.0", + "@smithy/middleware-stack": "^2.1.0", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/node-http-handler": "^2.3.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/smithy-client": "^2.3.0", + "@smithy/types": "^2.9.0", + "@smithy/url-parser": "^2.1.0", + "@smithy/util-base64": "^2.1.0", + "@smithy/util-body-length-browser": "^2.1.0", + "@smithy/util-body-length-node": "^2.2.0", + "@smithy/util-defaults-mode-browser": "^2.1.0", + "@smithy/util-defaults-mode-node": "^2.1.0", + "@smithy/util-endpoints": "^1.1.0", + "@smithy/util-retry": "^2.1.0", + "@smithy/util-utf8": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -315,48 +326,48 @@ } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.468.0.tgz", - "integrity": "sha512-EausH7ezv1AIgl/4rfZRNRxrFND5hChbIqkuAf8e5wZ74HUEVBMmD5Jiwfs0WRCso3ejOjsNtS8PAOA3djn28w==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.495.0.tgz", + "integrity": "sha512-lXQIx7D1MQ5+F8PaSYV7UiSxgP9M5ba/YFx1rcxi5l1GlbAWuHWhrk15qKe9d6vLxa2eTjJFiVzbO7pJqRBEWw==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/core": "3.468.0", - "@aws-sdk/credential-provider-node": "3.468.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-sdk-sts": "3.468.0", - "@aws-sdk/middleware-signing": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.468.0", - "@aws-sdk/region-config-resolver": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.468.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.468.0", - "@smithy/config-resolver": "^2.0.20", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.2", - "@smithy/middleware-retry": "^2.0.23", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/protocol-http": "^3.0.11", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.28", - "@smithy/util-endpoints": "^1.0.6", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-utf8": "^2.0.2", + "@aws-sdk/core": "3.495.0", + "@aws-sdk/credential-provider-node": "3.495.0", + "@aws-sdk/middleware-host-header": "3.495.0", + "@aws-sdk/middleware-logger": "3.495.0", + "@aws-sdk/middleware-recursion-detection": "3.495.0", + "@aws-sdk/middleware-user-agent": "3.495.0", + "@aws-sdk/region-config-resolver": "3.495.0", + "@aws-sdk/types": "3.495.0", + "@aws-sdk/util-endpoints": "3.495.0", + "@aws-sdk/util-user-agent-browser": "3.495.0", + "@aws-sdk/util-user-agent-node": "3.495.0", + "@smithy/config-resolver": "^2.1.0", + "@smithy/core": "^1.3.0", + "@smithy/fetch-http-handler": "^2.4.0", + "@smithy/hash-node": "^2.1.0", + "@smithy/invalid-dependency": "^2.1.0", + "@smithy/middleware-content-length": "^2.1.0", + "@smithy/middleware-endpoint": "^2.4.0", + "@smithy/middleware-retry": "^2.1.0", + "@smithy/middleware-serde": "^2.1.0", + "@smithy/middleware-stack": "^2.1.0", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/node-http-handler": "^2.3.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/smithy-client": "^2.3.0", + "@smithy/types": "^2.9.0", + "@smithy/url-parser": "^2.1.0", + "@smithy/util-base64": "^2.1.0", + "@smithy/util-body-length-browser": "^2.1.0", + "@smithy/util-body-length-node": "^2.2.0", + "@smithy/util-defaults-mode-browser": "^2.1.0", + "@smithy/util-defaults-mode-node": "^2.1.0", + "@smithy/util-endpoints": "^1.1.0", + "@smithy/util-middleware": "^2.1.0", + "@smithy/util-retry": "^2.1.0", + "@smithy/util-utf8": "^2.1.0", "fast-xml-parser": "4.2.5", "tslib": "^2.5.0" }, @@ -365,11 +376,15 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.468.0.tgz", - "integrity": "sha512-ezUJR9VvknKoXzNZ4wvzGi1jdkmm+/1dUYQ9Sw4r8bzlJDTsUnWbyvaDlBQh81RuhLtVkaUfTnQKoec0cwlZKQ==", - "dependencies": { - "@smithy/smithy-client": "^2.1.18", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.495.0.tgz", + "integrity": "sha512-TI/jq1cSUR+r1prJ9xXtxMO0u2/jXrWjf3Z2ekForsCObPtR9qkJCYyezargupoSJqZA60KUpOhxrKW/dFJ1rw==", + "dependencies": { + "@smithy/core": "^1.3.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/signature-v4": "^2.1.0", + "@smithy/smithy-client": "^2.3.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -377,13 +392,13 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.468.0.tgz", - "integrity": "sha512-k/1WHd3KZn0EQYjadooj53FC0z24/e4dUZhbSKTULgmxyO62pwh9v3Brvw4WRa/8o2wTffU/jo54tf4vGuP/ZA==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.495.0.tgz", + "integrity": "sha512-2CKlHiQRXyVA7t3VGXo39a/UwRrZs/VG0jYZFu60dK9afxesRkA4XOJto765VenT/eR3LkeVW+RBzOISHUFg0Q==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.7.0", + "@aws-sdk/types": "3.495.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -391,19 +406,19 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.468.0.tgz", - "integrity": "sha512-DBYsptYBq0xC+GTh+3dN3Q9/wRZiPpsHA4yCC1mskEbJfMy7EIZZKtZ8lOkZ24NOI5oea4o3L+wFTxOeFSKntA==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.468.0", - "@aws-sdk/credential-provider-process": "3.468.0", - "@aws-sdk/credential-provider-sso": "3.468.0", - "@aws-sdk/credential-provider-web-identity": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.495.0.tgz", + "integrity": "sha512-DGRfND+FIacuQQNozMa8fS4yUrWZgkB6CEH4ghiqUvtE7h2sGMMVEerlaCGgTnQlpWWvDS656orzwEO3vuMTVw==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.495.0", + "@aws-sdk/credential-provider-process": "3.495.0", + "@aws-sdk/credential-provider-sso": "3.495.0", + "@aws-sdk/credential-provider-web-identity": "3.495.0", + "@aws-sdk/types": "3.495.0", + "@smithy/credential-provider-imds": "^2.2.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/shared-ini-file-loader": "^2.3.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -411,20 +426,20 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.468.0.tgz", - "integrity": "sha512-iZlWWZXp6zAH4sP3VrqF7RpAmzl8Qr8tuVkF7ubUZhzyWzKfhLVzqRJqbMYCBPGmfZLAZWjsziPHaBErYkG/5g==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.468.0", - "@aws-sdk/credential-provider-ini": "3.468.0", - "@aws-sdk/credential-provider-process": "3.468.0", - "@aws-sdk/credential-provider-sso": "3.468.0", - "@aws-sdk/credential-provider-web-identity": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@smithy/credential-provider-imds": "^2.0.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.495.0.tgz", + "integrity": "sha512-OH3lV7erPLNxkZQ+QBEgX353mseelBaHutyJNFKdgCYMZUhENu2DNTvkasGtwA24TqG0sRiuO2yNhpqP8IF+LA==", + "dependencies": { + "@aws-sdk/credential-provider-env": "3.495.0", + "@aws-sdk/credential-provider-ini": "3.495.0", + "@aws-sdk/credential-provider-process": "3.495.0", + "@aws-sdk/credential-provider-sso": "3.495.0", + "@aws-sdk/credential-provider-web-identity": "3.495.0", + "@aws-sdk/types": "3.495.0", + "@smithy/credential-provider-imds": "^2.2.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/shared-ini-file-loader": "^2.3.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -432,14 +447,14 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.468.0.tgz", - "integrity": "sha512-OYSn1A/UsyPJ7Z8Q2cNhTf55O36shPmSsvOfND04nSfu1nPaR+VUvvsP7v+brhGpwC/GAKTIdGAo4blH31BS6A==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.495.0.tgz", + "integrity": "sha512-AouHJtg5qXeqzlY5plqbBkQPea1Kd3/tz9wfN+d5gbTUsDBlV7R6IinzhJWWgniS0jsaEOronlCXLIEOWUzTsw==", + "dependencies": { + "@aws-sdk/types": "3.495.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/shared-ini-file-loader": "^2.3.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -447,16 +462,16 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.468.0.tgz", - "integrity": "sha512-eIdGoIw10xyBm7TDcV5Y/W7tzNs2f4H+2G5ZdjG2XGLAELsKCoixe+9ZB662MLtLCxvm7eE1GjOjKsSua6MImQ==", - "dependencies": { - "@aws-sdk/client-sso": "3.468.0", - "@aws-sdk/token-providers": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/types": "^2.7.0", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.495.0.tgz", + "integrity": "sha512-brbgLtws+jmBPm6FrQ0CT2mHCgFKdopwxJj/4+j//OH0aAgzBH5gOztoDu1R556KU9K8Co220J79gJWV3s40zQ==", + "dependencies": { + "@aws-sdk/client-sso": "3.495.0", + "@aws-sdk/token-providers": "3.495.0", + "@aws-sdk/types": "3.495.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/shared-ini-file-loader": "^2.3.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -464,13 +479,13 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.468.0.tgz", - "integrity": "sha512-rexymPmXjtkwCPfhnUq3EjO1rSkf39R4Jz9CqiM7OsqK2qlT5Y/V3gnMKn0ZMXsYaQOMfM3cT5xly5R+OKDHlw==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.495.0.tgz", + "integrity": "sha512-w4S01mdQZ8kQn4J6CM2Fgral9xtNBh8h5i4DWSOwFxfiokott59zDoFMWJRUdUHzXsnAGULC8+wJ4VeiZZBq1Q==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/types": "^2.7.0", + "@aws-sdk/types": "3.495.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -478,13 +493,13 @@ } }, "node_modules/@aws-sdk/lib-storage": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.468.0.tgz", - "integrity": "sha512-0z2dtg0YQOik6kNM7Xyqgwjk1n5P4hdNVD3MGcjYElPBnp5jVIIZSv7KGaMzgtKSCaHtkjqMidS1DS8Oae9YJg==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.495.0.tgz", + "integrity": "sha512-/Vypp54qRUeXMeGVS6DPplK1kK/uzDIH6wl9hR9XxZCXHzKaDoC8O9uLE+9c4LLJy+/mC9KjpQUq9WMs2QRo5g==", "dependencies": { - "@smithy/abort-controller": "^2.0.1", - "@smithy/middleware-endpoint": "^2.2.2", - "@smithy/smithy-client": "^2.1.18", + "@smithy/abort-controller": "^2.1.0", + "@smithy/middleware-endpoint": "^2.4.0", + "@smithy/smithy-client": "^2.3.0", "buffer": "5.6.0", "events": "3.3.0", "stream-browserify": "3.0.0", @@ -498,16 +513,16 @@ } }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.468.0.tgz", - "integrity": "sha512-Dak7sSaPxkTWuBzvFI0zXL1t+/6JdeZZVLRckp2reoQ46CY/hnCbd5/wITtO7CYyjHX7WrEILjTynfZoa1E7Qw==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-arn-parser": "3.465.0", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", - "@smithy/util-config-provider": "^2.0.0", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.495.0.tgz", + "integrity": "sha512-KJ9hvVFsDIavaUWwT+nDcbyHNNYx0GQ9W0HQ136VR0Uuy3srHrIU2QivmhUi2n8SaDptm4t2K4osSKqgfxH3cQ==", + "dependencies": { + "@aws-sdk/types": "3.495.0", + "@aws-sdk/util-arn-parser": "3.495.0", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/types": "^2.9.0", + "@smithy/util-config-provider": "^2.2.0", "tslib": "^2.5.0" }, "engines": { @@ -515,13 +530,13 @@ } }, "node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.468.0.tgz", - "integrity": "sha512-/wmLjmfgeulxhhmnxX3X3N933TvGsYckVIFjAtDSpLjqkbwzEcNiLq7AdmNJ4BfxG0MCMgcht561DCCD19x8Bg==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.495.0.tgz", + "integrity": "sha512-WbSZ2AquYb6Wfdr3CZRO37dOSFhE2pnR7GuST+kWEYL+sLnNN3Ms85Bf2YUHNqnTNwD/R7KWw6I5CkyDRxLnkw==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", + "@aws-sdk/types": "3.495.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -529,17 +544,17 @@ } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.468.0.tgz", - "integrity": "sha512-LQwL/N5MCj3Y5keLLewHTqeAXUIMsHFZyxDXRm/uxrOon9ufLKDvGvzAmfwn1/CuSUo66ZfT8VPSA4BsC90RtA==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.495.0.tgz", + "integrity": "sha512-9pgwS4oLi0DhVo8V2dk6JB5HH5FOyLmnwBABWXDy3ASR6L7Rs+y/y3+jiS/wl7nUNOEFXbBfvdaQ1bI1t6+MDA==", "dependencies": { "@aws-crypto/crc32": "3.0.0", "@aws-crypto/crc32c": "3.0.0", - "@aws-sdk/types": "3.468.0", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", - "@smithy/util-utf8": "^2.0.2", + "@aws-sdk/types": "3.495.0", + "@smithy/is-array-buffer": "^2.1.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/types": "^2.9.0", + "@smithy/util-utf8": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -547,13 +562,13 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.468.0.tgz", - "integrity": "sha512-gwQ+/QhX+lhof304r6zbZ/V5l5cjhGRxLL3CjH1uJPMcOAbw9wUlMdl+ibr8UwBZ5elfKFGiB1cdW/0uMchw0w==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.495.0.tgz", + "integrity": "sha512-qqE6mVxbyJwn59NQMvtYyaZT3GEZnmsvBUry3sDtU7Be1g9w5OKhY4CnAAQyXZI288iQUtyxxDh+hnSLy6RFjA==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", + "@aws-sdk/types": "3.495.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -561,12 +576,12 @@ } }, "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.468.0.tgz", - "integrity": "sha512-0gBX/lDynQr4YIhM9h1dVnkVWqrg+34iOCVIUq8jHxzUzgZWglGkG9lHGGg0r1xkLTmegeoo1OKH8wrQ6n33Cg==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.495.0.tgz", + "integrity": "sha512-XFgoK+Pr4olMo6VqUnffwi7XvnoJv7Lm8qlZ5LiijcQGl7ZJZ9FOwYzrbGX8CuTXwfydOKrxyPNywUsS5LDeDw==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/types": "^2.7.0", + "@aws-sdk/types": "3.495.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -574,12 +589,12 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.468.0.tgz", - "integrity": "sha512-X5XHKV7DHRXI3f29SAhJPe/OxWRFgDWDMMCALfzhmJfCi6Jfh0M14cJKoC+nl+dk9lB+36+jKjhjETZaL2bPlA==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.495.0.tgz", + "integrity": "sha512-sgmr9fpCSg3rFvMnvfKeN7dhY+AmUpZPPWyc+s1kgQONeLUUxQkbdqR2/V+tz2ZPxUBD2dToTG/JhtMcIKmt4Q==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/types": "^2.7.0", + "@aws-sdk/types": "3.495.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -587,13 +602,13 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.468.0.tgz", - "integrity": "sha512-vch9IQib2Ng9ucSyRW2eKNQXHUPb5jUPCLA5otTW/8nGjcOU37LxQG4WrxO7uaJ9Oe8hjHO+hViE3P0KISUhtA==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.495.0.tgz", + "integrity": "sha512-jhuOcLsMrHengJy/oz6Waumwx/vtSMKnEbROR7qZ7CaTDHRUbriPYXGen7CHCs/6aWN0UeI3JBAqwlnSW5tpIg==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", + "@aws-sdk/types": "3.495.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -601,32 +616,18 @@ } }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.468.0.tgz", - "integrity": "sha512-8Ma8tdHYH0stMmGQHh/8eI53oAfiuUJvnQdILWcNArAwlVXt+DJirCSGWP8SqvYdKGa4+jr1YW3+nTdhnm2FZg==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-arn-parser": "3.465.0", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/protocol-http": "^3.0.11", - "@smithy/signature-v4": "^2.0.0", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/util-config-provider": "^2.0.0", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.468.0.tgz", - "integrity": "sha512-xRy8NKfHbmafHwdbotdWgHBvRs0YZgk20GrhFJKp43bkqVbJ5bNlh3nQXf1DeFY9fARR84Bfotya4fwCUHWgZg==", - "dependencies": { - "@aws-sdk/middleware-signing": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@smithy/types": "^2.7.0", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.495.0.tgz", + "integrity": "sha512-H6DPpRKJZaaElLo60nyZNGcZHrCVMq8tErEQPD/g5v4ZrAjLJlxJ1N/hVhw5IP3Q6ZXVNB2PhNi6pp9Lzd1kqQ==", + "dependencies": { + "@aws-sdk/types": "3.495.0", + "@aws-sdk/util-arn-parser": "3.495.0", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/signature-v4": "^2.1.0", + "@smithy/smithy-client": "^2.3.0", + "@smithy/types": "^2.9.0", + "@smithy/util-config-provider": "^2.2.0", "tslib": "^2.5.0" }, "engines": { @@ -634,16 +635,16 @@ } }, "node_modules/@aws-sdk/middleware-signing": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.468.0.tgz", - "integrity": "sha512-s+7fSB1gdnnTj5O0aCCarX3z5Vppop8kazbNSZADdkfHIDWCN80IH4ZNjY3OWqaAz0HmR4LNNrovdR304ojb4Q==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.7.0", - "@smithy/util-middleware": "^2.0.8", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.495.0.tgz", + "integrity": "sha512-QZuWRo6JQ7UKeHzqqnP/qmUXirVKXSMXSEFtpOHio/JkQPASVlD1TNs5L6RL7dKrnqLrg/jpTiw4b0UdAU8kOw==", + "dependencies": { + "@aws-sdk/types": "3.495.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/signature-v4": "^2.1.0", + "@smithy/types": "^2.9.0", + "@smithy/util-middleware": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -651,12 +652,12 @@ } }, "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.468.0.tgz", - "integrity": "sha512-y1qLW24wRkOGBTK5d6eJXf6d8HYo4rzT4a1mNDN1rd18NSffwQ6Yke5qeUiIaxa0y/l+FvvNYErbhYtij2rJoQ==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.495.0.tgz", + "integrity": "sha512-obXxHpCY8NPFgCkiqANLgTa0T1bAlEJCgXVsmCWasKLW1rrMrtVuJBNyOtk0NPx2XCJodsKJc+/9Mz8ByEOd5A==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/types": "^2.7.0", + "@aws-sdk/types": "3.495.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -664,14 +665,14 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.468.0.tgz", - "integrity": "sha512-lmqaEChVWK6MvNpM/LH504pRsP3p/IuZugWwxCbelKw4bGVU4IgG3mbjfATiIlHo4rW8ttHh1bTsZIGjWOqNeA==", - "dependencies": { - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.468.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.495.0.tgz", + "integrity": "sha512-n+lC43Z7+LyAF7b63bR+e5pBmBqPaqh4gupEmrORc4wKsX7U4OncDPiVn5jPD7ZC3IZbLeTuDsjQOK8Ev+Hraw==", + "dependencies": { + "@aws-sdk/types": "3.495.0", + "@aws-sdk/util-endpoints": "3.495.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -679,14 +680,15 @@ } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.468.0.tgz", - "integrity": "sha512-EkDfaumuBhDJFg4lmvWiBE8Ln4BF6hYNC2YfkjKCTEuePy5BKryFedwylYZZ3CJG/uVyfr8xBy+mvoR8plpHjg==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.7", - "@smithy/types": "^2.7.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.8", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.495.0.tgz", + "integrity": "sha512-ZgixNb+8dWUvc42Uso2fh38U7W7wW4OESUmQIFQzYW58B1ylZ4xuq/mo0xSY5b5j6u/+pJadvlIpx/QYBafVHg==", + "dependencies": { + "@aws-sdk/types": "3.495.0", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/types": "^2.9.0", + "@smithy/util-config-provider": "^2.2.0", + "@smithy/util-middleware": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -694,17 +696,17 @@ } }, "node_modules/@aws-sdk/s3-request-presigner": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.468.0.tgz", - "integrity": "sha512-B01d7O3LXaF+WWmDTUaALy/lYM7bMd/i3xJ0MvnypaFosUoE9qmWdq0+lGF2BUExCXe+uZ7ID0rtwXKNsHrExA==", - "dependencies": { - "@aws-sdk/signature-v4-multi-region": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-format-url": "3.468.0", - "@smithy/middleware-endpoint": "^2.2.2", - "@smithy/protocol-http": "^3.0.11", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.495.0.tgz", + "integrity": "sha512-k/m4DhDiNRbp6nz8Mf+OMnL8p9tHdUVsekMpwiBg9VuunhwHI9tw+kBrvN14C1iMpw6VEUUbYNGeoqT9hdd/Zg==", + "dependencies": { + "@aws-sdk/signature-v4-multi-region": "3.495.0", + "@aws-sdk/types": "3.495.0", + "@aws-sdk/util-format-url": "3.495.0", + "@smithy/middleware-endpoint": "^2.4.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/smithy-client": "^2.3.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -712,15 +714,15 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.468.0.tgz", - "integrity": "sha512-ADMWVrqUUjaiWmK7IcBuekOd8nNW6qV1G8ZM9Dgu2U7ezC4gzgZ3IFqZRcQXANX32EC1K3EpDx6fhPpOE/Unbg==", - "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/signature-v4": "^2.0.0", - "@smithy/types": "^2.7.0", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.495.0.tgz", + "integrity": "sha512-+U9Gpdafo8MYp98eRTx5flIazRdHWWv3UJVSteOaJRA1yErdM0IlwJRZAF1Q1E7sqzDP6ed4OkzcMLkpVG/clA==", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.495.0", + "@aws-sdk/types": "3.495.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/signature-v4": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -728,46 +730,46 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.468.0.tgz", - "integrity": "sha512-IpLbthZmFXotwtgkE1Bw4HcKjwpAsGM+6iTXs4amZJqllJClOgyV/sV5Cze+8AqanfCZoPIFTmXyg8LfJTYwbw==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.495.0.tgz", + "integrity": "sha512-1JSEx82FMKNNtPoV5NRpFxi0XHgfvonCKb4+2lR/k4nljqeysZPnOaIW/7C1eAwhoJ6buEIVxoHscemBtdKo+A==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/middleware-host-header": "3.468.0", - "@aws-sdk/middleware-logger": "3.468.0", - "@aws-sdk/middleware-recursion-detection": "3.468.0", - "@aws-sdk/middleware-user-agent": "3.468.0", - "@aws-sdk/region-config-resolver": "3.468.0", - "@aws-sdk/types": "3.468.0", - "@aws-sdk/util-endpoints": "3.468.0", - "@aws-sdk/util-user-agent-browser": "3.468.0", - "@aws-sdk/util-user-agent-node": "3.468.0", - "@smithy/config-resolver": "^2.0.20", - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/hash-node": "^2.0.17", - "@smithy/invalid-dependency": "^2.0.15", - "@smithy/middleware-content-length": "^2.0.17", - "@smithy/middleware-endpoint": "^2.2.2", - "@smithy/middleware-retry": "^2.0.23", - "@smithy/middleware-serde": "^2.0.15", - "@smithy/middleware-stack": "^2.0.9", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/property-provider": "^2.0.0", - "@smithy/protocol-http": "^3.0.11", - "@smithy/shared-ini-file-loader": "^2.0.6", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-body-length-browser": "^2.0.1", - "@smithy/util-body-length-node": "^2.1.0", - "@smithy/util-defaults-mode-browser": "^2.0.22", - "@smithy/util-defaults-mode-node": "^2.0.28", - "@smithy/util-endpoints": "^1.0.6", - "@smithy/util-retry": "^2.0.8", - "@smithy/util-utf8": "^2.0.2", + "@aws-sdk/middleware-host-header": "3.495.0", + "@aws-sdk/middleware-logger": "3.495.0", + "@aws-sdk/middleware-recursion-detection": "3.495.0", + "@aws-sdk/middleware-user-agent": "3.495.0", + "@aws-sdk/region-config-resolver": "3.495.0", + "@aws-sdk/types": "3.495.0", + "@aws-sdk/util-endpoints": "3.495.0", + "@aws-sdk/util-user-agent-browser": "3.495.0", + "@aws-sdk/util-user-agent-node": "3.495.0", + "@smithy/config-resolver": "^2.1.0", + "@smithy/fetch-http-handler": "^2.4.0", + "@smithy/hash-node": "^2.1.0", + "@smithy/invalid-dependency": "^2.1.0", + "@smithy/middleware-content-length": "^2.1.0", + "@smithy/middleware-endpoint": "^2.4.0", + "@smithy/middleware-retry": "^2.1.0", + "@smithy/middleware-serde": "^2.1.0", + "@smithy/middleware-stack": "^2.1.0", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/node-http-handler": "^2.3.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/shared-ini-file-loader": "^2.3.0", + "@smithy/smithy-client": "^2.3.0", + "@smithy/types": "^2.9.0", + "@smithy/url-parser": "^2.1.0", + "@smithy/util-base64": "^2.1.0", + "@smithy/util-body-length-browser": "^2.1.0", + "@smithy/util-body-length-node": "^2.2.0", + "@smithy/util-defaults-mode-browser": "^2.1.0", + "@smithy/util-defaults-mode-node": "^2.1.0", + "@smithy/util-endpoints": "^1.1.0", + "@smithy/util-retry": "^2.1.0", + "@smithy/util-utf8": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -775,11 +777,11 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.468.0.tgz", - "integrity": "sha512-rx/9uHI4inRbp2tw3Y4Ih4PNZkVj32h7WneSg3MVgVjAoVD5Zti9KhS5hkvsBxfgmQmg0AQbE+b1sy5WGAgntA==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.495.0.tgz", + "integrity": "sha512-KUpo2U1rD4U6gT1QNPUJGmbQnruvIJmPeuyKndil6h2zkCpG5I0AHE8ixpfuBbizIZQOIA/26pArQivDChOD9A==", "dependencies": { - "@smithy/types": "^2.7.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -787,9 +789,9 @@ } }, "node_modules/@aws-sdk/util-arn-parser": { - "version": "3.465.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.465.0.tgz", - "integrity": "sha512-zOJ82vzDJFqBX9yZBlNeHHrul/kpx/DCoxzW5UBbZeb26kfV53QhMSoEmY8/lEbBqlqargJ/sgRC845GFhHNQw==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.495.0.tgz", + "integrity": "sha512-hwdA3XAippSEUxs7jpznwD63YYFR+LtQvlEcebPTgWR9oQgG9TfS+39PUfbnEeje1ICuOrN3lrFqFbmP9uzbMg==", "dependencies": { "tslib": "^2.5.0" }, @@ -798,12 +800,13 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.468.0.tgz", - "integrity": "sha512-P91EbMG2+1ZToJeTLaRkdO7qM7RI0svuMVLkIdHV9rHR7PeUKUWMpf46xh8rQsIjKC9Arf+I9ueWp3iHJt1T5w==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.495.0.tgz", + "integrity": "sha512-pMJ6rb16y51I4G33xtinkXAXH/2mQ0WZCwoh1sNkCM2MUfZDw9zAyP+PvB2tpEytQX8Fc7bR4qIP+td+pPEXAg==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/util-endpoints": "^1.0.6", + "@aws-sdk/types": "3.495.0", + "@smithy/types": "^2.9.0", + "@smithy/util-endpoints": "^1.1.0", "tslib": "^2.5.0" }, "engines": { @@ -811,13 +814,13 @@ } }, "node_modules/@aws-sdk/util-format-url": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.468.0.tgz", - "integrity": "sha512-CtHApPmudJz/Z2MHVogWfkaSw4wWHQKVLQs4Q5XjvLcDSzODzxHbiOIckFCXQm2Mme4+TTe4GFU9g869ufegXg==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-format-url/-/util-format-url-3.495.0.tgz", + "integrity": "sha512-CmZcUoD2C+VSVvhAOpezkTyEiaGS31zJH8QNCvuKb/QA4yaZSdUrq4FUS9oxsVQr04MxjXVEfPZ427l0LTH1ow==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/querystring-builder": "^2.0.15", - "@smithy/types": "^2.7.0", + "@aws-sdk/types": "3.495.0", + "@smithy/querystring-builder": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -825,9 +828,9 @@ } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.465.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.465.0.tgz", - "integrity": "sha512-f+QNcWGswredzC1ExNAB/QzODlxwaTdXkNT5cvke2RLX8SFU5pYk6h4uCtWC0vWPELzOfMfloBrJefBzlarhsw==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.495.0.tgz", + "integrity": "sha512-MfaPXT0kLX2tQaR90saBT9fWQq2DHqSSJRzW+MZWsmF+y5LGCOhO22ac/2o6TKSQm7h0HRc2GaADqYYYor62yg==", "dependencies": { "tslib": "^2.5.0" }, @@ -836,24 +839,24 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.468.0.tgz", - "integrity": "sha512-OJyhWWsDEizR3L+dCgMXSUmaCywkiZ7HSbnQytbeKGwokIhD69HTiJcibF/sgcM5gk4k3Mq3puUhGnEZ46GIig==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.495.0.tgz", + "integrity": "sha512-CIlY54aKahUqF4kygbMkDkFRc9t+8Km/r+IWapy91h0Exy84V+S47MJdAelsMg8Id6hZ47jWmuuzz5UcjU/+sQ==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/types": "^2.7.0", + "@aws-sdk/types": "3.495.0", + "@smithy/types": "^2.9.0", "bowser": "^2.11.0", "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.468.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.468.0.tgz", - "integrity": "sha512-9p+Zyp6xmJUkcryTNmQQwdhRK6gAC6zVEJZLomLGQhD7sWcCzstolw//mAS3AKVQFYWnCEGKrDJdgT0KObCf4g==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.495.0.tgz", + "integrity": "sha512-BbEwwh9SCtMrcNES0u4q5/8BjAKkOiHGia0gDSlQHOmEzXxYvhx0ByRMaPeprL06iESFa6HcleJWenWktfxk3g==", "dependencies": { - "@aws-sdk/types": "3.468.0", - "@smithy/node-config-provider": "^2.1.7", - "@smithy/types": "^2.7.0", + "@aws-sdk/types": "3.495.0", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -877,10 +880,11 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.465.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.465.0.tgz", - "integrity": "sha512-9TKW5ZgsReygePTnAUdvaqxr/k1HXsEz2yDnk/jTLaUeRPsd5la8fFjb6OfgYYlbEVNlxTcKzaqOdrqxpUkmyQ==", + "version": "3.495.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.495.0.tgz", + "integrity": "sha512-bBrVLuldAnv53E9XvZD9MtW1dIWJXFswP8/JZuMdDQCyJh9ObjvUe/lFhTJ/AuNqEdujyE1nD4O1R7stzyBqOA==", "dependencies": { + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -888,9 +892,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", - "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz", + "integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==", "bin": { "parser": "bin/babel-parser.js" }, @@ -920,10 +924,26 @@ "esbuild": "*" } }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz", + "integrity": "sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@esbuild/android-arm": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.8.tgz", - "integrity": "sha512-31E2lxlGM1KEfivQl8Yf5aYU/mflz9g06H6S15ITUFQueMFtFjESRMoDSkvMo8thYvLBax+VKTPlpnx+sPicOA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.11.tgz", + "integrity": "sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==", "cpu": [ "arm" ], @@ -932,15 +952,14 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.8.tgz", - "integrity": "sha512-B8JbS61bEunhfx8kasogFENgQfr/dIp+ggYXwTqdbMAgGDhRa3AaPpQMuQU0rNxDLECj6FhDzk1cF9WHMVwrtA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz", + "integrity": "sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==", "cpu": [ "arm64" ], @@ -949,15 +968,14 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.8.tgz", - "integrity": "sha512-rdqqYfRIn4jWOp+lzQttYMa2Xar3OK9Yt2fhOhzFXqg0rVWEfSclJvZq5fZslnz6ypHvVf3CT7qyf0A5pM682A==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.11.tgz", + "integrity": "sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==", "cpu": [ "x64" ], @@ -966,15 +984,14 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.8.tgz", - "integrity": "sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz", + "integrity": "sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==", "cpu": [ "arm64" ], @@ -983,15 +1000,14 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.8.tgz", - "integrity": "sha512-3sur80OT9YdeZwIVgERAysAbwncom7b4bCI2XKLjMfPymTud7e/oY4y+ci1XVp5TfQp/bppn7xLw1n/oSQY3/Q==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz", + "integrity": "sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==", "cpu": [ "x64" ], @@ -1000,15 +1016,14 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.8.tgz", - "integrity": "sha512-WAnPJSDattvS/XtPCTj1tPoTxERjcTpH6HsMr6ujTT+X6rylVe8ggxk8pVxzf5U1wh5sPODpawNicF5ta/9Tmw==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz", + "integrity": "sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==", "cpu": [ "arm64" ], @@ -1017,15 +1032,14 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.8.tgz", - "integrity": "sha512-ICvZyOplIjmmhjd6mxi+zxSdpPTKFfyPPQMQTK/w+8eNK6WV01AjIztJALDtwNNfFhfZLux0tZLC+U9nSyA5Zg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz", + "integrity": "sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==", "cpu": [ "x64" ], @@ -1034,15 +1048,14 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.8.tgz", - "integrity": "sha512-H4vmI5PYqSvosPaTJuEppU9oz1dq2A7Mr2vyg5TF9Ga+3+MGgBdGzcyBP7qK9MrwFQZlvNyJrvz6GuCaj3OukQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz", + "integrity": "sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==", "cpu": [ "arm" ], @@ -1051,15 +1064,14 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.8.tgz", - "integrity": "sha512-z1zMZivxDLHWnyGOctT9JP70h0beY54xDDDJt4VpTX+iwA77IFsE1vCXWmprajJGa+ZYSqkSbRQ4eyLCpCmiCQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz", + "integrity": "sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==", "cpu": [ "arm64" ], @@ -1068,15 +1080,14 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.8.tgz", - "integrity": "sha512-1a8suQiFJmZz1khm/rDglOc8lavtzEMRo0v6WhPgxkrjcU0LkHj+TwBrALwoz/OtMExvsqbbMI0ChyelKabSvQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz", + "integrity": "sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==", "cpu": [ "ia32" ], @@ -1085,15 +1096,14 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.8.tgz", - "integrity": "sha512-fHZWS2JJxnXt1uYJsDv9+b60WCc2RlvVAy1F76qOLtXRO+H4mjt3Tr6MJ5l7Q78X8KgCFudnTuiQRBhULUyBKQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz", + "integrity": "sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==", "cpu": [ "loong64" ], @@ -1102,15 +1112,14 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.8.tgz", - "integrity": "sha512-Wy/z0EL5qZYLX66dVnEg9riiwls5IYnziwuju2oUiuxVc+/edvqXa04qNtbrs0Ukatg5HEzqT94Zs7J207dN5Q==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz", + "integrity": "sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==", "cpu": [ "mips64el" ], @@ -1119,15 +1128,14 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.8.tgz", - "integrity": "sha512-ETaW6245wK23YIEufhMQ3HSeHO7NgsLx8gygBVldRHKhOlD1oNeNy/P67mIh1zPn2Hr2HLieQrt6tWrVwuqrxg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz", + "integrity": "sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==", "cpu": [ "ppc64" ], @@ -1136,15 +1144,14 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.8.tgz", - "integrity": "sha512-T2DRQk55SgoleTP+DtPlMrxi/5r9AeFgkhkZ/B0ap99zmxtxdOixOMI570VjdRCs9pE4Wdkz7JYrsPvsl7eESg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz", + "integrity": "sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==", "cpu": [ "riscv64" ], @@ -1153,15 +1160,14 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.8.tgz", - "integrity": "sha512-NPxbdmmo3Bk7mbNeHmcCd7R7fptJaczPYBaELk6NcXxy7HLNyWwCyDJ/Xx+/YcNH7Im5dHdx9gZ5xIwyliQCbg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz", + "integrity": "sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==", "cpu": [ "s390x" ], @@ -1170,15 +1176,14 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.8.tgz", - "integrity": "sha512-lytMAVOM3b1gPypL2TRmZ5rnXl7+6IIk8uB3eLsV1JwcizuolblXRrc5ShPrO9ls/b+RTp+E6gbsuLWHWi2zGg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz", + "integrity": "sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==", "cpu": [ "x64" ], @@ -1187,15 +1192,14 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.8.tgz", - "integrity": "sha512-hvWVo2VsXz/8NVt1UhLzxwAfo5sioj92uo0bCfLibB0xlOmimU/DeAEsQILlBQvkhrGjamP0/el5HU76HAitGw==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz", + "integrity": "sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==", "cpu": [ "x64" ], @@ -1204,15 +1208,14 @@ "os": [ "netbsd" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.8.tgz", - "integrity": "sha512-/7Y7u77rdvmGTxR83PgaSvSBJCC2L3Kb1M/+dmSIvRvQPXXCuC97QAwMugBNG0yGcbEGfFBH7ojPzAOxfGNkwQ==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz", + "integrity": "sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==", "cpu": [ "x64" ], @@ -1221,15 +1224,14 @@ "os": [ "openbsd" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.8.tgz", - "integrity": "sha512-9Lc4s7Oi98GqFA4HzA/W2JHIYfnXbUYgekUP/Sm4BG9sfLjyv6GKKHKKVs83SMicBF2JwAX6A1PuOLMqpD001w==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz", + "integrity": "sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==", "cpu": [ "x64" ], @@ -1238,15 +1240,14 @@ "os": [ "sunos" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.8.tgz", - "integrity": "sha512-rq6WzBGjSzihI9deW3fC2Gqiak68+b7qo5/3kmB6Gvbh/NYPA0sJhrnp7wgV4bNwjqM+R2AApXGxMO7ZoGhIJg==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz", + "integrity": "sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==", "cpu": [ "arm64" ], @@ -1255,15 +1256,14 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.8.tgz", - "integrity": "sha512-AIAbverbg5jMvJznYiGhrd3sumfwWs8572mIJL5NQjJa06P8KfCPWZQ0NwZbPQnbQi9OWSZhFVSUWjjIrn4hSw==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz", + "integrity": "sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==", "cpu": [ "ia32" ], @@ -1272,15 +1272,14 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=12" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.8.tgz", - "integrity": "sha512-bfZ0cQ1uZs2PqpulNL5j/3w+GDhP36k1K5c38QdQg+Swy51jFZWWeIkteNsufkQxp986wnqRRsb/bHbY1WQ7TA==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz", + "integrity": "sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==", "cpu": [ "x64" ], @@ -1289,7 +1288,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">=12" } @@ -1382,13 +1380,13 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -1409,9 +1407,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@jridgewell/sourcemap-codec": { @@ -1465,19 +1463,11 @@ "node": ">= 8" } }, - "node_modules/@pkgr/utils": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", - "integrity": "sha512-POgTXhjrTfbTV63DiFXav4lBHiICLKKwDeaKn9Nphwj7WH6m0hMMCaJkMyRWjgtPFyRKRVoMXXjczsTQRDEhYw==", + "node_modules/@pkgr/core": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", + "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "fast-glob": "^3.3.0", - "is-glob": "^4.0.3", - "open": "^9.1.0", - "picocolors": "^1.0.0", - "tslib": "^2.6.0" - }, "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, @@ -1494,6 +1484,175 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.5.tgz", + "integrity": "sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.5.tgz", + "integrity": "sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.5.tgz", + "integrity": "sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.5.tgz", + "integrity": "sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.5.tgz", + "integrity": "sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.5.tgz", + "integrity": "sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.5.tgz", + "integrity": "sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.5.tgz", + "integrity": "sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.5.tgz", + "integrity": "sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.5.tgz", + "integrity": "sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.5.tgz", + "integrity": "sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.5.tgz", + "integrity": "sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.5.tgz", + "integrity": "sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rushstack/eslint-patch": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", @@ -1501,11 +1660,11 @@ "dev": true }, "node_modules/@smithy/abort-controller": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.0.15.tgz", - "integrity": "sha512-JkS36PIS3/UCbq/MaozzV7jECeL+BTt4R75bwY8i+4RASys4xOyUS1HsRyUNSqUXFP4QyCz5aNnh3ltuaxv+pw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-2.1.0.tgz", + "integrity": "sha512-fyPlWpzXyKzDVRRMUbsfH7AV/2xX+dyZ5RqeEo6Hjz9YUvDMGVSnm88iHH0zqZ+XmH4+sH4+mhwRL76HXX65uw==", "dependencies": { - "@smithy/types": "^2.7.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1513,31 +1672,49 @@ } }, "node_modules/@smithy/chunked-blob-reader": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.0.0.tgz", - "integrity": "sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-2.1.0.tgz", + "integrity": "sha512-meKoKCIXxixSGzUGVXGc1lnn6cEM21XzknDfUmHopPCaYSgt86w3gaJSua8Gr3VYcSkkMTW2MyAygTXprLEOZQ==", "dependencies": { "tslib": "^2.5.0" } }, "node_modules/@smithy/chunked-blob-reader-native": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.0.1.tgz", - "integrity": "sha512-N2oCZRglhWKm7iMBu7S6wDzXirjAofi7tAd26cxmgibRYOBS4D3hGfmkwCpHdASZzwZDD8rluh0Rcqw1JeZDRw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-2.1.0.tgz", + "integrity": "sha512-r9fRVRvQXpuWZtHX3VNAP4PQoCXvRDqcwr15TbaKSdtEJ/f0IPHDQ+M2MOEsYt2234FkNqCzAqtmeJrjpNak2g==", "dependencies": { - "@smithy/util-base64": "^2.0.1", + "@smithy/util-base64": "^2.1.0", "tslib": "^2.5.0" } }, "node_modules/@smithy/config-resolver": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.0.21.tgz", - "integrity": "sha512-rlLIGT+BeqjnA6C2FWumPRJS1UW07iU5ZxDHtFuyam4W65gIaOFMjkB90ofKCIh+0mLVQrQFrl/VLtQT/6FWTA==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.8", - "@smithy/types": "^2.7.0", - "@smithy/util-config-provider": "^2.0.0", - "@smithy/util-middleware": "^2.0.8", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-2.1.0.tgz", + "integrity": "sha512-NcR1Hw2uZgwHT7/KFsQH76YHb/mNGLFu+hS0ODnoFUpViE8ddIVOXm/8sgwdh0QvFPtWGzPn0Wcp19Cm31wv2A==", + "dependencies": { + "@smithy/node-config-provider": "^2.2.0", + "@smithy/types": "^2.9.0", + "@smithy/util-config-provider": "^2.2.0", + "@smithy/util-middleware": "^2.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/core": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-1.3.0.tgz", + "integrity": "sha512-XoU9eiICwhxZIyAdugijyD/YqsumDQ3FgGyFSJibO60qoUkdfMGSjnIvrTemjFBdnDsj4B26F/ZRxSR3PUJbJQ==", + "dependencies": { + "@smithy/middleware-endpoint": "^2.4.0", + "@smithy/middleware-retry": "^2.1.0", + "@smithy/middleware-serde": "^2.1.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/smithy-client": "^2.3.0", + "@smithy/types": "^2.9.0", + "@smithy/util-middleware": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -1545,14 +1722,14 @@ } }, "node_modules/@smithy/credential-provider-imds": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.1.4.tgz", - "integrity": "sha512-cwPJN1fa1YOQzhBlTXRavABEYRRchci1X79QRwzaNLySnIMJfztyv1Zkst0iZPLMnpn8+CnHu3wOHS11J5Dr3A==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-2.2.0.tgz", + "integrity": "sha512-uqoRizHR8rKih6SuWcJRSv46tdqZk1zPEk6r909O87XO85j21MfUcxRKzbkORM2JOlaFhCH4geRcvlvYfK6EyQ==", "dependencies": { - "@smithy/node-config-provider": "^2.1.8", - "@smithy/property-provider": "^2.0.16", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/types": "^2.9.0", + "@smithy/url-parser": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -1560,23 +1737,23 @@ } }, "node_modules/@smithy/eventstream-codec": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.0.15.tgz", - "integrity": "sha512-crjvz3j1gGPwA0us6cwS7+5gAn35CTmqu/oIxVbYJo2Qm/sGAye6zGJnMDk3BKhWZw5kcU1G4MxciTkuBpOZPg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.1.0.tgz", + "integrity": "sha512-1yQnf8bSycsZ5ICXVMf8pEj1DQSUsw6/3H4nEdzH2+E3RZdNGPjVecQEm9kWPW7fvXvNvzT8MvZOQdk1IWoVTg==", "dependencies": { "@aws-crypto/crc32": "3.0.0", - "@smithy/types": "^2.7.0", - "@smithy/util-hex-encoding": "^2.0.0", + "@smithy/types": "^2.9.0", + "@smithy/util-hex-encoding": "^2.1.0", "tslib": "^2.5.0" } }, "node_modules/@smithy/eventstream-serde-browser": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.0.15.tgz", - "integrity": "sha512-WiFG5N9j3jmS5P0z5Xev6dO0c3lf7EJYC2Ncb0xDnWFvShwXNn741AF71ABr5EcZw8F4rQma0362MMjAwJeZog==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-2.1.0.tgz", + "integrity": "sha512-pMw3HGN8yTGGoAO8z/fOMSSsfJxdtEwQ9p4/Y1eYw07sMlgQUPadwYFtxTMPDDzYvNmTWFjspR/nTBxYiUe8nA==", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.15", - "@smithy/types": "^2.7.0", + "@smithy/eventstream-serde-universal": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1584,11 +1761,11 @@ } }, "node_modules/@smithy/eventstream-serde-config-resolver": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.0.15.tgz", - "integrity": "sha512-o65d2LRjgCbWYH+VVNlWXtmsI231SO99ZTOL4UuIPa6WTjbSHWtlXvUcJG9libhEKWmEV9DIUiH2IqyPWi7ubA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-2.1.0.tgz", + "integrity": "sha512-tFhaEiJtitNmdyW6yLteh0EV+93EsV+CIb4yduwpL/WyMy7Hy7DLbRW5ImypA4auqebjWYBven876RjhpY6XLg==", "dependencies": { - "@smithy/types": "^2.7.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1596,12 +1773,12 @@ } }, "node_modules/@smithy/eventstream-serde-node": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.0.15.tgz", - "integrity": "sha512-9OOXiIhHq1VeOG6xdHkn2ZayfMYM3vzdUTV3zhcCnt+tMqA3BJK3XXTJFRR2BV28rtRM778DzqbBTf+hqwQPTg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-2.1.0.tgz", + "integrity": "sha512-/asga1STbTgxQ+ma/VfsjXlUHTH/Fofor4RZLhPAMpQ6lfVxJTRjm28ONSczcsnRPTWwOoiFBiXutM68WgK6IQ==", "dependencies": { - "@smithy/eventstream-serde-universal": "^2.0.15", - "@smithy/types": "^2.7.0", + "@smithy/eventstream-serde-universal": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1609,12 +1786,12 @@ } }, "node_modules/@smithy/eventstream-serde-universal": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.0.15.tgz", - "integrity": "sha512-dP8AQp/pXlWBjvL0TaPBJC3rM0GoYv7O0Uim8d/7UKZ2Wo13bFI3/BhQfY/1DeiP1m23iCHFNFtOQxfQNBB8rQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-2.1.0.tgz", + "integrity": "sha512-kZtTF0llc5pZ2QLMOrLttA2Cde/DXanfMqBhtJ0VZaQHdntPon+d7Gx7GhOkCxDP4lz1u0wMLdiIZNduaA4Qbg==", "dependencies": { - "@smithy/eventstream-codec": "^2.0.15", - "@smithy/types": "^2.7.0", + "@smithy/eventstream-codec": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1622,36 +1799,36 @@ } }, "node_modules/@smithy/fetch-http-handler": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.3.1.tgz", - "integrity": "sha512-6MNk16fqb8EwcYY8O8WxB3ArFkLZ2XppsSNo1h7SQcFdDDwIumiJeO6wRzm7iB68xvsOQzsdQKbdtTieS3hfSQ==", - "dependencies": { - "@smithy/protocol-http": "^3.0.11", - "@smithy/querystring-builder": "^2.0.15", - "@smithy/types": "^2.7.0", - "@smithy/util-base64": "^2.0.1", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-2.4.0.tgz", + "integrity": "sha512-fLhPNfbWG8vTcS9PsR1wjHaA54kDcSiAZKVuVAfjHleS7QDWjrCr1SDUqCB2yAc9NBLe2lIDbDL8+i9yoYhxoQ==", + "dependencies": { + "@smithy/protocol-http": "^3.1.0", + "@smithy/querystring-builder": "^2.1.0", + "@smithy/types": "^2.9.0", + "@smithy/util-base64": "^2.1.0", "tslib": "^2.5.0" } }, "node_modules/@smithy/hash-blob-browser": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-2.0.16.tgz", - "integrity": "sha512-cSYRi05LA7DZDwjB1HL0BP8B56eUNNeLglVH147QTXFyuXJq/7erAIiLRfsyXB8+GfFHkSS5BHbc76a7k/AYPA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-2.1.0.tgz", + "integrity": "sha512-MVlH6algsOuEaK745oSoymk7Tusny7AqP2bQ1yPzxJiWpHirHnzEzYP/aqZaZ4gWdSLMFF65WOwL6q2ijuKVgA==", "dependencies": { - "@smithy/chunked-blob-reader": "^2.0.0", - "@smithy/chunked-blob-reader-native": "^2.0.1", - "@smithy/types": "^2.7.0", + "@smithy/chunked-blob-reader": "^2.1.0", + "@smithy/chunked-blob-reader-native": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" } }, "node_modules/@smithy/hash-node": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.0.17.tgz", - "integrity": "sha512-Il6WuBcI1nD+e2DM7tTADMf01wEPGK8PAhz4D+YmDUVaoBqlA+CaH2uDJhiySifmuKBZj748IfygXty81znKhw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-2.1.0.tgz", + "integrity": "sha512-/B7b6NNjw+i4PlwsrYHmxmmrTxp2oRejgZH26HhXE77XWwAiPEI9iHu7GZR9fYhm7Fsj66Z9Bk6JA9aEvUC9/w==", "dependencies": { - "@smithy/types": "^2.7.0", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", + "@smithy/types": "^2.9.0", + "@smithy/util-buffer-from": "^2.1.0", + "@smithy/util-utf8": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -1659,12 +1836,12 @@ } }, "node_modules/@smithy/hash-stream-node": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-2.0.17.tgz", - "integrity": "sha512-ey8DtnATzp1mOXgS7rqMwSmAki6iJA+jgNucKcxRkhMB1rrICfHg+rhmIF50iLPDHUhTcS5pBMOrLzzpZftvNQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-2.1.0.tgz", + "integrity": "sha512-qhgWuXt8sVcDKrFNBRQmcIo6wfzONdeKlKDLsau4kKZ7xlEHScgUFtsAHvspV8sVREJIeMbOq4oSFSVmzvOikQ==", "dependencies": { - "@smithy/types": "^2.7.0", - "@smithy/util-utf8": "^2.0.2", + "@smithy/types": "^2.9.0", + "@smithy/util-utf8": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -1672,18 +1849,18 @@ } }, "node_modules/@smithy/invalid-dependency": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.0.15.tgz", - "integrity": "sha512-dlEKBFFwVfzA5QroHlBS94NpgYjXhwN/bFfun+7w3rgxNvVy79SK0w05iGc7UAeC5t+D7gBxrzdnD6hreZnDVQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-2.1.0.tgz", + "integrity": "sha512-hvryGI0KChV4jMgK/kwr6U4/HaYldzjiQAZ+c//QAMDoCp0KkP0Xt94XqAkr7Uq08577mAMW5U70YCaAx+KjSQ==", "dependencies": { - "@smithy/types": "^2.7.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" } }, "node_modules/@smithy/is-array-buffer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.0.0.tgz", - "integrity": "sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.1.0.tgz", + "integrity": "sha512-XnQvn/6ie5kjFyeW94NqSjGGOdMuB2WnNmDWKHHLVMCR/Emu7B8pcAZX4k8H3tjDujXAQvfBrEgmPRq6FgqmZg==", "dependencies": { "tslib": "^2.5.0" }, @@ -1692,22 +1869,22 @@ } }, "node_modules/@smithy/md5-js": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-2.0.17.tgz", - "integrity": "sha512-jmISTCnEkOnm2oCNx/rMkvBT/eQh3aA6nktevkzbmn/VYqYEuc5Z2n5sTTqsciMSO01Lvf56wG1A4twDqovYeQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-2.1.0.tgz", + "integrity": "sha512-pl0lDIn4i+J2aI2gqlCIsOczPRi+YtXS9noQ/KXMUCqapb6AWomRDAloBBxRTClBFHIV6ife9UQrOhLT/Y+Yrw==", "dependencies": { - "@smithy/types": "^2.7.0", - "@smithy/util-utf8": "^2.0.2", + "@smithy/types": "^2.9.0", + "@smithy/util-utf8": "^2.1.0", "tslib": "^2.5.0" } }, "node_modules/@smithy/middleware-content-length": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.0.17.tgz", - "integrity": "sha512-OyadvMcKC7lFXTNBa8/foEv7jOaqshQZkjWS9coEXPRZnNnihU/Ls+8ZuJwGNCOrN2WxXZFmDWhegbnM4vak8w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-2.1.0.tgz", + "integrity": "sha512-XYhKZPuS8nnecdx0IGGUt1Nt2/ekoVOw1zal4c0ARRaLJEw+umFLxwHUelIeBocbdOcPCeZRE6pdk35Y2T2wpw==", "dependencies": { - "@smithy/protocol-http": "^3.0.11", - "@smithy/types": "^2.7.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1715,16 +1892,16 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.2.3.tgz", - "integrity": "sha512-nYfxuq0S/xoAjdLbyn1ixeVB6cyH9wYCMtbbOCpcCRYR5u2mMtqUtVjjPAZ/DIdlK3qe0tpB0Q76szFGNuz+kQ==", - "dependencies": { - "@smithy/middleware-serde": "^2.0.15", - "@smithy/node-config-provider": "^2.1.8", - "@smithy/shared-ini-file-loader": "^2.2.7", - "@smithy/types": "^2.7.0", - "@smithy/url-parser": "^2.0.15", - "@smithy/util-middleware": "^2.0.8", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-2.4.0.tgz", + "integrity": "sha512-GMebLCihCxIlbPdA/l6WDpNJppIgW5OeTJkIAbqVArg1vFxZ92XhW+UwN12av5OAXswySGJ80/fpDFP7HmSyYg==", + "dependencies": { + "@smithy/middleware-serde": "^2.1.0", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/shared-ini-file-loader": "^2.3.0", + "@smithy/types": "^2.9.0", + "@smithy/url-parser": "^2.1.0", + "@smithy/util-middleware": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -1732,17 +1909,17 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "2.0.24", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.0.24.tgz", - "integrity": "sha512-q2SvHTYu96N7lYrn3VSuX3vRpxXHR/Cig6MJpGWxd0BWodUQUWlKvXpWQZA+lTaFJU7tUvpKhRd4p4MU3PbeJg==", - "dependencies": { - "@smithy/node-config-provider": "^2.1.8", - "@smithy/protocol-http": "^3.0.11", - "@smithy/service-error-classification": "^2.0.8", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", - "@smithy/util-middleware": "^2.0.8", - "@smithy/util-retry": "^2.0.8", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-2.1.0.tgz", + "integrity": "sha512-lGEVds90hFyIAvypH58rwC6j9mrCR2ZwYbcxow7AgW6sWCCoBppz5FtLpgSg6QV/CTRh8K7w4kxGVx8LqINQBg==", + "dependencies": { + "@smithy/node-config-provider": "^2.2.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/service-error-classification": "^2.1.0", + "@smithy/smithy-client": "^2.3.0", + "@smithy/types": "^2.9.0", + "@smithy/util-middleware": "^2.1.0", + "@smithy/util-retry": "^2.1.0", "tslib": "^2.5.0", "uuid": "^8.3.2" }, @@ -1751,11 +1928,11 @@ } }, "node_modules/@smithy/middleware-serde": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.0.15.tgz", - "integrity": "sha512-FOZRFk/zN4AT4wzGuBY+39XWe+ZnCFd0gZtyw3f9Okn2CJPixl9GyWe98TIaljeZdqWkgrzGyPre20AcW2UMHQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-2.1.0.tgz", + "integrity": "sha512-iysAUIDKsc354HMnYVQxMJEzNaOrQQvE86b1oSl2fRwcFqn+9TTi028a37PLFE+ccAiyVGjBjB8PBsAz9plUug==", "dependencies": { - "@smithy/types": "^2.7.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1763,11 +1940,11 @@ } }, "node_modules/@smithy/middleware-stack": { - "version": "2.0.9", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.0.9.tgz", - "integrity": "sha512-bCB5dUtGQ5wh7QNL2ELxmDc6g7ih7jWU3Kx6MYH1h4mZbv9xL3WyhKHojRltThCB1arLPyTUFDi+x6fB/oabtA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-2.1.0.tgz", + "integrity": "sha512-y5Ph/TWfO7oTfxNqKU+uAK5cFRTYeP16ReOmDweq+zQ8NQODDg7LSxsfQT4Wp0mhIvm0bt3pZp66T1YMtnihWw==", "dependencies": { - "@smithy/types": "^2.7.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1775,13 +1952,13 @@ } }, "node_modules/@smithy/node-config-provider": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.1.8.tgz", - "integrity": "sha512-+w26OKakaBUGp+UG+dxYZtFb5fs3tgHg3/QrRrmUZj+rl3cIuw840vFUXX35cVPTUCQIiTqmz7CpVF7+hdINdQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-2.2.0.tgz", + "integrity": "sha512-rU82PFR32Bxo4EMGUJ2BGG+K97zUp9j6SWjG83T2itmbXwA/+DoCc4xCON8kcmdej822x1yLcSzFiTeg0b472w==", "dependencies": { - "@smithy/property-provider": "^2.0.16", - "@smithy/shared-ini-file-loader": "^2.2.7", - "@smithy/types": "^2.7.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/shared-ini-file-loader": "^2.3.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1789,14 +1966,14 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.2.1.tgz", - "integrity": "sha512-8iAKQrC8+VFHPAT8pg4/j6hlsTQh+NKOWlctJBrYtQa4ExcxX7aSg3vdQ2XLoYwJotFUurg/NLqFCmZaPRrogw==", - "dependencies": { - "@smithy/abort-controller": "^2.0.15", - "@smithy/protocol-http": "^3.0.11", - "@smithy/querystring-builder": "^2.0.15", - "@smithy/types": "^2.7.0", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-2.3.0.tgz", + "integrity": "sha512-8jcQaOdrD/X0VihhM2W/KtJ5fvKaT8UpNf/pl/epvLQ6MkAttIMaCLex6xk31BpFSPvS2+q65ZdBBjQ3cMOSiA==", + "dependencies": { + "@smithy/abort-controller": "^2.1.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/querystring-builder": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1804,11 +1981,11 @@ } }, "node_modules/@smithy/property-provider": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.0.16.tgz", - "integrity": "sha512-28Ky0LlOqtEjwg5CdHmwwaDRHcTWfPRzkT6HrhwOSRS2RryAvuDfJrZpM+BMcrdeCyEg1mbcgIMoqTla+rdL8Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.1.0.tgz", + "integrity": "sha512-6cpCSsgwbKHnl567SrthpqLgZ7e5jc7qPHG6wz9U2T24vcUp2yiG0vdAlH1QdTH20+/PGamKR0ZM35a08X1Tbg==", "dependencies": { - "@smithy/types": "^2.7.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1816,11 +1993,11 @@ } }, "node_modules/@smithy/protocol-http": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.0.11.tgz", - "integrity": "sha512-3ziB8fHuXIRamV/akp/sqiWmNPR6X+9SB8Xxnozzj+Nq7hSpyKdFHd1FLpBkgfGFUTzzcBJQlDZPSyxzmdcx5A==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.1.0.tgz", + "integrity": "sha512-CGNzkKza1yUga7sv+U4gx3jbwSh5x42/9vy0E/NoR2HTFken2MuMc/bClxXAO0Z6EQoTYHHA6FMCREXwSP04lg==", "dependencies": { - "@smithy/types": "^2.7.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1828,12 +2005,12 @@ } }, "node_modules/@smithy/querystring-builder": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.0.15.tgz", - "integrity": "sha512-e1q85aT6HutvouOdN+dMsN0jcdshp50PSCvxDvo6aIM57LqeXimjfONUEgfqQ4IFpYWAtVixptyIRE5frMp/2A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-2.1.0.tgz", + "integrity": "sha512-8QColSkqn9TbvpX40zW0T8IrKcLXg7Um4bczm9qIYDRPh8T873WNIOWzYBw8chI8SWizMXbsSR95PFCP/YlgYw==", "dependencies": { - "@smithy/types": "^2.7.0", - "@smithy/util-uri-escape": "^2.0.0", + "@smithy/types": "^2.9.0", + "@smithy/util-uri-escape": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -1841,11 +2018,11 @@ } }, "node_modules/@smithy/querystring-parser": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.0.15.tgz", - "integrity": "sha512-jbBvoK3cc81Cj1c1TH1qMYxNQKHrYQ2DoTntN9FBbtUWcGhc+T4FP6kCKYwRLXyU4AajwGIZstvNAmIEgUUNTQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-2.1.0.tgz", + "integrity": "sha512-+l17LQQxelslo5CHsLXwSw2F1J6Qmf64OgByreNnLR82gHkJ91ZbMFhxZeLTo2qXxEu0uqraMc4uNw8qE9A6bw==", "dependencies": { - "@smithy/types": "^2.7.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1853,22 +2030,22 @@ } }, "node_modules/@smithy/service-error-classification": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.0.8.tgz", - "integrity": "sha512-jCw9+005im8tsfYvwwSc4TTvd29kXRFkH9peQBg5R/4DD03ieGm6v6Hpv9nIAh98GwgYg1KrztcINC1s4o7/hg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.1.0.tgz", + "integrity": "sha512-yBMJk4IfYqUxsPmc8P0YtWHd/Kbd0PP+kU0dgFksH6eiE2ZQJl7478xNtkUKp2QJLcooYEbA3gBFUza6ukXMiA==", "dependencies": { - "@smithy/types": "^2.7.0" + "@smithy/types": "^2.9.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@smithy/shared-ini-file-loader": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.2.7.tgz", - "integrity": "sha512-0Qt5CuiogIuvQIfK+be7oVHcPsayLgfLJGkPlbgdbl0lD28nUKu4p11L+UG3SAEsqc9UsazO+nErPXw7+IgDpQ==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-2.3.0.tgz", + "integrity": "sha512-jgm7cjj0d08jIB9cp4idtpIUY590Twecv4xpijgl2IzkrPfBddzKTH4Zk+Zwfyk8ecz2T/7ihqtnNcq7Qdj9lw==", "dependencies": { - "@smithy/types": "^2.7.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -1876,17 +2053,17 @@ } }, "node_modules/@smithy/signature-v4": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.0.17.tgz", - "integrity": "sha512-ru5IUbHUAYgJ5ZqZaBi6PEsMjFT/do0Eu21Qt7b07NuRuPlwAMhlqNRDy/KE9QAF20ygehb+xe9ebmyZ26/BSA==", - "dependencies": { - "@smithy/eventstream-codec": "^2.0.15", - "@smithy/is-array-buffer": "^2.0.0", - "@smithy/types": "^2.7.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-middleware": "^2.0.8", - "@smithy/util-uri-escape": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.1.0.tgz", + "integrity": "sha512-ONi89MBjxNtl497obaO/qGixsOedikTV3CAj3ZBPGY3IKykS8wQ2Wkctsx2T1J5B9OnynH0KuGGmgG91utX/7w==", + "dependencies": { + "@smithy/eventstream-codec": "^2.1.0", + "@smithy/is-array-buffer": "^2.1.0", + "@smithy/types": "^2.9.0", + "@smithy/util-hex-encoding": "^2.1.0", + "@smithy/util-middleware": "^2.1.0", + "@smithy/util-uri-escape": "^2.1.0", + "@smithy/util-utf8": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -1894,13 +2071,15 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "2.1.18", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.1.18.tgz", - "integrity": "sha512-7FqdbaJiVaHJDD9IfDhmzhSDbpjyx+ZsfdYuOpDJF09rl8qlIAIlZNoSaflKrQ3cEXZN2YxGPaNWGhbYimyIRQ==", - "dependencies": { - "@smithy/middleware-stack": "^2.0.9", - "@smithy/types": "^2.7.0", - "@smithy/util-stream": "^2.0.23", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-2.3.0.tgz", + "integrity": "sha512-oEaLdVmHcbdK8IHQ4yE7xOYK2nSkF2xXp6nRr5NhfKB5QTKNzpNsXLiGJgfmm7j0ol1S6BhjyBhi7tZ8M0JJtg==", + "dependencies": { + "@smithy/middleware-endpoint": "^2.4.0", + "@smithy/middleware-stack": "^2.1.0", + "@smithy/protocol-http": "^3.1.0", + "@smithy/types": "^2.9.0", + "@smithy/util-stream": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -1908,9 +2087,9 @@ } }, "node_modules/@smithy/types": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.7.0.tgz", - "integrity": "sha512-1OIFyhK+vOkMbu4aN2HZz/MomREkrAC/HqY5mlJMUJfGrPRwijJDTeiN8Rnj9zUaB8ogXAfIOtZrrgqZ4w7Wnw==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.9.0.tgz", + "integrity": "sha512-ST1M87Lf2cLHRI+irEFRIHXGY08HHTAUbiRFYkmFyJdTMg3VDxkcm7DwW9/EgV3X8M6wDPrbIkx/RXONyttrQg==", "dependencies": { "tslib": "^2.5.0" }, @@ -1919,21 +2098,21 @@ } }, "node_modules/@smithy/url-parser": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.15.tgz", - "integrity": "sha512-sADUncUj9rNbOTrdDGm4EXlUs0eQ9dyEo+V74PJoULY4jSQxS+9gwEgsPYyiu8PUOv16JC/MpHonOgqP/IEDZA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.1.0.tgz", + "integrity": "sha512-V3FMzNFCDwQNAgJdxI6Gj48qP9WAyvK59WE90hOoya3m8ey02uLDhWjZkl+505s7iTVVmJ7Mr7nKwG5vU2NIMQ==", "dependencies": { - "@smithy/querystring-parser": "^2.0.15", - "@smithy/types": "^2.7.0", + "@smithy/querystring-parser": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" } }, "node_modules/@smithy/util-base64": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.0.1.tgz", - "integrity": "sha512-DlI6XFYDMsIVN+GH9JtcRp3j02JEVuWIn/QOZisVzpIAprdsxGveFed0bjbMRCqmIFe8uetn5rxzNrBtIGrPIQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-2.1.0.tgz", + "integrity": "sha512-zjXlHFm7S+TEDVA3j1rWGpuNDTlTxIWDqzwIfWUENT0VqCGDAdJITd8RYVjduf3u8HWMlgALkrY6B62UTESQ5w==", "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-buffer-from": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -1941,17 +2120,17 @@ } }, "node_modules/@smithy/util-body-length-browser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.0.1.tgz", - "integrity": "sha512-NXYp3ttgUlwkaug4bjBzJ5+yIbUbUx8VsSLuHZROQpoik+gRkIBeEG9MPVYfvPNpuXb/puqodeeUXcKFe7BLOQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-2.1.0.tgz", + "integrity": "sha512-fkLY8W+jXGSkymLNe9NB7u6lGflHz6w1R+a3RxLOK6UrtwU4LBLskAP5Ag/zVPUNd5tmfv3/W6cTVzk8IBJuiw==", "dependencies": { "tslib": "^2.5.0" } }, "node_modules/@smithy/util-body-length-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.1.0.tgz", - "integrity": "sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-2.2.0.tgz", + "integrity": "sha512-ZLsqYH+s71y6Oc2Auws6zYI4LzsSi6N8+W+Gq7CwXaZm7QIKGiCeEunEwxo50OGAqJs0g6F9kCIwNxhlK1s4Aw==", "dependencies": { "tslib": "^2.5.0" }, @@ -1960,11 +2139,11 @@ } }, "node_modules/@smithy/util-buffer-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.0.0.tgz", - "integrity": "sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.1.0.tgz", + "integrity": "sha512-3w7AM0moGyBmr9gMBGE7+pqG3cjboRvmMyRhpesbJoOUHO0BV1Qrk00M/wQ3EHJAQXM3dehQfFNUf7sR6nT6+Q==", "dependencies": { - "@smithy/is-array-buffer": "^2.0.0", + "@smithy/is-array-buffer": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -1972,9 +2151,9 @@ } }, "node_modules/@smithy/util-config-provider": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.0.0.tgz", - "integrity": "sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-2.2.0.tgz", + "integrity": "sha512-D3Gx0BWXjsn1E25ikUt0+yc8oZnViTa5IHZ1JvD9J1NyyVS4c3IgHqbG64XRverEMnhzUb0EhqMTwQTY12in+w==", "dependencies": { "tslib": "^2.5.0" }, @@ -1983,13 +2162,13 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "2.0.22", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.0.22.tgz", - "integrity": "sha512-qcF20IHHH96FlktvBRICDXDhLPtpVmtksHmqNGtotb9B0DYWXsC6jWXrkhrrwF7tH26nj+npVTqh9isiFV1gdA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-2.1.0.tgz", + "integrity": "sha512-zmXL4aKeBGBz02kDZdks2QfG+HGq99Tp4/ICPmu2OvSbwTOLjmlCnUrtZJTmLhX4etP3o0voOL9gFEa2PSjlJg==", "dependencies": { - "@smithy/property-provider": "^2.0.16", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/smithy-client": "^2.3.0", + "@smithy/types": "^2.9.0", "bowser": "^2.11.0", "tslib": "^2.5.0" }, @@ -1998,16 +2177,16 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "2.0.29", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.0.29.tgz", - "integrity": "sha512-+uG/15VoUh6JV2fdY9CM++vnSuMQ1VKZ6BdnkUM7R++C/vLjnlg+ToiSR1FqKZbMmKBXmsr8c/TsDWMAYvxbxQ==", - "dependencies": { - "@smithy/config-resolver": "^2.0.21", - "@smithy/credential-provider-imds": "^2.1.4", - "@smithy/node-config-provider": "^2.1.8", - "@smithy/property-provider": "^2.0.16", - "@smithy/smithy-client": "^2.1.18", - "@smithy/types": "^2.7.0", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-2.1.0.tgz", + "integrity": "sha512-pVBaw2fBJMjjJj+AR69xQhjzYLZ5u9azdKyaAAjR16dthdBOcnczBClBVCfhb/Moj0ivIHnaXJ5AXCdbDok94g==", + "dependencies": { + "@smithy/config-resolver": "^2.1.0", + "@smithy/credential-provider-imds": "^2.2.0", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/property-provider": "^2.1.0", + "@smithy/smithy-client": "^2.3.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -2015,12 +2194,12 @@ } }, "node_modules/@smithy/util-endpoints": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.0.7.tgz", - "integrity": "sha512-Q2gEind3jxoLk6hdKWyESMU7LnXz8aamVwM+VeVjOYzYT1PalGlY/ETa48hv2YpV4+YV604y93YngyzzzQ4IIA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-1.1.0.tgz", + "integrity": "sha512-gKzfdj5pyEOg1fVOsZVpVPRWAXbWqt9JgZdwU4cjKlJ57Fuccfk0ui5twh1TYvuJWtR2Tw3GwUmUuBM3qRWJJg==", "dependencies": { - "@smithy/node-config-provider": "^2.1.8", - "@smithy/types": "^2.7.0", + "@smithy/node-config-provider": "^2.2.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -2028,9 +2207,9 @@ } }, "node_modules/@smithy/util-hex-encoding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.0.0.tgz", - "integrity": "sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.1.0.tgz", + "integrity": "sha512-haxSIaBxn3p/lK+bEyqC32myHffacBLD61/HHzBGcG1Vo8dFTm5y0vhdR5R4wakW7H8Tr/czx+uckDOWZ1Km9Q==", "dependencies": { "tslib": "^2.5.0" }, @@ -2039,11 +2218,11 @@ } }, "node_modules/@smithy/util-middleware": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.0.8.tgz", - "integrity": "sha512-qkvqQjM8fRGGA8P2ydWylMhenCDP8VlkPn8kiNuFEaFz9xnUKC2irfqsBSJrfrOB9Qt6pQsI58r3zvvumhFMkw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.1.0.tgz", + "integrity": "sha512-bKfhAsdjRyGmYDsJUW5hPsL3qofgPgLPsuV+V6nNGyD/kjMobwstiIpA3ddGFT+XDwVOIUHElg7I06/wOpwKiQ==", "dependencies": { - "@smithy/types": "^2.7.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -2051,12 +2230,12 @@ } }, "node_modules/@smithy/util-retry": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.0.8.tgz", - "integrity": "sha512-cQTPnVaVFMjjS6cb44WV2yXtHVyXDC5icKyIbejMarJEApYeJWpBU3LINTxHqp/tyLI+MZOUdosr2mZ3sdziNg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.1.0.tgz", + "integrity": "sha512-igJw+/olhAUtocMbEMBjy8SKRTHfefS+qcgmMUVEBLFgLjqMfpc8EDVB1BebNBQ1rre5yLDbi2UHUz48eZNkPQ==", "dependencies": { - "@smithy/service-error-classification": "^2.0.8", - "@smithy/types": "^2.7.0", + "@smithy/service-error-classification": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -2064,17 +2243,17 @@ } }, "node_modules/@smithy/util-stream": { - "version": "2.0.23", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.0.23.tgz", - "integrity": "sha512-OJMWq99LAZJUzUwTk+00plyxX3ESktBaGPhqNIEVab+53gLULiWN9B/8bRABLg0K6R6Xg4t80uRdhk3B/LZqMQ==", - "dependencies": { - "@smithy/fetch-http-handler": "^2.3.1", - "@smithy/node-http-handler": "^2.2.1", - "@smithy/types": "^2.7.0", - "@smithy/util-base64": "^2.0.1", - "@smithy/util-buffer-from": "^2.0.0", - "@smithy/util-hex-encoding": "^2.0.0", - "@smithy/util-utf8": "^2.0.2", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-2.1.0.tgz", + "integrity": "sha512-lcw9JVXLHvRawaXnfxdnGRw5pQM5c9XMEkBuMec+fIhGuPHIezqhQq7oO0jJcj0xwupJzW6HAvinktr9ozdKyg==", + "dependencies": { + "@smithy/fetch-http-handler": "^2.4.0", + "@smithy/node-http-handler": "^2.3.0", + "@smithy/types": "^2.9.0", + "@smithy/util-base64": "^2.1.0", + "@smithy/util-buffer-from": "^2.1.0", + "@smithy/util-hex-encoding": "^2.1.0", + "@smithy/util-utf8": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -2082,9 +2261,9 @@ } }, "node_modules/@smithy/util-uri-escape": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.0.0.tgz", - "integrity": "sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.1.0.tgz", + "integrity": "sha512-ZHYFGyF9o/MHGMGtsHfkxnn2DhGRZlDIFGNgipu4K3x8jMEVahQ+tGnlkFVMM2QrSQHCcjICbBTJ5JEgaD5+Jg==", "dependencies": { "tslib": "^2.5.0" }, @@ -2093,11 +2272,11 @@ } }, "node_modules/@smithy/util-utf8": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.0.2.tgz", - "integrity": "sha512-qOiVORSPm6Ce4/Yu6hbSgNHABLP2VMv8QOC3tTDNHHlWY19pPyc++fBTbZPtx6egPXi4HQxKDnMxVxpbtX2GoA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.1.0.tgz", + "integrity": "sha512-RnNNedYLpsNPQocMhr0nGEz0mGKdzI5dBi0h7vvmimULtBlyElgX1/hXozlkurIgx8R3bSy14/oRtmDsFClifg==", "dependencies": { - "@smithy/util-buffer-from": "^2.0.0", + "@smithy/util-buffer-from": "^2.1.0", "tslib": "^2.5.0" }, "engines": { @@ -2105,12 +2284,12 @@ } }, "node_modules/@smithy/util-waiter": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.0.15.tgz", - "integrity": "sha512-9Y+btzzB7MhLADW7xgD6SjvmoYaRkrb/9SCbNGmNdfO47v38rxb90IGXyDtAK0Shl9bMthTmLgjlfYc+vtz2Qw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-2.1.0.tgz", + "integrity": "sha512-BqfpYb4oNsQn6hhd4zDk8X6srVmiNOXHBFQz0vQSScS8Zliam7oLjlf/gHw02ewwxzi9229UQZF+UnG2jV6JGw==", "dependencies": { - "@smithy/abort-controller": "^2.0.15", - "@smithy/types": "^2.7.0", + "@smithy/abort-controller": "^2.1.0", + "@smithy/types": "^2.9.0", "tslib": "^2.5.0" }, "engines": { @@ -2141,18 +2320,42 @@ "@types/trusted-types": "*" } }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, - "node_modules/@types/node": { - "version": "16.18.68", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.68.tgz", - "integrity": "sha512-sG3hPIQwJLoewrN7cr0dwEy+yF5nD4D/4FxtQpFciRD/xwUzgD+G05uxZHv5mhfXo4F9Jkp13jjn0CC2q325sg==", + "node_modules/@types/lodash": { + "version": "4.14.202", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", + "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", "dev": true }, + "node_modules/@types/lodash.clonedeep": { + "version": "4.5.9", + "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.9.tgz", + "integrity": "sha512-19429mWC+FyaAhOLzsS8kZUsI+/GmBAQ0HFiCPsKGU+7pBXOQWhyrY6xNNDwUSX8SMZMJvuFVMF9O5dQOlQK9Q==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "18.19.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.8.tgz", + "integrity": "sha512-g1pZtPhsvGVTwmeVoexWZLTQaOvXwoSq//pTL0DHeNzUDrFnir4fgETdhjhIxjVnN+hKOuh98+E1eMLnUXstFg==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, "node_modules/@types/semver": { "version": "7.5.6", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", @@ -2360,15 +2563,15 @@ } }, "node_modules/@vitejs/plugin-vue": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.3.4.tgz", - "integrity": "sha512-ciXNIHKPriERBisHFBvnTbfKa6r9SAesOYXeGDzgegcvy9Q4xdScSHAmKbNT0M3O0S9LKhIf5/G+UYG4NnnzYw==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.3.tgz", + "integrity": "sha512-b8S5dVS40rgHdDrw+DQi/xOM9ed+kSRZzfm1T74bMmBDCd8XO87NKlFYInzCtwvtWwXZvo1QxE2OSspTATWrbA==", "dev": true, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.0.0 || >=20.0.0" }, "peerDependencies": { - "vite": "^4.0.0", + "vite": "^5.0.0", "vue": "^3.2.25" } }, @@ -2401,12 +2604,13 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.10.tgz", - "integrity": "sha512-doe0hODR1+i1menPkRzJ5MNR6G+9uiZHIknK3Zn5OcIztu6GGw7u0XUzf3AgB8h/dfsZC9eouzoLo3c3+N/cVA==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.15.tgz", + "integrity": "sha512-XcJQVOaxTKCnth1vCxEChteGuwG6wqnUHxAm1DO3gCz0+uXKaJNx8/digSz4dLALCy8n2lKq24jSUs8segoqIw==", "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/shared": "3.3.10", + "@babel/parser": "^7.23.6", + "@vue/shared": "3.4.15", + "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } @@ -2417,28 +2621,27 @@ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" }, "node_modules/@vue/compiler-dom": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.10.tgz", - "integrity": "sha512-NCrqF5fm10GXZIK0GrEAauBqdy+F2LZRt3yNHzrYjpYBuRssQbuPLtSnSNjyR9luHKkWSH8we5LMB3g+4z2HvA==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.15.tgz", + "integrity": "sha512-wox0aasVV74zoXyblarOM3AZQz/Z+OunYcIHe1OsGclCHt8RsRm04DObjefaI82u6XDzv+qGWZ24tIsRAIi5MQ==", "dependencies": { - "@vue/compiler-core": "3.3.10", - "@vue/shared": "3.3.10" + "@vue/compiler-core": "3.4.15", + "@vue/shared": "3.4.15" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.10.tgz", - "integrity": "sha512-xpcTe7Rw7QefOTRFFTlcfzozccvjM40dT45JtrE3onGm/jBLZ0JhpKu3jkV7rbDFLeeagR/5RlJ2Y9SvyS0lAg==", - "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/compiler-core": "3.3.10", - "@vue/compiler-dom": "3.3.10", - "@vue/compiler-ssr": "3.3.10", - "@vue/reactivity-transform": "3.3.10", - "@vue/shared": "3.3.10", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.15.tgz", + "integrity": "sha512-LCn5M6QpkpFsh3GQvs2mJUOAlBQcCco8D60Bcqmf3O3w5a+KWS5GvYbrrJBkgvL1BDnTp+e8q0lXCLgHhKguBA==", + "dependencies": { + "@babel/parser": "^7.23.6", + "@vue/compiler-core": "3.4.15", + "@vue/compiler-dom": "3.4.15", + "@vue/compiler-ssr": "3.4.15", + "@vue/shared": "3.4.15", "estree-walker": "^2.0.2", "magic-string": "^0.30.5", - "postcss": "^8.4.32", + "postcss": "^8.4.33", "source-map-js": "^1.0.2" } }, @@ -2459,12 +2662,12 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.10.tgz", - "integrity": "sha512-12iM4jA4GEbskwXMmPcskK5wImc2ohKm408+o9iox3tfN9qua8xL0THIZtoe9OJHnXP4eOWZpgCAAThEveNlqQ==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.15.tgz", + "integrity": "sha512-1jdeQyiGznr8gjFDadVmOJqZiLNSsMa5ZgqavkPZ8O2wjHv0tVuAEsw5hTdUoUW4232vpBbL/wJhzVW/JwY1Uw==", "dependencies": { - "@vue/compiler-dom": "3.3.10", - "@vue/shared": "3.3.10" + "@vue/compiler-dom": "3.4.15", + "@vue/shared": "3.4.15" } }, "node_modules/@vue/devtools-api": { @@ -2511,9 +2714,9 @@ } }, "node_modules/@vue/language-core": { - "version": "1.8.25", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.25.tgz", - "integrity": "sha512-NJk/5DnAZlpvXX8BdWmHI45bWGLViUaS3R/RMrmFSvFMSbJKuEODpM4kR0F0Ofv5SFzCWuNiMhxameWpVdQsnA==", + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.27.tgz", + "integrity": "sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==", "dev": true, "dependencies": { "@volar/language-core": "~1.11.1", @@ -2560,87 +2763,59 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.10.tgz", - "integrity": "sha512-H5Z7rOY/JLO+e5a6/FEXaQ1TMuOvY4LDVgT+/+HKubEAgs9qeeZ+NhADSeEtrNQeiKLDuzeKc8v0CUFpB6Pqgw==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.15.tgz", + "integrity": "sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w==", "dependencies": { - "@vue/shared": "3.3.10" + "@vue/shared": "3.4.15" } }, - "node_modules/@vue/reactivity-transform": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.10.tgz", - "integrity": "sha512-0xBdk+CKHWT+Gev8oZ63Tc0qFfj935YZx+UAynlutnrDZ4diFCVFMWixn65HzjE3S1iJppWOo6Tt1OzASH7VEg==", + "node_modules/@vue/runtime-core": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.15.tgz", + "integrity": "sha512-6E3by5m6v1AkW0McCeAyhHTw+3y17YCOKG0U0HDKDscV4Hs0kgNT5G+GCHak16jKgcCDHpI9xe5NKb8sdLCLdw==", "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/compiler-core": "3.3.10", - "@vue/shared": "3.3.10", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.5" + "@vue/reactivity": "3.4.15", + "@vue/shared": "3.4.15" } }, - "node_modules/@vue/reactivity-transform/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + "node_modules/@vue/runtime-dom": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.15.tgz", + "integrity": "sha512-EVW8D6vfFVq3V/yDKNPBFkZKGMFSvZrUQmx196o/v2tHKdwWdiZjYUBS+0Ez3+ohRyF8Njwy/6FH5gYJ75liUw==", + "dependencies": { + "@vue/runtime-core": "3.4.15", + "@vue/shared": "3.4.15", + "csstype": "^3.1.3" + } }, - "node_modules/@vue/reactivity-transform/node_modules/magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "node_modules/@vue/server-renderer": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.15.tgz", + "integrity": "sha512-3HYzaidu9cHjrT+qGUuDhFYvF/j643bHC6uUN9BgM11DVy+pM6ATsG6uPBLnkwOgs7BpJABReLmpL3ZPAsUaqw==", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" + "@vue/compiler-ssr": "3.4.15", + "@vue/shared": "3.4.15" }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@vue/runtime-core": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.10.tgz", - "integrity": "sha512-DZ0v31oTN4YHX9JEU5VW1LoIVgFovWgIVb30bWn9DG9a7oA415idcwsRNNajqTx8HQJyOaWfRKoyuP2P2TYIag==", - "dependencies": { - "@vue/reactivity": "3.3.10", - "@vue/shared": "3.3.10" - } - }, - "node_modules/@vue/runtime-dom": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.10.tgz", - "integrity": "sha512-c/jKb3ny05KJcYk0j1m7Wbhrxq7mZYr06GhKykDMNRRR9S+/dGT8KpHuNQjv3/8U4JshfkAk6TpecPD3B21Ijw==", - "dependencies": { - "@vue/runtime-core": "3.3.10", - "@vue/shared": "3.3.10", - "csstype": "^3.1.2" - } - }, - "node_modules/@vue/server-renderer": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.10.tgz", - "integrity": "sha512-0i6ww3sBV3SKlF3YTjSVqKQ74xialMbjVYGy7cOTi7Imd8ediE7t72SK3qnvhrTAhOvlQhq6Bk6nFPdXxe0sAg==", - "dependencies": { - "@vue/compiler-ssr": "3.3.10", - "@vue/shared": "3.3.10" - }, - "peerDependencies": { - "vue": "3.3.10" + "peerDependencies": { + "vue": "3.4.15" } }, "node_modules/@vue/shared": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.10.tgz", - "integrity": "sha512-2y3Y2J1a3RhFa0WisHvACJR2ncvWiVHcP8t0Inxo+NKz+8RKO4ZV8eZgCxRgQoA6ITfV12L4E6POOL9HOU5nqw==" + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.15.tgz", + "integrity": "sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==" }, "node_modules/@vue/tsconfig": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.4.0.tgz", - "integrity": "sha512-CPuIReonid9+zOG/CGTT05FXrPYATEqoDGNrEaqS4hwcw5BUNM2FguC0mOwJD4Jr16UpRVl9N0pY3P+srIbqmg==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.5.1.tgz", + "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==", "dev": true }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -2778,12 +2953,12 @@ } }, "node_modules/axios": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.2.tgz", - "integrity": "sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==", + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz", + "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.4", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -2813,15 +2988,6 @@ } ] }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -2860,18 +3026,6 @@ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==" }, - "node_modules/bplist-parser": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", - "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", - "dev": true, - "dependencies": { - "big-integer": "^1.6.44" - }, - "engines": { - "node": ">= 5.10.0" - } - }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2903,21 +3057,6 @@ "ieee754": "^1.1.4" } }, - "node_modules/bundle-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", - "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", - "dev": true, - "dependencies": { - "run-applescript": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/call-bind": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", @@ -2932,12 +3071,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", - "dev": true - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2976,9 +3109,9 @@ } }, "node_modules/chart.js": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.3.tgz", - "integrity": "sha512-aTk7pBw+x6sQYhon/NR3ikfUJuym/LdgpTlgZRe2PaEhjUMKBKyNaFCMVRAyTEWYFNO7qRu7iQVqOw/OqzxZxQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz", + "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==", "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -3152,40 +3285,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/default-browser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", - "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", - "dev": true, - "dependencies": { - "bundle-name": "^3.0.0", - "default-browser-id": "^3.0.0", - "execa": "^7.1.1", - "titleize": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/default-browser-id": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", - "integrity": "sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==", - "dev": true, - "dependencies": { - "bplist-parser": "^0.2.0", - "untildify": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/define-data-property": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", @@ -3200,18 +3299,6 @@ "node": ">= 0.4" } }, - "node_modules/define-lazy-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", - "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", @@ -3263,9 +3350,20 @@ } }, "node_modules/dompurify": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz", - "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==" + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.8.tgz", + "integrity": "sha512-b7uwreMYL2eZhrSCRC4ahLTeZcPZxSmYfmcQGXGkXiZSNW1X85v+SDM5KsWcpivIiUBH47Ji7NtyUdpLeF5JZQ==" + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } }, "node_modules/error-ex": { "version": "1.3.2", @@ -3361,12 +3459,11 @@ } }, "node_modules/esbuild": { - "version": "0.19.8", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.8.tgz", - "integrity": "sha512-l7iffQpT2OrZfH2rXIp7/FkmaeZM0vxbxN9KfiCwGYuZqzMg/JdvX26R31Zxn/Pxvsrg3Y9N6XTcnknqDyyv4w==", + "version": "0.19.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz", + "integrity": "sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA==", "dev": true, "hasInstallScript": true, - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -3374,28 +3471,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.19.8", - "@esbuild/android-arm64": "0.19.8", - "@esbuild/android-x64": "0.19.8", - "@esbuild/darwin-arm64": "0.19.8", - "@esbuild/darwin-x64": "0.19.8", - "@esbuild/freebsd-arm64": "0.19.8", - "@esbuild/freebsd-x64": "0.19.8", - "@esbuild/linux-arm": "0.19.8", - "@esbuild/linux-arm64": "0.19.8", - "@esbuild/linux-ia32": "0.19.8", - "@esbuild/linux-loong64": "0.19.8", - "@esbuild/linux-mips64el": "0.19.8", - "@esbuild/linux-ppc64": "0.19.8", - "@esbuild/linux-riscv64": "0.19.8", - "@esbuild/linux-s390x": "0.19.8", - "@esbuild/linux-x64": "0.19.8", - "@esbuild/netbsd-x64": "0.19.8", - "@esbuild/openbsd-x64": "0.19.8", - "@esbuild/sunos-x64": "0.19.8", - "@esbuild/win32-arm64": "0.19.8", - "@esbuild/win32-ia32": "0.19.8", - "@esbuild/win32-x64": "0.19.8" + "@esbuild/aix-ppc64": "0.19.11", + "@esbuild/android-arm": "0.19.11", + "@esbuild/android-arm64": "0.19.11", + "@esbuild/android-x64": "0.19.11", + "@esbuild/darwin-arm64": "0.19.11", + "@esbuild/darwin-x64": "0.19.11", + "@esbuild/freebsd-arm64": "0.19.11", + "@esbuild/freebsd-x64": "0.19.11", + "@esbuild/linux-arm": "0.19.11", + "@esbuild/linux-arm64": "0.19.11", + "@esbuild/linux-ia32": "0.19.11", + "@esbuild/linux-loong64": "0.19.11", + "@esbuild/linux-mips64el": "0.19.11", + "@esbuild/linux-ppc64": "0.19.11", + "@esbuild/linux-riscv64": "0.19.11", + "@esbuild/linux-s390x": "0.19.11", + "@esbuild/linux-x64": "0.19.11", + "@esbuild/netbsd-x64": "0.19.11", + "@esbuild/openbsd-x64": "0.19.11", + "@esbuild/sunos-x64": "0.19.11", + "@esbuild/win32-arm64": "0.19.11", + "@esbuild/win32-ia32": "0.19.11", + "@esbuild/win32-x64": "0.19.11" } }, "node_modules/escape-string-regexp": { @@ -3477,23 +3575,24 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz", - "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", + "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==", "dev": true, "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.8.5" + "synckit": "^0.8.6" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/prettier" + "url": "https://opencollective.com/eslint-plugin-prettier" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", + "eslint-config-prettier": "*", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -3506,9 +3605,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "9.17.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz", - "integrity": "sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==", + "version": "9.19.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.19.2.tgz", + "integrity": "sha512-CPDqTOG2K4Ni2o4J5wixkLVNwgctKXFu6oBpVJlpNq7f38lh9I80pRTouZSJ2MAebPJlINU/KTFSXyQfBUlymA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", @@ -3689,29 +3788,6 @@ "node": ">=0.8.x" } }, - "node_modules/execa": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", - "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -3785,9 +3861,9 @@ } }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", + "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -3862,9 +3938,9 @@ "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", - "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz", + "integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==", "dev": true, "funding": [ { @@ -3989,18 +4065,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -4050,9 +4114,9 @@ } }, "node_modules/globals": { - "version": "13.23.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", - "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -4242,21 +4306,21 @@ "he": "bin/he" } }, + "node_modules/highlight.js": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", + "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, - "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, - "engines": { - "node": ">=14.18.0" - } - }, "node_modules/idb-keyval": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", @@ -4449,21 +4513,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4485,24 +4534,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "dev": true, - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -4576,18 +4607,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -4645,33 +4664,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-wsl/node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -4708,19 +4700,6 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "node_modules/json-schema-ref-parser": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz", - "integrity": "sha512-qcP2lmGy+JUoQJ4DOQeLaZDqH9qSkeGCK3suKWxJXS82dg728Mn3j97azDMaOUmJAN4uCq91LdPx4K7E8F1a7Q==", - "deprecated": "Please switch to @apidevtools/json-schema-ref-parser", - "dev": true, - "dependencies": { - "@apidevtools/json-schema-ref-parser": "9.0.9" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -4802,6 +4781,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -4837,12 +4822,6 @@ "node": ">= 0.10.0" } }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4886,18 +4865,6 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5165,33 +5132,6 @@ "which": "bin/which" } }, - "node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -5249,50 +5189,17 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", - "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", - "dev": true, - "dependencies": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/openapi-typescript-codegen": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/openapi-typescript-codegen/-/openapi-typescript-codegen-0.25.0.tgz", - "integrity": "sha512-nN/TnIcGbP58qYgwEEy5FrAAjePcYgfMaCe3tsmYyTgI3v4RR9v8os14L+LEWDvV50+CmqiyTzRkKKtJeb6Ybg==", + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/openapi-typescript-codegen/-/openapi-typescript-codegen-0.26.0.tgz", + "integrity": "sha512-5D45xawBHu9efxaDdioeZAfAQGxE0v12aNk24dTymNHRA75A6bFP8tKUAIzx8+AKWN7d/S9RWD87yVWhlFLhDA==", "dev": true, "dependencies": { + "@apidevtools/json-schema-ref-parser": "^11.1.0", "camelcase": "^6.3.0", - "commander": "^11.0.0", - "fs-extra": "^11.1.1", - "handlebars": "^4.7.7", - "json-schema-ref-parser": "^9.0.9" + "commander": "^11.1.0", + "fs-extra": "^11.2.0", + "handlebars": "^4.7.8" }, "bin": { "openapi": "bin/index.js" @@ -5507,9 +5414,9 @@ } }, "node_modules/postcss": { - "version": "8.4.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.32.tgz", - "integrity": "sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==", + "version": "8.4.33", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.33.tgz", + "integrity": "sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==", "funding": [ { "type": "opencollective", @@ -5534,9 +5441,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", - "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz", + "integrity": "sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==", "dev": true, "dependencies": { "cssesc": "^3.0.0", @@ -5744,18 +5651,34 @@ } }, "node_modules/rollup": { - "version": "3.29.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", - "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.9.5.tgz", + "integrity": "sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ==", "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=14.18.0", + "node": ">=18.0.0", "npm": ">=8.0.0" }, "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.9.5", + "@rollup/rollup-android-arm64": "4.9.5", + "@rollup/rollup-darwin-arm64": "4.9.5", + "@rollup/rollup-darwin-x64": "4.9.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.9.5", + "@rollup/rollup-linux-arm64-gnu": "4.9.5", + "@rollup/rollup-linux-arm64-musl": "4.9.5", + "@rollup/rollup-linux-riscv64-gnu": "4.9.5", + "@rollup/rollup-linux-x64-gnu": "4.9.5", + "@rollup/rollup-linux-x64-musl": "4.9.5", + "@rollup/rollup-win32-arm64-msvc": "4.9.5", + "@rollup/rollup-win32-ia32-msvc": "4.9.5", + "@rollup/rollup-win32-x64-msvc": "4.9.5", "fsevents": "~2.3.2" } }, @@ -5789,149 +5712,45 @@ "estree-walker": "^0.6.1" } }, - "node_modules/run-applescript": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", - "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "dependencies": { - "execa": "^5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "queue-microtask": "^1.2.2" } }, - "node_modules/run-applescript/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", "dev": true, "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" }, "engines": { - "node": ">=10" + "node": ">=0.4" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/run-applescript/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/run-applescript/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/run-applescript/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/run-applescript/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/run-applescript/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/safe-buffer": { @@ -5954,15 +5773,18 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", + "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5999,15 +5821,16 @@ } }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", + "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", "dev": true, "dependencies": { "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.2", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -6094,12 +5917,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -6265,18 +6082,6 @@ "node": ">=4" } }, - "node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -6319,12 +6124,12 @@ } }, "node_modules/synckit": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.6.tgz", - "integrity": "sha512-laHF2savN6sMeHCjLRkheIU4wo3Zg9Ln5YOjOo7sZ5dVQW8yF5pPE5SIw1dsPhq3TRp1jisKRCdPhfs/1WMqDA==", + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", "dev": true, "dependencies": { - "@pkgr/utils": "^2.4.2", + "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" }, "engines": { @@ -6340,18 +6145,6 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/titleize": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", - "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6520,6 +6313,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -6529,15 +6328,6 @@ "node": ">= 10.0.0" } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -6570,29 +6360,29 @@ } }, "node_modules/vite": { - "version": "4.4.12", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.12.tgz", - "integrity": "sha512-KtPlUbWfxzGVul8Nut8Gw2Qe8sBzWY+8QVc5SL8iRFnpnrcoCaNlzO40c1R6hPmcdTwIPEDkq0Y9+27a5tVbdQ==", + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.11.tgz", + "integrity": "sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==", "dev": true, "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" + "esbuild": "^0.19.3", + "postcss": "^8.4.32", + "rollup": "^4.2.0" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^18.0.0 || >=20.0.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": ">= 14", + "@types/node": "^18.0.0 || >=20.0.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", @@ -6624,405 +6414,16 @@ } } }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, "node_modules/vue": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.10.tgz", - "integrity": "sha512-zg6SIXZdTBwiqCw/1p+m04VyHjLfwtjwz8N57sPaBhEex31ND0RYECVOC1YrRwMRmxFf5T1dabl6SGUbMKKuVw==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.15.tgz", + "integrity": "sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ==", "dependencies": { - "@vue/compiler-dom": "3.3.10", - "@vue/compiler-sfc": "3.3.10", - "@vue/runtime-dom": "3.3.10", - "@vue/server-renderer": "3.3.10", - "@vue/shared": "3.3.10" + "@vue/compiler-dom": "3.4.15", + "@vue/compiler-sfc": "3.4.15", + "@vue/runtime-dom": "3.4.15", + "@vue/server-renderer": "3.4.15", + "@vue/shared": "3.4.15" }, "peerDependencies": { "typescript": "*" @@ -7034,9 +6435,9 @@ } }, "node_modules/vue-eslint-parser": { - "version": "9.3.2", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.3.2.tgz", - "integrity": "sha512-q7tWyCVaV9f8iQyIA5Mkj/S6AoJ9KBN8IeUSf3XEmBrOtxOZnfTg5s4KClbZBCK3GtnT/+RyCLZyDHuZwTuBjg==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.0.tgz", + "integrity": "sha512-7KsNBb6gHFA75BtneJsoK/dbZ281whUIwFYdQxA68QrCrGMXYzUMbPDHGcOQ0OocIVKrWSKWXZ4mL7tonCXoUw==", "dev": true, "dependencies": { "debug": "^4.3.4", @@ -7097,9 +6498,9 @@ } }, "node_modules/vue-template-compiler": { - "version": "2.7.15", - "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.15.tgz", - "integrity": "sha512-yQxjxMptBL7UAog00O8sANud99C6wJF+7kgbcwqkvA38vCGF7HWE66w0ZFnS/kX5gSoJr/PQ4/oS3Ne2pW37Og==", + "version": "2.7.16", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", + "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==", "dev": true, "dependencies": { "de-indent": "^1.0.2", @@ -7107,13 +6508,13 @@ } }, "node_modules/vue-tsc": { - "version": "1.8.25", - "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.25.tgz", - "integrity": "sha512-lHsRhDc/Y7LINvYhZ3pv4elflFADoEOo67vfClAfF2heVHpHmVquLSjojgCSIwzA4F0Pc4vowT/psXCYcfk+iQ==", + "version": "1.8.27", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.27.tgz", + "integrity": "sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==", "dev": true, "dependencies": { "@volar/typescript": "~1.11.1", - "@vue/language-core": "1.8.25", + "@vue/language-core": "1.8.27", "semver": "^7.5.4" }, "bin": { diff --git a/package.json b/package.json index 2c7bbd8337e0cd7a9423ddcdac50b5c2d64a212e..f1334915fbe36a246e49a509047a78ec69bb156a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,8 @@ { "name": "clowm-ui", "version": "2.0.0", + "type": "module", + "license": "Apache-2.0", "scripts": { "dev": "vite", "build": "run-p type-check build-only", @@ -10,7 +12,8 @@ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", "generate-s3-client": "openapi --input http://localhost:9999/api/s3proxy-service/openapi.json --output src/client/s3proxy --client axios", "generate-auth-client": "openapi --input http://localhost:9999/api/auth-service/openapi.json --output src/client/auth --client axios", - "generate-workflow-client": "openapi --input http://localhost:9999/api/workflow-service/openapi.json --output src/client/workflow --client axios" + "generate-workflow-client": "openapi --input http://localhost:9999/api/workflow-service/openapi.json --output src/client/workflow --client axios", + "generate-resource-client": "openapi --input http://localhost:9999/api/resource-service/openapi.json --output src/client/resource --client axios" }, "dependencies": { "@aws-sdk/client-s3": "^3.440.0", @@ -19,44 +22,45 @@ "@fortawesome/fontawesome-free": "~6.4.2", "@popperjs/core": "~2.11.8", "ajv": "~8.12.0", - "bootstrap": "~5.3.1", - "chart.js": "~4.3.3", + "bootstrap": "~5.3.0", + "chart.js": "~4.4.0", "chartjs-plugin-zoom": "~2.0.1", - "dayjs": "~1.11.9", + "dayjs": "~1.11.0", "dompurify": "~3.0.5", "filesize": "~10.0.12", "idb-keyval": "^6.2.1", - "pinia": "~2.1.6", - "semver": "~7.5.4", + "pinia": "~2.1.0", + "semver": "~7.5.0", "showdown": "~2.1.0", - "vue": "~3.3.4", - "vue-router": "~4.2.4", - "vue3-cookies": "~1.0.6" + "vue": "~3.4.0", + "vue-router": "~4.2.0", + "vue3-cookies": "~1.0.0" }, "devDependencies": { "@esbuild-plugins/node-globals-polyfill": "~0.2.3", "@esbuild-plugins/node-modules-polyfill": "~0.2.2", "@rushstack/eslint-patch": "~1.2.0", "@tsconfig/node18": "^18.2.1", - "@types/bootstrap": "~5.2.6", - "@types/dompurify": "~3.0.2", - "@types/node": "^16.18.48", + "@types/bootstrap": "~5.2.0", + "@types/dompurify": "~3.0.0", + "@types/node": "^18.19.5", "@types/semver": "~7.5.1", "@types/showdown": "~2.0.1", - "@vitejs/plugin-vue": "~4.3.4", + "@vitejs/plugin-vue": "~5.0.0", "@vue/eslint-config-prettier": "~8.0.0", "@vue/eslint-config-typescript": "~11.0.3", - "@vue/tsconfig": "~0.4.0", + "@vue/tsconfig": "~0.5.0", "axios": "~1.6.0", "eslint": "~8.48.0", - "eslint-plugin-vue": "~9.17.0", + "eslint-plugin-vue": "~9.19.0", + "highlight.js": "^11.9.0", "npm-run-all": "~4.1.5", - "openapi-typescript-codegen": "^0.25.0", + "openapi-typescript-codegen": "^0.26.0", "prettier": "~3.0.3", "rollup-plugin-node-polyfills": "~0.2.1", "sass": "~1.66.1", "typescript": "~5.1.6", - "vite": "~4.4.9", - "vue-tsc": "~1.8.10" + "vite": "~5.0.0", + "vue-tsc": "~1.8.0" } } diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000000000000000000000000000000000000..425b9009cc803d48afe473fd660965af121b1f73 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,3 @@ +User-agent: * +Disallow: /dashboard +Allow: /login diff --git a/src/App.vue b/src/App.vue index a9b94a9a34d38fffe98a9e950256d42049652a10..65c7b0dfe57e1c361aa9ea7d36cad82395b59ca6 100644 --- a/src/App.vue +++ b/src/App.vue @@ -7,18 +7,22 @@ import { useRouter } from "vue-router"; import { OpenAPI as S3ProxyOpenAPI } from "@/client/s3proxy"; import { OpenAPI as AuthOpenAPI } from "@/client/auth"; import { OpenAPI as WorkflowOpenAPI } from "@/client/workflow"; +import { OpenAPI as ResourceOpenAPI } from "@/client/resource"; import { environment } from "@/environment"; import FooterBottom from "@/components/FooterBottom.vue"; import axios from "axios"; +import { useNameStore } from "@/stores/names"; const { cookies } = useCookies(); const store = useAuthStore(); const router = useRouter(); +const nameRepository = useNameStore(); onBeforeMount(() => { S3ProxyOpenAPI.BASE = environment.S3PROXY_API_BASE_URL; AuthOpenAPI.BASE = environment.AUTH_API_BASE_URL; WorkflowOpenAPI.BASE = environment.WORKFLOW_API_BASE_URL; + ResourceOpenAPI.BASE = environment.RESOURCE_API_BASE_URL; axios.interceptors.response.use( (res) => res, (err) => { @@ -56,20 +60,36 @@ onBeforeMount(() => { return { name: "dashboard" }; } else if ( to.meta.requiresReviewerRole && - !(store.workflowReviewer || store.admin) + !(store.rewiewer || store.admin) ) { return { name: "dashboard" }; + } else if ( + to.meta.requiresMaintainerRole && + !(store.resourceMaintainer || store.admin) + ) { + return { name: "dashboard" }; + } else if (to.meta.adminRole && !store.admin) { + return { name: "dashboard" }; } }); + nameRepository.loadNameMapping(); }); </script> <template> <NavbarTop /> <div class="container-xxl mt-4 flex-grow-1"> + <div + id="global-toast-container" + class="toast-container position-fixed top-toast end-0 p-3" + ></div> <router-view></router-view> </div> <FooterBottom /> </template> -<style scoped></style> +<style scoped> +.top-toast { + top: 4rem; +} +</style> diff --git a/src/assets/env.template.js b/src/assets/env.template.js index c2ddbd6f476a9e787b158e38a695bef8924f79c9..5667de5dae989b17408ae49369cc2069c234718a 100644 --- a/src/assets/env.template.js +++ b/src/assets/env.template.js @@ -6,5 +6,6 @@ window["env"]["workflowApiUrl"] = "${WORKFLOW_API_BASE_URL}"; window["env"]["s3proxyApiUrl"] = "${S3PROXY_API_BASE_URL}"; window["env"]["authApiUrl"] = "${AUTH_API_BASE_URL}"; + window["env"]["resourceApiUrl"] = "${RESOURCE_API_BASE_URL}"; window["env"]["devSystem"] = "${DEV_SYSTEM}"; })(this); diff --git a/src/assets/main.css b/src/assets/main.css index 24f661e1ba5b45e145150f636947b284828c9656..cb6974cba0e2a5c6b64ede79fec9c1befe81c2f9 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -1,13 +1,10 @@ @import "base.css"; +@import "highlight.js/styles/default.min.css"; .fs-0 { font-size: 3.5rem; } -.top-toast { - top: 4rem; -} - .w-fit { width: fit-content; } @@ -32,3 +29,7 @@ pre { transform: translateY(-2px); backdrop-filter: brightness(0.95); } + +.hover-info:hover { + color: var(--bs-info) !important; +} diff --git a/src/client/auth/core/CancelablePromise.ts b/src/client/auth/core/CancelablePromise.ts index 55fef8517238d2dab7478598eefca72e657b9fb5..eb02246c31f61b897667a6433d55b8b413bafbc1 100644 --- a/src/client/auth/core/CancelablePromise.ts +++ b/src/client/auth/core/CancelablePromise.ts @@ -51,7 +51,7 @@ export class CancelablePromise<T> implements Promise<T> { return; } this.#isResolved = true; - this.#resolve?.(value); + if (this.#resolve) this.#resolve(value); }; const onReject = (reason?: any): void => { @@ -59,7 +59,7 @@ export class CancelablePromise<T> implements Promise<T> { return; } this.#isRejected = true; - this.#reject?.(reason); + if (this.#reject) this.#reject(reason); }; const onCancel = (cancelHandler: () => void): void => { @@ -122,7 +122,7 @@ export class CancelablePromise<T> implements Promise<T> { } } this.#cancelHandlers.length = 0; - this.#reject?.(new CancelError('Request aborted')); + if (this.#reject) this.#reject(new CancelError('Request aborted')); } public get isCancelled(): boolean { diff --git a/src/client/auth/core/request.ts b/src/client/auth/core/request.ts index 1142d43219797c94e09f35ba83a9f5441892ddd2..c6a0602a006d2d1855c2ab50d2d7f43c2eb1bab4 100644 --- a/src/client/auth/core/request.ts +++ b/src/client/auth/core/request.ts @@ -145,10 +145,13 @@ export const resolve = async <T>(options: ApiRequestOptions, resolver?: T | Reso }; export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions, formData?: FormData): Promise<Record<string, string>> => { - const token = await resolve(options, config.TOKEN); - const username = await resolve(options, config.USERNAME); - const password = await resolve(options, config.PASSWORD); - const additionalHeaders = await resolve(options, config.HEADERS); + const [token, username, password, additionalHeaders] = await Promise.all([ + resolve(options, config.TOKEN), + resolve(options, config.USERNAME), + resolve(options, config.PASSWORD), + resolve(options, config.HEADERS), + ]); + const formHeaders = typeof formData?.getHeaders === 'function' && formData?.getHeaders() || {} const headers = Object.entries({ diff --git a/src/client/auth/models/ErrorDetail.ts b/src/client/auth/models/ErrorDetail.ts index eba50ab9335b70df9b29cada4c54cf9ffaad10a4..69dd37eb86bc15e2ab2037f3f82516493801e74d 100644 --- a/src/client/auth/models/ErrorDetail.ts +++ b/src/client/auth/models/ErrorDetail.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Schema for a error due to a rejected request. */ diff --git a/src/client/auth/models/HTTPValidationError.ts b/src/client/auth/models/HTTPValidationError.ts index c0bcc87cf7f3222638466bc2e5753ca1accf01f7..892e4257ccbb49769737cb2e78e0aad49d81a3b1 100644 --- a/src/client/auth/models/HTTPValidationError.ts +++ b/src/client/auth/models/HTTPValidationError.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { ValidationError } from './ValidationError'; - export type HTTPValidationError = { detail?: Array<ValidationError>; }; diff --git a/src/client/auth/models/RoleEnum.ts b/src/client/auth/models/RoleEnum.ts index c38121aa528efe32ad2db1868fe05ca559006f4b..d1a23ae7bd28accb81fa3d196c78cafd7aebe846 100644 --- a/src/client/auth/models/RoleEnum.ts +++ b/src/client/auth/models/RoleEnum.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Enumeration for the Roles in the CloWM Services. */ @@ -12,4 +11,5 @@ export enum RoleEnum { REVIEWER = 'reviewer', DEVELOPER = 'developer', FOREIGN_USER = 'foreign_user', + DB_MAINTAINER = 'db_maintainer', } diff --git a/src/client/auth/models/User.ts b/src/client/auth/models/User.ts index 8804790e499d6f84af8e66835bdfc8f9a1a269ff..5a1a2a0818d6fde1ed83cf5085a558edd232589b 100644 --- a/src/client/auth/models/User.ts +++ b/src/client/auth/models/User.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { RoleEnum } from './RoleEnum'; - /** * Schema for a user. */ diff --git a/src/client/auth/models/ValidationError.ts b/src/client/auth/models/ValidationError.ts index 18997ec72f4103731f38d915508522ba23ba8506..f2ff49a2b9ad95d18a90c95dc2a7c0b60b7e85e7 100644 --- a/src/client/auth/models/ValidationError.ts +++ b/src/client/auth/models/ValidationError.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export type ValidationError = { loc: Array<(string | number)>; msg: string; diff --git a/src/client/auth/services/AuthService.ts b/src/client/auth/services/AuthService.ts index 0472d3962a5f73dac257fe6de7e4c74cfe56f987..ff4c0213646a9f24e8e8471bcd4cae3f116af2b7 100644 --- a/src/client/auth/services/AuthService.ts +++ b/src/client/auth/services/AuthService.ts @@ -5,9 +5,7 @@ import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; - export class AuthService { - /** * Redirect to LifeScience OIDC Login * Redirect route to OIDC provider to kickstart the login process. @@ -23,7 +21,6 @@ export class AuthService { }, }); } - /** * LifeScience Login Callback * Callback for the Life Science Identity Provider. @@ -48,5 +45,4 @@ export class AuthService { }, }); } - } diff --git a/src/client/auth/services/UserService.ts b/src/client/auth/services/UserService.ts index ae578426600f01927ec075bafe3d68b849366327..0e52ed2f45be911672273c012f8c53859ca25c4c 100644 --- a/src/client/auth/services/UserService.ts +++ b/src/client/auth/services/UserService.ts @@ -4,17 +4,14 @@ /* eslint-disable */ import type { RoleEnum } from '../models/RoleEnum'; import type { User } from '../models/User'; - import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; - export class UserService { - /** * Get the logged in user * Return the user associated with the used JWT. - * Permission 'user:read' required. + * Permission `user:read` required. * @returns User Successful Response * @throws ApiError */ @@ -29,21 +26,21 @@ export class UserService { }, }); } - /** * List users and search by their name * Return the users that have a specific substring in their name. - * Permission 'user:read_any' required, except when 'name_substring' as only query parameter is set. - * Then permission 'user:search' required. - * @param nameSubstring Filter users by a substring in their name. Permission 'search' required - * @param filterRoles Filter users by their role. If multiple are selected, they are concatenating by an OR Expresssion. Permission 'read_any' required - * @param includeRoles Flag whether to include the roles of the users in the response. If True, permission 'read_any' required. + * + * Permission `user:read_any` required, except when `name_substring` as only query parameter is set, + * then permission `user:search` required. + * @param nameSubstring Filter users by a substring in their name. Permission `user:search` required + * @param filterRoles Filter users by their role. If multiple are selected, they are concatenating by an OR Expression. Permission `user:read_any` required + * @param includeRoles Flag whether to include the roles of the users in the response. If True, permission `user:read_any` required. * @returns User Successful Response * @throws ApiError */ public static userListUsers( - nameSubstring?: (string | null), - filterRoles?: (Array<RoleEnum> | null), + nameSubstring?: string, + filterRoles?: Array<RoleEnum>, includeRoles: boolean = false, ): CancelablePromise<Array<User>> { return __request(OpenAPI, { @@ -62,13 +59,13 @@ export class UserService { }, }); } - /** * Get a user by its uid - * Return the user with the specific uid. A user can only view himself. - * Permission 'user:read' required + * Return the user with the specific uid. + * + * Permission `user:read` required if the current user has the same uid as `uid` otherwise `user:read_any` required. * @param uid UID of a user - * @param includeRoles Flag whether to include the roles of the users in the response. If True, permission 'read_any' required. + * @param includeRoles Flag whether to include the roles of the users in the response. If True, permission `user:read_any` required. * @returns User Successful Response * @throws ApiError */ @@ -93,5 +90,4 @@ export class UserService { }, }); } - } diff --git a/src/client/resource/core/ApiError.ts b/src/client/resource/core/ApiError.ts new file mode 100644 index 0000000000000000000000000000000000000000..d6b8fcc3ad0b6b2bdf1aa4df97ec598e64995648 --- /dev/null +++ b/src/client/resource/core/ApiError.ts @@ -0,0 +1,25 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ApiRequestOptions } from './ApiRequestOptions'; +import type { ApiResult } from './ApiResult'; + +export class ApiError extends Error { + public readonly url: string; + public readonly status: number; + public readonly statusText: string; + public readonly body: any; + public readonly request: ApiRequestOptions; + + constructor(request: ApiRequestOptions, response: ApiResult, message: string) { + super(message); + + this.name = 'ApiError'; + this.url = response.url; + this.status = response.status; + this.statusText = response.statusText; + this.body = response.body; + this.request = request; + } +} diff --git a/src/client/resource/core/ApiRequestOptions.ts b/src/client/resource/core/ApiRequestOptions.ts new file mode 100644 index 0000000000000000000000000000000000000000..c19adcc94dc5f015865368d6d64751de5c243aa3 --- /dev/null +++ b/src/client/resource/core/ApiRequestOptions.ts @@ -0,0 +1,17 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type ApiRequestOptions = { + readonly method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'HEAD' | 'PATCH'; + readonly url: string; + readonly path?: Record<string, any>; + readonly cookies?: Record<string, any>; + readonly headers?: Record<string, any>; + readonly query?: Record<string, any>; + readonly formData?: Record<string, any>; + readonly body?: any; + readonly mediaType?: string; + readonly responseHeader?: string; + readonly errors?: Record<number, string>; +}; diff --git a/src/client/resource/core/ApiResult.ts b/src/client/resource/core/ApiResult.ts new file mode 100644 index 0000000000000000000000000000000000000000..ad8fef2bc334c2aedf5c043896fd394229453ff0 --- /dev/null +++ b/src/client/resource/core/ApiResult.ts @@ -0,0 +1,11 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type ApiResult = { + readonly url: string; + readonly ok: boolean; + readonly status: number; + readonly statusText: string; + readonly body: any; +}; diff --git a/src/client/resource/core/CancelablePromise.ts b/src/client/resource/core/CancelablePromise.ts new file mode 100644 index 0000000000000000000000000000000000000000..eb02246c31f61b897667a6433d55b8b413bafbc1 --- /dev/null +++ b/src/client/resource/core/CancelablePromise.ts @@ -0,0 +1,131 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export class CancelError extends Error { + + constructor(message: string) { + super(message); + this.name = 'CancelError'; + } + + public get isCancelled(): boolean { + return true; + } +} + +export interface OnCancel { + readonly isResolved: boolean; + readonly isRejected: boolean; + readonly isCancelled: boolean; + + (cancelHandler: () => void): void; +} + +export class CancelablePromise<T> implements Promise<T> { + #isResolved: boolean; + #isRejected: boolean; + #isCancelled: boolean; + readonly #cancelHandlers: (() => void)[]; + readonly #promise: Promise<T>; + #resolve?: (value: T | PromiseLike<T>) => void; + #reject?: (reason?: any) => void; + + constructor( + executor: ( + resolve: (value: T | PromiseLike<T>) => void, + reject: (reason?: any) => void, + onCancel: OnCancel + ) => void + ) { + this.#isResolved = false; + this.#isRejected = false; + this.#isCancelled = false; + this.#cancelHandlers = []; + this.#promise = new Promise<T>((resolve, reject) => { + this.#resolve = resolve; + this.#reject = reject; + + const onResolve = (value: T | PromiseLike<T>): void => { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#isResolved = true; + if (this.#resolve) this.#resolve(value); + }; + + const onReject = (reason?: any): void => { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#isRejected = true; + if (this.#reject) this.#reject(reason); + }; + + const onCancel = (cancelHandler: () => void): void => { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#cancelHandlers.push(cancelHandler); + }; + + Object.defineProperty(onCancel, 'isResolved', { + get: (): boolean => this.#isResolved, + }); + + Object.defineProperty(onCancel, 'isRejected', { + get: (): boolean => this.#isRejected, + }); + + Object.defineProperty(onCancel, 'isCancelled', { + get: (): boolean => this.#isCancelled, + }); + + return executor(onResolve, onReject, onCancel as OnCancel); + }); + } + + get [Symbol.toStringTag]() { + return "Cancellable Promise"; + } + + public then<TResult1 = T, TResult2 = never>( + onFulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null, + onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null + ): Promise<TResult1 | TResult2> { + return this.#promise.then(onFulfilled, onRejected); + } + + public catch<TResult = never>( + onRejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null + ): Promise<T | TResult> { + return this.#promise.catch(onRejected); + } + + public finally(onFinally?: (() => void) | null): Promise<T> { + return this.#promise.finally(onFinally); + } + + public cancel(): void { + if (this.#isResolved || this.#isRejected || this.#isCancelled) { + return; + } + this.#isCancelled = true; + if (this.#cancelHandlers.length) { + try { + for (const cancelHandler of this.#cancelHandlers) { + cancelHandler(); + } + } catch (error) { + console.warn('Cancellation threw an error', error); + return; + } + } + this.#cancelHandlers.length = 0; + if (this.#reject) this.#reject(new CancelError('Request aborted')); + } + + public get isCancelled(): boolean { + return this.#isCancelled; + } +} diff --git a/src/client/resource/core/OpenAPI.ts b/src/client/resource/core/OpenAPI.ts new file mode 100644 index 0000000000000000000000000000000000000000..6b53d3b96ba6dd7e71fd2068a1a9e3a0a139eab6 --- /dev/null +++ b/src/client/resource/core/OpenAPI.ts @@ -0,0 +1,32 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ApiRequestOptions } from './ApiRequestOptions'; + +type Resolver<T> = (options: ApiRequestOptions) => Promise<T>; +type Headers = Record<string, string>; + +export type OpenAPIConfig = { + BASE: string; + VERSION: string; + WITH_CREDENTIALS: boolean; + CREDENTIALS: 'include' | 'omit' | 'same-origin'; + TOKEN?: string | Resolver<string> | undefined; + USERNAME?: string | Resolver<string> | undefined; + PASSWORD?: string | Resolver<string> | undefined; + HEADERS?: Headers | Resolver<Headers> | undefined; + ENCODE_PATH?: ((path: string) => string) | undefined; +}; + +export const OpenAPI: OpenAPIConfig = { + BASE: '/api/resource-service', + VERSION: '1.0.0', + WITH_CREDENTIALS: false, + CREDENTIALS: 'include', + TOKEN: undefined, + USERNAME: undefined, + PASSWORD: undefined, + HEADERS: undefined, + ENCODE_PATH: undefined, +}; diff --git a/src/client/resource/core/request.ts b/src/client/resource/core/request.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6a0602a006d2d1855c2ab50d2d7f43c2eb1bab4 --- /dev/null +++ b/src/client/resource/core/request.ts @@ -0,0 +1,322 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import axios from 'axios'; +import type { AxiosError, AxiosRequestConfig, AxiosResponse, AxiosInstance } from 'axios'; +import FormData from 'form-data'; + +import { ApiError } from './ApiError'; +import type { ApiRequestOptions } from './ApiRequestOptions'; +import type { ApiResult } from './ApiResult'; +import { CancelablePromise } from './CancelablePromise'; +import type { OnCancel } from './CancelablePromise'; +import type { OpenAPIConfig } from './OpenAPI'; + +export const isDefined = <T>(value: T | null | undefined): value is Exclude<T, null | undefined> => { + return value !== undefined && value !== null; +}; + +export const isString = (value: any): value is string => { + return typeof value === 'string'; +}; + +export const isStringWithValue = (value: any): value is string => { + return isString(value) && value !== ''; +}; + +export const isBlob = (value: any): value is Blob => { + return ( + typeof value === 'object' && + typeof value.type === 'string' && + typeof value.stream === 'function' && + typeof value.arrayBuffer === 'function' && + typeof value.constructor === 'function' && + typeof value.constructor.name === 'string' && + /^(Blob|File)$/.test(value.constructor.name) && + /^(Blob|File)$/.test(value[Symbol.toStringTag]) + ); +}; + +export const isFormData = (value: any): value is FormData => { + return value instanceof FormData; +}; + +export const isSuccess = (status: number): boolean => { + return status >= 200 && status < 300; +}; + +export const base64 = (str: string): string => { + try { + return btoa(str); + } catch (err) { + // @ts-ignore + return Buffer.from(str).toString('base64'); + } +}; + +export const getQueryString = (params: Record<string, any>): string => { + const qs: string[] = []; + + const append = (key: string, value: any) => { + qs.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`); + }; + + const process = (key: string, value: any) => { + if (isDefined(value)) { + if (Array.isArray(value)) { + value.forEach(v => { + process(key, v); + }); + } else if (typeof value === 'object') { + Object.entries(value).forEach(([k, v]) => { + process(`${key}[${k}]`, v); + }); + } else { + append(key, value); + } + } + }; + + Object.entries(params).forEach(([key, value]) => { + process(key, value); + }); + + if (qs.length > 0) { + return `?${qs.join('&')}`; + } + + return ''; +}; + +const getUrl = (config: OpenAPIConfig, options: ApiRequestOptions): string => { + const encoder = config.ENCODE_PATH || encodeURI; + + const path = options.url + .replace('{api-version}', config.VERSION) + .replace(/{(.*?)}/g, (substring: string, group: string) => { + if (options.path?.hasOwnProperty(group)) { + return encoder(String(options.path[group])); + } + return substring; + }); + + const url = `${config.BASE}${path}`; + if (options.query) { + return `${url}${getQueryString(options.query)}`; + } + return url; +}; + +export const getFormData = (options: ApiRequestOptions): FormData | undefined => { + if (options.formData) { + const formData = new FormData(); + + const process = (key: string, value: any) => { + if (isString(value) || isBlob(value)) { + formData.append(key, value); + } else { + formData.append(key, JSON.stringify(value)); + } + }; + + Object.entries(options.formData) + .filter(([_, value]) => isDefined(value)) + .forEach(([key, value]) => { + if (Array.isArray(value)) { + value.forEach(v => process(key, v)); + } else { + process(key, value); + } + }); + + return formData; + } + return undefined; +}; + +type Resolver<T> = (options: ApiRequestOptions) => Promise<T>; + +export const resolve = async <T>(options: ApiRequestOptions, resolver?: T | Resolver<T>): Promise<T | undefined> => { + if (typeof resolver === 'function') { + return (resolver as Resolver<T>)(options); + } + return resolver; +}; + +export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions, formData?: FormData): Promise<Record<string, string>> => { + const [token, username, password, additionalHeaders] = await Promise.all([ + resolve(options, config.TOKEN), + resolve(options, config.USERNAME), + resolve(options, config.PASSWORD), + resolve(options, config.HEADERS), + ]); + + const formHeaders = typeof formData?.getHeaders === 'function' && formData?.getHeaders() || {} + + const headers = Object.entries({ + Accept: 'application/json', + ...additionalHeaders, + ...options.headers, + ...formHeaders, + }) + .filter(([_, value]) => isDefined(value)) + .reduce((headers, [key, value]) => ({ + ...headers, + [key]: String(value), + }), {} as Record<string, string>); + + if (isStringWithValue(token)) { + headers['Authorization'] = `Bearer ${token}`; + } + + if (isStringWithValue(username) && isStringWithValue(password)) { + const credentials = base64(`${username}:${password}`); + headers['Authorization'] = `Basic ${credentials}`; + } + + if (options.body) { + if (options.mediaType) { + headers['Content-Type'] = options.mediaType; + } else if (isBlob(options.body)) { + headers['Content-Type'] = options.body.type || 'application/octet-stream'; + } else if (isString(options.body)) { + headers['Content-Type'] = 'text/plain'; + } else if (!isFormData(options.body)) { + headers['Content-Type'] = 'application/json'; + } + } + + return headers; +}; + +export const getRequestBody = (options: ApiRequestOptions): any => { + if (options.body) { + return options.body; + } + return undefined; +}; + +export const sendRequest = async <T>( + config: OpenAPIConfig, + options: ApiRequestOptions, + url: string, + body: any, + formData: FormData | undefined, + headers: Record<string, string>, + onCancel: OnCancel, + axiosClient: AxiosInstance +): Promise<AxiosResponse<T>> => { + const source = axios.CancelToken.source(); + + const requestConfig: AxiosRequestConfig = { + url, + headers, + data: body ?? formData, + method: options.method, + withCredentials: config.WITH_CREDENTIALS, + cancelToken: source.token, + }; + + onCancel(() => source.cancel('The user aborted a request.')); + + try { + return await axiosClient.request(requestConfig); + } catch (error) { + const axiosError = error as AxiosError<T>; + if (axiosError.response) { + return axiosError.response; + } + throw error; + } +}; + +export const getResponseHeader = (response: AxiosResponse<any>, responseHeader?: string): string | undefined => { + if (responseHeader) { + const content = response.headers[responseHeader]; + if (isString(content)) { + return content; + } + } + return undefined; +}; + +export const getResponseBody = (response: AxiosResponse<any>): any => { + if (response.status !== 204) { + return response.data; + } + return undefined; +}; + +export const catchErrorCodes = (options: ApiRequestOptions, result: ApiResult): void => { + const errors: Record<number, string> = { + 400: 'Bad Request', + 401: 'Unauthorized', + 403: 'Forbidden', + 404: 'Not Found', + 500: 'Internal Server Error', + 502: 'Bad Gateway', + 503: 'Service Unavailable', + ...options.errors, + } + + const error = errors[result.status]; + if (error) { + throw new ApiError(options, result, error); + } + + if (!result.ok) { + const errorStatus = result.status ?? 'unknown'; + const errorStatusText = result.statusText ?? 'unknown'; + const errorBody = (() => { + try { + return JSON.stringify(result.body, null, 2); + } catch (e) { + return undefined; + } + })(); + + throw new ApiError(options, result, + `Generic Error: status: ${errorStatus}; status text: ${errorStatusText}; body: ${errorBody}` + ); + } +}; + +/** + * Request method + * @param config The OpenAPI configuration object + * @param options The request options from the service + * @param axiosClient The axios client instance to use + * @returns CancelablePromise<T> + * @throws ApiError + */ +export const request = <T>(config: OpenAPIConfig, options: ApiRequestOptions, axiosClient: AxiosInstance = axios): CancelablePromise<T> => { + return new CancelablePromise(async (resolve, reject, onCancel) => { + try { + const url = getUrl(config, options); + const formData = getFormData(options); + const body = getRequestBody(options); + const headers = await getHeaders(config, options, formData); + + if (!onCancel.isCancelled) { + const response = await sendRequest<T>(config, options, url, body, formData, headers, onCancel, axiosClient); + const responseBody = getResponseBody(response); + const responseHeader = getResponseHeader(response, options.responseHeader); + + const result: ApiResult = { + url, + ok: isSuccess(response.status), + status: response.status, + statusText: response.statusText, + body: responseHeader ?? responseBody, + }; + + catchErrorCodes(options, result); + + resolve(result.body); + } + } catch (error) { + reject(error); + } + }); +}; diff --git a/src/client/resource/index.ts b/src/client/resource/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..b09145551bb2ba92b29464bf79439a76544bed28 --- /dev/null +++ b/src/client/resource/index.ts @@ -0,0 +1,20 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export { ApiError } from './core/ApiError'; +export { CancelablePromise, CancelError } from './core/CancelablePromise'; +export { OpenAPI } from './core/OpenAPI'; +export type { OpenAPIConfig } from './core/OpenAPI'; + +export type { ErrorDetail } from './models/ErrorDetail'; +export type { HTTPValidationError } from './models/HTTPValidationError'; +export type { ResourceIn } from './models/ResourceIn'; +export type { ResourceOut } from './models/ResourceOut'; +export type { ResourceVersionIn } from './models/ResourceVersionIn'; +export type { ResourceVersionOut } from './models/ResourceVersionOut'; +export { Status } from './models/Status'; +export type { ValidationError } from './models/ValidationError'; + +export { ResourceService } from './services/ResourceService'; +export { ResourceVersionService } from './services/ResourceVersionService'; diff --git a/src/client/resource/models/ErrorDetail.ts b/src/client/resource/models/ErrorDetail.ts new file mode 100644 index 0000000000000000000000000000000000000000..69dd37eb86bc15e2ab2037f3f82516493801e74d --- /dev/null +++ b/src/client/resource/models/ErrorDetail.ts @@ -0,0 +1,14 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +/** + * Schema for a error due to a rejected request. + */ +export type ErrorDetail = { + /** + * Detail about the occurred error + */ + detail: string; +}; + diff --git a/src/client/resource/models/HTTPValidationError.ts b/src/client/resource/models/HTTPValidationError.ts new file mode 100644 index 0000000000000000000000000000000000000000..892e4257ccbb49769737cb2e78e0aad49d81a3b1 --- /dev/null +++ b/src/client/resource/models/HTTPValidationError.ts @@ -0,0 +1,9 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ValidationError } from './ValidationError'; +export type HTTPValidationError = { + detail?: Array<ValidationError>; +}; + diff --git a/src/client/resource/models/ResourceIn.ts b/src/client/resource/models/ResourceIn.ts new file mode 100644 index 0000000000000000000000000000000000000000..bb3eddc4e2b8bc0763e0e1f71eb2b51d074e7e9d --- /dev/null +++ b/src/client/resource/models/ResourceIn.ts @@ -0,0 +1,23 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type ResourceIn = { + /** + * Short tag describing the version of the resource + */ + release: string; + /** + * Short Name for the resource + */ + name: string; + /** + * Short description for this resource + */ + description: string; + /** + * A link or similar where the resource originates from + */ + source: string; +}; + diff --git a/src/client/resource/models/ResourceOut.ts b/src/client/resource/models/ResourceOut.ts new file mode 100644 index 0000000000000000000000000000000000000000..dcb34557a6459d8d4a98764ce9376417ead6e4f7 --- /dev/null +++ b/src/client/resource/models/ResourceOut.ts @@ -0,0 +1,32 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ResourceVersionOut } from './ResourceVersionOut'; +export type ResourceOut = { + /** + * Short Name for the resource + */ + name: string; + /** + * Short description for this resource + */ + description: string; + /** + * A link or similar where the resource originates from + */ + source: string; + /** + * ID of the resource + */ + resource_id: string; + /** + * ID of the maintainer + */ + maintainer_id: string; + /** + * Versions of the resource + */ + versions: Array<ResourceVersionOut>; +}; + diff --git a/src/client/resource/models/ResourceVersionIn.ts b/src/client/resource/models/ResourceVersionIn.ts new file mode 100644 index 0000000000000000000000000000000000000000..68eb986b9852ca442172b4d9ac7ba2b1e33d8d00 --- /dev/null +++ b/src/client/resource/models/ResourceVersionIn.ts @@ -0,0 +1,11 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type ResourceVersionIn = { + /** + * Short tag describing the version of the resource + */ + release: string; +}; + diff --git a/src/client/resource/models/ResourceVersionOut.ts b/src/client/resource/models/ResourceVersionOut.ts new file mode 100644 index 0000000000000000000000000000000000000000..7ab1dda6759829a8e9a4e3c4b0b9cf3658c8cb56 --- /dev/null +++ b/src/client/resource/models/ResourceVersionOut.ts @@ -0,0 +1,36 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { Status } from './Status'; +export type ResourceVersionOut = { + /** + * Short tag describing the version of the resource + */ + release: string; + /** + * Status of the resource version + */ + status: Status; + /** + * ID of the resource version + */ + resource_version_id: string; + /** + * ID of the resource + */ + resource_id: string; + /** + * Timestamp when the version was created as UNIX timestamp + */ + created_at: number; + /** + * Path to the resource on the cluster if the resource is synchronized + */ + readonly cluster_path: (string | null); + /** + * Path to the resource in the S3 Bucket. Not publicly available. + */ + readonly s3_path: string; +}; + diff --git a/src/client/resource/models/Status.ts b/src/client/resource/models/Status.ts new file mode 100644 index 0000000000000000000000000000000000000000..51aaaaac28610eeb989f2d761d1d9f525cdd8c4b --- /dev/null +++ b/src/client/resource/models/Status.ts @@ -0,0 +1,17 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +/** + * Enumeration for the possible status of a resource version. + */ +export enum Status { + RESOURCE_REQUESTED = 'RESOURCE_REQUESTED', + SYNC_REQUESTED = 'SYNC_REQUESTED', + SYNCHRONIZING = 'SYNCHRONIZING', + SYNCHRONIZED = 'SYNCHRONIZED', + LATEST = 'LATEST', + DENIED = 'DENIED', + CLUSTER_DELETED = 'CLUSTER_DELETED', + S3_DELETED = 'S3_DELETED', +} diff --git a/src/client/resource/models/ValidationError.ts b/src/client/resource/models/ValidationError.ts new file mode 100644 index 0000000000000000000000000000000000000000..f2ff49a2b9ad95d18a90c95dc2a7c0b60b7e85e7 --- /dev/null +++ b/src/client/resource/models/ValidationError.ts @@ -0,0 +1,10 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type ValidationError = { + loc: Array<(string | number)>; + msg: string; + type: string; +}; + diff --git a/src/client/resource/services/ResourceService.ts b/src/client/resource/services/ResourceService.ts new file mode 100644 index 0000000000000000000000000000000000000000..2c182a2bdc2b2aec492e95d0f6b0b26951b367cd --- /dev/null +++ b/src/client/resource/services/ResourceService.ts @@ -0,0 +1,126 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ResourceIn } from '../models/ResourceIn'; +import type { ResourceOut } from '../models/ResourceOut'; +import type { Status } from '../models/Status'; +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; +export class ResourceService { + /** + * List resources + * List all resources. + * + * Permission `resource:list` required. + * @param maintainerId Filter for resource by maintainer. If current user is the same as maintainer ID, permission `resource:list` required, otherwise `resource:list_filter`. + * @param versionStatus Which versions of the resource to include in the response. Permission `resource:list_filter` required, unless `maintainer_id` is provided and current user is maintainer, then only permission `resource:list` required. Default `LATEST` and `SYNCHRONIZED`. + * @param nameSubstring + * @returns ResourceOut Successful Response + * @throws ApiError + */ + public static resourceListResources( + maintainerId?: string, + versionStatus?: Array<Status>, + nameSubstring?: string, + ): CancelablePromise<Array<ResourceOut>> { + return __request(OpenAPI, { + method: 'GET', + url: '/resources', + query: { + 'maintainer_id': maintainerId, + 'version_status': versionStatus, + 'name_substring': nameSubstring, + }, + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } + /** + * Request a new resource + * Request a new resources. + * + * Permission `resource:create` required. + * @param requestBody + * @returns ResourceOut Successful Response + * @throws ApiError + */ + public static resourceCreateResource( + requestBody: ResourceIn, + ): CancelablePromise<ResourceOut> { + return __request(OpenAPI, { + method: 'POST', + url: '/resources', + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } + /** + * Get a resource + * Get a specific resource. + * + * Permission `resource:read` required. + * @param rid + * @param versionStatus Which versions of the resource to include in the response. Permission `resource:read_any` required, unless the current user is the maintainer, then only permission `resource:read` required. Default `LATEST` and `SYNCHRONIZED`. + * @returns ResourceOut Successful Response + * @throws ApiError + */ + public static resourceGetResource( + rid: string, + versionStatus?: Array<Status>, + ): CancelablePromise<ResourceOut> { + return __request(OpenAPI, { + method: 'GET', + url: '/resources/{rid}', + path: { + 'rid': rid, + }, + query: { + 'version_status': versionStatus, + }, + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } + /** + * Delete a resource + * Delete a resources. + * + * Permission `resource:delete` required. + * @param rid + * @returns void + * @throws ApiError + */ + public static resourceDeleteResource( + rid: string, + ): CancelablePromise<void> { + return __request(OpenAPI, { + method: 'DELETE', + url: '/resources/{rid}', + path: { + 'rid': rid, + }, + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } +} diff --git a/src/client/resource/services/ResourceVersionService.ts b/src/client/resource/services/ResourceVersionService.ts new file mode 100644 index 0000000000000000000000000000000000000000..804d721aaab59aea45dff36fda2481770c257149 --- /dev/null +++ b/src/client/resource/services/ResourceVersionService.ts @@ -0,0 +1,248 @@ +/* generated using openapi-typescript-codegen -- do no edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { ResourceVersionIn } from '../models/ResourceVersionIn'; +import type { ResourceVersionOut } from '../models/ResourceVersionOut'; +import type { Status } from '../models/Status'; +import type { CancelablePromise } from '../core/CancelablePromise'; +import { OpenAPI } from '../core/OpenAPI'; +import { request as __request } from '../core/request'; +export class ResourceVersionService { + /** + * List versions of a resource + * List all the resource version for a specific resource. + * + * Permission 'resource:read' required. + * @param rid + * @param versionStatus Which versions to include in the response. Permission `resource:read_any` required, current user is the maintainer, then only permission `resource:read` required. Default `LATEST` and `SYNCHRONIZED`. + * @returns ResourceVersionOut Successful Response + * @throws ApiError + */ + public static resourceVersionListResourceVersions( + rid: string, + versionStatus?: Array<Status>, + ): CancelablePromise<Array<ResourceVersionOut>> { + return __request(OpenAPI, { + method: 'GET', + url: '/resources/{rid}/versions', + path: { + 'rid': rid, + }, + query: { + 'version_status': versionStatus, + }, + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } + /** + * Request new version of a resource + * Request a new resource version. + * + * Permission `resource:update` required if the current user is the maintainer, `resource:update_any` otherwise. + * @param rid + * @param requestBody + * @returns ResourceVersionOut Successful Response + * @throws ApiError + */ + public static resourceVersionRequestResourceVersion( + rid: string, + requestBody: ResourceVersionIn, + ): CancelablePromise<ResourceVersionOut> { + return __request(OpenAPI, { + method: 'POST', + url: '/resources/{rid}/versions', + path: { + 'rid': rid, + }, + body: requestBody, + mediaType: 'application/json', + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } + /** + * Get version of a resource + * Get a specific resource version for a specific resource. + * + * Permission `resource:read` required. If the status of the resource version is not `LATEST` or `SYNCHRONIZED` and + * the current user is not the maintainer, then the permission `resource:read_any` is required. + * @param rid + * @param rvid + * @returns ResourceVersionOut Successful Response + * @throws ApiError + */ + public static resourceVersionGetResourceVersion( + rid: string, + rvid: string, + ): CancelablePromise<ResourceVersionOut> { + return __request(OpenAPI, { + method: 'GET', + url: '/resources/{rid}/versions/{rvid}', + path: { + 'rid': rid, + 'rvid': rvid, + }, + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } + /** + * Request resource version synchronization + * Request the synchronization of a resource version to the cluster. + * + * Permission `resource:request_sync` required if current user is the maintainer, `resource:request_sync_any` otherwise. + * @param rid + * @param rvid + * @returns ResourceVersionOut Successful Response + * @throws ApiError + */ + public static resourceVersionRequestResourceVersionSync( + rid: string, + rvid: string, + ): CancelablePromise<ResourceVersionOut> { + return __request(OpenAPI, { + method: 'PUT', + url: '/resources/{rid}/versions/{rvid}/request_sync', + path: { + 'rid': rid, + 'rvid': rvid, + }, + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } + /** + * Synchronize resource version with cluster + * Synchronize the resource version to the cluster. + * + * Permission `resource:sync` required. + * @param rid + * @param rvid + * @returns ResourceVersionOut Successful Response + * @throws ApiError + */ + public static resourceVersionResourceVersionSync( + rid: string, + rvid: string, + ): CancelablePromise<ResourceVersionOut> { + return __request(OpenAPI, { + method: 'PUT', + url: '/resources/{rid}/versions/{rvid}/sync', + path: { + 'rid': rid, + 'rvid': rvid, + }, + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } + /** + * Set resource version to latest + * Set the resource version as the latest version. + * + * Permission `resource:set_latest` required. + * @param rid + * @param rvid + * @returns ResourceVersionOut Successful Response + * @throws ApiError + */ + public static resourceVersionResourceVersionLatest( + rid: string, + rvid: string, + ): CancelablePromise<ResourceVersionOut> { + return __request(OpenAPI, { + method: 'PUT', + url: '/resources/{rid}/versions/{rvid}/latest', + path: { + 'rid': rid, + 'rvid': rvid, + }, + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } + /** + * Delete resource version on cluster + * Delete the resource version on the cluster. + * + * Permission `resource:delete_cluster` required. + * @param rid + * @param rvid + * @returns ResourceVersionOut Successful Response + * @throws ApiError + */ + public static resourceVersionDeleteResourceVersionCluster( + rid: string, + rvid: string, + ): CancelablePromise<ResourceVersionOut> { + return __request(OpenAPI, { + method: 'DELETE', + url: '/resources/{rid}/versions/{rvid}/cluster', + path: { + 'rid': rid, + 'rvid': rvid, + }, + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } + /** + * Delete resource version in S3 + * Delete the resource version in the S3 bucket. + * + * Permission `resource:delete_s3` required. + * @param rid + * @param rvid + * @returns ResourceVersionOut Successful Response + * @throws ApiError + */ + public static resourceVersionDeleteResourceVersionS3( + rid: string, + rvid: string, + ): CancelablePromise<ResourceVersionOut> { + return __request(OpenAPI, { + method: 'DELETE', + url: '/resources/{rid}/versions/{rvid}/s3', + path: { + 'rid': rid, + 'rvid': rvid, + }, + errors: { + 400: `Error decoding JWT Token`, + 403: `Not authenticated`, + 404: `Entity not Found`, + 422: `Validation Error`, + }, + }); + } +} diff --git a/src/client/s3proxy/core/CancelablePromise.ts b/src/client/s3proxy/core/CancelablePromise.ts index 55fef8517238d2dab7478598eefca72e657b9fb5..eb02246c31f61b897667a6433d55b8b413bafbc1 100644 --- a/src/client/s3proxy/core/CancelablePromise.ts +++ b/src/client/s3proxy/core/CancelablePromise.ts @@ -51,7 +51,7 @@ export class CancelablePromise<T> implements Promise<T> { return; } this.#isResolved = true; - this.#resolve?.(value); + if (this.#resolve) this.#resolve(value); }; const onReject = (reason?: any): void => { @@ -59,7 +59,7 @@ export class CancelablePromise<T> implements Promise<T> { return; } this.#isRejected = true; - this.#reject?.(reason); + if (this.#reject) this.#reject(reason); }; const onCancel = (cancelHandler: () => void): void => { @@ -122,7 +122,7 @@ export class CancelablePromise<T> implements Promise<T> { } } this.#cancelHandlers.length = 0; - this.#reject?.(new CancelError('Request aborted')); + if (this.#reject) this.#reject(new CancelError('Request aborted')); } public get isCancelled(): boolean { diff --git a/src/client/s3proxy/core/request.ts b/src/client/s3proxy/core/request.ts index 1142d43219797c94e09f35ba83a9f5441892ddd2..c6a0602a006d2d1855c2ab50d2d7f43c2eb1bab4 100644 --- a/src/client/s3proxy/core/request.ts +++ b/src/client/s3proxy/core/request.ts @@ -145,10 +145,13 @@ export const resolve = async <T>(options: ApiRequestOptions, resolver?: T | Reso }; export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions, formData?: FormData): Promise<Record<string, string>> => { - const token = await resolve(options, config.TOKEN); - const username = await resolve(options, config.USERNAME); - const password = await resolve(options, config.PASSWORD); - const additionalHeaders = await resolve(options, config.HEADERS); + const [token, username, password, additionalHeaders] = await Promise.all([ + resolve(options, config.TOKEN), + resolve(options, config.USERNAME), + resolve(options, config.PASSWORD), + resolve(options, config.HEADERS), + ]); + const formHeaders = typeof formData?.getHeaders === 'function' && formData?.getHeaders() || {} const headers = Object.entries({ diff --git a/src/client/s3proxy/models/BucketIn.ts b/src/client/s3proxy/models/BucketIn.ts index 96ff7b44981b9551e21fd5562e8d82caeb080043..9505a6420088ebf53b6601e1700d92a865272eb0 100644 --- a/src/client/s3proxy/models/BucketIn.ts +++ b/src/client/s3proxy/models/BucketIn.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Schema for creating a new bucket. */ diff --git a/src/client/s3proxy/models/BucketOut.ts b/src/client/s3proxy/models/BucketOut.ts index 5b38801ea29b9a411113b9b5c2343d33c6f1ef15..cbb67fb5d8ca30e046785ffb35be521c81e49937 100644 --- a/src/client/s3proxy/models/BucketOut.ts +++ b/src/client/s3proxy/models/BucketOut.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { Constraint } from './Constraint'; - /** * Schema for answering a request with a bucket. */ diff --git a/src/client/s3proxy/models/BucketPermissionIn.ts b/src/client/s3proxy/models/BucketPermissionIn.ts index 06bd223c69ce58189c1699343b1018187a8942c1..e0e38255d47fedaf9bf6abda58b1e8e5e5537ef5 100644 --- a/src/client/s3proxy/models/BucketPermissionIn.ts +++ b/src/client/s3proxy/models/BucketPermissionIn.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { Permission } from './Permission'; - export type BucketPermissionIn = { /** * Start date of permission as UNIX timestamp diff --git a/src/client/s3proxy/models/BucketPermissionOut.ts b/src/client/s3proxy/models/BucketPermissionOut.ts index 38ac0254a4332ab86e098af5767e16cd022d0d80..ec3c79d39c434447e2df2791206f05f5f278f909 100644 --- a/src/client/s3proxy/models/BucketPermissionOut.ts +++ b/src/client/s3proxy/models/BucketPermissionOut.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { Permission } from './Permission'; - /** * Schema for the bucket permissions. */ diff --git a/src/client/s3proxy/models/BucketPermissionParameters.ts b/src/client/s3proxy/models/BucketPermissionParameters.ts index 4d8ef97bf2f6c6f51fbb3a1c4f2937fba8a0aefb..47c7576e18ad4ec0e6ff29040c723153eeee612b 100644 --- a/src/client/s3proxy/models/BucketPermissionParameters.ts +++ b/src/client/s3proxy/models/BucketPermissionParameters.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { Permission } from './Permission'; - /** * Schema for the parameters of a bucket permission. */ diff --git a/src/client/s3proxy/models/BucketType.ts b/src/client/s3proxy/models/BucketType.ts index b096c70b0b7234bc57dd1ecc2223bd41aa3e0d08..8001a27664273bd2a5ad360f6f10444be2e7046d 100644 --- a/src/client/s3proxy/models/BucketType.ts +++ b/src/client/s3proxy/models/BucketType.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Enumeration for the type of buckets to fetch from the DB * diff --git a/src/client/s3proxy/models/Constraint.ts b/src/client/s3proxy/models/Constraint.ts index afa995a983b5e08b66d55b8dfa4243553351d3a7..99043221bd2e12d3e2a112ae9308437d99e7df40 100644 --- a/src/client/s3proxy/models/Constraint.ts +++ b/src/client/s3proxy/models/Constraint.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Enumeration for the possible permission on a bucket. */ diff --git a/src/client/s3proxy/models/ErrorDetail.ts b/src/client/s3proxy/models/ErrorDetail.ts index eba50ab9335b70df9b29cada4c54cf9ffaad10a4..69dd37eb86bc15e2ab2037f3f82516493801e74d 100644 --- a/src/client/s3proxy/models/ErrorDetail.ts +++ b/src/client/s3proxy/models/ErrorDetail.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Schema for a error due to a rejected request. */ diff --git a/src/client/s3proxy/models/HTTPValidationError.ts b/src/client/s3proxy/models/HTTPValidationError.ts index c0bcc87cf7f3222638466bc2e5753ca1accf01f7..892e4257ccbb49769737cb2e78e0aad49d81a3b1 100644 --- a/src/client/s3proxy/models/HTTPValidationError.ts +++ b/src/client/s3proxy/models/HTTPValidationError.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { ValidationError } from './ValidationError'; - export type HTTPValidationError = { detail?: Array<ValidationError>; }; diff --git a/src/client/s3proxy/models/Permission.ts b/src/client/s3proxy/models/Permission.ts index 00592a496a01e178e7192ba3bd76c51b29a3a138..33aebf753f36ab7b85a50e0de9d47501f3ff8709 100644 --- a/src/client/s3proxy/models/Permission.ts +++ b/src/client/s3proxy/models/Permission.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Enumeration for the possible permission on a bucket. */ diff --git a/src/client/s3proxy/models/PermissionStatus.ts b/src/client/s3proxy/models/PermissionStatus.ts index d51e0928ec89e662e033c833ceacd5bd6c66bc74..0d858f08edd1fdb664ee83cc5805423dc3dd93f5 100644 --- a/src/client/s3proxy/models/PermissionStatus.ts +++ b/src/client/s3proxy/models/PermissionStatus.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Status of a bucket permission. Can be either `ACTIVE` or `INACTIVE`. A permission can only get `INACTIVE` if the * permission itself has a time limit and the current time is not in the timespan. diff --git a/src/client/s3proxy/models/S3Key.ts b/src/client/s3proxy/models/S3Key.ts index cc9f01a57583423aeaad174dc68c8e96c16706a9..b3c30da182357c5a2d3b3c07c315c3cc3a6ff917 100644 --- a/src/client/s3proxy/models/S3Key.ts +++ b/src/client/s3proxy/models/S3Key.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Schema for a S3 key associated with a user. */ diff --git a/src/client/s3proxy/models/ValidationError.ts b/src/client/s3proxy/models/ValidationError.ts index 18997ec72f4103731f38d915508522ba23ba8506..f2ff49a2b9ad95d18a90c95dc2a7c0b60b7e85e7 100644 --- a/src/client/s3proxy/models/ValidationError.ts +++ b/src/client/s3proxy/models/ValidationError.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export type ValidationError = { loc: Array<(string | number)>; msg: string; diff --git a/src/client/s3proxy/services/BucketPermissionService.ts b/src/client/s3proxy/services/BucketPermissionService.ts index 3b55d1bc1c6674483f24e3471fd5ae07d4cfa189..d5119dc321fff3d195d7638805baa255aefaad6f 100644 --- a/src/client/s3proxy/services/BucketPermissionService.ts +++ b/src/client/s3proxy/services/BucketPermissionService.ts @@ -7,13 +7,10 @@ import type { BucketPermissionOut } from '../models/BucketPermissionOut'; import type { BucketPermissionParameters } from '../models/BucketPermissionParameters'; import type { Permission } from '../models/Permission'; import type { PermissionStatus } from '../models/PermissionStatus'; - import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; - export class BucketPermissionService { - /** * Get permission for bucket and user combination. * Get the bucket permissions for the specific combination of bucket and user. @@ -46,7 +43,6 @@ export class BucketPermissionService { }, }); } - /** * Delete a bucket permission * Delete the bucket permissions for the specific combination of bucket and user. @@ -79,7 +75,6 @@ export class BucketPermissionService { }, }); } - /** * Update a bucket permission * Update a permission for a bucket and user. @@ -114,7 +109,6 @@ export class BucketPermissionService { }, }); } - /** * Get all permissions for a bucket. * List all the bucket permissions for the given bucket. @@ -150,7 +144,6 @@ export class BucketPermissionService { }, }); } - /** * Get all permissions for a user. * List all the bucket permissions for the given user. @@ -186,7 +179,6 @@ export class BucketPermissionService { }, }); } - /** * Create a permission. * Create a permission for a bucket and user. @@ -212,5 +204,4 @@ export class BucketPermissionService { }, }); } - } diff --git a/src/client/s3proxy/services/BucketService.ts b/src/client/s3proxy/services/BucketService.ts index d51b66804563285d8e72e555076407af7ee381d9..92cee996275bb497a6151023f844736cb7d6a8c5 100644 --- a/src/client/s3proxy/services/BucketService.ts +++ b/src/client/s3proxy/services/BucketService.ts @@ -5,13 +5,10 @@ import type { BucketIn } from '../models/BucketIn'; import type { BucketOut } from '../models/BucketOut'; import type { BucketType } from '../models/BucketType'; - import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; - export class BucketService { - /** * List buckets of user * List all the buckets in the system or of the desired user where the user has READ permissions for. @@ -41,7 +38,6 @@ export class BucketService { }, }); } - /** * Create a bucket for the current user * Create a bucket for the current user. @@ -71,7 +67,6 @@ export class BucketService { }, }); } - /** * Get a bucket by its name * Get a bucket by its name if the current user has READ permissions for the bucket. @@ -99,7 +94,6 @@ export class BucketService { }, }); } - /** * Delete a bucket * Delete a bucket by its name. Only the owner of the bucket can delete the bucket. @@ -132,5 +126,4 @@ export class BucketService { }, }); } - } diff --git a/src/client/s3proxy/services/S3KeyService.ts b/src/client/s3proxy/services/S3KeyService.ts index c8e048bdc22fbbd683259c5850045063938a7aee..732fd680c4e5530909a9e67fb3d5eb28137d057f 100644 --- a/src/client/s3proxy/services/S3KeyService.ts +++ b/src/client/s3proxy/services/S3KeyService.ts @@ -3,13 +3,10 @@ /* tslint:disable */ /* eslint-disable */ import type { S3Key } from '../models/S3Key'; - import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; - export class S3KeyService { - /** * Get the S3 Access keys from a user * Get all the S3 Access keys for a specific user. @@ -36,7 +33,6 @@ export class S3KeyService { }, }); } - /** * Create a Access key for a user * Create a S3 Access key for a specific user. @@ -63,7 +59,6 @@ export class S3KeyService { }, }); } - /** * Get a specific S3 Access key from a user * Get a specific S3 Access Key for a specific user. @@ -93,7 +88,6 @@ export class S3KeyService { }, }); } - /** * Delete a specific S3 Access key from a user * Delete a specific S3 Access key for a specific user. @@ -123,5 +117,4 @@ export class S3KeyService { }, }); } - } diff --git a/src/client/workflow/core/CancelablePromise.ts b/src/client/workflow/core/CancelablePromise.ts index 55fef8517238d2dab7478598eefca72e657b9fb5..eb02246c31f61b897667a6433d55b8b413bafbc1 100644 --- a/src/client/workflow/core/CancelablePromise.ts +++ b/src/client/workflow/core/CancelablePromise.ts @@ -51,7 +51,7 @@ export class CancelablePromise<T> implements Promise<T> { return; } this.#isResolved = true; - this.#resolve?.(value); + if (this.#resolve) this.#resolve(value); }; const onReject = (reason?: any): void => { @@ -59,7 +59,7 @@ export class CancelablePromise<T> implements Promise<T> { return; } this.#isRejected = true; - this.#reject?.(reason); + if (this.#reject) this.#reject(reason); }; const onCancel = (cancelHandler: () => void): void => { @@ -122,7 +122,7 @@ export class CancelablePromise<T> implements Promise<T> { } } this.#cancelHandlers.length = 0; - this.#reject?.(new CancelError('Request aborted')); + if (this.#reject) this.#reject(new CancelError('Request aborted')); } public get isCancelled(): boolean { diff --git a/src/client/workflow/core/request.ts b/src/client/workflow/core/request.ts index 1142d43219797c94e09f35ba83a9f5441892ddd2..c6a0602a006d2d1855c2ab50d2d7f43c2eb1bab4 100644 --- a/src/client/workflow/core/request.ts +++ b/src/client/workflow/core/request.ts @@ -145,10 +145,13 @@ export const resolve = async <T>(options: ApiRequestOptions, resolver?: T | Reso }; export const getHeaders = async (config: OpenAPIConfig, options: ApiRequestOptions, formData?: FormData): Promise<Record<string, string>> => { - const token = await resolve(options, config.TOKEN); - const username = await resolve(options, config.USERNAME); - const password = await resolve(options, config.PASSWORD); - const additionalHeaders = await resolve(options, config.HEADERS); + const [token, username, password, additionalHeaders] = await Promise.all([ + resolve(options, config.TOKEN), + resolve(options, config.USERNAME), + resolve(options, config.PASSWORD), + resolve(options, config.HEADERS), + ]); + const formHeaders = typeof formData?.getHeaders === 'function' && formData?.getHeaders() || {} const headers = Object.entries({ diff --git a/src/client/workflow/models/AnonymizedWorkflowExecution.ts b/src/client/workflow/models/AnonymizedWorkflowExecution.ts index eb4085fe63360b4b3018cf3e85a097f9679422ed..11497f73bf3bb867a29356784391a47e8b028df0 100644 --- a/src/client/workflow/models/AnonymizedWorkflowExecution.ts +++ b/src/client/workflow/models/AnonymizedWorkflowExecution.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { WorkflowExecutionStatus } from './WorkflowExecutionStatus'; - export type AnonymizedWorkflowExecution = { /** * ID of the workflow execution diff --git a/src/client/workflow/models/Body_Workflow_Version_upload_workflow_version_icon.ts b/src/client/workflow/models/Body_Workflow_Version_upload_workflow_version_icon.ts index 208b0c24d5b34514fe1156aafeddabd72645a53c..fa8dd9ee4c8d6757fd68c4ede429a0122f03546d 100644 --- a/src/client/workflow/models/Body_Workflow_Version_upload_workflow_version_icon.ts +++ b/src/client/workflow/models/Body_Workflow_Version_upload_workflow_version_icon.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export type Body_Workflow_Version_upload_workflow_version_icon = { /** * Optional Icon for the Workflow. diff --git a/src/client/workflow/models/DevWorkflowExecutionIn.ts b/src/client/workflow/models/DevWorkflowExecutionIn.ts index e8c8a5268a58669f45acee40630ad7d6c1d9c21a..ad6cbd949c0011a656dfd2ef699cfe7e90c180ac 100644 --- a/src/client/workflow/models/DevWorkflowExecutionIn.ts +++ b/src/client/workflow/models/DevWorkflowExecutionIn.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { WorkflowModeIn } from './WorkflowModeIn'; - export type DevWorkflowExecutionIn = { /** * Parameters for this workflow diff --git a/src/client/workflow/models/DocumentationEnum.ts b/src/client/workflow/models/DocumentationEnum.ts index 1ae04856a01b1b0b6dfe8c550ec97720aaeb4cd6..2f5b3e3d5833fb1775dd5d45ccef997b2e9b471f 100644 --- a/src/client/workflow/models/DocumentationEnum.ts +++ b/src/client/workflow/models/DocumentationEnum.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export enum DocumentationEnum { USAGE = 'usage', INPUT = 'input', diff --git a/src/client/workflow/models/ErrorDetail.ts b/src/client/workflow/models/ErrorDetail.ts index eba50ab9335b70df9b29cada4c54cf9ffaad10a4..69dd37eb86bc15e2ab2037f3f82516493801e74d 100644 --- a/src/client/workflow/models/ErrorDetail.ts +++ b/src/client/workflow/models/ErrorDetail.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Schema for a error due to a rejected request. */ diff --git a/src/client/workflow/models/HTTPValidationError.ts b/src/client/workflow/models/HTTPValidationError.ts index c0bcc87cf7f3222638466bc2e5753ca1accf01f7..892e4257ccbb49769737cb2e78e0aad49d81a3b1 100644 --- a/src/client/workflow/models/HTTPValidationError.ts +++ b/src/client/workflow/models/HTTPValidationError.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { ValidationError } from './ValidationError'; - export type HTTPValidationError = { detail?: Array<ValidationError>; }; diff --git a/src/client/workflow/models/IconUpdateOut.ts b/src/client/workflow/models/IconUpdateOut.ts index 0499796ef14433d99fae156f3508df5ed0db9984..1210a9304608adaafc41a6be01dbbb145f8d9964 100644 --- a/src/client/workflow/models/IconUpdateOut.ts +++ b/src/client/workflow/models/IconUpdateOut.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export type IconUpdateOut = { /** * URL to the uploaded icon diff --git a/src/client/workflow/models/Status.ts b/src/client/workflow/models/Status.ts index 8da66ea5e286d86b0f4d9d1c3b7bac8167d769ab..fd918bd83e94662808073249cf91cc0d8b721fac 100644 --- a/src/client/workflow/models/Status.ts +++ b/src/client/workflow/models/Status.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Enumeration for the possible status of a workflow version. */ diff --git a/src/client/workflow/models/ValidationError.ts b/src/client/workflow/models/ValidationError.ts index 18997ec72f4103731f38d915508522ba23ba8506..f2ff49a2b9ad95d18a90c95dc2a7c0b60b7e85e7 100644 --- a/src/client/workflow/models/ValidationError.ts +++ b/src/client/workflow/models/ValidationError.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export type ValidationError = { loc: Array<(string | number)>; msg: string; diff --git a/src/client/workflow/models/WorkflowCredentialsIn.ts b/src/client/workflow/models/WorkflowCredentialsIn.ts index 37723a3e3a9384f04e6d52ecd6ac4f302d6ac304..a3b3c105701dfc4949bd81bb26409275e60a7b64 100644 --- a/src/client/workflow/models/WorkflowCredentialsIn.ts +++ b/src/client/workflow/models/WorkflowCredentialsIn.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export type WorkflowCredentialsIn = { /** * Token to access the content git repository diff --git a/src/client/workflow/models/WorkflowCredentialsOut.ts b/src/client/workflow/models/WorkflowCredentialsOut.ts index 8a447b4228303bd6e0204694408a131b9a15b0d2..371252ccef56cbab9fae83919271e08aa6ae198d 100644 --- a/src/client/workflow/models/WorkflowCredentialsOut.ts +++ b/src/client/workflow/models/WorkflowCredentialsOut.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export type WorkflowCredentialsOut = { /** * Token to access the content git repository diff --git a/src/client/workflow/models/WorkflowExecutionIn.ts b/src/client/workflow/models/WorkflowExecutionIn.ts index 3532aa80d246e34c0974e847894e043dfbc6b02d..223447aee1646e8aa2cb72943f6772a5812e044e 100644 --- a/src/client/workflow/models/WorkflowExecutionIn.ts +++ b/src/client/workflow/models/WorkflowExecutionIn.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export type WorkflowExecutionIn = { /** * Parameters for this workflow diff --git a/src/client/workflow/models/WorkflowExecutionOut.ts b/src/client/workflow/models/WorkflowExecutionOut.ts index a804c6ade04581facc1d0543e3fcc60a3a030803..dc3e9811125d2bb768b207dfa0ae0e738a798a32 100644 --- a/src/client/workflow/models/WorkflowExecutionOut.ts +++ b/src/client/workflow/models/WorkflowExecutionOut.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { WorkflowExecutionStatus } from './WorkflowExecutionStatus'; - export type WorkflowExecutionOut = { /** * Workflow version git commit hash diff --git a/src/client/workflow/models/WorkflowExecutionStatus.ts b/src/client/workflow/models/WorkflowExecutionStatus.ts index dee8c8fea4f0bbb84f2b8aaf69f626989e1639a6..6b92108d72486d7dbf7cd63606e0e5210d479c02 100644 --- a/src/client/workflow/models/WorkflowExecutionStatus.ts +++ b/src/client/workflow/models/WorkflowExecutionStatus.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - /** * Enumeration for the status on a workflow execution. */ diff --git a/src/client/workflow/models/WorkflowIn.ts b/src/client/workflow/models/WorkflowIn.ts index 9367556e9ffa26da9b64044efbd577d24dc145f7..c5322ce22a5df57eade165e222023333d7d79dd1 100644 --- a/src/client/workflow/models/WorkflowIn.ts +++ b/src/client/workflow/models/WorkflowIn.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { WorkflowModeIn } from './WorkflowModeIn'; - export type WorkflowIn = { /** * Short descriptive name of the workflow diff --git a/src/client/workflow/models/WorkflowModeIn.ts b/src/client/workflow/models/WorkflowModeIn.ts index a50b038c1abd7c60352b1526e164c652aa99e7df..7d8d2d439cc4fa451a071aa2edbf5457c2c84c06 100644 --- a/src/client/workflow/models/WorkflowModeIn.ts +++ b/src/client/workflow/models/WorkflowModeIn.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export type WorkflowModeIn = { /** * Path to the alternative parameter schema diff --git a/src/client/workflow/models/WorkflowModeOut.ts b/src/client/workflow/models/WorkflowModeOut.ts index 1d52e08bd2580b58af3b5204a6e6ebc1fa2d6ee8..d3b61d56fadb4e1e93d4ba47a6fb65e2118b6906 100644 --- a/src/client/workflow/models/WorkflowModeOut.ts +++ b/src/client/workflow/models/WorkflowModeOut.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export type WorkflowModeOut = { /** * Path to the alternative parameter schema diff --git a/src/client/workflow/models/WorkflowOut.ts b/src/client/workflow/models/WorkflowOut.ts index a3d055f5a99d8683b29183cfe42cf01b9903ad28..90fbae386c4790be3b6063d3cff5db722dcd9d4d 100644 --- a/src/client/workflow/models/WorkflowOut.ts +++ b/src/client/workflow/models/WorkflowOut.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { WorkflowVersion } from './WorkflowVersion'; - export type WorkflowOut = { /** * Short descriptive name of the workflow diff --git a/src/client/workflow/models/WorkflowStatistic.ts b/src/client/workflow/models/WorkflowStatistic.ts index 4b7fbade791196f814a52cee40e8cca117ea8102..d84e2dc9ce8a30ce6d93a355774e56957fb117e3 100644 --- a/src/client/workflow/models/WorkflowStatistic.ts +++ b/src/client/workflow/models/WorkflowStatistic.ts @@ -2,7 +2,6 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - export type WorkflowStatistic = { /** * Day of the datapoint diff --git a/src/client/workflow/models/WorkflowUpdate.ts b/src/client/workflow/models/WorkflowUpdate.ts index 6aa6f1874344aff94967d05ddd3958cd86726d71..879f4bc2d303f3e3bd247b63b3996a14b9fa1b41 100644 --- a/src/client/workflow/models/WorkflowUpdate.ts +++ b/src/client/workflow/models/WorkflowUpdate.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { WorkflowModeIn } from './WorkflowModeIn'; - export type WorkflowUpdate = { /** * Version of the Workflow. Should follow semantic versioning diff --git a/src/client/workflow/models/WorkflowVersion.ts b/src/client/workflow/models/WorkflowVersion.ts index 26b656fb2a8edb63630ab92736f2f6c6b592a656..d27d809fcdb2796a2967c04cb429cc9e3528cc86 100644 --- a/src/client/workflow/models/WorkflowVersion.ts +++ b/src/client/workflow/models/WorkflowVersion.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { Status } from './Status'; - export type WorkflowVersion = { /** * Status of the workflow version diff --git a/src/client/workflow/models/WorkflowVersionStatus.ts b/src/client/workflow/models/WorkflowVersionStatus.ts index 0c66d1dd6b28229891c5c7d5ceed3eefab291c4e..765e6881cbcd8211096130a094584eb7f04ffa1d 100644 --- a/src/client/workflow/models/WorkflowVersionStatus.ts +++ b/src/client/workflow/models/WorkflowVersionStatus.ts @@ -2,9 +2,7 @@ /* istanbul ignore file */ /* tslint:disable */ /* eslint-disable */ - import type { Status } from './Status'; - export type WorkflowVersionStatus = { /** * Status of the workflow version diff --git a/src/client/workflow/services/WorkflowCredentialsService.ts b/src/client/workflow/services/WorkflowCredentialsService.ts index 1f9f891efb06fa6cd1b4304e817b59ef954d6cd7..cf305facb9a62fb2441bb3db98d42d53a76a0be4 100644 --- a/src/client/workflow/services/WorkflowCredentialsService.ts +++ b/src/client/workflow/services/WorkflowCredentialsService.ts @@ -4,13 +4,10 @@ /* eslint-disable */ import type { WorkflowCredentialsIn } from '../models/WorkflowCredentialsIn'; import type { WorkflowCredentialsOut } from '../models/WorkflowCredentialsOut'; - import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; - export class WorkflowCredentialsService { - /** * Get the credentials of a workflow * Get the credentials for the repository of a workflow. Only the developer of a workflow can do this. @@ -37,7 +34,6 @@ export class WorkflowCredentialsService { }, }); } - /** * Update the credentials of a workflow * Update the credentials for the repository of a workflow. @@ -68,7 +64,6 @@ export class WorkflowCredentialsService { }, }); } - /** * Delete the credentials of a workflow * Delete the credentials for the repository of a workflow. @@ -95,5 +90,4 @@ export class WorkflowCredentialsService { }, }); } - } diff --git a/src/client/workflow/services/WorkflowExecutionService.ts b/src/client/workflow/services/WorkflowExecutionService.ts index 199ba7b7ac8000a30397d7136a0cc7bec8056c1d..db4e486b8de62e08f85e7d965cc1fb4f667df7b4 100644 --- a/src/client/workflow/services/WorkflowExecutionService.ts +++ b/src/client/workflow/services/WorkflowExecutionService.ts @@ -6,13 +6,10 @@ import type { DevWorkflowExecutionIn } from '../models/DevWorkflowExecutionIn'; import type { WorkflowExecutionIn } from '../models/WorkflowExecutionIn'; import type { WorkflowExecutionOut } from '../models/WorkflowExecutionOut'; import type { WorkflowExecutionStatus } from '../models/WorkflowExecutionStatus'; - import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; - export class WorkflowExecutionService { - /** * Start a new workflow execution * Start a new workflow execution. Workflow versions wit status `DEPRECATED` or `DENIED` can't be started. @@ -39,7 +36,6 @@ export class WorkflowExecutionService { }, }); } - /** * Get all workflow executions * Get all workflow executions. @@ -73,7 +69,6 @@ export class WorkflowExecutionService { }, }); } - /** * Start a workflow execution with arbitrary git repository * Start a new workflow execution from an arbitrary git repository. @@ -103,7 +98,6 @@ export class WorkflowExecutionService { }, }); } - /** * Get a workflow execution * Get a specific workflow execution. @@ -131,7 +125,6 @@ export class WorkflowExecutionService { }, }); } - /** * Delete a workflow execution * Delete a specific workflow execution. @@ -159,7 +152,6 @@ export class WorkflowExecutionService { }, }); } - /** * Get the parameters of a workflow execution * Get the parameters of a specific workflow execution. @@ -187,7 +179,6 @@ export class WorkflowExecutionService { }, }); } - /** * Cancel a workflow execution * Cancel a running workflow execution. @@ -215,5 +206,4 @@ export class WorkflowExecutionService { }, }); } - } diff --git a/src/client/workflow/services/WorkflowModeService.ts b/src/client/workflow/services/WorkflowModeService.ts index f5e1926c3ffbe233d8fe9027c91683a71fd23f94..f0fa89dca30c50887a27346f3e647c0fda00c91e 100644 --- a/src/client/workflow/services/WorkflowModeService.ts +++ b/src/client/workflow/services/WorkflowModeService.ts @@ -3,13 +3,10 @@ /* tslint:disable */ /* eslint-disable */ import type { WorkflowModeOut } from '../models/WorkflowModeOut'; - import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; - export class WorkflowModeService { - /** * Get workflow mode * Get a workflow mode @@ -36,5 +33,4 @@ export class WorkflowModeService { }, }); } - } diff --git a/src/client/workflow/services/WorkflowService.ts b/src/client/workflow/services/WorkflowService.ts index b173a102fe754904bcd8acfb703ef02616a7d5e5..9dc2f2ca53a4544e0e67abafcab7c8d6d375730e 100644 --- a/src/client/workflow/services/WorkflowService.ts +++ b/src/client/workflow/services/WorkflowService.ts @@ -13,13 +13,10 @@ import type { WorkflowStatistic } from '../models/WorkflowStatistic'; import type { WorkflowUpdate } from '../models/WorkflowUpdate'; import type { WorkflowVersion } from '../models/WorkflowVersion'; import type { WorkflowVersionStatus } from '../models/WorkflowVersionStatus'; - import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; - export class WorkflowService { - /** * List workflows * List all workflows. @@ -52,7 +49,6 @@ export class WorkflowService { }, }); } - /** * Create a new workflow * Create a new workflow. @@ -82,7 +78,6 @@ export class WorkflowService { }, }); } - /** * Get anonymized workflow execution * Get the workflow executions with meta information and anonymized user IDs. @@ -119,7 +114,6 @@ export class WorkflowService { }, }); } - /** * Get a workflow * Get a specific workflow. @@ -151,7 +145,6 @@ export class WorkflowService { }, }); } - /** * Delete a workflow * Delete a workflow. @@ -178,7 +171,6 @@ export class WorkflowService { }, }); } - /** * Get statistics for a workflow * Get the number of started workflow per day. @@ -205,7 +197,6 @@ export class WorkflowService { }, }); } - /** * Update a workflow * Create a new workflow version. @@ -236,7 +227,6 @@ export class WorkflowService { }, }); } - /** * Get all versions of a workflow * List all versions of a Workflow. @@ -268,7 +258,6 @@ export class WorkflowService { }, }); } - /** * Get a workflow version * Get a specific version of a workflow. @@ -299,7 +288,6 @@ export class WorkflowService { }, }); } - /** * Update status of workflow version * Update the status of a workflow version. @@ -333,7 +321,6 @@ export class WorkflowService { }, }); } - /** * Deprecate a workflow version * Deprecate a workflow version. @@ -364,7 +351,6 @@ export class WorkflowService { }, }); } - /** * Fetch documentation for a workflow version * Get the documentation for a specific workflow version. @@ -403,7 +389,6 @@ export class WorkflowService { }, }); } - /** * Upload icon for workflow version * Upload an icon for the workflow version and returns the new icon URL. @@ -437,7 +422,6 @@ export class WorkflowService { }, }); } - /** * Delete icon of workflow version * Delete the icon of the workflow version. @@ -467,5 +451,4 @@ export class WorkflowService { }, }); } - } diff --git a/src/client/workflow/services/WorkflowVersionService.ts b/src/client/workflow/services/WorkflowVersionService.ts index 9553b053cc3ee6f33dd087620f8ad227758324ef..47eb077b1e3a64e7b8e444e74739f4da674e97e4 100644 --- a/src/client/workflow/services/WorkflowVersionService.ts +++ b/src/client/workflow/services/WorkflowVersionService.ts @@ -8,13 +8,10 @@ import type { IconUpdateOut } from '../models/IconUpdateOut'; import type { Status } from '../models/Status'; import type { WorkflowVersion } from '../models/WorkflowVersion'; import type { WorkflowVersionStatus } from '../models/WorkflowVersionStatus'; - import type { CancelablePromise } from '../core/CancelablePromise'; import { OpenAPI } from '../core/OpenAPI'; import { request as __request } from '../core/request'; - export class WorkflowVersionService { - /** * Get all versions of a workflow * List all versions of a Workflow. @@ -46,7 +43,6 @@ export class WorkflowVersionService { }, }); } - /** * Get a workflow version * Get a specific version of a workflow. @@ -77,7 +73,6 @@ export class WorkflowVersionService { }, }); } - /** * Update status of workflow version * Update the status of a workflow version. @@ -111,7 +106,6 @@ export class WorkflowVersionService { }, }); } - /** * Deprecate a workflow version * Deprecate a workflow version. @@ -142,7 +136,6 @@ export class WorkflowVersionService { }, }); } - /** * Fetch documentation for a workflow version * Get the documentation for a specific workflow version. @@ -181,7 +174,6 @@ export class WorkflowVersionService { }, }); } - /** * Upload icon for workflow version * Upload an icon for the workflow version and returns the new icon URL. @@ -215,7 +207,6 @@ export class WorkflowVersionService { }, }); } - /** * Delete icon of workflow version * Delete the icon of the workflow version. @@ -245,5 +236,4 @@ export class WorkflowVersionService { }, }); } - } diff --git a/src/components/BootstrapToast.vue b/src/components/BootstrapToast.vue new file mode 100644 index 0000000000000000000000000000000000000000..02b92fa3213f8d2e33e508645718abd4a6cadea4 --- /dev/null +++ b/src/components/BootstrapToast.vue @@ -0,0 +1,56 @@ +<script setup lang="ts"> +import { useSlots, computed } from "vue"; + +const slots = useSlots(); +const props = defineProps({ + colorClass: { type: String, required: false, default: "success" }, + toastId: { type: String, required: true }, +}); + +const colorClassName = computed<string>(() => { + return "text-bg-" + props.colorClass; +}); +</script> + +<template> + <Teleport to="#global-toast-container"> + <div + role="alert" + aria-live="assertive" + aria-atomic="true" + class="toast align-items-center border-0" + :class="colorClassName" + data-bs-autohide="true" + :id="props.toastId" + > + <div v-if="slots.body" class="toast-header" :class="colorClassName"> + <div class="me-auto"> + <slot></slot> + </div> + <button + type="button" + class="btn-close btn-close-white me-2 m-auto" + data-bs-dismiss="toast" + aria-label="Close" + ></button> + </div> + <div v-else class="d-flex"> + <div class="toast-body"> + <slot></slot> + </div> + <button + type="button" + class="btn-close btn-close-white me-2 m-auto" + data-bs-dismiss="toast" + aria-label="Close" + ></button> + </div> + + <div class="toast-body" v-if="slots.body"> + <slot name="body"></slot> + </div> + </div> + </Teleport> +</template> + +<style scoped></style> diff --git a/src/components/CopyToClipboardIcon.vue b/src/components/CopyToClipboardIcon.vue index 9d28cbaac691f1c1a6f8098a4e48396144561203..b0d34b4967cf27383093ed940df08e07f934be79 100644 --- a/src/components/CopyToClipboardIcon.vue +++ b/src/components/CopyToClipboardIcon.vue @@ -2,9 +2,11 @@ import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; import { onMounted } from "vue"; import { Toast, Tooltip } from "bootstrap"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const props = defineProps<{ text: string; + button?: boolean; }>(); let successToast: Toast | null = null; @@ -26,52 +28,28 @@ function copyToClipboard() { } onMounted(() => { - new Tooltip("#tooltip-" + randomIDSuffix); + if (!props.button) { + new Tooltip("#tooltip-" + randomIDSuffix); + } successToast = new Toast("#successToast-" + randomIDSuffix); failToast = new Toast("#failToast-" + randomIDSuffix); }); </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-success align-items-center border-0" - data-bs-autohide="true" - :id="'successToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div class="toast-body">Successfully copied to clipboard</div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-danger align-items-center border-0" - data-bs-autohide="true" - :id="'failToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div class="toast-body">Can't copy to clipboard</div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast :toast-id="'successToast-' + randomIDSuffix" + >Successfully copied to clipboard + </bootstrap-toast> + <bootstrap-toast + :toast-id="'failToast-' + randomIDSuffix" + color-class="danger" + >Can't copy to clipboard + </bootstrap-toast> + <button v-if="props.button" @click="copyToClipboard" class="btn btn-primary"> + Copy to Clipboard + </button> <span + v-else class="hover-info cursor-pointer" data-bs-toggle="tooltip" data-bs-title="Copy to Clipboard" @@ -81,8 +59,4 @@ onMounted(() => { </span> </template> -<style scoped> -.hover-info:hover { - color: var(--bs-info) !important; -} -</style> +<style scoped></style> diff --git a/src/components/NavbarTop.vue b/src/components/NavbarTop.vue index c3bb9a44c8437cf3c8c845f3cae3b00b5e478bd3..37a3540c874d27e715d88a1b9e3b8e32cb2acbf1 100644 --- a/src/components/NavbarTop.vue +++ b/src/components/NavbarTop.vue @@ -8,6 +8,7 @@ import BootstrapModal from "@/components/modals/BootstrapModal.vue"; import { OpenAPI as S3ProxyOpenAPI } from "@/client/s3proxy"; import { OpenAPI as AuthOpenAPI } from "@/client/auth"; import { OpenAPI as WorkflowOpenAPI } from "@/client/workflow"; +import { OpenAPI as ResourceOpenAPI } from "@/client/resource"; import CopyToClipboardIcon from "@/components/CopyToClipboardIcon.vue"; import dayjs from "dayjs"; @@ -27,6 +28,8 @@ const objectStorageActive = computed<boolean>( const workflowActive = computed<boolean>( () => activeRoute.value == "workflows", ); +const resourceActive = computed<boolean>(() => activeRoute.value == "resource"); +const adminActive = computed<boolean>(() => activeRoute.value == "admin"); watch( () => route.name, @@ -36,6 +39,10 @@ watch( activeRoute.value = "buckets"; } else if (to.startsWith("workflow")) { activeRoute.value = "workflows"; + } else if (to.startsWith("resource")) { + activeRoute.value = "resource"; + } else if (to.startsWith("admin")) { + activeRoute.value = "admin"; } else { activeRoute.value = to; } @@ -48,7 +55,7 @@ watch( <template> <header - class="navbar navbar-expand-lg bd-navbar sticky-top border-bottom border-secondary" + class="navbar navbar-expand bd-navbar sticky-top border-bottom border-secondary" > <nav class="container-xxl bd-gutter flex-wrap flex-lg-nowrap text-light"> <router-link @@ -65,7 +72,7 @@ watch( CloWM </router-link> - <div class="d-flex me-auto w-fit" v-if="store.authenticated"> + <div class="d-flex flex-grow-1" v-if="store.authenticated"> <ul class="navbar-nav"> <li class="nav-item dropdown"> <a @@ -125,11 +132,7 @@ watch( >My Workflow Executions </router-link> </li> - <li - v-if=" - store.workflowDev || store.workflowReviewer || store.admin - " - > + <li v-if="store.workflowDev || store.rewiewer || store.admin"> <hr class="dropdown-divider" /> </li> <li v-if="store.workflowDev || store.admin"> @@ -139,7 +142,7 @@ watch( >My Workflows </router-link> </li> - <li v-if="store.workflowReviewer || store.admin"> + <li v-if="store.rewiewer || store.admin"> <router-link class="dropdown-item" :to="{ name: 'workflows-reviewer' }" @@ -148,6 +151,78 @@ watch( </li> </ul> </li> + <li class="nav-item dropdown"> + <a + class="nav-link dropdown-toggle" + :class="{ 'text-black': resourceActive }" + id="resourceDropdown" + href="#" + role="button" + data-bs-toggle="dropdown" + aria-expanded="false" + data-bs-auto-close="true" + > + Resources + </a> + <ul + class="dropdown-menu shadow m-0" + aria-labelledby="workflowDropdown" + > + <li> + <router-link class="dropdown-item" :to="{ name: 'resources' }" + >Available Resources + </router-link> + </li> + <li + v-if="store.resourceMaintainer || store.rewiewer || store.admin" + > + <hr class="dropdown-divider" /> + </li> + <li v-if="store.resourceMaintainer || store.admin"> + <router-link + class="dropdown-item" + :to="{ name: 'resource-maintainer' }" + >My Resources + </router-link> + </li> + <li v-if="store.rewiewer || store.admin"> + <router-link + class="dropdown-item" + :to="{ name: 'resource-review' }" + >Review + </router-link> + </li> + </ul> + </li> + <li v-if="store.admin"> + <a + class="nav-link dropdown-toggle" + :class="{ 'text-black': adminActive }" + id="adminDropdown" + href="#" + role="button" + data-bs-toggle="dropdown" + aria-expanded="false" + data-bs-auto-close="true" + > + Admin + </a> + <ul + class="dropdown-menu shadow m-0" + aria-labelledby="adminDropdown" + > + <li><a class="dropdown-item disabled" href="#">User</a></li> + <li><a class="dropdown-item disabled" href="#">Bucket</a></li> + <li><a class="dropdown-item disabled" href="#">Workflow</a></li> + <li> + <router-link + class="dropdown-item" + :to="{ name: 'admin-resources' }" + >Resources + </router-link> + </li> + </ul> + </li> </ul> </div> <div class="dropdown" v-if="store.authenticated && store.user != null"> @@ -158,7 +233,7 @@ watch( data-bs-toggle="dropdown" aria-expanded="false" > - <strong class="me-2">{{ store.user.display_name }}</strong> + <strong class="me-2">{{ store.user?.display_name }}</strong> <font-awesome-icon icon="fa-solid fa-circle-user" class="fs-5" /> </a> <ul @@ -202,10 +277,10 @@ watch( </nav> </header> <bootstrap-modal - static-backdrop - modal-i-d="advancedUsageModal" + modal-id="advancedUsageModal" modal-label="Advanced Usage Modal" v-if="store.authenticated" + size-modifier="lg" > <template v-slot:header> <h3>Advanced Usage</h3> @@ -249,6 +324,18 @@ watch( > </td> </tr> + <tr> + <td class="text-end">Resource Service:</td> + <td> + <a :href="ResourceOpenAPI.BASE + '/docs'" target="_blank"> + <font-awesome-icon + class="me-1" + icon="fa-solid fa-arrow-up-right-from-square" + /> + {{ ResourceOpenAPI.BASE }}</a + > + </td> + </tr> </tbody> </table> <div class="mt-4"> diff --git a/src/components/modals/BootstrapModal.vue b/src/components/modals/BootstrapModal.vue index 4e6fd34d52d553fe70460bc048f0d9461572f383..bb4940543ce0dbab9669e28f299d0a443ab74989 100644 --- a/src/components/modals/BootstrapModal.vue +++ b/src/components/modals/BootstrapModal.vue @@ -1,15 +1,25 @@ <script setup lang="ts"> -defineProps<{ - modalID: string; +import { computed } from "vue"; + +const props = defineProps<{ + modalId: string; modalLabel: string; - staticBackdrop: boolean; + staticBackdrop?: boolean; + sizeModifier?: string; // https://getbootstrap.com/docs/5.3/components/modal/#optional-sizes, e.g. sm, lg and xl }>(); + +const modalSizeClass = computed<string>(() => { + if (props.sizeModifier == undefined) { + return ""; + } + return "modal-" + props.sizeModifier; +}); </script> <template> <div class="modal" - :id="modalID" + :id="modalId" tabindex="-1" :aria-labelledby="modalLabel" aria-hidden="true" @@ -17,7 +27,7 @@ defineProps<{ > <div class="modal-dialog modal-dialog-centered modal-dialog-scrollable" - style="min-width: 30%" + :class="[modalSizeClass]" > <div class="modal-content"> <div class="modal-header"> @@ -38,7 +48,15 @@ defineProps<{ <slot name="body" /> </div> <div class="modal-footer"> - <slot name="footer" /> + <slot name="footer"> + <button + type="button" + class="btn btn-secondary" + data-bs-dismiss="modal" + > + Close + </button> + </slot> </div> </div> </div> diff --git a/src/components/modals/DeleteModal.vue b/src/components/modals/DeleteModal.vue index b51c55f02d5f6c357fc758f0d5311cc453eaa30c..0a7c662f06a0e2e73e43cf3d81b8719d846c54ed 100644 --- a/src/components/modals/DeleteModal.vue +++ b/src/components/modals/DeleteModal.vue @@ -34,7 +34,7 @@ onMounted(() => { <template> <bootstrap-modal - :modalID="props.modalID" + :modalId="props.modalID" :static-backdrop="true" modal-label="Confirm Delete Modal" v-on="{ 'hidden.bs.modal': modalClosed }" diff --git a/src/components/modals/SearchUserModal.vue b/src/components/modals/SearchUserModal.vue index 85f24c3167c77a967f8288b128ef081f0499e235..414369508f1be90c59a4dab83446ddddb89450b7 100644 --- a/src/components/modals/SearchUserModal.vue +++ b/src/components/modals/SearchUserModal.vue @@ -1,18 +1,22 @@ <script setup lang="ts"> -import { reactive, watch } from "vue"; +import { reactive, ref, watch } from "vue"; import BootstrapModal from "@/components/modals/BootstrapModal.vue"; import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; import { UserService } from "@/client/auth"; import type { User } from "@/client/auth"; import { useAuthStore } from "@/stores/users"; +import { useNameStore } from "@/stores/names"; const props = defineProps<{ - modalID: string; + modalId: string; backModalId?: string; + filterUserSelf?: boolean; }>(); const randomIDSuffix = Math.random().toString(16).substring(2, 8); const store = useAuthStore(); +const nameStore = useNameStore(); +const textInputElement = ref<HTMLInputElement | undefined>(undefined); const formState = reactive<{ searchString: string; @@ -53,18 +57,24 @@ function modalClosed() { formState.potentialUsers = []; } +function modalShown() { + textInputElement.value?.focus(); +} + function searchUser(name: string) { formState.error = false; UserService.userListUsers(name) .then((userSuggestions) => { - formState.potentialUsers = userSuggestions.filter( - (user) => store.currentUID != user.uid, - ); - const uidToName: Record<string, string> = {}; + if (props.filterUserSelf) { + formState.potentialUsers = userSuggestions.filter( + (user) => store.currentUID != user.uid, + ); + } else { + formState.potentialUsers = userSuggestions; + } for (const user of userSuggestions) { - uidToName[user.uid] = user.display_name; + nameStore.addNameToMapping(user.uid, user.display_name); } - store.addUidToNameMapping(uidToName); }) .catch((err) => { formState.error = true; @@ -78,10 +88,10 @@ function searchUser(name: string) { <template> <bootstrap-modal - :modalID="props.modalID" + :modalId="props.modalId" :static-backdrop="true" modal-label="Search User Modal" - v-on="{ 'hidden.bs.modal': modalClosed }" + v-on="{ 'hidden.bs.modal': modalClosed, 'shown.bs.modal': modalShown }" > <template v-slot:header>Search User</template> <template v-slot:body> @@ -94,6 +104,7 @@ function searchUser(name: string) { :id="'searchUserInput' + randomIDSuffix" placeholder="Search for a user" v-model.trim="formState.searchString" + ref="textInputElement" /> </div> <div v-if="formState.loading" class="text-center"> @@ -106,7 +117,8 @@ function searchUser(name: string) { icon="fa-solid fa-x" class="mb-2" style="color: var(--bs-danger); font-size: 4em" - /><br /> + /> + <br /> <span class="text-danger" >There seems to be an error<br />Try again later</span > @@ -117,8 +129,9 @@ function searchUser(name: string) { :key="user.uid" type="button" class="list-group-item list-group-item-action" - :data-bs-target="'#' + props.backModalId" - data-bs-toggle="modal" + :data-bs-target="props.backModalId ? '#' + props.backModalId : null" + :data-bs-toggle="props.backModalId ? 'modal' : null" + :data-bs-dismiss="props.backModalId ? null : 'modal'" @click="emit('user-found', user)" > {{ user.display_name }} @@ -129,7 +142,8 @@ function searchUser(name: string) { icon="fa-solid fa-magnifying-glass" class="mb-2" style="color: var(--bs-secondary); font-size: 4em" - /><br /> + /> + <br /> <span v-if="formState.searchString.length > 2" >Could not find any Users</span > diff --git a/src/components/object-storage/BucketListItem.vue b/src/components/object-storage/BucketListItem.vue index a1db0ae77fa2f80099523ab93c1dc26b94ccb542..04f5f4462fd8f1ff7f677e039a0a101b30ab6f81 100644 --- a/src/components/object-storage/BucketListItem.vue +++ b/src/components/object-storage/BucketListItem.vue @@ -12,6 +12,7 @@ import { useBucketStore } from "@/stores/buckets"; import { useRouter } from "vue-router"; import { useAuthStore } from "@/stores/users"; import type { FolderTree } from "@/types/PseudoFolder"; +import { useNameStore } from "@/stores/names"; const props = defineProps<{ active: boolean; @@ -23,6 +24,7 @@ const props = defineProps<{ const randomIDSuffix = Math.random().toString(16).substring(2, 8); const permissionRepository = useBucketStore(); const userRepository = useAuthStore(); +const nameRepository = useNameStore(); const router = useRouter(); const permission = computed<BucketPermissionOut | undefined>( @@ -168,7 +170,7 @@ onMounted(() => { <tr v-if="permission"> <th scope="row" class="fw-bold">Owner:</th> <td class="text-truncate"> - {{ userRepository.userMapping[bucket.owner] }} + {{ nameRepository.getName(bucket.owner) }} </td> </tr> <tr diff --git a/src/components/object-storage/modals/BucketDetailModal.vue b/src/components/object-storage/modals/BucketDetailModal.vue index 09788df9d94e1e290c501bc98cc7e53aadbf1bd5..49eef5918ab7e1e2f26d7a49e876d9a95f386be1 100644 --- a/src/components/object-storage/modals/BucketDetailModal.vue +++ b/src/components/object-storage/modals/BucketDetailModal.vue @@ -12,7 +12,7 @@ const props = defineProps<{ <template> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="false" modal-label="Bucket Detail Modal" > diff --git a/src/components/object-storage/modals/CopyObjectModal.vue b/src/components/object-storage/modals/CopyObjectModal.vue index 0687aaa6a9ceee3c848e94eac1a588108848a6fb..68f8b3d1a386ca24b0b712836b728e7eeaec85d1 100644 --- a/src/components/object-storage/modals/CopyObjectModal.vue +++ b/src/components/object-storage/modals/CopyObjectModal.vue @@ -5,6 +5,7 @@ import { onMounted, reactive, watch } from "vue"; import type { _Object as S3Object } from "@aws-sdk/client-s3"; import { useBucketStore } from "@/stores/buckets"; import { useS3ObjectStore } from "@/stores/s3objects"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const objectRepository = useS3ObjectStore(); @@ -83,51 +84,18 @@ onMounted(() => { </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-success align-items-center border-0" - data-bs-autohide="true" - :id="'successToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div class="toast-body">Successfully copied file</div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-danger align-items-center border-0" - data-bs-autohide="true" - :id="'errorToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div class="toast-body"> - There has been some Error.<br /> - Try again later - </div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast :toast-id="'successToast-' + randomIDSuffix"> + Successfully copied file + </bootstrap-toast> + <bootstrap-toast + :toast-id="'errorToast-' + randomIDSuffix" + color-class="danger" + > + There has been some Error.<br /> + Try again later + </bootstrap-toast> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="true" modal-label="Copy Object Modal" v-on="{ 'hidden.bs.modal': modalClosed }" diff --git a/src/components/object-storage/modals/CreateBucketModal.vue b/src/components/object-storage/modals/CreateBucketModal.vue index ae030960e3ab025834d85ba26ef3f56a17d297a4..9de88c11559748cd7fc22d701c42ef294b879af9 100644 --- a/src/components/object-storage/modals/CreateBucketModal.vue +++ b/src/components/object-storage/modals/CreateBucketModal.vue @@ -82,7 +82,7 @@ function modalClosed() { <template> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="true" modal-label="Create Bucket Modal" v-on="{ 'hidden.bs.modal': modalClosed }" diff --git a/src/components/object-storage/modals/CreateFolderModal.vue b/src/components/object-storage/modals/CreateFolderModal.vue index cd26d2c2a94ff03d6abe9a68e0f2fb5e623a081a..7791c9c7a62de44f7b7e290a7be4d0b2fbd9c76d 100644 --- a/src/components/object-storage/modals/CreateFolderModal.vue +++ b/src/components/object-storage/modals/CreateFolderModal.vue @@ -4,6 +4,7 @@ import { computed, onMounted, reactive } from "vue"; import { Modal, Toast } from "bootstrap"; import { useS3ObjectStore } from "@/stores/s3objects"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const objectRepository = useS3ObjectStore(); @@ -67,51 +68,18 @@ onMounted(() => { </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-success align-items-center border-0" - data-bs-autohide="true" - :id="'successToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div class="toast-body">Successfully created Folder</div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-danger align-items-center border-0" - data-bs-autohide="true" - :id="'errorToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div class="toast-body"> - There has been some Error.<br /> - Try again later - </div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast :toast-id="'successToast-' + randomIDSuffix"> + Successfully created Folder + </bootstrap-toast> + <bootstrap-toast + :toast-id="'errorToast-' + randomIDSuffix" + color-class="danger" + > + There has been some Error.<br /> + Try again later + </bootstrap-toast> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="true" modal-label="Create Folder Modal" > diff --git a/src/components/object-storage/modals/ObjectDetailModal.vue b/src/components/object-storage/modals/ObjectDetailModal.vue index 08f5280a86aac2400e20909bae8723377ac92916..c1c2eaf0b1f2006db22acb8f893daf221af573c8 100644 --- a/src/components/object-storage/modals/ObjectDetailModal.vue +++ b/src/components/object-storage/modals/ObjectDetailModal.vue @@ -53,7 +53,7 @@ onMounted(() => { <template> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="false" modal-label="Object Detail Modal" > diff --git a/src/components/object-storage/modals/PermissionListModal.vue b/src/components/object-storage/modals/PermissionListModal.vue index 1d5c4d020a74e2bf737026c03ad5610cb095b41e..8d74a24c67c91f2a10dfa910c6f522e94c4c1cf6 100644 --- a/src/components/object-storage/modals/PermissionListModal.vue +++ b/src/components/object-storage/modals/PermissionListModal.vue @@ -6,8 +6,13 @@ import { onBeforeMount, watch } from "vue"; import BootstrapModal from "@/components/modals/BootstrapModal.vue"; import PermissionModal from "@/components/object-storage/modals/PermissionModal.vue"; import { useBucketStore } from "@/stores/buckets"; +import { useNameStore } from "@/stores/names"; +import { useAuthStore } from "@/stores/users"; const bucketRepository = useBucketStore(); +const nameRepository = useNameStore(); +const userRepository = useAuthStore(); + // Props // ----------------------------------------------------------------------------- const props = defineProps<{ @@ -46,7 +51,9 @@ watch( // Function // ----------------------------------------------------------------------------- function updateBucketPermissions(bucketName: string) { - bucketRepository.fetchBucketPermissions(bucketName); + bucketRepository.fetchBucketPermissions(bucketName).then((permissions) => { + userRepository.fetchUsernames(permissions.map((p) => p.uid)); + }); } // Lifecycle Hooks @@ -68,7 +75,7 @@ onBeforeMount(() => { :modalID="'permission-list-edit-modal' + randomIDSuffix" /> <bootstrap-modal - :modalID="props.modalID" + :modalId="props.modalID" :static-backdrop="true" modal-label="Permission List Modal" > @@ -99,7 +106,7 @@ onBeforeMount(() => { permission.permission }}</span> <span class="col-9 text-center"> - {{ permission.grantee_display_name }}</span + {{ nameRepository.getName(permission.uid) }}</span > </div> </button> diff --git a/src/components/object-storage/modals/PermissionModal.vue b/src/components/object-storage/modals/PermissionModal.vue index 60ad031740571fd138c8cb918a68137d4bf94259..846aad4522e2f640ef46e01b4f6eec3086a798df 100644 --- a/src/components/object-storage/modals/PermissionModal.vue +++ b/src/components/object-storage/modals/PermissionModal.vue @@ -16,6 +16,8 @@ import { Permission } from "@/client/s3proxy"; import { Toast } from "bootstrap"; import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; import { useBucketStore } from "@/stores/buckets"; +import BootstrapToast from "@/components/BootstrapToast.vue"; +import { useNameStore } from "@/stores/names"; // Props // ----------------------------------------------------------------------------- @@ -31,6 +33,7 @@ const props = defineProps<{ }>(); const bucketRepository = useBucketStore(); +const nameRepository = useNameStore(); const emit = defineEmits<{ (e: "permission-deleted"): void }>(); // Variables @@ -44,12 +47,10 @@ let successToast: Toast | null = null; // eslint-disable-next-line vue/no-setup-props-destructure const formState = reactive<{ loading: boolean; - grantee_name: string; error: boolean; readonly: boolean; }>({ loading: false, - grantee_name: "", error: false, readonly: props.readonly, }); @@ -132,7 +133,6 @@ function updateLocalPermission() { permission.bucket_name = props.editUserPermission.bucket_name; permission.file_prefix = props.editUserPermission.file_prefix; permission.uid = props.editUserPermission.uid; - formState.grantee_name = props.editUserPermission.grantee_display_name; permission.from_timestamp = props.editUserPermission.from_timestamp; permission.to_timestamp = props.editUserPermission.to_timestamp; permission.permission = props.editUserPermission.permission; @@ -142,7 +142,6 @@ function updateLocalPermission() { permission.from_timestamp = undefined; permission.to_timestamp = undefined; permission.permission = undefined; - formState.grantee_name = ""; } } @@ -233,7 +232,6 @@ function confirmedDeletePermission(bucketName: string, uid: string) { function updateUser(user: User) { permission.uid = user.uid; - formState.grantee_name = user.display_name; } // Lifecycle Hooks @@ -266,40 +264,24 @@ function toTimestampChanged(target?: HTMLInputElement | null) { confirmedDeletePermission(permission.bucket_name, permission.uid) " /> - <SearchUserModal - :modalID="'search-user-modal' + randomIDSuffix" + <search-user-modal + :modal-id="'search-user-modal' + randomIDSuffix" :back-modal-id="modalID" + filter-user-self @user-found="updateUser" /> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-success align-items-center border-0" - data-bs-autohide="true" - :id="'toast-' + randomIDSuffix" - v-on="{ 'hidden.bs.toast': toastHidden }" - > - <div class="d-flex"> - <div class="toast-body"> - Successfully - <span v-if="permissionDeleted">deleted</span> - <span v-else-if="editPermission">edited</span> - <span v-else>created</span> - Permission - </div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast + :toast-id="'toast-' + randomIDSuffix" + v-on="{ 'hidden.bs.toast': toastHidden }" + > + Successfully + <template v-if="permissionDeleted">deleted</template> + <template v-else-if="editPermission">edited</template> + <template v-else>created</template> + Permission + </bootstrap-toast> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="true" modal-label="Permission Modal" v-on="{ 'hidden.bs.modal': modalClosed }" @@ -352,32 +334,23 @@ function toTimestampChanged(target?: HTMLInputElement | null) { <label for="permissionGranteeInput" class="col-2 col-form-label"> User<span v-if="!formState.readonly">*</span> </label> - <div - :class="{ - 'col-10': permissionUserReadonly, - 'col-9': !permissionUserReadonly, - }" - > + <div class="col-10"> <input type="text" class="form-control" id="permissionGranteeInput" required placeholder="Search for a user" - v-model.trim="formState.grantee_name" + :value="nameRepository.getName(permission.uid)" readonly + :data-bs-toggle="permissionUserReadonly ? null : 'modal'" + :data-bs-target=" + permissionUserReadonly + ? null + : '#search-user-modal' + randomIDSuffix + " /> </div> - <div v-if="!permissionUserReadonly" class="col-1"> - <button - type="button" - class="btn btn-secondary btn-sm float-end" - data-bs-toggle="modal" - :data-bs-target="'#search-user-modal' + randomIDSuffix" - > - <font-awesome-icon icon="fa-solid fa-magnifying-glass" /> - </button> - </div> </div> <div class="mb-3 row"> <label for="permissionTypeInput" class="col-3 col-form-label"> diff --git a/src/components/object-storage/modals/UploadObjectModal.vue b/src/components/object-storage/modals/UploadObjectModal.vue index adafe9a20af1735e997005d1737f9b3dc2edaa1b..331fbf62a255527b1e1220c4d4b9db089eb554c6 100644 --- a/src/components/object-storage/modals/UploadObjectModal.vue +++ b/src/components/object-storage/modals/UploadObjectModal.vue @@ -4,6 +4,7 @@ import { computed, onMounted, reactive, ref, watch } from "vue"; import { Modal, Toast } from "bootstrap"; import { partial } from "filesize"; import { useS3ObjectStore } from "@/stores/s3objects"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const fsize = partial({ base: 2, standard: "jedec" }); const objectRepository = useS3ObjectStore(); @@ -101,51 +102,18 @@ onMounted(() => { </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-success align-items-center border-0" - data-bs-autohide="true" - :id="'successToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div class="toast-body">Successfully uploaded file</div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-danger align-items-center border-0" - data-bs-autohide="true" - :id="'errorToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div class="toast-body"> - There has been some Error.<br /> - Try again later - </div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast :toast-id="'successToast-' + randomIDSuffix"> + Successfully uploaded file + </bootstrap-toast> + <bootstrap-toast + :toast-id="'errorToast-' + randomIDSuffix" + color-class="danger" + > + There has been some Error.<br /> + Try again later + </bootstrap-toast> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="true" modal-label="Upload Object Modal" > @@ -221,15 +189,17 @@ onMounted(() => { </template> <template v-slot:footer> <div class="w-50 me-auto" v-if="formState.uploading"> - <div class="progress"> + <div + class="progress" + aria-valuemin="0" + aria-valuemax="100" + role="progressbar" + :aria-valuenow="uploadProgress" + aria-label="Upload Progressbar" + > <div class="progress-bar bg-info" - role="progressbar" - aria-label="Basic example" :style="{ width: uploadProgress + '%' }" - :aria-valuenow="uploadProgress" - aria-valuemin="0" - aria-valuemax="100" > {{ uploadProgress }}% </div> diff --git a/src/components/parameter-schema/ParameterSchemaFormComponent.vue b/src/components/parameter-schema/ParameterSchemaFormComponent.vue index 7546e8bbb109e223955dd0c548f8ca097799c33d..aed548155d295a5a6e57765799f9626a3661e422 100644 --- a/src/components/parameter-schema/ParameterSchemaFormComponent.vue +++ b/src/components/parameter-schema/ParameterSchemaFormComponent.vue @@ -8,9 +8,12 @@ import ParameterStringInput from "@/components/parameter-schema/form-mode/Parame import { Toast } from "bootstrap"; import { useBucketStore } from "@/stores/buckets"; import { useS3KeyStore } from "@/stores/s3keys"; +import BootstrapToast from "@/components/BootstrapToast.vue"; +import { useResourceStore } from "@/stores/resources"; const bucketRepository = useBucketStore(); -const s3KeyRepository = useS3KeyStore(); +const resourceRepository = useResourceStore(); +const keyRepository = useS3KeyStore(); // Props // ============================================================================= @@ -180,40 +183,25 @@ onMounted(() => { if (props.schema) updateSchema(props.schema); bucketRepository.fetchBuckets(); bucketRepository.fetchOwnPermissions(); - s3KeyRepository.fetchS3Keys(); + keyRepository.fetchS3Keys(); + resourceRepository.fetchPublicResources(); errorToast = new Toast("#workflowExecutionErrorToast"); }); </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-danger align-items-center border-0" - data-bs-autohide="true" - id="workflowExecutionErrorToast" - > - <div class="d-flex p-2 justify-content-between align-items-center"> - <div class="toast-body"> - <template v-if="formState.errorType === 'form'"> - Some inputs are not valid. - </template> - <template v-else> - There was an error with starting the workflow execution. Look in the - console for more information. - </template> - </div> - <button - type="button" - class="btn-close btn-close-white" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast toast-id="workflowExecutionErrorToast" color-class="danger"> + <template>Error starting workflow</template> + <template #body> + <template v-if="formState.errorType === 'form'"> + Some inputs are not valid. + </template> + <template v-else> + There was an error with starting the workflow execution. Look in the + console for more information. + </template> + </template> + </bootstrap-toast> <div class="row mb-5 align-items-start"> <form v-if="props.schema" @@ -245,14 +233,11 @@ onMounted(() => { <h5 class="card-title"> General Options about the pipeline execution </h5> - <template v-if="props.allowNotes"> + <div v-if="props.allowNotes"> + <code class="bg-secondary-subtle p-2 rounded-top">--notes</code> <div class="input-group"> <span class="input-group-text" id="pipelineNotes"> - <font-awesome-icon - class="me-2" - icon="fa-solid fa-sticky-note" - /> - <code>--notes</code> + <font-awesome-icon icon="fa-solid fa-sticky-note" /> </span> <textarea class="form-control" @@ -263,60 +248,75 @@ onMounted(() => { <label class="mb-3" for="pipelineNotes" >Personal notes about the pipeline execution</label > - </template> - <div class="input-group"> - <span class="input-group-text" id="logsS3Path"> - <font-awesome-icon class="me-2" icon="fa-solid fa-folder" /> - <code>--logs_s3_path</code> - </span> - <parameter-string-input - parameter-name="logs_s3_path" - v-model="formState.logs_s3_path" - :parameter="{ - format: 'directory-path', - type: 'string', - }" - /> </div> - <label class="mb-3" for="logsS3Path"> - Directory in bucket where to save Nextflow log and reports - </label> - <div class="input-group"> - <span class="input-group-text" id="provenanceS3Path"> - <font-awesome-icon class="me-2" icon="fa-solid fa-folder" /> - <code>--provenance_s3_path</code> - </span> - <parameter-string-input - parameter-name="provenance_s3_path" - v-model="formState.provenance_s3_path" - :parameter="{ - format: 'directory-path', - type: 'string', - }" - /> + <div> + <code class="bg-secondary-subtle p-2 rounded-top" + >--logs_s3_path</code + > + <div class="input-group"> + <span class="input-group-text"> + <font-awesome-icon icon="fa-solid fa-folder" /> + </span> + <parameter-string-input + parameter-name="logs_s3_path" + v-model="formState.logs_s3_path" + :parameter="{ + format: 'directory-path', + type: 'string', + }" + remove-advanced + /> + </div> + <label class="mb-3" for="logsS3Path"> + Directory in bucket where to save Nextflow log and reports + </label> </div> - <label class="mb-3" for="provenanceS3Path"> - Directory in bucket where to save provenance information about the - workflow execution - </label> - <div class="input-group"> - <span class="input-group-text" id="debugS3Path"> - <font-awesome-icon class="me-2" icon="fa-solid fa-folder" /> - <code>--debug_s3_path</code> - </span> - <parameter-string-input - parameter-name="debug_s3_path" - v-model="formState.debug_s3_path" - :parameter="{ - format: 'directory-path', - type: 'string', - }" - /> + <div> + <code class="bg-secondary-subtle p-2 rounded-top" + >--provenance_s3_path</code + > + <div class="input-group"> + <span class="input-group-text"> + <font-awesome-icon icon="fa-solid fa-folder" /> + </span> + <parameter-string-input + parameter-name="provenance_s3_path" + v-model="formState.provenance_s3_path" + :parameter="{ + format: 'directory-path', + type: 'string', + }" + remove-advanced + /> + </div> + <label class="mb-3" for="provenanceS3Path"> + Directory in bucket where to save provenance information about the + workflow execution + </label> + </div> + <div> + <code class="bg-secondary-subtle p-2 rounded-top" + >--debug_s3_path</code + > + <div class="input-group"> + <span class="input-group-text"> + <font-awesome-icon icon="fa-solid fa-folder" /> + </span> + <parameter-string-input + parameter-name="debug_s3_path" + v-model="formState.debug_s3_path" + :parameter="{ + format: 'directory-path', + type: 'string', + }" + remove-advanced + /> + </div> + <label class="mb-3" for="debugS3Path"> + Directory in bucket where to save debug information about the + workflow execution + </label> </div> - <label class="mb-3" for="debugS3Path"> - Directory in bucket where to save debug information about the - workflow execution - </label> </div> </div> </form> diff --git a/src/components/parameter-schema/form-mode/ParameterGroupForm.vue b/src/components/parameter-schema/form-mode/ParameterGroupForm.vue index e66ef66d0dfdaaa8468d303dd18325a22e7fafe5..7789da50ea7c040b399271b5d35d7cf5706a9fff 100644 --- a/src/components/parameter-schema/form-mode/ParameterGroupForm.vue +++ b/src/components/parameter-schema/form-mode/ParameterGroupForm.vue @@ -65,7 +65,6 @@ function parameterRequired( watch( formInput, (newVal) => { - //console.log("Group", props.parameterGroupName, newVal); emit("update:modelValue", newVal); }, { @@ -87,14 +86,12 @@ watch( :key="parameterName" > <div :hidden="!showHidden && parameter['hidden']"> + <code class="bg-secondary-subtle p-2 rounded-top" + >--{{ parameter["name"] ?? parameterName }}</code + > <div class="input-group"> - <span class="input-group-text" :id="parameterName + '-help'"> - <font-awesome-icon - class="me-2" - :icon="parameter['fa_icon']" - v-if="parameter['fa_icon']" - /> - <code>--{{ parameterName }}</code> + <span class="input-group-text" v-if="parameter['fa_icon']"> + <font-awesome-icon :icon="parameter['fa_icon']" /> </span> <parameter-number-input v-if=" @@ -146,9 +143,11 @@ watch( class="input-group-text cursor-pointer px-2" v-if="parameter['help_text']" data-bs-toggle="collapse" - :data-bs-target="'#helpCollapse' + parameterName" + :data-bs-target=" + '#helpCollapse' + parameterName.replace(/\./g, '') + " aria-expanded="false" - :aria-controls="'helpCollapse' + parameterName" + :aria-controls="'helpCollapse' + parameterName.replace(/\./g, '')" > <font-awesome-icon class="cursor-pointer" @@ -161,7 +160,7 @@ watch( </label> <div class="collapse" - :id="'helpCollapse' + parameterName" + :id="'helpCollapse' + parameterName.replace(/\./g, '')" v-if="parameter['help_text']" > <div class="p-2 pb-0 mx-2 mb-2 mt-1 flex-shrink-1 border rounded"> diff --git a/src/components/parameter-schema/form-mode/ParameterStringInput.vue b/src/components/parameter-schema/form-mode/ParameterStringInput.vue index 0ba406b7f1eb838040cd2b60dc2101f1652bebb9..7d38aae038ea9d12f597f758a377fa08d7d42f81 100644 --- a/src/components/parameter-schema/form-mode/ParameterStringInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterStringInput.vue @@ -1,10 +1,14 @@ <script setup lang="ts"> -import { computed, watch, ref, onMounted, reactive } from "vue"; +import { computed, watch, onMounted, reactive } from "vue"; import { useBucketStore } from "@/stores/buckets"; import { useS3ObjectStore } from "@/stores/s3objects"; +import { useResourceStore } from "@/stores/resources"; +import { Status } from "@/client/resource"; const bucketRepository = useBucketStore(); const s3objectRepository = useS3ObjectStore(); +const resourceRepository = useResourceStore(); +const randomIDSuffix = Math.random().toString(16).substring(2, 8); const props = defineProps({ parameter: { @@ -25,50 +29,49 @@ const props = defineProps({ helpId: { type: String, }, + removeAdvanced: { + type: Boolean, + default: false, + }, }); -const randomIDSuffix = Math.random().toString(16).substring(2, 8); - -const defaultValue = computed<string>(() => props.parameter["default"]); +const emit = defineEmits<{ + (e: "update:modelValue", value?: string): void; +}>(); const s3Path = reactive<{ - bucket: string | undefined; - key: string | undefined; + bucket: string; + key?: string; }>({ - bucket: undefined, + bucket: "", key: undefined, }); -watch(defaultValue, (newVal, oldVal) => { - if (newVal != oldVal && newVal != undefined) { - emit("update:modelValue", newVal); - } +const selectedResource = reactive<{ + resourceId: string; + resourceVersionIndex: number; +}>({ + resourceId: "", + resourceVersionIndex: 0, }); -watch(s3Path, () => { - if (format.value) { - updateValue(); - } +const formState = reactive<{ + advancedInput: boolean; + stringVal?: string; +}>({ + advancedInput: false, + stringVal: undefined, }); -watch( - () => s3Path.bucket, - (newVal, oldVal) => { - if (newVal !== oldVal) { - updateKeysInBucket(newVal); - } - }, -); - +const defaultValue = computed<string>(() => props.parameter["default"]); const pattern = computed<string>(() => props.parameter["pattern"]); - -const emit = defineEmits<{ - (e: "update:modelValue", value: string | undefined): void; -}>(); - -const stringInput = ref<HTMLInputElement | undefined>(undefined); - -const format = computed<string | undefined>(() => props.parameter["format"]); +const dataFormat = computed<string | undefined>( + () => props.parameter["format"], +); +const dataPath = computed<boolean>(() => dataFormat.value != undefined); +const clowmResource = computed<boolean>( + () => props.parameter["clowm-resource"] ?? false, +); const filesInBucket = computed<string[]>(() => (s3objectRepository.objectMapping[s3Path.bucket ?? ""] ?? []) @@ -98,7 +101,7 @@ const filesAndFoldersInBucket = computed<string[]>(() => ); const keyDataList = computed<string[]>(() => { - switch (format.value) { + switch (dataFormat.value) { case "file-path": return filesInBucket.value; case "directory-path": @@ -110,23 +113,63 @@ const keyDataList = computed<string[]>(() => { } }); -function updateValue() { - if (format.value) { - emit( - "update:modelValue", - !s3Path.bucket && s3Path.key - ? undefined - : `s3://${s3Path.bucket}${s3Path.key ? "/" + s3Path.key : ""}`, - ); - } else { - emit( - "update:modelValue", - stringInput.value?.value ? stringInput.value?.value : undefined, - ); +watch(defaultValue, (newVal, oldVal) => { + if (newVal != oldVal && newVal != undefined) { + emit("update:modelValue", newVal); } +}); + +watch(s3Path, () => { + if (dataPath.value && !formState.advancedInput) { + updateStringFromS3(); + } +}); + +watch( + () => s3Path.bucket, + (newVal, oldVal) => { + if (newVal !== oldVal) { + updateKeysInBucket(newVal); + } + }, +); + +watch(() => formState.stringVal, updateValue); +watch(selectedResource, () => { + if (clowmResource.value && !formState.advancedInput) { + updateStringFromResource(); + } +}); + +watch( + () => formState.advancedInput, + (newVal, oldValue) => { + if (newVal != oldValue) { + if (clowmResource.value) { + updateStringFromResource(); + } else if (dataPath.value) { + updateStringFromS3(); + } + } + }, +); + +function updateValue() { + emit("update:modelValue", formState.stringVal); } -const helpTextPresent = computed<boolean>(() => props.parameter["help_text"]); +function updateStringFromS3() { + formState.stringVal = !s3Path.bucket + ? undefined + : `s3://${s3Path.bucket}${s3Path.key ? "/" + s3Path.key : ""}`; +} + +function updateStringFromResource() { + formState.stringVal = + resourceRepository.resourceMapping[selectedResource.resourceId]?.versions[ + selectedResource.resourceVersionIndex + ]?.cluster_path ?? undefined; +} function updateKeysInBucket(bucketName?: string) { if (bucketName != null) { @@ -138,14 +181,46 @@ function updateKeysInBucket(bucketName?: string) { } onMounted(() => { - if (format.value) { - s3Path.key = defaultValue.value; - } + formState.stringVal = defaultValue.value; }); </script> <template> - <template v-if="format"> + <template v-if="clowmResource && !formState.advancedInput"> + <select + class="form-select" + :required="props.required" + v-model="selectedResource.resourceId" + > + <option selected disabled value="">Please select a resource</option> + <option + v-for="resource in resourceRepository.resources" + :key="resource.resource_id" + :value="resource.resource_id" + > + {{ resource.name }} + </option> + </select> + <select + class="form-select" + :required="props.required || selectedResource.resourceId != undefined" + v-model="selectedResource.resourceVersionIndex" + :disabled="selectedResource.resourceId.length === 0" + > + <option disabled>Please select a version</option> + <option + v-for="(version, index) in resourceRepository.resourceMapping[ + selectedResource.resourceId + ]?.versions ?? []" + :key="version.resource_version_id" + :value="index" + > + {{ version.release }} + {{ version.status === Status.LATEST ? "- Latest" : "" }} + </option> + </select> + </template> + <template v-else-if="dataPath && !formState.advancedInput"> <select class="form-select" :required="props.required" @@ -162,10 +237,9 @@ onMounted(() => { </select> <input class="form-control" - :class="{ 'rounded-end': !helpTextPresent }" :list="'datalistOptions2' + randomIDSuffix" placeholder="Type to search in bucket..." - :required="props.required && format === 'file-path'" + :required="props.required && dataFormat === 'file-path'" v-model="s3Path.key" :pattern="pattern" /> @@ -173,17 +247,32 @@ onMounted(() => { <option v-for="obj in keyDataList" :value="obj" :key="obj" /> </datalist> </template> - <input - v-else - ref="stringInput" - class="form-control" - type="text" - :value="props.modelValue" - :required="props.required" - :aria-describedby="props.helpId" - :pattern="pattern" - @input="updateValue" - /> + <template v-else> + <input + ref="stringInput" + class="form-control" + type="text" + v-model="formState.stringVal" + :required="props.required" + :aria-describedby="props.helpId" + :pattern="pattern" + /> + </template> + <div v-if="(clowmResource || dataPath) && !props.removeAdvanced"> + <input + type="checkbox" + class="btn-check" + :id="'flexCheckDefault' + randomIDSuffix" + autocomplete="off" + v-model="formState.advancedInput" + /> + <label + class="btn btn-outline-secondary rounded-end" + style="border-top-left-radius: 0; border-bottom-left-radius: 0" + :for="'flexCheckDefault' + randomIDSuffix" + >Advanced</label + > + </div> </template> <style scoped></style> diff --git a/src/components/resources/ResourceCard.vue b/src/components/resources/ResourceCard.vue new file mode 100644 index 0000000000000000000000000000000000000000..ad96e63899a6a8b0f5f47a235e39d29658b4afa3 --- /dev/null +++ b/src/components/resources/ResourceCard.vue @@ -0,0 +1,337 @@ +<script setup lang="ts"> +import { + type ResourceOut, + type ResourceVersionOut, + Status, +} from "@/client/resource"; +import { computed, onMounted, ref } from "vue"; +import dayjs from "dayjs"; +import CopyToClipboardIcon from "@/components/CopyToClipboardIcon.vue"; +import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; +import { useS3ObjectStore } from "@/stores/s3objects"; +import { useResourceStore } from "@/stores/resources"; +import { Tooltip } from "bootstrap"; +import { useNameStore } from "@/stores/names"; + +const randomIDSuffix: string = Math.random().toString(16).substring(2, 8); +const objectRepository = useS3ObjectStore(); +const resourceRepository = useResourceStore(); +const nameRepository = useNameStore(); + +const props = defineProps<{ + resource: ResourceOut; + loading: boolean; + extended?: boolean; +}>(); +let refreshTimeout: NodeJS.Timeout | undefined = undefined; + +const stateToUIMapping: Record<Status, string> = { + CLUSTER_DELETED: "Deleted on Cluster", + DENIED: "Rejected", + RESOURCE_REQUESTED: "Resource created", + S3_DELETED: "Deleted in S3", + SYNCHRONIZED: "Available", + SYNCHRONIZING: "Synchronizing to Cluster", + SYNC_REQUESTED: "Wait for Approval", + LATEST: "Available (Latest)", +}; + +const emit = defineEmits<{ + (e: "click-info", resourceVersion: ResourceVersionOut): void; + (e: "click-update", resource: ResourceOut): void; +}>(); + +const resourceVersionS3Ready = ref<Record<string, boolean>>({}); + +const resourceVersions = computed<ResourceVersionOut[]>(() => + [...props.resource.versions].sort((a, b) => + a.created_at < b.created_at ? 1 : -1, + ), +); + +function checkS3Resource(resourceVersion: ResourceVersionOut) { + const bucket = resourceVersion.s3_path.slice(5).split("/")[0]; + const key = resourceVersion.s3_path.split(bucket)[1].slice(1); + objectRepository + .fetchS3ObjectMeta(bucket, key) + .then(() => { + resourceVersionS3Ready.value[resourceVersion.resource_version_id] = true; + }) + .catch(() => { + resourceVersionS3Ready.value[resourceVersion.resource_version_id] = false; + }); +} + +function clickCheckS3Resource(resourceVersion: ResourceVersionOut) { + clearTimeout(refreshTimeout); + refreshTimeout = setTimeout(() => { + checkS3Resource(resourceVersion); + }, 500); +} + +function requestSynchronization(resourceVersion: ResourceVersionOut) { + resourceRepository.requestSynchronization(resourceVersion); +} + +onMounted(() => { + if (!props.loading) { + for (const r of props.resource.versions) { + if (r.status == Status.RESOURCE_REQUESTED) { + checkS3Resource(r); + } + } + [ + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + ...(document + .querySelector("#resource-card-" + randomIDSuffix) + ?.querySelectorAll("[data-bs-toggle='tooltip']") ?? []), + ].map((el) => new Tooltip(el)); + } +}); +</script> + +<template> + <div + :id="'resource-card-' + randomIDSuffix" + class="card-hover border border-secondary card m-2" + > + <div class="card-body"> + <div + class="card-title fs-3 d-flex justify-content-between align-items-center" + > + <div v-if="props.loading" class="placeholder-glow w-100"> + <span class="placeholder col-6"></span> + </div> + <div v-else> + <span>{{ props.resource.name }}</span> + </div> + <button + v-if="props.extended" + :disabled="props.loading" + class="btn btn-primary" + type="button" + data-bs-toggle="modal" + data-bs-target="#updateResourceModal" + @click="emit('click-update', props.resource)" + > + Update + </button> + </div> + <p class="card-text"> + <span v-if="props.loading" class="placeholder-glow" + ><span class="placeholder col-12"></span + ></span> + <span v-else>{{ props.resource.description }}</span> + <br /> + Source: + <span v-if="props.loading" class="placeholder-glow" + ><span class="placeholder col-2"></span + ></span> + <span v-else>{{ props.resource.source }}</span> + </p> + <div v-if="!props.loading"> + <div class="accordion" :id="'accordion-' + props.resource.resource_id"> + <div + v-for="resourceVersion of resourceVersions" + :key="resourceVersion.resource_version_id" + class="accordion-item" + > + <h2 class="accordion-header"> + <button + class="accordion-button" + :class="{ + collapsed: + resourceVersion.status != Status.LATEST || props.extended, + }" + type="button" + data-bs-toggle="collapse" + :data-bs-target=" + '#collapseResourceVersion-' + + resourceVersion.resource_version_id + " + :aria-expanded=" + resourceVersion.status == Status.LATEST && !props.extended + " + :aria-controls=" + '#collapseResourceVersion-' + + resourceVersion.resource_version_id + " + > + {{ resourceVersion.release }} - + {{ stateToUIMapping[resourceVersion.status] }} + </button> + </h2> + <div + :id=" + 'collapseResourceVersion-' + resourceVersion.resource_version_id + " + class="accordion-collapse collapse" + :class="{ + show: + resourceVersion.status == Status.LATEST && !props.extended, + }" + :data-bs-parent="'#accordion-' + props.resource.resource_id" + > + <div class="accordion-body"> + <div> + Registered at: + {{ + dayjs.unix(resourceVersion.created_at).format("DD MMM YYYY") + }} + </div> + <div + v-if=" + props.extended && + (resourceVersion.status == Status.RESOURCE_REQUESTED || + resourceVersion.status == Status.CLUSTER_DELETED) + " + > + <div class="btn-group" role="group"> + <button + type="button" + class="btn btn-primary" + data-bs-toggle="modal" + data-bs-target="#uploadResourceInfoModal" + @click="emit('click-info', resourceVersion)" + > + <font-awesome-icon icon="fa-solid fa-circle-question" /> + </button> + <button + type="button" + class="btn btn-primary" + :disabled=" + !resourceVersionS3Ready[ + resourceVersion.resource_version_id + ] + " + @click="requestSynchronization(resourceVersion)" + > + Request Synchronization + </button> + <button + v-if="resourceVersion.status == Status.RESOURCE_REQUESTED" + type="button" + class="btn btn-primary" + @click="clickCheckS3Resource(resourceVersion)" + > + <font-awesome-icon + icon="fa-solid fa-arrow-rotate-right" + /> + </button> + </div> + </div> + <div + v-if=" + resourceVersion.status === Status.SYNCHRONIZED || + resourceVersion.status === Status.LATEST + " + class="my-1" + > + <label + :for=" + 'nextflow-access-path-' + + resourceVersion.resource_version_id + " + class="form-label" + >Nextflow Access Path:</label + > + <div class="input-group fs-4 mb-3"> + <div + class="input-group-text hover-info" + :id=" + 'tooltip-cluster-path-' + + resourceVersion.resource_version_id + " + data-bs-toggle="tooltip" + data-bs-title="Path on the cluster where a workflow can access the resource" + > + <font-awesome-icon icon="fa-solid fa-circle-question" /> + </div> + <input + :id=" + 'nextflow-access-path-' + + resourceVersion.resource_version_id + " + class="form-control" + type="text" + :value="resourceVersion.cluster_path" + aria-label="Nextflow Access Path" + readonly + /> + <span class="input-group-text" + ><copy-to-clipboard-icon + :text="resourceVersion.cluster_path ?? ''" + /></span> + </div> + </div> + <div + v-if=" + props.extended && + resourceVersion.status !== Status.S3_DELETED + " + class="my-1" + > + <label + :for=" + 's3-access-path-' + resourceVersion.resource_version_id + " + class="form-label" + >S3 Upload Path:</label + > + <div class="input-group fs-4 mb-3"> + <div + class="input-group-text hover-info" + :id=" + 'tooltip-s3-path-' + resourceVersion.resource_version_id + " + data-bs-toggle="tooltip" + data-bs-title="S3 Path where the resource should be uploaded" + > + <font-awesome-icon icon="fa-solid fa-circle-question" /> + </div> + <input + :id=" + 's3-access-path-' + resourceVersion.resource_version_id + " + class="form-control" + type="text" + :value="resourceVersion.s3_path" + aria-label="S3 Access Path" + readonly + /> + <span class="input-group-text" + ><copy-to-clipboard-icon :text="resourceVersion.s3_path" + /></span> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + <div class="mt-2"> + Maintainer: + <span + v-if=" + props.loading || !nameRepository.getName(resource.maintainer_id) + " + class="placeholder-glow" + ><span class="placeholder col-2"></span + ></span> + <span v-else>{{ nameRepository.getName(resource.maintainer_id) }}</span> + </div> + </div> + </div> +</template> + +<style scoped> +.card-hover { + transition: transform 0.3s ease-out; +} + +.card-hover:hover { + transform: translate(0, -5px); + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} +</style> diff --git a/src/components/resources/ResourceVersionInfoModal.vue b/src/components/resources/ResourceVersionInfoModal.vue new file mode 100644 index 0000000000000000000000000000000000000000..1fb0e2fdff5f56d9899938a9d9febcdb9b49c1ef --- /dev/null +++ b/src/components/resources/ResourceVersionInfoModal.vue @@ -0,0 +1,264 @@ +<script setup lang="ts"> +import BootstrapModal from "@/components/modals/BootstrapModal.vue"; +import type { ResourceVersionOut, ResourceOut } from "@/client/resource"; +import CopyToClipboardIcon from "@/components/CopyToClipboardIcon.vue"; +import dayjs from "dayjs"; +import { computed } from "vue"; +import { useNameStore } from "@/stores/names"; + +const props = defineProps<{ + modalId: string; + resourceVersionIndex: number; + resource?: ResourceOut; +}>(); + +const nameRepository = useNameStore(); + +const resourceVersion = computed<ResourceVersionOut | undefined>( + () => props.resource?.versions[props.resourceVersionIndex], +); +</script> + +<template> + <bootstrap-modal + :modal-id="props.modalId" + modal-label="Resource Version Info Modal" + size-modifier="lg" + > + <template #header + >Resource + <b v-if="resourceVersion" + >{{ resource?.name }}@{{ resourceVersion?.release }}</b + > + </template> + <template #body> + <h5>Resource</h5> + <div class="mb-3 row"> + <div class="col-8"> + <label + for="resource-version-info-modal-resource-id" + class="form-label" + >ID</label + > + <div class="input-group"> + <input + type="text" + class="form-control" + id="resource-version-info-modal-resource-id" + readonly + :value="props.resource?.resource_id" + /> + <span class="input-group-text" + ><copy-to-clipboard-icon + :text="props.resource?.resource_id ?? ''" + /></span> + </div> + </div> + <div class="col-4"> + <label + for="resource-version-info-modal-resource-name" + class="form-label" + >Name</label + > + <div class="input-group"> + <input + type="text" + class="form-control" + id="resource-version-info-modal-resource-name" + readonly + :value="props.resource?.name" + /> + </div> + </div> + </div> + <div class="mb-3 row"> + <div class="col-8"> + <label + for="resource-version-info-modal-maintainer-id" + class="form-label" + >Maintainer ID</label + > + <div class="input-group"> + <input + type="text" + class="form-control" + id="resource-version-info-modal-maintainer-id" + readonly + :value="props.resource?.maintainer_id" + /> + <span class="input-group-text" + ><copy-to-clipboard-icon + :text="props.resource?.maintainer_id ?? ''" + /></span> + </div> + </div> + <div class="col-4"> + <label + for="resource-version-info-modal-maintainer-name" + class="form-label" + >Maintainer Name</label + > + <div class="input-group"> + <input + type="text" + class="form-control" + id="resource-version-info-modal-maintainer-name" + readonly + :value="nameRepository.getName(props.resource?.maintainer_id)" + /> + </div> + </div> + </div> + <div class="mb-3"> + <label + for="resource-version-info-modal-resource-description" + class="form-label" + >Description</label + > + <div class="input-group"> + <textarea + class="form-control" + id="resource-version-info-modal-resource-description" + readonly + rows="2" + :value="props.resource?.description" + /> + </div> + </div> + <div class="mb-5"> + <label + for="resource-version-info-modal-resource-source" + class="form-label" + >Source</label + > + <div class="input-group"> + <input + type="text" + class="form-control" + id="resource-version-info-modal-resource-source" + readonly + :value="props.resource?.source" + /> + </div> + </div> + <h5>Resource Version</h5> + <div class="mb-3 row"> + <div class="col-8"> + <label + for="resource-version-info-modal-resource-version-id" + class="form-label" + >Resource Version ID</label + > + <div class="input-group"> + <input + type="text" + class="form-control" + id="resource-version-info-modal-resource-version-id" + readonly + :value="resourceVersion?.resource_version_id" + /> + <span class="input-group-text" + ><copy-to-clipboard-icon + :text="resourceVersion?.resource_version_id ?? ''" + /></span> + </div> + </div> + <div class="col-4"> + <label + for="resource-version-info-modal-resource-version-release" + class="form-label" + >Resource Version Release</label + > + <div class="input-group"> + <input + type="text" + class="form-control" + id="resource-version-info-modal-resource-version-release" + readonly + :value="resourceVersion?.release" + /> + </div> + </div> + </div> + <div class="mb-3 row"> + <div class="col-4"> + <label + for="resource-version-info-modal-resource-version-status" + class="form-label" + >Status</label + > + <div class="input-group"> + <input + type="text" + class="form-control" + id="resource-version-info-modal-resource-version-status" + readonly + :value="resourceVersion?.status" + /> + </div> + </div> + <div class="col-4"> + <label + for="resource-version-info-modal-resource-version-timestamp" + class="form-label" + >Created At</label + > + <div class="input-group"> + <input + type="datetime-local" + class="form-control" + id="resource-version-info-modal-resource-version-timestamp" + readonly + :value=" + dayjs + .unix(resourceVersion?.created_at ?? 0) + .format('YYYY-MM-DDTHH:mm') + " + /> + </div> + </div> + </div> + <div class="mb-3"> + <label + for="resource-version-info-modal-resource-version-s3-path" + class="form-label" + >S3 Path</label + > + <div class="input-group"> + <input + type="text" + class="form-control" + id="resource-version-info-modal-resource-version-s3-path" + readonly + :value="resourceVersion?.s3_path" + /> + <span class="input-group-text" + ><copy-to-clipboard-icon :text="resourceVersion?.s3_path ?? ''" + /></span> + </div> + </div> + <div class="mb-3"> + <label + for="resource-version-info-modal-resource-version-cluster-path" + class="form-label" + >Cluster Path</label + > + <div class="input-group"> + <input + type="text" + class="form-control" + id="resource-version-info-modal-resource-version-cluster-path" + readonly + :value="resourceVersion?.cluster_path" + /> + <span class="input-group-text" + ><copy-to-clipboard-icon + :text="resourceVersion?.cluster_path ?? ''" + /></span> + </div> + </div> + </template> + </bootstrap-modal> +</template> + +<style scoped></style> diff --git a/src/components/resources/modals/CreateResourceModal.vue b/src/components/resources/modals/CreateResourceModal.vue new file mode 100644 index 0000000000000000000000000000000000000000..8bf7a012971ac41ea5a94865e3018333f417986c --- /dev/null +++ b/src/components/resources/modals/CreateResourceModal.vue @@ -0,0 +1,229 @@ +<script setup lang="ts"> +import { reactive, onMounted, ref } from "vue"; +import BootstrapModal from "@/components/modals/BootstrapModal.vue"; +import { Modal } from "bootstrap"; +import { useResourceStore } from "@/stores/resources"; +import type { ResourceIn } from "@/client/resource"; +import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; +import { Tooltip } from "bootstrap"; + +const resourceRepository = useResourceStore(); + +const resourceCreateForm = ref<HTMLFormElement | undefined>(undefined); +const resourceNameElement = ref<HTMLInputElement | undefined>(undefined); + +const resource = reactive<ResourceIn>({ + name: "", + description: "", + release: "", + source: "", +}); + +const formState = reactive<{ + validated: boolean; + resourceNameTaken: boolean; + loading: boolean; +}>({ + validated: false, + resourceNameTaken: false, + loading: false, +}); + +const props = defineProps<{ + modalID: string; +}>(); + +let createResourceModal: Modal | null = null; + +function createResource() { + formState.validated = true; + formState.resourceNameTaken = false; + resource.description = resource.description.trim(); + resource.name = resource.name.trim(); + resourceNameElement.value?.setCustomValidity(""); + if (resourceCreateForm.value?.checkValidity()) { + formState.loading = true; + resourceRepository + .createResource(resource) + .then(() => { + createResourceModal?.hide(); + resource.name = ""; + resource.description = ""; + resource.source = ""; + resource.release = ""; + formState.resourceNameTaken = false; + formState.validated = false; + }) + .catch((error) => { + if ( + error.status === 400 && + error.body["detail"] === + `Resource with name '${resource.name}' already exists` + ) { + formState.resourceNameTaken = true; + resourceNameElement.value?.setCustomValidity( + "Resource name is already taken", + ); + } + }) + .finally(() => { + formState.loading = false; + }); + } +} + +function modalClosed() { + formState.validated = false; + formState.resourceNameTaken = false; + resourceNameElement.value?.setCustomValidity(""); +} + +onMounted(() => { + createResourceModal = new Modal("#" + props.modalID); + new Tooltip("#tooltip-new-resource-source"); + new Tooltip("#tooltip-new-resource-release"); +}); +</script> + +<template> + <bootstrap-modal + :modalId="modalID" + static-backdrop + modal-label="Create Resource Modal" + v-on="{ 'hidden.bs.modal': modalClosed }" + > + <template #header> Create new Resource</template> + <template #body> + <form + id="resourceCreateForm" + :class="{ 'was-validated': formState.validated }" + ref="resourceCreateForm" + > + <div class="mb-3"> + <label for="resourceNameInput" class="form-label" + >Resource Name</label + > + <div class="input-group"> + <input + type="text" + class="form-control" + id="resourceNameInput" + required + minlength="3" + maxlength="32" + v-model="resource.name" + ref="resourceNameElement" + /> + <div class="invalid-feedback"> + <div v-if="formState.resourceNameTaken"> + Resource name already taken. + </div> + <div> + Requirements + <ul> + <li>At least 3 Characters long</li> + <li>Unique in CloWM</li> + </ul> + </div> + </div> + </div> + </div> + <div class="mb-3"> + <label for="resourceDescriptionInput" class="form-label"> + Description + </label> + <div class="input-group"> + <textarea + class="form-control" + id="resourceDescriptionInput" + required + rows="3" + minlength="16" + maxlength="256" + v-model="resource.description" + placeholder="Describe the purpose of the resource" + ></textarea> + <div class="invalid-feedback"> + Requirements + <ul> + <li>At least 16 Characters long</li> + </ul> + </div> + </div> + </div> + <div class="mb-3"> + <label for="resourceSourceInput" class="form-label"> Source </label> + <div class="input-group"> + <div class="input-group-text"> + <font-awesome-icon icon="fa-solid fa-link" /> + </div> + <input + class="form-control" + id="resourceSourceInput" + required + minlength="8" + maxlength="264" + v-model="resource.source" + placeholder="The source of the resource (e.g. a link)" + /> + <div + class="input-group-text hover-info" + id="tooltip-new-resource-source" + data-bs-toggle="tooltip" + data-bs-title="The source from where the resource comes" + > + <font-awesome-icon icon="fa-solid fa-circle-question" /> + </div> + </div> + </div> + <div class="mb-3"> + <label for="resourceReleaseInput" class="form-label"> Release </label> + <div class="input-group"> + <div class="input-group-text"> + <font-awesome-icon icon="fa-solid fa-tag" /> + </div> + <input + class="form-control" + id="resourceReleaseInput" + required + minlength="3" + maxlength="32" + v-model="resource.release" + placeholder="Initial release name" + /> + <div + class="input-group-text hover-info" + id="tooltip-new-resource-release" + data-bs-toggle="tooltip" + data-bs-title="The name of the first resource version" + > + <font-awesome-icon icon="fa-solid fa-circle-question" /> + </div> + </div> + </div> + </form> + </template> + <template v-slot:footer> + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal"> + Close + </button> + <button + type="submit" + form="resourceCreateForm" + class="btn btn-primary" + :disabled="formState.loading" + @click.prevent="createResource" + > + <span + v-if="formState.loading" + class="spinner-border spinner-border-sm" + role="status" + aria-hidden="true" + ></span> + Save + </button> + </template> + </bootstrap-modal> +</template> + +<style scoped></style> diff --git a/src/components/resources/modals/UpdateResourceModal.vue b/src/components/resources/modals/UpdateResourceModal.vue new file mode 100644 index 0000000000000000000000000000000000000000..f0e73c341af5384ae0b64216b26eb02a86e782c9 --- /dev/null +++ b/src/components/resources/modals/UpdateResourceModal.vue @@ -0,0 +1,129 @@ +<script setup lang="ts"> +import { reactive, onMounted, ref } from "vue"; +import BootstrapModal from "@/components/modals/BootstrapModal.vue"; +import { Modal } from "bootstrap"; +import { useResourceStore } from "@/stores/resources"; +import type { ResourceVersionIn, ResourceOut } from "@/client/resource"; +import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; +import { Tooltip } from "bootstrap"; + +const resourceRepository = useResourceStore(); + +const resourceUpdateForm = ref<HTMLFormElement | undefined>(undefined); + +const resourceUpdate = reactive<ResourceVersionIn>({ + release: "", +}); + +const formState = reactive<{ + validated: boolean; + loading: boolean; +}>({ + validated: false, + loading: false, +}); + +const props = defineProps<{ + modalId: string; + resource: ResourceOut; +}>(); + +let updateResourceModal: Modal | null = null; + +function updateResource() { + formState.validated = true; + resourceUpdate.release = resourceUpdate.release.trim(); + if (resourceUpdateForm.value?.checkValidity()) { + formState.loading = true; + resourceRepository + .updateResource(props.resource.resource_id, resourceUpdate) + .then(() => { + updateResourceModal?.hide(); + resourceUpdate.release = ""; + formState.validated = false; + }) + .finally(() => { + formState.loading = false; + }); + } +} + +function modalClosed() { + formState.validated = false; +} + +onMounted(() => { + updateResourceModal = new Modal("#" + props.modalId); + new Tooltip("#tooltip-update-resource-release"); +}); +</script> + +<template> + <bootstrap-modal + :modalId="modalId" + static-backdrop + modal-label="Update Resource Modal" + v-on="{ 'hidden.bs.modal': modalClosed }" + > + <template #header> + Update Resource <b>{{ props.resource.name }}</b></template + > + <template #body> + <form + id="resourceUpdateForm" + :class="{ 'was-validated': formState.validated }" + ref="resourceUpdateForm" + > + <div class="mb-3"> + <label for="resourceUpdateReleaseInput" class="form-label"> + Release + </label> + <div class="input-group"> + <div class="input-group-text"> + <font-awesome-icon icon="fa-solid fa-tag" /> + </div> + <input + class="form-control" + id="resourceUpdateReleaseInput" + required + minlength="3" + maxlength="32" + v-model="resourceUpdate.release" + placeholder="Next release name" + /> + <div + class="input-group-text hover-info" + id="tooltip-update-resource-release" + data-bs-toggle="tooltip" + data-bs-title="The name of the next resource version" + > + <font-awesome-icon icon="fa-solid fa-circle-question" /> + </div> + </div> + </div> + </form> + </template> + <template v-slot:footer> + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal"> + Close + </button> + <button + type="submit" + form="resourceUpdateForm" + class="btn btn-primary" + :disabled="formState.loading || !props.resource.resource_id" + @click.prevent="updateResource" + > + <span + v-if="formState.loading" + class="spinner-border spinner-border-sm" + role="status" + aria-hidden="true" + ></span> + Save + </button> + </template> + </bootstrap-modal> +</template> + +<style scoped></style> diff --git a/src/components/resources/modals/UploadResourceInfoModal.vue b/src/components/resources/modals/UploadResourceInfoModal.vue new file mode 100644 index 0000000000000000000000000000000000000000..10463ea778ce2f0f11991e61470337f786da86aa --- /dev/null +++ b/src/components/resources/modals/UploadResourceInfoModal.vue @@ -0,0 +1,337 @@ +<script setup lang="ts"> +import BootstrapModal from "@/components/modals/BootstrapModal.vue"; +import { type ResourceVersionOut, Status } from "@/client/resource"; +import { computed, onMounted, ref, watch } from "vue"; +import { environment } from "@/environment"; +import CopyToClipboardIcon from "@/components/CopyToClipboardIcon.vue"; +import { useS3KeyStore } from "@/stores/s3keys"; +import type { S3Key } from "@/client/s3proxy"; +import { useS3ObjectStore } from "@/stores/s3objects"; +import { useResourceStore } from "@/stores/resources"; +import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; +import { Modal } from "bootstrap"; + +const props = defineProps<{ + modalId: string; + resourceVersion?: ResourceVersionOut; +}>(); + +const s3KeyRepository = useS3KeyStore(); +const objectRepository = useS3ObjectStore(); +const resourceRepository = useResourceStore(); + +let infoResourceModal: Modal | null = null; +let refreshTimeout: NodeJS.Timeout | undefined = undefined; + +enum Tool { + PYTHON = "python", + S5CMD = "s5cmd", + MINIO = "minio", +} + +watch( + () => props.resourceVersion, + (newVersion, oldVersion) => { + if (newVersion?.resource_version_id !== oldVersion?.resource_version_id) { + resourceSynchronizationEnabled.value = false; + if (newVersion?.status === Status.RESOURCE_REQUESTED) { + checkS3Resource(newVersion); + } + } + }, +); + +const activeTool = ref<Tool>(Tool.S5CMD); +const resourceSynchronizationEnabled = ref<boolean>(false); + +const resourceS3Path = computed<string>(() => { + return ( + props.resourceVersion?.s3_path ?? + "s3://examplebucket/RESOURCE-ID/RESOURCE-VERSION-ID/resource.tar.gz" + ); +}); +const resourceMinioS3Path = computed<string>(() => { + return resourceS3Path.value.slice(5); +}); +const resourceBucket = computed<string>(() => { + return resourceMinioS3Path.value.split("/")[0]; +}); +const resourceKey = computed<string>(() => { + return resourceS3Path.value.split(resourceBucket.value)[1].slice(1); +}); +const codeExample = computed<string>(() => { + if (activeTool.value === Tool.S5CMD) { + return `export AWS_REGION="us-west-1" +export AWS_ACCESS_KEY_ID="${s3Key.value.access_key}" +export AWS_SECRET_ACCESS_KEY="${s3Key.value.secret_key}" +export S3_ENDPOINT="${environment.S3_URL}" + +s5cmd cp --show-progress /PATH/TO/RESOURCE \\ + ${resourceS3Path.value}`; + } else if (activeTool.value === Tool.MINIO) { + return `mc alias set ${environment.S3_URL} "${s3Key.value.access_key}" "${s3Key.value.secret_key}" +mc cp /PATH/TO/RESOURCE \\ + clowm-s3/clowm-resources/CLDB-eaa7aae4/eaaa1c99b14911ee9f5d0242ac120004/resource.tar.gz`; + } else if (activeTool.value === Tool.PYTHON) { + return `import boto3 + +s3 = boto3.resource( + service_name="s3", + aws_access_key_id="${s3Key.value.access_key}", + aws_secret_access_key="${s3Key.value.secret_key}", + endpoint_url="${environment.S3_URL}", + verify=True, +) + +with open("/PATH/TO/RESOURCE", "rb") as f: + s3.Object( + bucket="${resourceBucket.value}", + key="${resourceKey.value}" + ).upload_fileobj(f)`; + } + return ""; +}); + +const s3Key = computed<S3Key>(() => { + return ( + s3KeyRepository.keys[0] ?? { + access_key: "abc", + secret_key: "def", + } + ); +}); + +function checkS3Resource(resourceVersion: ResourceVersionOut) { + const bucket = resourceVersion.s3_path.slice(5).split("/")[0]; + const key = resourceVersion.s3_path.split(bucket)[1].slice(1); + objectRepository + .fetchS3ObjectMeta(bucket, key) + .then(() => { + resourceSynchronizationEnabled.value = true; + }) + .catch(() => { + resourceSynchronizationEnabled.value = false; + }); +} + +function clickCheckS3Resource(resourceVersion: ResourceVersionOut) { + clearTimeout(refreshTimeout); + refreshTimeout = setTimeout(() => { + checkS3Resource(resourceVersion); + }, 500); +} + +function requestSynchronization(resourceVersion: ResourceVersionOut) { + resourceRepository.requestSynchronization(resourceVersion).then(() => { + infoResourceModal?.hide(); + }); +} + +onMounted(() => { + infoResourceModal = new Modal("#" + props.modalId); +}); +</script> + +<template> + <bootstrap-modal + :modalId="props.modalId" + modal-label="Upload Resource Info Modal" + sizeModifier="lg" + > + <template #header>How to upload a resource to the cluster</template> + <template #body> + <ol> + <li :class="{ 'text-decoration-line-through': props.resourceVersion }"> + <h6> + Prerequisite: Prepare a single compressed tar archive of your data + </h6> + <p :hidden="props.resourceVersion != undefined"> + The data of your resource must be compressed into a single tar + archive to save bandwidth and storage space.<br /> + <code>tar -czf resource.tar.gz /PATH/TO/MY/RESOURCE/DATA</code> + </p> + </li> + <li :class="{ 'text-decoration-line-through': props.resourceVersion }"> + <h6>Request a resource in CloWM</h6> + <p :hidden="props.resourceVersion != undefined"> + Click on <b>Create Resource</b> and fill out the form + </p> + </li> + <li + :class="{ + 'text-decoration-line-through': resourceSynchronizationEnabled, + }" + > + <h6>Upload the resource</h6> + <template v-if="!resourceSynchronizationEnabled"> + <p> + Upload the tar archive to the provided S3 path with a tool of your + choice. + </p> + <ul class="nav nav-tabs mb-2"> + <li class="nav-item"> + <a + class="nav-link" + :class="{ active: activeTool === Tool.S5CMD }" + aria-current="page" + href="#" + @click="activeTool = Tool.S5CMD" + >s5cmd</a + > + </li> + <li class="nav-item"> + <a + class="nav-link" + :class="{ active: activeTool === Tool.MINIO }" + href="#" + @click="activeTool = Tool.MINIO" + >Minio</a + > + </li> + <li class="nav-item"> + <a + class="nav-link" + :class="{ active: activeTool === Tool.PYTHON }" + href="#" + @click="activeTool = Tool.PYTHON" + >Python</a + > + </li> + </ul> + <template v-if="activeTool === Tool.S5CMD"> + <p> + <code>s5cmd</code> is a very fast S3 and local filesystem + execution tool. It comes with support for a multitude of + operations including tab completion and wildcard support for + files, which can be very handy for your object storage workflow + while working with large number of files. + </p> + <p> + The GitHub repository contains a + <a + href="https://github.com/peak/s5cmd?tab=readme-ov-file#installation" + target="_blank" + >installation guide</a + >. + </p> + <pre class="w-100"><code class="hljs language-bash"><span + class="hljs-built_in">export</span> AWS_REGION=<span class="hljs-string">"us-west-1"</span> +<span class="hljs-built_in">export</span> AWS_ACCESS_KEY_ID=<span class="hljs-string">"{{ s3Key.access_key }}"</span> +<span class="hljs-built_in">export</span> AWS_SECRET_ACCESS_KEY=<span class="hljs-string">"{{ + s3Key.secret_key + }}"</span> +<span class="hljs-built_in">export</span> S3_ENDPOINT=<span class="hljs-string">"{{ environment.S3_URL }}"</span> + +<span class="hljs-built_in">s5cmd</span> cp --show-progress /PATH/TO/RESOURCE \ + {{ resourceS3Path }}</code></pre> + </template> + <template v-else-if="activeTool === Tool.MINIO"> + <p> + The MinIO Client <code>mc</code> command line tool provides a + modern alternative to UNIX commands like <code>ls</code>, + <code>cat</code>, <code>cp</code>, <code>mirror</code>, and + <code>diff</code> with support for both filesystems and Amazon + S3-compatible cloud storage services. + </p> + <p> + The official documentation contains a + <a + href="https://min.io/docs/minio/linux/reference/minio-mc.html#install-mc" + target="_blank" + >installation guide</a + >. + </p> + <pre + class="w-100" + ><code class="hljs language-bash">mc <span class="hljs-built_in">alias</span> <span + class="hljs-built_in">set</span> {{ environment.S3_URL }} <span + class="hljs-string">"{{ s3Key.access_key }}"</span> <span + class="hljs-string">"{{ s3Key.secret_key }}"</span> +mc <span class="hljs-built_in">cp</span> /PATH/TO/RESOURCE \ + clowm-s3/{{ resourceMinioS3Path }}</code></pre> + </template> + <template v-else-if="activeTool === Tool.PYTHON"> + <p> + You use the AWS SDK for Python (<a + href="https://boto3.amazonaws.com/v1/documentation/api/latest/index.html" + target="_blank" + >Boto3</a + >) to create, configure, and manage AWS services, such as Amazon + Elastic Compute Cloud (Amazon EC2) and Amazon Simple Storage + Service (Amazon S3). The SDK provides an object-oriented API as + well as low-level access to AWS services. + </p> + <p> + The package can be installed with pip: + <code>pip install boto3</code> + </p> + <pre + class="w-100" + ><code class="hljs language-python"><span class="hljs-keyword">import</span> boto3 + +s3 = boto3.resource( + service_name=<span class="hljs-string">"s3"</span>, + aws_access_key_id=<span class="hljs-string">"{{ s3Key.access_key }}"</span>, + aws_secret_access_key=<span class="hljs-string">"{{ s3Key.secret_key }}"</span>, + endpoint_url=<span class="hljs-string">"{{ environment.S3_URL }}"</span>, + verify=<span class="hljs-literal">True</span>, +) + +<span class="hljs-keyword">with</span> <span class="hljs-built_in">open</span>(<span class="hljs-string">"/PATH/TO/RESOURCE"</span>, <span + class="hljs-string">"rb"</span>) <span class="hljs-keyword">as</span> f: + s3.Object( + bucket=<span class="hljs-string">"{{ resourceBucket }}"</span>, + key=<span class="hljs-string">"{{ resourceKey }}"</span> + ).upload_fileobj(f)</code></pre> + </template> + </template> + </li> + <li> + <h6>Request a synchronization</h6> + <p> + Click <b>Request Synchronization</b> to request the synchronization + to CloWM's compute cluster. + </p> + <div class="btn-group" role="group" v-if="props.resourceVersion"> + <button + type="button" + class="btn btn-primary" + :disabled="!resourceSynchronizationEnabled" + @click="requestSynchronization(props.resourceVersion)" + > + Request Synchronization + </button> + <button + v-if="props.resourceVersion.status === Status.RESOURCE_REQUESTED" + type="button" + class="btn btn-primary" + @click="clickCheckS3Resource(props.resourceVersion)" + > + <font-awesome-icon icon="fa-solid fa-arrow-rotate-right" /> + </button> + </div> + </li> + <li> + <h6>Resource availability</h6> + <p> + Once a Reviewer approves your resource synchronization request, the + resource will be made available in CloWM and is accessible for every + workflow via its <b>Nextflow Access Path</b>. + </p> + </li> + </ol> + </template> + <template #footer> + <copy-to-clipboard-icon + v-if="props.resourceVersion && !resourceSynchronizationEnabled" + button + :text="codeExample" + /> + <button type="button" class="btn btn-secondary" data-bs-dismiss="modal"> + Close + </button> + </template> + </bootstrap-modal> +</template> + +<style scoped></style> diff --git a/src/components/workflows/WorkflowStatisticsChart.vue b/src/components/workflows/WorkflowStatisticsChart.vue index ee4711cfc8829daa8390973a303b1af6aaf1da07..56a9648686e8d2b153373cc096bc43fdf0366cc5 100644 --- a/src/components/workflows/WorkflowStatisticsChart.vue +++ b/src/components/workflows/WorkflowStatisticsChart.vue @@ -135,7 +135,7 @@ onMounted(() => { chart = new Chart(canvas.value, { type: "bar", data: { - labels: [], // Days as lables + labels: [], // Days as labels datasets: [ { // Workflow count per day diff --git a/src/components/workflows/modals/ArbitraryWorkflowModal.vue b/src/components/workflows/modals/ArbitraryWorkflowModal.vue index 65fce9d4fdd315b462ea2d30d1efef49c07a3238..c33d00d11f856eeb47d9f0dba00045f31215723a 100644 --- a/src/components/workflows/modals/ArbitraryWorkflowModal.vue +++ b/src/components/workflows/modals/ArbitraryWorkflowModal.vue @@ -186,7 +186,7 @@ onMounted(() => { <template> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="false" modal-label="Create Workflow Modal" v-on="{ 'hidden.bs.modal': modalClosed }" @@ -424,8 +424,4 @@ onMounted(() => { </bootstrap-modal> </template> -<style scoped> -.hover-info:hover { - color: var(--bs-info) !important; -} -</style> +<style scoped></style> diff --git a/src/components/workflows/modals/CreateWorkflowModal.vue b/src/components/workflows/modals/CreateWorkflowModal.vue index 86bd5862fcfe811428259c97758a9fb9ca299ee7..3d7d1bcca8a6ed80cb6532d6c2b3628d52897e04 100644 --- a/src/components/workflows/modals/CreateWorkflowModal.vue +++ b/src/components/workflows/modals/CreateWorkflowModal.vue @@ -17,6 +17,7 @@ import { import { valid } from "semver"; import WorkflowModeTransitionGroup from "@/components/transitions/WorkflowModeTransitionGroup.vue"; import { useWorkflowStore } from "@/stores/workflows"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const workflowRepository = useWorkflowStore(); // Emitted Events @@ -319,28 +320,11 @@ onMounted(() => { </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-success align-items-center border-0" - data-bs-autohide="true" - :id="'successToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div class="toast-body">Successfully created Workflow</div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast :toast-id="'successToast-' + randomIDSuffix"> + Successfully created Workflow + </bootstrap-toast> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="true" modal-label="Create Workflow Modal" v-on="{ 'hidden.bs.modal': modalClosed }" @@ -700,8 +684,4 @@ onMounted(() => { </bootstrap-modal> </template> -<style scoped> -.hover-info:hover { - color: var(--bs-info) !important; -} -</style> +<style scoped></style> diff --git a/src/components/workflows/modals/ParameterModal.vue b/src/components/workflows/modals/ParameterModal.vue index 576746b44668556bf079f70a015d88b9bd1315c1..76f0d35f2ae516fd616ec0baf486931dc183fd79 100644 --- a/src/components/workflows/modals/ParameterModal.vue +++ b/src/components/workflows/modals/ParameterModal.vue @@ -6,10 +6,10 @@ import type { RouteParamsRaw } from "vue-router"; import { Modal } from "bootstrap"; import { useRouter } from "vue-router"; import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; -import { useWorkflowStore } from "@/stores/workflows"; import type { WorkflowExecutionOut } from "@/client/workflow"; +import { useNameStore } from "@/stores/names"; -const workflowRepository = useWorkflowStore(); +const nameRepository = useNameStore(); const executionRepository = useWorkflowExecutionStore(); const router = useRouter(); @@ -71,9 +71,9 @@ const workflowName = computed<string>(() => { execution?.workflow_version_id != undefined ) { return ( - workflowRepository.getName(execution.workflow_id) + + nameRepository.getName(execution.workflow_id) + "@" + - workflowRepository.getName(execution.workflow_version_id) + nameRepository.getName(execution.workflow_version_id) ); } } @@ -139,7 +139,7 @@ onMounted(() => { <template> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="false" modal-label="Workflow Execution Parameters Modal" > diff --git a/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue b/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue index 43f057f9103cf72bdc387ce8b0896f64542786c9..ea0a1d22b232ebe9b4fb9e4186dffb73e3e3a95c 100644 --- a/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue +++ b/src/components/workflows/modals/UpdateWorkflowCredentialsModal.vue @@ -7,6 +7,7 @@ import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; import DeleteModal from "@/components/modals/DeleteModal.vue"; import { GitRepository } from "@/utils/GitRepository"; import { useWorkflowStore } from "@/stores/workflows"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const workflowRepository = useWorkflowStore(); // Constants @@ -131,31 +132,11 @@ onMounted(() => { :back-modal-id="modalID" @confirm-delete="deleteCredentials()" /> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-success align-items-center border-0" - data-bs-autohide="true" - :id="'successToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div v-if="formState.updateCredentials" class="toast-body"> - Successfully updated credentials - </div> - <div v-else class="toast-body">Successfully deleted credentials</div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast :toast-id="'successToast-' + randomIDSuffix"> + Successfully updated credentials + </bootstrap-toast> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="true" modal-label="Update Workflow Version Icon Modal" v-on="{ 'hidden.bs.modal': modalClosed }" diff --git a/src/components/workflows/modals/UpdateWorkflowModal.vue b/src/components/workflows/modals/UpdateWorkflowModal.vue index 1b393686f6bdd81ebcdf4ce82d6e975fcac7eaa4..2961a8d5db685984b352fc55fb49f81b66bc88de 100644 --- a/src/components/workflows/modals/UpdateWorkflowModal.vue +++ b/src/components/workflows/modals/UpdateWorkflowModal.vue @@ -21,6 +21,7 @@ import { valid, lte, inc } from "semver"; import { latestVersion as calculateLatestVersion } from "@/utils/Workflow"; import WorkflowModeTransitionGroup from "@/components/transitions/WorkflowModeTransitionGroup.vue"; import { useWorkflowStore } from "@/stores/workflows"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const workflowRepository = useWorkflowStore(); // Bootstrap Elements @@ -307,28 +308,11 @@ onMounted(() => { </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-success align-items-center border-0" - data-bs-autohide="true" - :id="'successToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div class="toast-body">Successfully updated Workflow</div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast :toast-id="'successToast-' + randomIDSuffix"> + Successfully updated Workflow + </bootstrap-toast> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="true" modal-label="Update Workflow Modal" v-on="{ 'hidden.bs.modal': modalClosed }" diff --git a/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue b/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue index ef529298b5b71f8f3fdb059a7d05801201b1c7a1..b820af5335b0021bfbd7538ce8e0c20d664e0d0c 100644 --- a/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue +++ b/src/components/workflows/modals/UpdateWorkflowVersionIconModal.vue @@ -6,6 +6,7 @@ import { Modal, Toast } from "bootstrap"; import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; import DeleteModal from "@/components/modals/DeleteModal.vue"; import { useWorkflowStore } from "@/stores/workflows"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const workflowRepository = useWorkflowStore(); // Constants @@ -140,31 +141,12 @@ onMounted(() => { :back-modal-id="modalID" @confirm-delete="deleteIcon()" /> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-success align-items-center border-0" - data-bs-autohide="true" - :id="'successToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div v-if="formState.uploadIcon" class="toast-body"> - Successfully uploaded icon - </div> - <div v-else class="toast-body">Successfully deleted icon</div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast :toast-id="'successToast-' + randomIDSuffix"> + <div v-if="formState.uploadIcon">Successfully uploaded icon</div> + <div v-else>Successfully deleted icon</div> + </bootstrap-toast> <bootstrap-modal - :modalID="modalID" + :modalId="modalID" :static-backdrop="true" modal-label="Update Workflow Version IconModal" v-on="{ 'hidden.bs.modal': modalClosed }" diff --git a/src/environment.ts b/src/environment.ts index cb756b7e77d18de3fe8208de0e8670b87e123a66..fd58108f1e1127b8178a2f11056323ea99e3a99f 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -6,6 +6,7 @@ export const environment: env = { S3PROXY_API_BASE_URL: windowEnv["s3proxyApiUrl"], AUTH_API_BASE_URL: windowEnv["authApiUrl"], WORKFLOW_API_BASE_URL: windowEnv["workflowApiUrl"], + RESOURCE_API_BASE_URL: windowEnv["resourceApiUrl"], DEV_SYSTEM: windowEnv["devSystem"].toLowerCase() === "true", }; @@ -14,5 +15,6 @@ type env = { S3PROXY_API_BASE_URL: string; AUTH_API_BASE_URL: string; WORKFLOW_API_BASE_URL: string; + RESOURCE_API_BASE_URL: string; DEV_SYSTEM: boolean; }; diff --git a/src/router/adminRoutes.ts b/src/router/adminRoutes.ts new file mode 100644 index 0000000000000000000000000000000000000000..a7a4384781a425879efc121e17f1c2ea24253195 --- /dev/null +++ b/src/router/adminRoutes.ts @@ -0,0 +1,12 @@ +import type { RouteRecordRaw } from "vue-router"; + +export const adminRoutes: RouteRecordRaw[] = [ + { + path: "admin/resources", + name: "admin-resources", + component: () => import("../views/admin/AdminResourcesView.vue"), + meta: { + requiresAdminRole: true, + }, + }, +]; diff --git a/src/router/index.ts b/src/router/index.ts index 3f43bacab4caa4623ac235782926875e579273c3..21ae88be87f65a9832c6fcdbb7b83d8dc62a6214 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -1,6 +1,10 @@ import { createRouter, createWebHistory } from "vue-router"; import DashboardView from "../views/DashboardView.vue"; import LoginView from "../views/LoginView.vue"; +import { workflowRoutes } from "@/router/workflowRoutes"; +import { s3Routes } from "@/router/s3Routes"; +import { resourceRoutes } from "@/router/resourceRoutes"; +import { adminRoutes } from "@/router/adminRoutes"; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -10,102 +14,10 @@ const router = createRouter({ name: "dashboard", component: DashboardView, children: [ - { - path: "object-storage/buckets", - name: "buckets", - component: () => import("../views/object-storage/BucketsView.vue"), - props: (route) => ({ - bucketName: route.params.bucketName ?? undefined, - }), - children: [ - { - path: ":bucketName/:subFolders*", - name: "bucket", - component: () => import("../views/object-storage/BucketView.vue"), - props: true, - }, - ], - }, - { - path: "object-storage/s3-keys", - name: "s3_keys", - component: () => import("../views/object-storage/S3KeysView.vue"), - }, - { - path: "workflow-executions", - name: "workflow-executions", - component: () => - import("../views/workflows/ListWorkflowExecutionsView.vue"), - }, - { - path: "workflows", - name: "workflows", - component: () => import("../views/workflows/ListWorkflowsView.vue"), - }, - { - path: "developer/workflows", - name: "workflows-developer", - component: () => import("../views/workflows/MyWorkflowsView.vue"), - meta: { - requiresDeveloperRole: true, - }, - }, - { - path: "reviewer/workflows", - name: "workflows-reviewer", - component: () => import("../views/workflows/ReviewWorkflowsView.vue"), - meta: { - requiresReviewerRole: true, - }, - }, - { - path: "workflows/arbitrary", - name: "arbitrary-workflow", - component: () => - import("../views/workflows/ArbitraryWorkflowView.vue"), - meta: { - requiresDeveloperRole: true, - }, - props: (route) => ({ - wid: route.query.wid, - }), - }, - { - path: "workflows/:workflowId", - name: "workflow", - component: () => import("../views/workflows/WorkflowView.vue"), - props: (route) => ({ - versionId: route.params.versionId ?? undefined, - workflowId: route.params.workflowId, - workflowModeId: route.query.workflowModeId ?? undefined, - developerView: route.query.developerView == "true" ?? false, - }), - children: [ - { - path: "version/:versionId", - name: "workflow-version", - component: () => - import("../views/workflows/WorkflowVersionView.vue"), - props: (route) => ({ - versionId: route.params.versionId, - workflowId: route.params.workflowId, - activeTab: route.query.tab ?? "description", - workflowModeId: route.query.workflowModeId ?? undefined, - }), - }, - { - path: "version/:versionId/start", - name: "workflow-start", - component: () => - import("../views/workflows/StartWorkflowView.vue"), - props: (route) => ({ - versionId: route.params.versionId, - workflowId: route.params.workflowId, - workflowModeId: route.query.workflowModeId ?? undefined, - }), - }, - ], - }, + ...resourceRoutes, + ...s3Routes, + ...workflowRoutes, + ...adminRoutes, ], }, { diff --git a/src/router/resourceRoutes.ts b/src/router/resourceRoutes.ts new file mode 100644 index 0000000000000000000000000000000000000000..69cd0cffc0282ff9dc6063bc6bd47e551bd50178 --- /dev/null +++ b/src/router/resourceRoutes.ts @@ -0,0 +1,25 @@ +import type { RouteRecordRaw } from "vue-router"; + +export const resourceRoutes: RouteRecordRaw[] = [ + { + path: "resources", + name: "resources", + component: () => import("../views/resources/ListResourcesView.vue"), + }, + { + path: "maintainer/resources", + name: "resource-maintainer", + component: () => import("../views/resources/MyResourcesView.vue"), + meta: { + requiresMaintainerRole: true, + }, + }, + { + path: "reviewer/resources", + name: "resource-review", + component: () => import("../views/resources/ReviewResourceView.vue"), + meta: { + requiresReviewerRole: true, + }, + }, +]; diff --git a/src/router/s3Routes.ts b/src/router/s3Routes.ts new file mode 100644 index 0000000000000000000000000000000000000000..30ff3e0799e723c28e0c9dc61d78ea3b503680cb --- /dev/null +++ b/src/router/s3Routes.ts @@ -0,0 +1,25 @@ +import type { RouteRecordRaw } from "vue-router"; + +export const s3Routes: RouteRecordRaw[] = [ + { + path: "object-storage/buckets", + name: "buckets", + component: () => import("../views/object-storage/BucketsView.vue"), + props: (route) => ({ + bucketName: route.params.bucketName ?? undefined, + }), + children: [ + { + path: ":bucketName/:subFolders*", + name: "bucket", + component: () => import("../views/object-storage/BucketView.vue"), + props: true, + }, + ], + }, + { + path: "object-storage/s3-keys", + name: "s3_keys", + component: () => import("../views/object-storage/S3KeysView.vue"), + }, +]; diff --git a/src/router/workflowRoutes.ts b/src/router/workflowRoutes.ts new file mode 100644 index 0000000000000000000000000000000000000000..9d53737130d2766e62b44667122b634c71713747 --- /dev/null +++ b/src/router/workflowRoutes.ts @@ -0,0 +1,76 @@ +import type { RouteRecordRaw } from "vue-router"; + +export const workflowRoutes: RouteRecordRaw[] = [ + { + path: "workflow-executions", + name: "workflow-executions", + component: () => + import("../views/workflows/ListWorkflowExecutionsView.vue"), + }, + { + path: "workflows", + name: "workflows", + component: () => import("../views/workflows/ListWorkflowsView.vue"), + }, + { + path: "developer/workflows", + name: "workflows-developer", + component: () => import("../views/workflows/MyWorkflowsView.vue"), + meta: { + requiresDeveloperRole: true, + }, + }, + { + path: "reviewer/workflows", + name: "workflows-reviewer", + component: () => import("../views/workflows/ReviewWorkflowsView.vue"), + meta: { + requiresReviewerRole: true, + }, + }, + { + path: "workflows/arbitrary", + name: "arbitrary-workflow", + component: () => import("../views/workflows/ArbitraryWorkflowView.vue"), + meta: { + requiresDeveloperRole: true, + }, + props: (route) => ({ + wid: route.query.wid, + }), + }, + { + path: "workflows/:workflowId", + name: "workflow", + component: () => import("../views/workflows/WorkflowView.vue"), + props: (route) => ({ + versionId: route.params.versionId ?? undefined, + workflowId: route.params.workflowId, + workflowModeId: route.query.workflowModeId ?? undefined, + developerView: route.query.developerView == "true", + }), + children: [ + { + path: "version/:versionId", + name: "workflow-version", + component: () => import("../views/workflows/WorkflowVersionView.vue"), + props: (route) => ({ + versionId: route.params.versionId, + workflowId: route.params.workflowId, + activeTab: route.query.tab ?? "description", + workflowModeId: route.query.workflowModeId ?? undefined, + }), + }, + { + path: "version/:versionId/start", + name: "workflow-start", + component: () => import("../views/workflows/StartWorkflowView.vue"), + props: (route) => ({ + versionId: route.params.versionId, + workflowId: route.params.workflowId, + workflowModeId: route.query.workflowModeId ?? undefined, + }), + }, + ], + }, +]; diff --git a/src/stores/names.ts b/src/stores/names.ts new file mode 100644 index 0000000000000000000000000000000000000000..e2b76aa70e58f926db013beb7b5f106950fd6cdd --- /dev/null +++ b/src/stores/names.ts @@ -0,0 +1,45 @@ +import { defineStore } from "pinia"; + +export const useNameStore = defineStore({ + id: "names", + state: () => + ({ + nameMapping: {}, + }) as { + nameMapping: Record<string, string>; + }, + getters: { + getName(): (objectID?: string) => string | undefined { + return (objectID) => { + if (objectID) { + return this.nameMapping[objectID] ?? localStorage.getItem(objectID); + } + return undefined; + }; + }, + }, + actions: { + addNameToMapping(objectId: string, objectName: string) { + this.nameMapping[objectId] = objectName; + localStorage.setItem(objectId, objectName); + }, + deleteNameFromMapping(objectId: string) { + delete this.nameMapping[objectId]; + localStorage.removeItem(objectId); + }, + loadNameMapping() { + if (Object.keys(this.nameMapping).length > 0) { + return; + } + for (let i = 0; i < localStorage.length; i++) { + const key = localStorage.key(i); + if (key != null) { + const value = localStorage.getItem(key); + if (value != null) { + this.nameMapping[key] = value; + } + } + } + }, + }, +}); diff --git a/src/stores/resources.ts b/src/stores/resources.ts new file mode 100644 index 0000000000000000000000000000000000000000..03f153a607db56a037c47928699ce8ca18dc643d --- /dev/null +++ b/src/stores/resources.ts @@ -0,0 +1,272 @@ +import { defineStore } from "pinia"; +import type { + ResourceIn, + ResourceOut, + ResourceVersionIn, + ResourceVersionOut, +} from "@/client/resource"; +import { + ResourceService, + ResourceVersionService, + Status, +} from "@/client/resource"; +import { useAuthStore } from "@/stores/users"; +import { useNameStore } from "@/stores/names"; + +export const useResourceStore = defineStore({ + id: "resources", + state: () => + ({ + resourceMapping: {}, + ownResourceMapping: {}, + reviewableResourceMapping: {}, + }) as { + resourceMapping: Record<string, ResourceOut>; + ownResourceMapping: Record<string, ResourceOut>; + reviewableResourceMapping: Record<string, ResourceOut>; + }, + getters: { + resources(): ResourceOut[] { + return Object.values(this.resourceMapping); + }, + ownResources(): ResourceOut[] { + return Object.values(this.ownResourceMapping); + }, + reviewableResources(): ResourceOut[] { + return Object.values(this.reviewableResourceMapping); + }, + }, + actions: { + fetchResource( + resource_id: string, + versionStatus?: Status[], + ): Promise<ResourceOut> { + return ResourceService.resourceGetResource( + resource_id, + versionStatus, + ).then((resource) => { + const nameStore = useNameStore(); + nameStore.addNameToMapping(resource.resource_id, resource.name); + for (const version of resource.versions) { + nameStore.addNameToMapping( + version.resource_version_id, + version.release, + ); + } + return resource; + }); + }, + fetchResources( + maintainerId?: string, + versionStatus?: Status[], + searchString?: string, + ): Promise<ResourceOut[]> { + return ResourceService.resourceListResources( + maintainerId, + versionStatus, + searchString, + ).then((resources) => { + const nameStore = useNameStore(); + for (const resource of resources) { + nameStore.addNameToMapping(resource.resource_id, resource.name); + for (const version of resource.versions) { + nameStore.addNameToMapping( + version.resource_version_id, + version.release, + ); + } + } + return resources; + }); + }, + fetchReviewableResources(onFinally?: () => void): Promise<ResourceOut[]> { + if (Object.keys(this.reviewableResourceMapping).length > 0) { + onFinally?.(); + } + return this.fetchResources(undefined, [ + Status.SYNC_REQUESTED, + Status.SYNCHRONIZING, + ]) + .then((resources) => { + const newMapping: Record<string, ResourceOut> = {}; + for (const resource of resources) { + newMapping[resource.resource_id] = resource; + } + this.reviewableResourceMapping = newMapping; + return resources; + }) + .finally(onFinally); + }, + fetchPublicResources(onFinally?: () => void): Promise<ResourceOut[]> { + if (this.resources.length > 0) { + onFinally?.(); + } + return this.fetchResources() + .then((resources) => { + const newMapping: Record<string, ResourceOut> = {}; + for (const resource of resources) { + newMapping[resource.resource_id] = resource; + } + this.resourceMapping = newMapping; + return resources; + }) + .finally(onFinally); + }, + fetchOwnResource( + resource_id: string, + onFinally?: () => void, + ): Promise<ResourceOut> { + if (this.ownResourceMapping[resource_id]) { + onFinally?.(); + } + return this.fetchResource(resource_id, Object.values(Status)) + .then((resource) => { + this.ownResourceMapping[resource.resource_id] = resource; + return resource; + }) + .finally(onFinally); + }, + fetchOwnResources(onFinally?: () => void): Promise<ResourceOut[]> { + const authStore = useAuthStore(); + if (this.ownResources.length > 0) { + onFinally?.(); + } + return this.fetchResources(authStore.currentUID, Object.values(Status)) + .then((resources) => { + const newMapping: Record<string, ResourceOut> = {}; + for (const resource of resources) { + newMapping[resource.resource_id] = resource; + } + this.ownResourceMapping = newMapping; + return resources; + }) + .finally(onFinally); + }, + async createResource(resource: ResourceIn): Promise<ResourceOut> { + const createdResource = + await ResourceService.resourceCreateResource(resource); + this.ownResourceMapping[createdResource.resource_id] = createdResource; + const nameStore = useNameStore(); + nameStore.addNameToMapping( + createdResource.resource_id, + createdResource.name, + ); + nameStore.addNameToMapping( + createdResource.versions[0].resource_version_id, + createdResource.versions[0].release, + ); + + return createdResource; + }, + requestSynchronization( + resourceVersion: ResourceVersionOut, + ): Promise<ResourceVersionOut> { + return ResourceVersionService.resourceVersionRequestResourceVersionSync( + resourceVersion.resource_id, + resourceVersion.resource_version_id, + ).then((changedResourceVersion) => { + if ( + this.ownResourceMapping[changedResourceVersion.resource_id] == + undefined + ) { + this.fetchOwnResource(resourceVersion.resource_id); + return changedResourceVersion; + } + const versionIndex = this.ownResourceMapping[ + changedResourceVersion.resource_id + ].versions.findIndex( + (version) => + version.resource_version_id == + changedResourceVersion.resource_version_id, + ); + if (versionIndex > -1) { + this.ownResourceMapping[changedResourceVersion.resource_id].versions[ + versionIndex + ] = changedResourceVersion; + } else { + this.ownResourceMapping[ + changedResourceVersion.resource_id + ].versions.push(changedResourceVersion); + } + return changedResourceVersion; + }); + }, + updateResource( + resource_id: string, + version: ResourceVersionIn, + ): Promise<ResourceVersionOut> { + return ResourceVersionService.resourceVersionRequestResourceVersion( + resource_id, + version, + ).then((versionOut) => { + if (this.ownResourceMapping[versionOut.resource_id] == undefined) { + this.fetchOwnResource(versionOut.resource_id); + return versionOut; + } + useNameStore().addNameToMapping( + versionOut.resource_version_id, + versionOut.release, + ); + this.ownResourceMapping[versionOut.resource_id].versions.push( + versionOut, + ); + return versionOut; + }); + }, + syncResource( + resourceVersion: ResourceVersionOut, + ): Promise<ResourceVersionOut> { + return ResourceVersionService.resourceVersionResourceVersionSync( + resourceVersion.resource_id, + resourceVersion.resource_version_id, + ).then((changedVersion) => { + if ( + this.reviewableResourceMapping[changedVersion.resource_id] == + undefined + ) { + return changedVersion; + } + const versionIndex = this.reviewableResourceMapping[ + changedVersion.resource_id + ].versions.findIndex( + (version) => + version.resource_version_id == changedVersion.resource_version_id, + ); + if (versionIndex > -1) { + this.reviewableResourceMapping[changedVersion.resource_id].versions[ + versionIndex + ] = changedVersion; + } else { + this.reviewableResourceMapping[ + changedVersion.resource_id + ].versions.push(changedVersion); + } + return changedVersion; + }); + }, + setLatestResource( + resourceVersion: ResourceVersionOut, + ): Promise<ResourceVersionOut> { + return ResourceVersionService.resourceVersionResourceVersionLatest( + resourceVersion.resource_id, + resourceVersion.resource_version_id, + ); + }, + deleteOnCluster( + resourceVersion: ResourceVersionOut, + ): Promise<ResourceVersionOut> { + return ResourceVersionService.resourceVersionDeleteResourceVersionCluster( + resourceVersion.resource_id, + resourceVersion.resource_version_id, + ); + }, + deleteInS3( + resourceVersion: ResourceVersionOut, + ): Promise<ResourceVersionOut> { + return ResourceVersionService.resourceVersionDeleteResourceVersionS3( + resourceVersion.resource_id, + resourceVersion.resource_version_id, + ); + }, + }, +}); diff --git a/src/stores/users.ts b/src/stores/users.ts index 37497e582784ef6f0fdebcdb2ce205aeb561dc10..928ed2956df6f5a9d322d219b329c4f0f1b59fe3 100644 --- a/src/stores/users.ts +++ b/src/stores/users.ts @@ -4,12 +4,14 @@ import { UserService, RoleEnum } from "@/client/auth"; import { OpenAPI as S3ProxyOpenAPI } from "@/client/s3proxy"; import { OpenAPI as AuthOpenAPI } from "@/client/auth"; import { OpenAPI as WorkflowOpenAPI } from "@/client/workflow"; +import { OpenAPI as ResourceOpenAPI } from "@/client/resource"; import { useWorkflowExecutionStore } from "@/stores/workflowExecutions"; import { useBucketStore } from "@/stores/buckets"; import { useWorkflowStore } from "@/stores/workflows"; import { useS3KeyStore } from "@/stores/s3keys"; import { useS3ObjectStore } from "@/stores/s3objects"; import { clear as dbclear } from "idb-keyval"; +import { useNameStore } from "@/stores/names"; type DecodedToken = { exp: number; @@ -22,7 +24,6 @@ export type RootState = { token: string | null; decodedToken: DecodedToken | null; user: User | null; - userMapping: Record<string, string>; }; function parseJwt(token: string): DecodedToken { @@ -48,7 +49,6 @@ export const useAuthStore = defineStore({ token: null, decodedToken: null, user: null, - userMapping: {}, }) as RootState, getters: { roles(): string[] { @@ -70,7 +70,7 @@ export const useAuthStore = defineStore({ state.user?.roles?.includes(RoleEnum.USER) ?? state.decodedToken?.roles.includes(RoleEnum.USER) ?? false, - workflowReviewer: (state) => + rewiewer: (state) => state.user?.roles?.includes(RoleEnum.REVIEWER) ?? state.decodedToken?.roles.includes(RoleEnum.REVIEWER) ?? false, @@ -78,6 +78,10 @@ export const useAuthStore = defineStore({ state.user?.roles?.includes(RoleEnum.DEVELOPER) ?? state.decodedToken?.roles.includes(RoleEnum.DEVELOPER) ?? false, + resourceMaintainer: (state) => + state.user?.roles?.includes(RoleEnum.DB_MAINTAINER) ?? + state.decodedToken?.roles.includes(RoleEnum.DB_MAINTAINER) ?? + false, admin: (state) => state.user?.roles?.includes(RoleEnum.ADMINISTRATOR) ?? state.decodedToken?.roles.includes(RoleEnum.ADMINISTRATOR) ?? @@ -91,6 +95,7 @@ export const useAuthStore = defineStore({ S3ProxyOpenAPI.TOKEN = token; AuthOpenAPI.TOKEN = token; WorkflowOpenAPI.TOKEN = token; + ResourceOpenAPI.TOKEN = token; UserService.userGetLoggedInUser() .then((user) => { this.updateUser(user); @@ -104,8 +109,13 @@ export const useAuthStore = defineStore({ }, updateUser(user: User) { this.user = user; + useNameStore().addNameToMapping(user.uid, user.display_name); }, logout() { + S3ProxyOpenAPI.TOKEN = undefined; + AuthOpenAPI.TOKEN = undefined; + WorkflowOpenAPI.TOKEN = undefined; + ResourceOpenAPI.TOKEN = undefined; this.$reset(); localStorage.clear(); dbclear(); @@ -115,15 +125,10 @@ export const useAuthStore = defineStore({ useS3KeyStore().$reset(); useS3ObjectStore().$reset(); }, - async addUidToNameMapping(mapping: Record<string, string>): Promise<void> { - for (const uid of Object.keys(mapping)) { - this.userMapping[uid] = mapping[uid]; - localStorage.setItem(uid, mapping[uid]); - } - }, async fetchUsernames(uids: string[]): Promise<string[]> { + const nameStore = useNameStore(); const filteredIds = uids - .filter((uid) => !this.userMapping[uid]) // filter already present UIDs + .filter((uid) => !nameStore.getName(uid)) // filter already present UIDs .filter( // filter unique UIDs (modeId, index, array) => @@ -131,7 +136,8 @@ export const useAuthStore = defineStore({ ); // If all uids are already in the store, then return them if (filteredIds.length === 0) { - return uids.map((uid) => this.userMapping[uid]); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return uids.map((uid) => nameStore.getName(uid)!); } const missingIds: string[] = []; const storedNames = filteredIds.map((uid) => localStorage.getItem(uid)); @@ -142,23 +148,19 @@ export const useAuthStore = defineStore({ missingIds.push(filteredIds[index]); } else { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this.userMapping[filteredIds[index]] = storedNames[index]!; + nameStore.addNameToMapping(filteredIds[index], storedNames[index]!); } } - // If all uids could be resolved from cache, return them - if (missingIds.length === 0) { - return uids.map((uid) => this.userMapping[uid]); - } // fetch missing users from backend const fetchedUsers = await Promise.all( missingIds.map((uid) => UserService.userGetUser(uid)), ); // Put users in store for (const user of fetchedUsers) { - this.userMapping[user.uid] = user.display_name; - localStorage.setItem(user.uid, user.display_name); + nameStore.addNameToMapping(user.uid, user.display_name); } - return uids.map((uid) => this.userMapping[uid]); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return uids.map((uid) => nameStore.getName(uid)!); }, }, }); diff --git a/src/stores/workflows.ts b/src/stores/workflows.ts index 6c7e04b3e2ba72d49ffed420cd41953e2a6e3b81..8b1bd2473e96e9b20d98fc0205edebe695a18af5 100644 --- a/src/stores/workflows.ts +++ b/src/stores/workflows.ts @@ -18,19 +18,17 @@ import { } from "@/client/workflow"; import { useAuthStore } from "@/stores/users"; import { set, get } from "idb-keyval"; +import { useNameStore } from "@/stores/names"; export const useWorkflowStore = defineStore({ id: "workflows", state: () => ({ workflowMapping: {}, - nameMapping: {}, comprehensiveWorkflowMapping: {}, modeMapping: {}, - modeNameMapping: {}, }) as { workflowMapping: Record<string, WorkflowOut>; - nameMapping: Record<string, string>; comprehensiveWorkflowMapping: Record<string, WorkflowOut>; modeMapping: Record<string, WorkflowModeOut>; }, @@ -61,18 +59,13 @@ export const useWorkflowStore = defineStore({ } return mapping; }, - getName(): (objectID: string) => string | undefined { - return (objectID) => - this.nameMapping[objectID] ?? localStorage.getItem(objectID); - }, getArbitraryWorkflow(): (wid: string) => Promise<WorkflowIn | undefined> { return (wid: string) => get(wid); }, }, actions: { __addNameToMapping(key: string, value: string) { - this.nameMapping[key] = value; - localStorage.setItem(key, value); + useNameStore().addNameToMapping(key, value); }, fetchWorkflows(onFinally?: () => void): Promise<WorkflowOut[]> { if (Object.keys(this.workflowMapping).length > 0) { @@ -300,8 +293,7 @@ export const useWorkflowStore = defineStore({ }, deleteWorkflow(workflow_id: string): Promise<void> { return WorkflowService.workflowDeleteWorkflow(workflow_id).then(() => { - delete this.nameMapping[workflow_id]; - localStorage.removeItem(workflow_id); + useNameStore().deleteNameFromMapping(workflow_id); delete this.workflowMapping[workflow_id]; delete this.comprehensiveWorkflowMapping[workflow_id]; }); diff --git a/src/views/LoginView.vue b/src/views/LoginView.vue index d9e1987acd5cf60c7093f05aee006c90f5fc6ffd..ef5a66c6935b0ac6055d59a3afe0c35d7d42b194 100644 --- a/src/views/LoginView.vue +++ b/src/views/LoginView.vue @@ -4,6 +4,7 @@ import { useAuthStore } from "@/stores/users"; import { useRouter, useRoute } from "vue-router"; import { OpenAPI as AuthOpenAPI } from "@/client/auth"; import { Toast } from "bootstrap"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const router = useRouter(); const route = useRoute(); @@ -29,35 +30,16 @@ onMounted(() => { </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-danger align-items-center border-0" - style="--bs-bg-opacity: 0.7" - data-bs-config="{'delay': 8000}" - data-bs-autohide="true" - id="loginErrorToast" - > - <div class="toast-header text-bg-danger"> - <strong class="me-auto">Login Error</strong> - <button - type="button" - class="btn-close btn-close-white" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - <div class="toast-body"> - <p> - There has been some kind of error during the login.<br /> - Please try again later. - </p> - <p>Error Code: {{ route.query.login_error }}</p> - </div> - </div> - </div> + <bootstrap-toast toast-id="loginErrorToast" color-class="danger"> + <template> Login Error </template> + <template #body> + <p> + There has been some kind of error during the login.<br /> + Please try again later. + </p> + <p>Error Code: {{ route.query.login_error }}</p> + </template> + </bootstrap-toast> <div class="position-fixed start-50 translate-middle-x text-center"> <img src="/src/assets/images/clowm.svg" diff --git a/src/views/admin/AdminResourcesView.vue b/src/views/admin/AdminResourcesView.vue new file mode 100644 index 0000000000000000000000000000000000000000..9ff663eced269ab6edb8468a8849e5c3a5eafb16 --- /dev/null +++ b/src/views/admin/AdminResourcesView.vue @@ -0,0 +1,351 @@ +<script setup lang="ts"> +import { useResourceStore } from "@/stores/resources"; +import { reactive } from "vue"; +import { + type ResourceOut, + type ResourceVersionOut, + Status, +} from "@/client/resource"; +import SearchUserModal from "@/components/modals/SearchUserModal.vue"; +import type { User } from "@/client/auth"; +import { useNameStore } from "@/stores/names"; +import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; +import dayjs from "dayjs"; +import ResourceVersionInfoModal from "@/components/resources/ResourceVersionInfoModal.vue"; + +const resourceRepository = useResourceStore(); +const nameRepository = useNameStore(); + +const resourceState = reactive<{ + loading: boolean; + resources: ResourceOut[]; + maintainerId: string; + searchString: string; + resourceStatus: Status[]; + inspectVersionIndex: number; + inspectResource?: ResourceOut; +}>({ + loading: false, + resources: [], + maintainerId: "", + searchString: "", + resourceStatus: [], + inspectVersionIndex: 0, + inspectResource: undefined, +}); + +function updateUser(user: User) { + resourceState.maintainerId = user.uid; +} + +function searchResources() { + resourceState.loading = true; + resourceRepository + .fetchResources( + resourceState.maintainerId ? resourceState.maintainerId : undefined, + resourceState.resourceStatus ? resourceState.resourceStatus : undefined, + resourceState.searchString ? resourceState.searchString : undefined, + ) + .then((resources) => { + resourceState.resources = resources; + }) + .finally(() => { + resourceState.loading = false; + }); +} + +function replaceResourceVersion( + resourceVersion: ResourceVersionOut, +): ResourceVersionOut { + const resourceIndex = resourceState.resources.findIndex( + (r) => r.resource_id == resourceVersion.resource_id, + ); + if (resourceIndex > -1) { + const versionIndex = resourceState.resources[ + resourceIndex + ].versions.findIndex( + (r) => r.resource_version_id == resourceVersion.resource_version_id, + ); + if (versionIndex > -1) { + resourceState.resources[resourceIndex].versions[versionIndex] = + resourceVersion; + } + } + return resourceVersion; +} + +function setLatest(resourceVersion: ResourceVersionOut) { + resourceState.loading = true; + resourceRepository + .setLatestResource(resourceVersion) + .then(replaceResourceVersion) + .finally(() => { + resourceState.loading = false; + }); +} + +function deleteOnCluster(resourceVersion: ResourceVersionOut) { + resourceState.loading = true; + resourceRepository + .deleteOnCluster(resourceVersion) + .then(replaceResourceVersion) + .finally(() => { + resourceState.loading = false; + }); +} + +function deleteInS3(resourceVersion: ResourceVersionOut) { + resourceState.loading = true; + resourceRepository + .deleteInS3(resourceVersion) + .then(replaceResourceVersion) + .finally(() => { + resourceState.loading = false; + }); +} + +function syncToCluster(resourceVersion: ResourceVersionOut) { + resourceState.loading = true; + resourceRepository + .syncResource(resourceVersion) + .then(replaceResourceVersion) + .finally(() => { + resourceState.loading = false; + }); +} + +function resetForm() { + resourceState.maintainerId = ""; + resourceState.searchString = ""; + resourceState.resourceStatus = []; + resourceState.resources = []; +} +</script> + +<template> + <search-user-modal + modal-id="admin-resource-search-user-modal" + @user-found="updateUser" + /> + <resource-version-info-modal + modal-id="admin-resource-version-info-modal" + :resource-version-index="resourceState.inspectVersionIndex" + :resource="resourceState.inspectResource" + /> + <div + class="row m-2 border-bottom mb-4 justify-content-between align-items-center" + > + <h2>Manage Resources</h2> + </div> + <form @submit.prevent="searchResources" id="admin-resource-search-form"> + <div class="d-flex justify-content-evenly align-content-center"> + <div class="mx-2"> + <label for="admin-resource-state-select" class="form-label" + >Status of Resource Versions</label + > + <select + v-model="resourceState.resourceStatus" + multiple + class="form-select mb-4 w-fit" + id="admin-resource-state-select" + > + <option v-for="state in Object.values(Status)" :key="state"> + {{ state }} + </option> + </select> + </div> + <div class="flex-fill mx-2"> + <label for="admin-resource-name-search" class="form-label" + >Name of the Resource</label + > + <div class="input-group"> + <input + id="admin-resource-name-search" + type="text" + class="form-control" + maxlength="32" + v-model="resourceState.searchString" + placeholder="Search for resource name" + /> + </div> + </div> + <div class="flex-fill mx-2"> + <label for="admin-resource-user-search" class="form-label" + >Name of the Maintainer</label + > + <div class="input-group"> + <div class="input-group-text"> + <font-awesome-icon icon="fa-solid fa-user" /> + </div> + <input + id="admin-resource-user-search" + type="text" + class="form-control" + readonly + :value="nameRepository.getName(resourceState.maintainerId)" + placeholder="Search for maintainer" + data-bs-toggle="modal" + data-bs-target="#admin-resource-search-user-modal" + /> + </div> + </div> + </div> + <button + type="submit" + class="btn btn-primary w-fit" + :disabled="resourceState.loading" + > + Search + </button> + <button + type="button" + class="btn-primary btn w-fit ms-4" + :disabled="resourceState.loading" + @click="resetForm" + > + Reset + </button> + </form> + <table class="table table-striped" v-if="resourceState.resources"> + <thead> + <tr> + <th scope="col"><b>Resource ID</b></th> + <th scope="col">Name</th> + <th scope="col">Source</th> + <th scope="col">Maintainer</th> + </tr> + </thead> + <tbody v-if="resourceState.resources.length === 0"> + <tr> + <td colspan="5" class="text-center fst-italic fw-light"> + Select a filter and search for Resources + </td> + </tr> + </tbody> + <tbody v-else> + <template + v-for="resource in resourceState.resources" + :key="resource.resource_id" + > + <tr> + <th scope="row">{{ resource.resource_id }}</th> + <td>{{ resource.name }}</td> + <td>{{ resource.source }}</td> + <td>{{ nameRepository.getName(resource.maintainer_id) }}</td> + </tr> + <tr> + <td colspan="5"> + <table class="table mb-0 table-hover"> + <thead> + <tr> + <th scope="col"><b>Version ID</b></th> + <th scope="col">Release</th> + <th scope="col">Created At</th> + <th scope="col">State</th> + <th scope="col" class="text-end">Action</th> + </tr> + </thead> + <tbody> + <tr + v-for="(version, index) in resource.versions" + :key="version.resource_version_id" + > + <th scope="row">{{ version.resource_version_id }}</th> + <th>{{ version.release }}</th> + <th> + {{ + dayjs + .unix(version.created_at) + .format("DD.MM.YYYY HH:mm:ss") + }} + </th> + <th>{{ version.status }}</th> + <th class="text-end"> + <div class="btn-group"> + <button + type="button" + class="btn btn-secondary" + data-bs-toggle="modal" + data-bs-target="#admin-resource-version-info-modal" + @click=" + resourceState.inspectResource = resource; + resourceState.inspectVersionIndex = index; + " + > + Inspect + </button> + <button + type="button" + class="btn btn-secondary dropdown-toggle dropdown-toggle-split" + data-bs-toggle="dropdown" + aria-expanded="false" + :disabled="resourceState.loading" + > + <span class="visually-hidden">Toggle Dropdown</span> + </button> + <ul class="dropdown-menu"> + <li v-if="version.status === Status.SYNCHRONIZED"> + <button + class="dropdown-item" + type="button" + @click="setLatest(version)" + > + Set to Latest + </button> + </li> + <li + v-if=" + version.status === Status.CLUSTER_DELETED || + version.status === Status.SYNC_REQUESTED + " + > + <button + class="dropdown-item" + type="button" + @click="syncToCluster(version)" + > + <font-awesome-icon + icon="fa-solid fa-cloud-arrow-down" + /> + <span class="ms-1">Sync to Cluster</span> + </button> + </li> + <li + v-if=" + version.status === Status.SYNCHRONIZED || + version.status === Status.LATEST + " + > + <button + class="dropdown-item text-danger align-middle" + type="button" + @click="deleteOnCluster(version)" + > + <font-awesome-icon icon="fa-solid fa-trash" /> + <span class="ms-1">Delete on Cluster</span> + </button> + </li> + <li v-if="version.status === Status.CLUSTER_DELETED"> + <button + class="dropdown-item text-danger align-middle" + type="button" + @click="deleteInS3(version)" + > + <font-awesome-icon icon="fa-solid fa-trash" /> + <span class="ms-1">Delete in S3</span> + </button> + </li> + </ul> + </div> + </th> + </tr> + </tbody> + </table> + </td> + </tr> + </template> + </tbody> + </table> +</template> + +<style scoped></style> diff --git a/src/views/object-storage/BucketView.vue b/src/views/object-storage/BucketView.vue index b3bd3768dc2e75d1d7607400d5a777f9487cc8eb..9f43cbc44fa1de1ed93971a2d578161526b85e18 100644 --- a/src/views/object-storage/BucketView.vue +++ b/src/views/object-storage/BucketView.vue @@ -21,6 +21,7 @@ import { useAuthStore } from "@/stores/users"; import { useBucketStore } from "@/stores/buckets"; import { useS3ObjectStore } from "@/stores/s3objects"; import { useS3KeyStore } from "@/stores/s3keys"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const authStore = useAuthStore(); const bucketRepository = useBucketStore(); @@ -420,28 +421,9 @@ function getObjectFileName(key: string): string { </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-success align-items-center border-0" - data-bs-autohide="true" - :id="'successToast-' + randomIDSuffix" - > - <div class="d-flex"> - <div class="toast-body"> - Successfully deleted {{ deleteObjectsState.deletedItem }} - </div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast :toast-id="'successToast-' + randomIDSuffix"> + Successfully deleted {{ deleteObjectsState.deletedItem }} + </bootstrap-toast> <DeleteModal modalID="delete-object-modal" :object-name-delete="deleteObjectsState.potentialObjectToDelete" diff --git a/src/views/object-storage/S3KeysView.vue b/src/views/object-storage/S3KeysView.vue index 12218064e3e4ca66cc8c1d832b4fcf47033cf9cd..1735cdb1c8d1a67448ea932770c6c5eac42fa6d2 100644 --- a/src/views/object-storage/S3KeysView.vue +++ b/src/views/object-storage/S3KeysView.vue @@ -5,6 +5,7 @@ import { reactive, onMounted, computed } from "vue"; import { useAuthStore } from "@/stores/users"; import { Toast, Tooltip } from "bootstrap"; import { useS3KeyStore } from "@/stores/s3keys"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const authStore = useAuthStore(); const keyRepository = useS3KeyStore(); @@ -76,28 +77,9 @@ onMounted(() => { </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-success align-items-center border-0" - data-bs-autohide="true" - :id="'successKeyToast'" - > - <div class="d-flex"> - <div class="toast-body"> - Successfully deleted S3 Key {{ keyState.deletedKey.slice(0, 5) }}... - </div> - <button - type="button" - class="btn-close btn-close-white me-2 m-auto" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast toast-id="successKeyToast"> + Successfully deleted S3 Key {{ keyState.deletedKey.slice(0, 5) }}... + </bootstrap-toast> <div class="row m-2 border-bottom mt-4"> <div class="col-12"></div> <h2 class="mb-2">S3 Keys</h2> diff --git a/src/views/resources/ListResourcesView.vue b/src/views/resources/ListResourcesView.vue new file mode 100644 index 0000000000000000000000000000000000000000..b615344d6aadb6e6602fd47a984953b9f3e6e8b7 --- /dev/null +++ b/src/views/resources/ListResourcesView.vue @@ -0,0 +1,149 @@ +<script setup lang="ts"> +import { computed, onMounted, reactive } from "vue"; +import { useResourceStore } from "@/stores/resources"; +import ResourceCard from "@/components/resources/ResourceCard.vue"; +import CardTransitionGroup from "@/components/transitions/CardTransitionGroup.vue"; +import { useAuthStore } from "@/stores/users"; +import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; +import type { ResourceOut } from "@/client/resource"; + +const resourceRepository = useResourceStore(); +const userRepository = useAuthStore(); + +const resourceState = reactive<{ + loading: boolean; + filterString: string; + sortDesc: boolean; +}>({ + loading: true, + filterString: "", + sortDesc: true, +}); + +const sortedResourcesByName = computed<ResourceOut[]>(() => { + return [...resourceRepository.resources].sort((a, b) => + a.name < b.name ? 1 : -1, + ); +}); + +const sortedResources = computed<ResourceOut[]>(() => { + if (resourceState.sortDesc) { + return [...sortedResourcesByName.value].reverse(); + } + return sortedResourcesByName.value; +}); + +const filteredSortedResources = computed<ResourceOut[]>(() => { + return sortedResources.value.filter((resource) => { + return resourceState.filterString.length > 0 + ? resource.name.includes(resourceState.filterString) + : true; + }); +}); + +onMounted(() => { + resourceRepository + .fetchPublicResources(() => { + resourceState.loading = false; + }) + .then((resources) => { + userRepository.fetchUsernames(resources.map((r) => r.maintainer_id)); + }); +}); +</script> + +<template> + <div class="row m-2 border-bottom mb-4"> + <h2 class="mb-2">Available Resources</h2> + </div> + <div class="d-flex m-2 mb-3 align-items-center justify-content-start"> + <div class="col-5"> + <div class="input-group rounded shadow-sm"> + <span class="input-group-text" id="resources-search-wrapping" + ><font-awesome-icon icon="fa-solid fa-magnifying-glass" + /></span> + <input + type="text" + id="filterResourcesInput" + class="form-control" + placeholder="Filter Resources" + aria-label="Filter Resources" + aria-describedby="resources-search-wrapping" + :disabled="resourceState.loading" + v-model.trim="resourceState.filterString" + maxlength="20" + /> + </div> + </div> + <font-awesome-icon + :icon=" + resourceState.sortDesc + ? 'fa-solid fa-arrow-down-wide-short' + : 'fa-solid fa-arrow-up-wide-short' + " + @click="resourceState.sortDesc = !resourceState.sortDesc" + class="fs-5 ms-3 cursor-pointer" + /> + </div> + <div v-if="!resourceState.loading"> + <div + v-if="resourceRepository.resources.length === 0" + class="text-center fs-2 mt-5" + > + <font-awesome-icon + icon="fa-solid fa-x" + class="my-5 fs-0" + style="color: var(--bs-secondary)" + /> + <p>There are no resources in the system. Please come again later.</p> + </div> + <div + v-else-if="filteredSortedResources.length === 0" + class="text-center fs-2 mt-5" + > + <font-awesome-icon + icon="fa-solid fa-magnifying-glass" + class="my-5 fs-0" + style="color: var(--bs-secondary)" + /> + <p> + Could not find any Resources containing<br />'{{ + resourceState.filterString + }}' + </p> + </div> + <CardTransitionGroup + v-else + class="d-flex flex-wrap align-items-center justify-content-between" + > + <resource-card + v-for="resource in filteredSortedResources" + :key="resource.resource_id" + :resource="resource" + :loading="false" + style="min-width: 48%" + /> + </CardTransitionGroup> + </div> + <div + v-else + class="d-flex flex-wrap align-items-center justify-content-between" + > + <resource-card + v-for="resource in 4" + :key="resource" + :resource="{ + name: '', + description: '', + source: '', + resource_id: '', + versions: [], + maintainer_id: '', + }" + style="min-width: 48%" + loading + /> + </div> +</template> + +<style scoped></style> diff --git a/src/views/resources/MyResourcesView.vue b/src/views/resources/MyResourcesView.vue new file mode 100644 index 0000000000000000000000000000000000000000..e9a3d231e44cd6288bf83e748d2dfe9b7bf37a61 --- /dev/null +++ b/src/views/resources/MyResourcesView.vue @@ -0,0 +1,137 @@ +<script setup lang="ts"> +import { onMounted, reactive } from "vue"; +import { useResourceStore } from "@/stores/resources"; +import CardTransitionGroup from "@/components/transitions/CardTransitionGroup.vue"; +import ResourceCard from "@/components/resources/ResourceCard.vue"; +import CreateResourceModal from "@/components/resources/modals/CreateResourceModal.vue"; +import UploadResourceInfoModal from "@/components/resources/modals/UploadResourceInfoModal.vue"; +import { useS3KeyStore } from "@/stores/s3keys"; +import type { ResourceVersionOut, ResourceOut } from "@/client/resource"; +import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; +import UpdateResourceModal from "@/components/resources/modals/UpdateResourceModal.vue"; + +const resourceRepository = useResourceStore(); +const s3KeyRepository = useS3KeyStore(); + +const resourceState = reactive<{ + loading: boolean; + resourceVersionInfo?: ResourceVersionOut; + updateResource: ResourceOut; +}>({ + loading: true, + resourceVersionInfo: undefined, + updateResource: { + name: "", + description: "", + source: "", + resource_id: "", + versions: [], + maintainer_id: "", + }, +}); + +function setResourceVersionInfo(resourceVersionInfo?: ResourceVersionOut) { + resourceState.resourceVersionInfo = resourceVersionInfo; +} + +function setResourceUpdate(resource: ResourceOut) { + resourceState.updateResource = resource; +} + +onMounted(() => { + let fetchedResources = false; + s3KeyRepository.fetchS3Keys(() => { + if (!fetchedResources) { + fetchedResources = true; + resourceRepository.fetchOwnResources(() => { + resourceState.loading = false; + }); + } + }); +}); +</script> + +<template> + <create-resource-modal modal-i-d="createResourceModal" /> + <upload-resource-info-modal + modal-id="uploadResourceInfoModal" + :resource-version="resourceState.resourceVersionInfo" + /> + <update-resource-modal + :resource="resourceState.updateResource" + modal-id="updateResourceModal" + /> + <div + class="row m-2 border-bottom mb-4 justify-content-between align-items-center pb-2" + > + <h2 class="w-fit">My Resources</h2> + <div class="w-fit"> + <button + type="button" + class="btn btn-info btn-lg w-fit me-3" + data-bs-toggle="modal" + data-bs-target="#uploadResourceInfoModal" + @click="setResourceVersionInfo(undefined)" + > + Tutorial + </button> + <button + class="btn btn-lg btn-primary w-fit" + data-bs-toggle="modal" + data-bs-target="#createResourceModal" + > + Create Resource + </button> + </div> + </div> + <div v-if="!resourceState.loading"> + <div + v-if="resourceRepository.ownResources.length === 0" + class="text-center fs-2 mt-5" + > + <font-awesome-icon + icon="fa-solid fa-x" + class="my-5 fs-0" + style="color: var(--bs-secondary)" + /> + <p>You don't have any resources registered in the system.</p> + </div> + <CardTransitionGroup + v-else + class="d-flex flex-wrap align-items-center justify-content-between" + > + <resource-card + v-for="resource in resourceRepository.ownResources" + :key="resource.resource_id" + :resource="resource" + :loading="false" + style="width: 48%" + extended + @click-info="setResourceVersionInfo" + @click-update="setResourceUpdate" + /> + </CardTransitionGroup> + </div> + <div + v-else + class="d-flex flex-wrap align-items-center justify-content-between" + > + <resource-card + v-for="resource in 4" + :key="resource" + :resource="{ + name: '', + description: '', + source: '', + resource_id: '', + versions: [], + maintainer_id: '', + }" + style="min-width: 48%" + loading + extended + /> + </div> +</template> + +<style scoped></style> diff --git a/src/views/resources/ReviewResourceView.vue b/src/views/resources/ReviewResourceView.vue new file mode 100644 index 0000000000000000000000000000000000000000..4e9a33a08a34f0fe619d57d0e1ca129f19e75d14 --- /dev/null +++ b/src/views/resources/ReviewResourceView.vue @@ -0,0 +1,186 @@ +<script setup lang="ts"> +import { useResourceStore } from "@/stores/resources"; +import { computed, onMounted, reactive } from "vue"; +import { + type ResourceOut, + type ResourceVersionOut, + Status, +} from "@/client/resource"; +import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; +import { Tooltip } from "bootstrap"; +import ResourceVersionInfoModal from "@/components/resources/ResourceVersionInfoModal.vue"; +import { useNameStore } from "@/stores/names"; + +const resourceRepository = useResourceStore(); +const nameRepository = useNameStore(); +let refreshTimeout: NodeJS.Timeout | undefined = undefined; + +const resourceState = reactive<{ + sendingRequest: boolean; + loading: boolean; + inspectResource?: ResourceOut; + inspectVersionIndex: number; +}>({ + sendingRequest: false, + loading: true, + inspectResource: undefined, + inspectVersionIndex: 0, +}); + +const countItems = computed<number>(() => + resourceRepository.reviewableResources.reduce( + (previousValue, currentValue) => + previousValue + currentValue.versions.length, + 0, + ), +); + +function fetchResources() { + resourceRepository.fetchReviewableResources(() => { + resourceState.loading = false; + }); +} + +function clickRefreshResources() { + clearTimeout(refreshTimeout); + refreshTimeout = setTimeout(() => { + fetchResources(); + }, 500); +} + +function syncResource(resourceVersion: ResourceVersionOut) { + resourceState.sendingRequest = true; + resourceRepository.syncResource(resourceVersion).finally(() => { + resourceState.sendingRequest = false; + }); +} + +onMounted(() => { + fetchResources(); + new Tooltip("#refreshReviewableResourcesButton"); +}); +</script> + +<template> + <resource-version-info-modal + modal-id="review-resource-version-info-modal" + :resource-version-index="resourceState.inspectVersionIndex" + :resource="resourceState.inspectResource" + /> + <div + class="row m-2 border-bottom mb-4 justify-content-between align-items-center" + > + <h2 class="w-fit">Resource Requests</h2> + <span + class="w-fit" + tabindex="0" + data-bs-title="Refresh Reviewable Resources" + data-bs-toggle="tooltip" + id="refreshReviewableResourcesButton" + > + <button + type="button" + class="btn btn-primary btn-light me-2 shadow-sm border w-fit" + :disabled="resourceState.loading" + @click="clickRefreshResources" + > + <font-awesome-icon icon="fa-solid fa-arrow-rotate-right" /> + <span class="visually-hidden">Refresh Reviewable Resources</span> + </button> + </span> + </div> + <div v-if="resourceState.loading" class="text-center mt-5"> + <div class="spinner-border" style="width: 3rem; height: 3rem" role="status"> + <span class="visually-hidden">Loading...</span> + </div> + </div> + <table + class="table caption-top table-striped table-hover align-middle" + v-else-if="resourceRepository.reviewableResources.length > 0" + > + <caption> + Display + {{ + countItems + }} + resource versions + </caption> + <thead> + <tr> + <th scope="col">Resource</th> + <th scope="col">Release</th> + <th scope="col">Status</th> + <th scope="col">Maintainer</th> + <th scope="col"></th> + <th scope="col" class="text-end">Action</th> + </tr> + </thead> + <tbody> + <template + v-for="resource in resourceRepository.reviewableResources" + :key="resource.resource_id" + > + <tr + v-for="(version, index) in resource.versions" + :key="version.resource_version_id" + > + <th>{{ resource.name }}</th> + <th>{{ version.release }}</th> + <th>{{ version.status }}</th> + <th>{{ nameRepository.getName(resource.maintainer_id) }}</th> + <th> + <button + type="button" + class="btn btn-secondary" + data-bs-toggle="modal" + data-bs-target="#review-resource-version-info-modal" + @click=" + resourceState.inspectResource = resource; + resourceState.inspectVersionIndex = index; + " + > + Inspect + </button> + </th> + <th class="text-end"> + <div + v-if="version.status === Status.SYNC_REQUESTED" + class="btn-group" + > + <button + type="button" + class="btn btn-success btn-sm" + :disabled="resourceState.sendingRequest" + @click="syncResource(version)" + > + Synchronize + </button> + <button type="button" class="btn btn-danger btn-sm" disabled> + Deny + </button> + </div> + <div + v-else-if="version.status === Status.SYNCHRONIZING" + class="progress" + role="progressbar" + aria-label="Animated striped example" + aria-valuenow="100" + aria-valuemin="0" + aria-valuemax="100" + > + <div + class="progress-bar progress-bar-striped progress-bar-animated" + style="width: 100%" + ></div> + </div> + </th> + </tr> + </template> + </tbody> + </table> + <div v-else class="text-center mt-5 fs-4"> + There are currently no Resources to review + </div> +</template> + +<style scoped></style> diff --git a/src/views/workflows/ArbitraryWorkflowView.vue b/src/views/workflows/ArbitraryWorkflowView.vue index faedb73a65de83a07412979247856226b7bfd29b..e31a3389eae4d7f2eeb571fb7202f47dc1d59e3b 100644 --- a/src/views/workflows/ArbitraryWorkflowView.vue +++ b/src/views/workflows/ArbitraryWorkflowView.vue @@ -10,6 +10,7 @@ import { useWorkflowStore } from "@/stores/workflows"; import type { WorkflowIn } from "@/client/workflow"; import { useWorkflowExecutionStore } from "@/stores/workflowExecutions"; import ParameterSchemaFormComponent from "@/components/parameter-schema/ParameterSchemaFormComponent.vue"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const props = defineProps<{ wid: string; @@ -148,34 +149,21 @@ onMounted(() => { </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-danger align-items-center border-0" - data-bs-autohide="true" - id="arbitraryWorkflowExecutionViewErrorToast" - > - <div class="d-flex p-2 justify-content-between align-items-center"> - <div class="toast-body"> - <template v-if="workflowExecutionState.errorType === 'limit'"> - You have too many active workflow executions to start a new one. - </template> - <template v-else> - There was an error with starting the workflow execution. Look in the - console for more information. - </template> - </div> - <button - type="button" - class="btn-close btn-close-white" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast + toast-id="arbitraryWorkflowExecutionViewErrorToast" + color-class="danger" + > + <template> Error starting workflow </template> + <template #body> + <template v-if="workflowExecutionState.errorType === 'limit'"> + You have too many active workflow executions to start a new one. + </template> + <template v-else> + There was an error with starting the workflow execution. Look in the + console for more information. + </template> + </template> + </bootstrap-toast> <template v-if="workflowState.workflow"> <div class="row m-1 border-bottom mb-4"> <h1 class="mb-2">Arbitrary Workflow</h1> diff --git a/src/views/workflows/ListWorkflowExecutionsView.vue b/src/views/workflows/ListWorkflowExecutionsView.vue index cbf7b1f06fd45f9af5a399a853ea5a78e7f20db7..c3d87aa57e68ecc94186a639712d8e0cd45dd492 100644 --- a/src/views/workflows/ListWorkflowExecutionsView.vue +++ b/src/views/workflows/ListWorkflowExecutionsView.vue @@ -9,8 +9,10 @@ import { useWorkflowStore } from "@/stores/workflows"; import { useWorkflowExecutionStore } from "@/stores/workflowExecutions"; import ParameterModal from "@/components/workflows/modals/ParameterModal.vue"; import { ExponentialBackoff } from "@/utils/BackoffStrategy"; +import { useNameStore } from "@/stores/names"; const workflowRepository = useWorkflowStore(); +const nameRepository = useNameStore(); const executionRepository = useWorkflowExecutionStore(); const backoff = new ExponentialBackoff(); @@ -247,8 +249,8 @@ onUnmounted(() => { }, }" > - {{ workflowRepository.getName(execution.workflow_id) }}@{{ - workflowRepository.getName(execution.workflow_version_id) + {{ nameRepository.getName(execution.workflow_id) }}@{{ + nameRepository.getName(execution.workflow_version_id) }} </router-link> </td> diff --git a/src/views/workflows/ReviewWorkflowsView.vue b/src/views/workflows/ReviewWorkflowsView.vue index 63ed00942e6f2e04d7c57e76b4a3544de0e07dcd..80baa8d935ffa8908b784ec04f58f0e3aa024681 100644 --- a/src/views/workflows/ReviewWorkflowsView.vue +++ b/src/views/workflows/ReviewWorkflowsView.vue @@ -6,8 +6,10 @@ import { determineGitIcon } from "@/utils/GitRepository"; import { sortedVersions } from "@/utils/Workflow"; import { useWorkflowStore } from "@/stores/workflows"; import { useAuthStore } from "@/stores/users"; +import { useNameStore } from "@/stores/names"; const workflowRepository = useWorkflowStore(); +const nameRepository = useNameStore(); const userRepository = useAuthStore(); const workflowsState = reactive<{ @@ -78,8 +80,8 @@ onMounted(() => { {{ workflow.repository_url }} </a> </td> - <td v-if="userRepository.userMapping[workflow.developer_id]"> - {{ userRepository.userMapping[workflow.developer_id] }} + <td v-if="nameRepository.getName(workflow.developer_id)"> + {{ nameRepository.getName(workflow.developer_id) }} </td> <td v-else class="placeholder-glow"> <div class="placeholder w-75"></div> diff --git a/src/views/workflows/StartWorkflowView.vue b/src/views/workflows/StartWorkflowView.vue index a8d84cb7da764c53a97ec862daf979d21b76a14a..d215cdaf972649ad24c42ec59b836ee2a495e640 100644 --- a/src/views/workflows/StartWorkflowView.vue +++ b/src/views/workflows/StartWorkflowView.vue @@ -10,6 +10,7 @@ import { onMounted, ref, reactive, watch } from "vue"; import { useRouter } from "vue-router"; import { Toast } from "bootstrap"; import { useWorkflowExecutionStore } from "@/stores/workflowExecutions"; +import BootstrapToast from "@/components/BootstrapToast.vue"; const executionRepository = useWorkflowExecutionStore(); const props = defineProps<{ @@ -108,34 +109,21 @@ onMounted(() => { </script> <template> - <div class="toast-container position-fixed top-toast end-0 p-3"> - <div - role="alert" - aria-live="assertive" - aria-atomic="true" - class="toast text-bg-danger align-items-center border-0" - data-bs-autohide="true" - id="workflowExecutionViewErrorToast" - > - <div class="d-flex p-2 justify-content-between align-items-center"> - <div class="toast-body"> - <template v-if="versionState.workflowExecutionError === 'limit'"> - You have too many active workflow executions to start a new one. - </template> - <template v-else> - There was an error with starting the workflow execution. Look in the - console for more information. - </template> - </div> - <button - type="button" - class="btn-close btn-close-white" - data-bs-dismiss="toast" - aria-label="Close" - ></button> - </div> - </div> - </div> + <bootstrap-toast + toast-id="workflowExecutionViewErrorToast" + color-class="danger" + > + <template>Error starting workflow</template> + <template #body> + <template v-if="versionState.workflowExecutionError === 'limit'"> + You have too many active workflow executions to start a new one. + </template> + <template v-else> + There was an error with starting the workflow execution. Look in the + console for more information. + </template> + </template> + </bootstrap-toast> <parameter-schema-form-component :workflow-version-id="versionId" :schema="parameterSchema" diff --git a/src/views/workflows/WorkflowView.vue b/src/views/workflows/WorkflowView.vue index 2ece0235006271559b4ecc77ba7946f48e5f0a49..08b1395de3189580cd1bc72484199c14f109f38f 100644 --- a/src/views/workflows/WorkflowView.vue +++ b/src/views/workflows/WorkflowView.vue @@ -157,7 +157,7 @@ const activeVersionIcon = computed<string | undefined>( ); const versionLaunchable = computed<boolean>( - () => activeVersion.value?.status == Status.PUBLISHED ?? false, + () => activeVersion.value?.status == Status.PUBLISHED, ); const gitIcon = computed<string>(() => @@ -166,7 +166,7 @@ const gitIcon = computed<string>(() => const allowVersionDeprecation = computed<boolean>(() => { if (activeVersion.value?.status === Status.PUBLISHED) { - if (userRepository.workflowReviewer || userRepository.admin) { + if (userRepository.rewiewer || userRepository.admin) { return true; } else if ( userRepository.workflowDev &&