From f8035c11c2642894d568a687731734565be95515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20G=C3=B6bel?= <dgoebel@techfak.uni-bielefeld.de> Date: Wed, 13 Nov 2024 15:45:02 +0000 Subject: [PATCH] Support anyOf and newer drafts of JSON schema in parameter form * Update to node 22 #164 --- .gitlab-ci.yml | 2 +- Dockerfile | 2 +- package-lock.json | 451 ++++++++-------- package.json | 10 +- src/assets/main.css | 4 + .../ParameterSchemaFormComponent.vue | 23 +- .../form-mode/ParameterBooleanInput.vue | 48 +- .../form-mode/ParameterEnumInput.vue | 2 + .../form-mode/ParameterFileInput.vue | 3 + .../form-mode/ParameterGroupForm.vue | 272 ++++++++-- .../form-mode/ParameterInput.vue | 12 + .../form-mode/ParameterMappingInput.vue | 2 + .../form-mode/ParameterNumberInput.vue | 2 + .../form-mode/ParameterResourceInput.vue | 9 +- .../form-mode/ParameterStringInput.vue | 2 + .../workflows/modals/CreateWorkflowModal.vue | 1 + src/utils/md5.d.ts | 7 + src/utils/md5.js | 498 ++++++++++++++++++ tsconfig.json | 2 +- 19 files changed, 1059 insertions(+), 293 deletions(-) create mode 100644 src/utils/md5.d.ts create mode 100644 src/utils/md5.js diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 411cd34..d14f478 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/node:20 +image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/node:22 cache: paths: - node_modules diff --git a/Dockerfile b/Dockerfile index 9232a56..4d2e598 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # build stage -FROM node:20 AS build-stage +FROM node:22 AS build-stage WORKDIR /app COPY package.json ./ COPY package-lock.json ./ diff --git a/package-lock.json b/package-lock.json index 910946d..2829002 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "chart.js": "~4.4.0", "chartjs-plugin-zoom": "~2.0.1", "dayjs": "~1.11.0", - "dompurify": "~3.1.0", + "dompurify": "~3.2.0", "filesize": "~10.1.0", "idb-keyval": "^6.2.1", "pinia": "~2.2.0", @@ -37,7 +37,7 @@ "@eslint/compat": "^1.2.0", "@hey-api/openapi-ts": "^0.55.0", "@rushstack/eslint-patch": "~1.10.0", - "@tsconfig/node20": "^20.1.2", + "@tsconfig/node22": "^22.0.0", "@types/bootstrap": "~5.2.0", "@types/dompurify": "~3.0.0", "@types/node": "^20.11.0", @@ -45,12 +45,12 @@ "@types/semver": "~7.5.1", "@types/showdown": "~2.0.1", "@types/sortablejs": "^1.15.7", - "@vitejs/plugin-vue": "~5.1.0", + "@vitejs/plugin-vue": "~5.2.0", "@vue/eslint-config-prettier": "~10.1.0", "@vue/eslint-config-typescript": "~14.1.0", - "@vue/tsconfig": "~0.5.0", + "@vue/tsconfig": "~0.6.0", "eslint": "~9.12.0", - "eslint-plugin-vue": "~9.30.0", + "eslint-plugin-vue": "~9.31.0", "highlight.js": "^11.9.0", "npm-run-all": "~4.1.5", "prettier": "~3.3.0", @@ -282,9 +282,9 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.687.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.687.0.tgz", - "integrity": "sha512-2IoaVAd7HCIDhfeTTrk8CAosEVqnQig47Tra2uOBEyzpcCFQLmcY57/sbHCpJ3ntnU8see53q0bQ+fdew4MGLA==", + "version": "3.689.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.689.0.tgz", + "integrity": "sha512-qYD1GJEPeLM6H3x8BuAAMXZltvVce5vGiwtZc9uMkBBo3HyFnmPitIPTPfaD1q8LOn/7KFdkY4MJ4e8D3YpV9g==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", @@ -296,7 +296,7 @@ "@aws-sdk/credential-provider-node": "3.687.0", "@aws-sdk/middleware-bucket-endpoint": "3.686.0", "@aws-sdk/middleware-expect-continue": "3.686.0", - "@aws-sdk/middleware-flexible-checksums": "3.687.0", + "@aws-sdk/middleware-flexible-checksums": "3.689.0", "@aws-sdk/middleware-host-header": "3.686.0", "@aws-sdk/middleware-location-constraint": "3.686.0", "@aws-sdk/middleware-logger": "3.686.0", @@ -667,9 +667,9 @@ } }, "node_modules/@aws-sdk/lib-storage": { - "version": "3.687.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.687.0.tgz", - "integrity": "sha512-LAJOH1Ddm8vlA6j8WyFAt1Ithfj58XuJN1d2WJSDZLhGDGQp3+nDFzovOKODw/Bc9x6ZnDYm9rE+QMTbGSvqkA==", + "version": "3.689.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.689.0.tgz", + "integrity": "sha512-5onxtoSunbrTIt5bttlEAF92A7OJfYDL1+qTEMxdyvLXzOENp3WElXVpKKPeqowuOffABT9ZcoTo/0aHOdZ81w==", "license": "Apache-2.0", "dependencies": { "@smithy/abort-controller": "^3.1.5", @@ -684,7 +684,7 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-s3": "^3.687.0" + "@aws-sdk/client-s3": "^3.689.0" } }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { @@ -721,13 +721,14 @@ } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.687.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.687.0.tgz", - "integrity": "sha512-hsEr3eiJs7gOzj9nDMCMfhLkoYv4Z8m7fbic63TkeyimXvsHycqqF6PX0TkPykwa1ueyxVpz0vtO5u1rlucN2w==", + "version": "3.689.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.689.0.tgz", + "integrity": "sha512-6VxMOf3mgmAgg6SMagwKj5pAe+putcx2F2odOAWviLcobFpdM/xK9vNry7p6kY+RDNmSlBvcji9wnU59fjV74Q==", "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", + "@aws-crypto/util": "5.2.0", "@aws-sdk/core": "3.686.0", "@aws-sdk/types": "3.686.0", "@smithy/is-array-buffer": "^3.0.0", @@ -876,9 +877,9 @@ } }, "node_modules/@aws-sdk/s3-request-presigner": { - "version": "3.687.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.687.0.tgz", - "integrity": "sha512-/fX3F4nYjVEgdlVamsb2tDgnFA5dtzxkeN+hH91e+ZoBMJBow+FUb2EEtjloreGUynPx6E00UxdDXIKWmt99lA==", + "version": "3.689.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.689.0.tgz", + "integrity": "sha512-E9P59HEsPeFuO10yKyYE180J3V1DRVFTa0H0XzrBTP+s2g9g8xvfyGqoDYJw5YHUckqls39jT5nlbrf+kBSrfg==", "license": "Apache-2.0", "dependencies": { "@aws-sdk/signature-v4-multi-region": "3.687.0", @@ -1694,21 +1695,21 @@ } }, "node_modules/@hey-api/client-axios": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@hey-api/client-axios/-/client-axios-0.2.9.tgz", - "integrity": "sha512-K4T0KdBKl4LKbAVtfL1E9y9l2Q79NskptPBQcV1+RayjADCJctOtwdjwJitkpxj31UfQ79TSKHH96mMs9HrSsQ==", + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@hey-api/client-axios/-/client-axios-0.2.10.tgz", + "integrity": "sha512-EXTf9WcZCyzRIi1JEbKbJ4JvB+TLy9WsSaBKRUwd7d8c6PYQ+MRJCTnkzGJk1wXkeBLqJEwyf2IZH/qmCkDhqg==", "license": "MIT", "funding": { - "url": "https://github.com/sponsors/mrlubos" + "url": "https://github.com/sponsors/hey-api" }, "peerDependencies": { "axios": ">= 1.0.0 < 2" } }, "node_modules/@hey-api/openapi-ts": { - "version": "0.55.1", - "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.55.1.tgz", - "integrity": "sha512-wLwrnb/MrwRpPCywizrbegZdXbdWWtiC7JerInGhkDksaigihszRyq3GHsibZsvs6gvpPQk0OioaSvgKoNP6ZA==", + "version": "0.55.2", + "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.55.2.tgz", + "integrity": "sha512-EdVslFxtV27prj8oLWCm4ZOFAx+zGOqRVbDkKOcaYzg6wQQdvQ0j14LMapvhM0PtP2hkffh6PGeh6dt9aJORZQ==", "dev": true, "license": "FSL-1.1-MIT", "dependencies": { @@ -1724,7 +1725,7 @@ "node": "^18.0.0 || >=20.0.0" }, "funding": { - "url": "https://github.com/sponsors/mrlubos" + "url": "https://github.com/sponsors/hey-api" }, "peerDependencies": { "typescript": "^5.x" @@ -2232,9 +2233,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.4.tgz", - "integrity": "sha512-jfUJrFct/hTA0XDM5p/htWKoNNTbDLY0KRwEt6pyOA6k2fmk0WVwl65PdUdJZgzGEHWx+49LilkcSaumQRyNQw==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.26.0.tgz", + "integrity": "sha512-gJNwtPDGEaOEgejbaseY6xMFu+CPltsc8/T+diUTTbOQLqD+bnrJq9ulH6WD69TqwqWmrfRAtUv30cCFZlbGTQ==", "cpu": [ "arm" ], @@ -2246,9 +2247,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.4.tgz", - "integrity": "sha512-j4nrEO6nHU1nZUuCfRKoCcvh7PIywQPUCBa2UsootTHvTHIoIu2BzueInGJhhvQO/2FTRdNYpf63xsgEqH9IhA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.26.0.tgz", + "integrity": "sha512-YJa5Gy8mEZgz5JquFruhJODMq3lTHWLm1fOy+HIANquLzfIOzE9RA5ie3JjCdVb9r46qfAQY/l947V0zfGJ0OQ==", "cpu": [ "arm64" ], @@ -2260,9 +2261,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.4.tgz", - "integrity": "sha512-GmU/QgGtBTeraKyldC7cDVVvAJEOr3dFLKneez/n7BvX57UdhOqDsVwzU7UOnYA7AAOt+Xb26lk79PldDHgMIQ==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.26.0.tgz", + "integrity": "sha512-ErTASs8YKbqTBoPLp/kA1B1Um5YSom8QAc4rKhg7b9tyyVqDBlQxy7Bf2wW7yIlPGPg2UODDQcbkTlruPzDosw==", "cpu": [ "arm64" ], @@ -2274,9 +2275,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.4.tgz", - "integrity": "sha512-N6oDBiZCBKlwYcsEPXGDE4g9RoxZLK6vT98M8111cW7VsVJFpNEqvJeIPfsCzbf0XEakPslh72X0gnlMi4Ddgg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.26.0.tgz", + "integrity": "sha512-wbgkYDHcdWW+NqP2mnf2NOuEbOLzDblalrOWcPyY6+BRbVhliavon15UploG7PpBRQ2bZJnbmh8o3yLoBvDIHA==", "cpu": [ "x64" ], @@ -2288,9 +2289,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.4.tgz", - "integrity": "sha512-py5oNShCCjCyjWXCZNrRGRpjWsF0ic8f4ieBNra5buQz0O/U6mMXCpC1LvrHuhJsNPgRt36tSYMidGzZiJF6mw==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.26.0.tgz", + "integrity": "sha512-Y9vpjfp9CDkAG4q/uwuhZk96LP11fBz/bYdyg9oaHYhtGZp7NrbkQrj/66DYMMP2Yo/QPAsVHkV891KyO52fhg==", "cpu": [ "arm64" ], @@ -2302,9 +2303,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.4.tgz", - "integrity": "sha512-L7VVVW9FCnTTp4i7KrmHeDsDvjB4++KOBENYtNYAiYl96jeBThFfhP6HVxL74v4SiZEVDH/1ILscR5U9S4ms4g==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.26.0.tgz", + "integrity": "sha512-A/jvfCZ55EYPsqeaAt/yDAG4q5tt1ZboWMHEvKAH9Zl92DWvMIbnZe/f/eOXze65aJaaKbL+YeM0Hz4kLQvdwg==", "cpu": [ "x64" ], @@ -2316,9 +2317,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.4.tgz", - "integrity": "sha512-10ICosOwYChROdQoQo589N5idQIisxjaFE/PAnX2i0Zr84mY0k9zul1ArH0rnJ/fpgiqfu13TFZR5A5YJLOYZA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.26.0.tgz", + "integrity": "sha512-paHF1bMXKDuizaMODm2bBTjRiHxESWiIyIdMugKeLnjuS1TCS54MF5+Y5Dx8Ui/1RBPVRE09i5OUlaLnv8OGnA==", "cpu": [ "arm" ], @@ -2330,9 +2331,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.4.tgz", - "integrity": "sha512-ySAfWs69LYC7QhRDZNKqNhz2UKN8LDfbKSMAEtoEI0jitwfAG2iZwVqGACJT+kfYvvz3/JgsLlcBP+WWoKCLcw==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.26.0.tgz", + "integrity": "sha512-cwxiHZU1GAs+TMxvgPfUDtVZjdBdTsQwVnNlzRXC5QzIJ6nhfB4I1ahKoe9yPmoaA/Vhf7m9dB1chGPpDRdGXg==", "cpu": [ "arm" ], @@ -2344,9 +2345,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.4.tgz", - "integrity": "sha512-uHYJ0HNOI6pGEeZ/5mgm5arNVTI0nLlmrbdph+pGXpC9tFHFDQmDMOEqkmUObRfosJqpU8RliYoGz06qSdtcjg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.26.0.tgz", + "integrity": "sha512-4daeEUQutGRCW/9zEo8JtdAgtJ1q2g5oHaoQaZbMSKaIWKDQwQ3Yx0/3jJNmpzrsScIPtx/V+1AfibLisb3AMQ==", "cpu": [ "arm64" ], @@ -2358,9 +2359,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.4.tgz", - "integrity": "sha512-38yiWLemQf7aLHDgTg85fh3hW9stJ0Muk7+s6tIkSUOMmi4Xbv5pH/5Bofnsb6spIwD5FJiR+jg71f0CH5OzoA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.26.0.tgz", + "integrity": "sha512-eGkX7zzkNxvvS05ROzJ/cO/AKqNvR/7t1jA3VZDi2vRniLKwAWxUr85fH3NsvtxU5vnUUKFHKh8flIBdlo2b3Q==", "cpu": [ "arm64" ], @@ -2372,9 +2373,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.4.tgz", - "integrity": "sha512-q73XUPnkwt9ZNF2xRS4fvneSuaHw2BXuV5rI4cw0fWYVIWIBeDZX7c7FWhFQPNTnE24172K30I+dViWRVD9TwA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.26.0.tgz", + "integrity": "sha512-Odp/lgHbW/mAqw/pU21goo5ruWsytP7/HCC/liOt0zcGG0llYWKrd10k9Fj0pdj3prQ63N5yQLCLiE7HTX+MYw==", "cpu": [ "ppc64" ], @@ -2386,9 +2387,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.4.tgz", - "integrity": "sha512-Aie/TbmQi6UXokJqDZdmTJuZBCU3QBDA8oTKRGtd4ABi/nHgXICulfg1KI6n9/koDsiDbvHAiQO3YAUNa/7BCw==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.26.0.tgz", + "integrity": "sha512-MBR2ZhCTzUgVD0OJdTzNeF4+zsVogIR1U/FsyuFerwcqjZGvg2nYe24SAHp8O5sN8ZkRVbHwlYeHqcSQ8tcYew==", "cpu": [ "riscv64" ], @@ -2400,9 +2401,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.4.tgz", - "integrity": "sha512-P8MPErVO/y8ohWSP9JY7lLQ8+YMHfTI4bAdtCi3pC2hTeqFJco2jYspzOzTUB8hwUWIIu1xwOrJE11nP+0JFAQ==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.26.0.tgz", + "integrity": "sha512-YYcg8MkbN17fMbRMZuxwmxWqsmQufh3ZJFxFGoHjrE7bv0X+T6l3glcdzd7IKLiwhT+PZOJCblpnNlz1/C3kGQ==", "cpu": [ "s390x" ], @@ -2414,9 +2415,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.4.tgz", - "integrity": "sha512-K03TljaaoPK5FOyNMZAAEmhlyO49LaE4qCsr0lYHUKyb6QacTNF9pnfPpXnFlFD3TXuFbFbz7tJ51FujUXkXYA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.26.0.tgz", + "integrity": "sha512-ZuwpfjCwjPkAOxpjAEjabg6LRSfL7cAJb6gSQGZYjGhadlzKKywDkCUnJ+KEfrNY1jH5EEoSIKLCb572jSiglA==", "cpu": [ "x64" ], @@ -2428,9 +2429,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.4.tgz", - "integrity": "sha512-VJYl4xSl/wqG2D5xTYncVWW+26ICV4wubwN9Gs5NrqhJtayikwCXzPL8GDsLnaLU3WwhQ8W02IinYSFJfyo34Q==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.26.0.tgz", + "integrity": "sha512-+HJD2lFS86qkeF8kNu0kALtifMpPCZU80HvwztIKnYwym3KnA1os6nsX4BGSTLtS2QVAGG1P3guRgsYyMA0Yhg==", "cpu": [ "x64" ], @@ -2442,9 +2443,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.4.tgz", - "integrity": "sha512-ku2GvtPwQfCqoPFIJCqZ8o7bJcj+Y54cZSr43hHca6jLwAiCbZdBUOrqE6y29QFajNAzzpIOwsckaTFmN6/8TA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.26.0.tgz", + "integrity": "sha512-WUQzVFWPSw2uJzX4j6YEbMAiLbs0BUysgysh8s817doAYhR5ybqTI1wtKARQKo6cGop3pHnrUJPFCsXdoFaimQ==", "cpu": [ "arm64" ], @@ -2456,9 +2457,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.4.tgz", - "integrity": "sha512-V3nCe+eTt/W6UYNr/wGvO1fLpHUrnlirlypZfKCT1fG6hWfqhPgQV/K/mRBXBpxc0eKLIF18pIOFVPh0mqHjlg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.26.0.tgz", + "integrity": "sha512-D4CxkazFKBfN1akAIY6ieyOqzoOoBV1OICxgUblWxff/pSjCA2khXlASUx7mK6W1oP4McqhgcCsu6QaLj3WMWg==", "cpu": [ "ia32" ], @@ -2470,9 +2471,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.4.tgz", - "integrity": "sha512-LTw1Dfd0mBIEqUVCxbvTE/LLo+9ZxVC9k99v1v4ahg9Aak6FpqOfNu5kRkeTAn0wphoC4JU7No1/rL+bBCEwhg==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.26.0.tgz", + "integrity": "sha512-2x8MO1rm4PGEP0xWbubJW5RtbNLk3puzAMaLQd3B3JHVw4KcHlmXcO+Wewx9zCoo7EUFiMlu/aZbCJ7VjMzAag==", "cpu": [ "x64" ], @@ -3180,10 +3181,10 @@ "node": ">=16.0.0" } }, - "node_modules/@tsconfig/node20": { - "version": "20.1.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node20/-/node20-20.1.4.tgz", - "integrity": "sha512-sqgsT69YFeLWf5NtJ4Xq/xAF8p4ZQHlmGW74Nu2tD4+g5fAsposc4ZfaaPixVu4y01BEiDCWLRDCvDM5JOsRxg==", + "node_modules/@tsconfig/node22": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/@tsconfig/node22/-/node22-22.0.0.tgz", + "integrity": "sha512-twLQ77zevtxobBOD4ToAtVmuYrpeYUh3qh+TEp+08IWhpsrIflVHqQ1F1CiPxQGL7doCdBIOOCF+1Tm833faNg==", "dev": true, "license": "MIT" }, @@ -3267,17 +3268,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz", - "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.14.0.tgz", + "integrity": "sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/type-utils": "8.13.0", - "@typescript-eslint/utils": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/type-utils": "8.14.0", + "@typescript-eslint/utils": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -3301,16 +3302,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz", - "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz", + "integrity": "sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/typescript-estree": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4" }, "engines": { @@ -3330,14 +3331,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz", - "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.14.0.tgz", + "integrity": "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0" + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3348,14 +3349,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz", - "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.14.0.tgz", + "integrity": "sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.13.0", - "@typescript-eslint/utils": "8.13.0", + "@typescript-eslint/typescript-estree": "8.14.0", + "@typescript-eslint/utils": "8.14.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -3373,9 +3374,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz", - "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.14.0.tgz", + "integrity": "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==", "dev": true, "license": "MIT", "engines": { @@ -3387,14 +3388,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz", - "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.14.0.tgz", + "integrity": "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/visitor-keys": "8.13.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/visitor-keys": "8.14.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3416,16 +3417,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz", - "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.14.0.tgz", + "integrity": "sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.13.0", - "@typescript-eslint/types": "8.13.0", - "@typescript-eslint/typescript-estree": "8.13.0" + "@typescript-eslint/scope-manager": "8.14.0", + "@typescript-eslint/types": "8.14.0", + "@typescript-eslint/typescript-estree": "8.14.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3439,13 +3440,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz", - "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.14.0.tgz", + "integrity": "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.13.0", + "@typescript-eslint/types": "8.14.0", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -3457,9 +3458,9 @@ } }, "node_modules/@vitejs/plugin-vue": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.1.4.tgz", - "integrity": "sha512-N2XSI2n3sQqp5w7Y/AN/L2XDjBIRGqXko+eDp42sydYSBeJuSm5a1sLf8zakmo8u7tA8NmBgoDLA1HeOESjp9A==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.0.tgz", + "integrity": "sha512-7n7KdUEtx/7Yl7I/WVAMZ1bEb0eVvXF3ummWTeLcs/9gvo9pJhuLdouSXGjdZ/MKD1acf1I272+X0RMua4/R3g==", "dev": true, "license": "MIT", "engines": { @@ -3683,11 +3684,23 @@ "license": "MIT" }, "node_modules/@vue/tsconfig": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.5.1.tgz", - "integrity": "sha512-VcZK7MvpjuTPx2w6blwnwZAu5/LgBUtejFOi3pPGQFXQN5Ela03FUtd2Qtg4yWGGissVL0dr6Ro1LfOFh+PCuQ==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.6.0.tgz", + "integrity": "sha512-MHXNd6lzugsEHvuA6l1GqrF5jROqUon8sP/HInLPnthJiYvB0VvpHMywg7em1dBZfFZNBSkR68qH37zOdRHmCw==", "dev": true, - "license": "MIT" + "license": "MIT", + "peerDependencies": { + "typescript": "5.x", + "vue": "^3.3.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } }, "node_modules/acorn": { "version": "8.14.0", @@ -3729,9 +3742,9 @@ } }, "node_modules/alien-signals": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-0.2.0.tgz", - "integrity": "sha512-StlonZhBBrsPPwrDjiPAiVTf/rolxffLxVPT60Qv/t88BZ81BvUVzHgGqEFvJ1ii8HXtm1+zU2Icr59tfWEcag==", + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-0.2.1.tgz", + "integrity": "sha512-FlEQrDJe9r2RI4cDlnK2zYqJezvx1uJaWEuwxsnlFqnPwvJbgitNBRumWrLDv8lA+7cCikpMxfJD2TTHiaTklA==", "dev": true, "license": "MIT" }, @@ -3811,9 +3824,9 @@ } }, "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", "dev": true, "license": "MIT" }, @@ -4375,9 +4388,9 @@ } }, "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", "dev": true, "license": "MIT" }, @@ -4667,9 +4680,9 @@ } }, "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", "dev": true, "license": "MIT" }, @@ -4687,9 +4700,9 @@ } }, "node_modules/dompurify": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", - "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.0.tgz", + "integrity": "sha512-AMdOzK44oFWqHEi0wpOqix/fUNY707OmoeFDnbi3Q5I8uOpy21ufUA5cDJPr0bosxrflOVD/H2DMSvuGKJGfmQ==", "license": "(MPL-2.0 OR Apache-2.0)" }, "node_modules/dotenv": { @@ -4706,9 +4719,9 @@ } }, "node_modules/elliptic": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz", - "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", "dev": true, "license": "MIT", "dependencies": { @@ -4722,9 +4735,9 @@ } }, "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", "dev": true, "license": "MIT" }, @@ -4751,9 +4764,9 @@ } }, "node_modules/es-abstract": { - "version": "1.23.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", - "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "version": "1.23.4", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.4.tgz", + "integrity": "sha512-HR1gxH5OaiN7XH7uiWH0RLw0RcFySiSoW1ctxmD1ahTw3uGBtkmm/ng0tDU1OtYx5OK6EOL5Y6O21cDflG3Jcg==", "dev": true, "license": "MIT", "dependencies": { @@ -4772,7 +4785,7 @@ "function.prototype.name": "^1.1.6", "get-intrinsic": "^1.2.4", "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.3", + "globalthis": "^1.0.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", @@ -4788,10 +4801,10 @@ "is-string": "^1.0.7", "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.13.1", + "object-inspect": "^1.13.3", "object-keys": "^1.1.1", "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.2", + "regexp.prototype.flags": "^1.5.3", "safe-array-concat": "^1.1.2", "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.9", @@ -5036,9 +5049,9 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "9.30.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.30.0.tgz", - "integrity": "sha512-CyqlRgShvljFkOeYK8wN5frh/OGTvkj1S7wlr2Q2pUvwq+X5VYiLd6ZjujpgSgLnys2W8qrBLkXQ41SUYaoPIQ==", + "version": "9.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.31.0.tgz", + "integrity": "sha512-aYMUCgivhz1o4tLkRHj5oq9YgYPM4/EJc0M7TAKRLCUA5OYxRLAhYEVD2nLtTwLyixEFI+/QXSvKU9ESZFgqjQ==", "dev": true, "license": "MIT", "dependencies": { @@ -5957,9 +5970,9 @@ } }, "node_modules/immutable": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", - "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.2.tgz", + "integrity": "sha512-1NU7hWZDkV7hJ4PJ9dur9gTNQ4ePNPN4k9/0YhwjzykTi/+3Q5pF93YU5QoVj8BuOnhLgaY8gs0U2pj4kSYVcw==", "dev": true, "license": "MIT" }, @@ -6565,9 +6578,9 @@ } }, "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", "dev": true, "license": "MIT" }, @@ -6698,15 +6711,15 @@ } }, "node_modules/mlly": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.2.tgz", - "integrity": "sha512-tN3dvVHYVz4DhSXinXIk7u9syPYaJvio118uomkovAtWBT+RdbP6Lfh/5Lvo519YMmwBafwlh20IPTXIStscpA==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.7.3.tgz", + "integrity": "sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.12.1", + "acorn": "^8.14.0", "pathe": "^1.1.2", - "pkg-types": "^1.2.0", + "pkg-types": "^1.2.1", "ufo": "^1.5.4" } }, @@ -7130,9 +7143,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -7527,9 +7540,9 @@ } }, "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "funding": [ { "type": "opencollective", @@ -7547,7 +7560,7 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.1.0", + "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { @@ -7647,9 +7660,9 @@ } }, "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", "dev": true, "license": "MIT" }, @@ -7859,9 +7872,9 @@ } }, "node_modules/rollup": { - "version": "4.24.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.4.tgz", - "integrity": "sha512-vGorVWIsWfX3xbcyAS+I047kFKapHYivmkaT63Smj77XwvLSJos6M1xGqZnBPFQFBRZDOcG1QnYEIxAvTr/HjA==", + "version": "4.26.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.26.0.tgz", + "integrity": "sha512-ilcl12hnWonG8f+NxU6BlgysVA0gvY2l8N0R84S1HcINbW20bvwuCngJkkInV6LXhwRpucsW5k1ovDwEdBVrNg==", "dev": true, "license": "MIT", "dependencies": { @@ -7875,24 +7888,24 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.24.4", - "@rollup/rollup-android-arm64": "4.24.4", - "@rollup/rollup-darwin-arm64": "4.24.4", - "@rollup/rollup-darwin-x64": "4.24.4", - "@rollup/rollup-freebsd-arm64": "4.24.4", - "@rollup/rollup-freebsd-x64": "4.24.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.24.4", - "@rollup/rollup-linux-arm-musleabihf": "4.24.4", - "@rollup/rollup-linux-arm64-gnu": "4.24.4", - "@rollup/rollup-linux-arm64-musl": "4.24.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.24.4", - "@rollup/rollup-linux-riscv64-gnu": "4.24.4", - "@rollup/rollup-linux-s390x-gnu": "4.24.4", - "@rollup/rollup-linux-x64-gnu": "4.24.4", - "@rollup/rollup-linux-x64-musl": "4.24.4", - "@rollup/rollup-win32-arm64-msvc": "4.24.4", - "@rollup/rollup-win32-ia32-msvc": "4.24.4", - "@rollup/rollup-win32-x64-msvc": "4.24.4", + "@rollup/rollup-android-arm-eabi": "4.26.0", + "@rollup/rollup-android-arm64": "4.26.0", + "@rollup/rollup-darwin-arm64": "4.26.0", + "@rollup/rollup-darwin-x64": "4.26.0", + "@rollup/rollup-freebsd-arm64": "4.26.0", + "@rollup/rollup-freebsd-x64": "4.26.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.26.0", + "@rollup/rollup-linux-arm-musleabihf": "4.26.0", + "@rollup/rollup-linux-arm64-gnu": "4.26.0", + "@rollup/rollup-linux-arm64-musl": "4.26.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.26.0", + "@rollup/rollup-linux-riscv64-gnu": "4.26.0", + "@rollup/rollup-linux-s390x-gnu": "4.26.0", + "@rollup/rollup-linux-x64-gnu": "4.26.0", + "@rollup/rollup-linux-x64-musl": "4.26.0", + "@rollup/rollup-win32-arm64-msvc": "4.26.0", + "@rollup/rollup-win32-ia32-msvc": "4.26.0", + "@rollup/rollup-win32-x64-msvc": "4.26.0", "fsevents": "~2.3.2" } }, @@ -7978,14 +7991,14 @@ } }, "node_modules/sass": { - "version": "1.80.6", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.6.tgz", - "integrity": "sha512-ccZgdHNiBF1NHBsWvacvT5rju3y1d/Eu+8Ex6c21nHp2lZGLBEtuwc415QfiI1PJa1TpCo3iXwwSRjRpn2Ckjg==", + "version": "1.80.7", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.80.7.tgz", + "integrity": "sha512-MVWvN0u5meytrSjsU7AWsbhoXi1sc58zADXFllfZzbsBT1GHjjar6JwBINYPRrkx/zqnQ6uqbQuHgE95O+C+eQ==", "dev": true, "license": "MIT", "dependencies": { "chokidar": "^4.0.0", - "immutable": "^4.0.0", + "immutable": "^5.0.2", "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { @@ -8597,15 +8610,15 @@ } }, "node_modules/typescript-eslint": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.13.0.tgz", - "integrity": "sha512-vIMpDRJrQd70au2G8w34mPps0ezFSPMEX4pXkTzUkrNbRX+36ais2ksGWN0esZL+ZMaFJEneOBHzCgSqle7DHw==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.14.0.tgz", + "integrity": "sha512-K8fBJHxVL3kxMmwByvz8hNdBJ8a0YqKzKDX6jRlrjMuNXyd5T2V02HIq37+OiWXvUUOXgOOGiSSOh26Mh8pC3w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.13.0", - "@typescript-eslint/parser": "8.13.0", - "@typescript-eslint/utils": "8.13.0" + "@typescript-eslint/eslint-plugin": "8.14.0", + "@typescript-eslint/parser": "8.14.0", + "@typescript-eslint/utils": "8.14.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -8743,9 +8756,9 @@ } }, "node_modules/vite": { - "version": "5.4.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", - "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 4052dab..84696ec 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "chart.js": "~4.4.0", "chartjs-plugin-zoom": "~2.0.1", "dayjs": "~1.11.0", - "dompurify": "~3.1.0", + "dompurify": "~3.2.0", "filesize": "~10.1.0", "idb-keyval": "^6.2.1", "pinia": "~2.2.0", @@ -41,7 +41,7 @@ "@eslint/compat": "^1.2.0", "@hey-api/openapi-ts": "^0.55.0", "@rushstack/eslint-patch": "~1.10.0", - "@tsconfig/node20": "^20.1.2", + "@tsconfig/node22": "^22.0.0", "@types/bootstrap": "~5.2.0", "@types/dompurify": "~3.0.0", "@types/node": "^20.11.0", @@ -49,12 +49,12 @@ "@types/semver": "~7.5.1", "@types/showdown": "~2.0.1", "@types/sortablejs": "^1.15.7", - "@vitejs/plugin-vue": "~5.1.0", + "@vitejs/plugin-vue": "~5.2.0", "@vue/eslint-config-prettier": "~10.1.0", "@vue/eslint-config-typescript": "~14.1.0", - "@vue/tsconfig": "~0.5.0", + "@vue/tsconfig": "~0.6.0", "eslint": "~9.12.0", - "eslint-plugin-vue": "~9.30.0", + "eslint-plugin-vue": "~9.31.0", "highlight.js": "^11.9.0", "npm-run-all": "~4.1.5", "prettier": "~3.3.0", diff --git a/src/assets/main.css b/src/assets/main.css index 78974d4..0409e70 100644 --- a/src/assets/main.css +++ b/src/assets/main.css @@ -42,3 +42,7 @@ pre { .execution-notes p { margin-bottom: 0; } + +.parameter-form-tooltip { + --bs-tooltip-max-width: 350px; +} diff --git a/src/components/parameter-schema/ParameterSchemaFormComponent.vue b/src/components/parameter-schema/ParameterSchemaFormComponent.vue index cac3540..1b5086c 100644 --- a/src/components/parameter-schema/ParameterSchemaFormComponent.vue +++ b/src/components/parameter-schema/ParameterSchemaFormComponent.vue @@ -20,7 +20,7 @@ import type { FlatWorkflowParameters, } from "@/types/WorkflowParameters"; import { useWorkflowExecutionStore } from "@/stores/workflowExecutions"; -import { NextflowVersion, type ParameterExtension } from "@/client"; +import { NextflowVersion, type ParameterExtension } from "@/client/types.gen"; import { flattenParameters, nestParameters } from "@/utils/Workflow"; const bucketRepository = useBucketStore(); @@ -318,7 +318,7 @@ onMounted(() => { v-if="formState.formInput" v-model="formState.formInput" :parameter-group-name="groupName" - :parameter-group="group" + :schema-properties="parameterGroups" :show-hidden="showHidden" :show-optional="showOptional" :resource-parameters="props.clowmInfo?.resourceParameters" @@ -347,14 +347,15 @@ onMounted(() => { <font-awesome-icon icon="fa-solid fa-sticky-note" /> </span> <textarea + id="pipelineNotes" v-model="formState.metaParameters.notes" class="form-control border border-secondary" rows="2" /> </div> - <label class="mb-3" for="pipelineNotes" - >Personal notes about the pipeline execution</label - > + <div class="mb-3 d-inline-block"> + Personal notes about the pipeline execution + </div> </div> <div> <code @@ -374,9 +375,9 @@ onMounted(() => { border="secondary" /> </div> - <label class="mb-3" for="logsS3Path"> + <div class="mb-3 d-inline-block"> Directory in bucket where to save Nextflow log and reports - </label> + </div> </div> <div v-if="props.nextflowVersion >= NextflowVersion._23_04_0"> <code @@ -396,10 +397,10 @@ onMounted(() => { border="secondary" /> </div> - <label class="mb-3" for="provenanceS3Path"> + <div class="mb-3 d-inline-block"> Directory in bucket where to save provenance information about the workflow execution - </label> + </div> </div> <div :hidden="!showHidden"> <code @@ -419,10 +420,10 @@ onMounted(() => { border="secondary" /> </div> - <label class="mb-3" for="debugS3Path"> + <div class="mb-3 d-inline-block"> Directory in bucket where to save debug information about the workflow execution - </label> + </div> </div> </div> </div> diff --git a/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue b/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue index 75529fc..567eec0 100644 --- a/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterBooleanInput.vue @@ -1,5 +1,5 @@ <script setup lang="ts"> -import { computed, onMounted, type PropType, watch } from "vue"; +import { computed, onMounted, type PropType, ref, watch } from "vue"; import type { ExtendedColors } from "@/types/PropTypes"; const model = defineModel({ required: true }); @@ -13,13 +13,16 @@ const props = defineProps({ }, }, border: String as PropType<ExtendedColors>, + required: Boolean, + id: String, }); -const randomIDSuffix = Math.random().toString(16).substring(2, 8); - const helpTextPresent = computed<boolean>(() => props.parameter["help_text"]); const iconPresent = computed<boolean>(() => props.parameter["fa_icon"]); +const trueOption = ref<HTMLInputElement | undefined>(undefined); +const falseOption = ref<HTMLInputElement | undefined>(undefined); + const dynamicCssClasses = computed<string[]>(() => { const cssClasses = []; if (props.border) { @@ -39,13 +42,34 @@ watch(model, (newVal) => { // type conversion if true/false is represented by 0/1 model.value = !!newVal; } + /* eslint-disable @typescript-eslint/ban-ts-comment */ + // @ts-ignore + setCustomValidity(props.required, newVal); }); +watch( + () => props.required, + (newVal) => { + /* eslint-disable @typescript-eslint/ban-ts-comment */ + // @ts-ignore + setCustomValidity(newVal, model.value); + }, +); + +function setCustomValidity(required: boolean, value: boolean | undefined) { + const reason = required && value == undefined ? "Unset" : ""; + trueOption.value?.setCustomValidity(reason); + falseOption.value?.setCustomValidity(reason); +} + onMounted(() => { if (model.value != undefined) { // type conversion if true/false is represented by 0/1 model.value = model.value ? true : false; } + /* eslint-disable @typescript-eslint/ban-ts-comment */ + // @ts-ignore + setCustomValidity(props.required, model.value); }); </script> @@ -55,30 +79,28 @@ onMounted(() => { :class="dynamicCssClasses" > <div class="form-check form-check-inline mb-0"> - <label class="form-check-label" :for="'trueOption' + randomIDSuffix" - >True</label - > <input - :id="'trueOption' + randomIDSuffix" + :id="id + 'TrueOption'" + ref="trueOption" v-model="model" class="form-check-input" type="radio" - :name="'inlineRadioOptions' + randomIDSuffix" + :name="id + 'inlineRadioOptions'" :value="true" /> + <label class="form-check-label" :for="id + 'TrueOption'">True</label> </div> <div class="form-check form-check-inline mb-0"> <input - :id="'falseOption' + randomIDSuffix" + :id="id + 'FalseOption'" + ref="falseOption" v-model="model" class="form-check-input" type="radio" - :name="'inlineRadioOptions' + randomIDSuffix" + :name="id + 'inlineRadioOptions'" :value="false" /> - <label class="form-check-label" :for="'falseOption' + randomIDSuffix" - >False</label - > + <label class="form-check-label" :for="id + 'FalseOption'">False</label> </div> </div> </template> diff --git a/src/components/parameter-schema/form-mode/ParameterEnumInput.vue b/src/components/parameter-schema/form-mode/ParameterEnumInput.vue index 06b0308..76d5f45 100644 --- a/src/components/parameter-schema/form-mode/ParameterEnumInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterEnumInput.vue @@ -17,6 +17,7 @@ const props = defineProps({ type: String as PropType<SizeModifierType>, }, border: String as PropType<ExtendedColors>, + id: String, }); const possibleValues = computed<string[]>(() => props.parameter["enum"]); @@ -35,6 +36,7 @@ const dynamicCssClasses = computed<string[]>(() => { <template> <select + :id="id" v-model="model" class="form-select" :class="dynamicCssClasses" diff --git a/src/components/parameter-schema/form-mode/ParameterFileInput.vue b/src/components/parameter-schema/form-mode/ParameterFileInput.vue index ac590d8..3880a82 100644 --- a/src/components/parameter-schema/form-mode/ParameterFileInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterFileInput.vue @@ -24,6 +24,7 @@ const props = defineProps({ }, border: String as PropType<ExtendedColors>, allowRaw: Boolean, + id: String, }); const emit = defineEmits<{ @@ -167,6 +168,7 @@ onMounted(() => { <template> <select + :id="id + 'BucketSelect'" class="form-select" :class="selectDynamicClass" :required="props.required" @@ -191,6 +193,7 @@ onMounted(() => { </option> </select> <input + :id="id + 'FilePath'" v-model="s3Path.key" class="form-control" :list="'keys-options-' + randomIDSuffix" diff --git a/src/components/parameter-schema/form-mode/ParameterGroupForm.vue b/src/components/parameter-schema/form-mode/ParameterGroupForm.vue index 6d3235e..caeeb6d 100644 --- a/src/components/parameter-schema/form-mode/ParameterGroupForm.vue +++ b/src/components/parameter-schema/form-mode/ParameterGroupForm.vue @@ -1,20 +1,17 @@ <script setup lang="ts"> import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue"; -import { computed, type PropType } from "vue"; +import { computed, onMounted, type PropType } from "vue"; import MarkdownRenderer from "@/components/MarkdownRenderer.vue"; import type { FlatWorkflowParameters } from "@/types/WorkflowParameters"; import ParameterInput from "@/components/parameter-schema/form-mode/ParameterInput.vue"; +import { Tooltip } from "bootstrap"; +import { md5 } from "@/utils/md5"; const model = defineModel<FlatWorkflowParameters>({ required: true }); +const groupId = Math.random().toString(16).substring(2, 8); + const props = defineProps({ - parameterGroup: { - type: Object, - required: true, - validator(value: Record<string, never>) { - return "object" === value["type"]; - }, - }, parameterGroupName: { type: String, required: true, @@ -32,10 +29,14 @@ const props = defineProps({ required: false, }, mapping: Object as PropType<Record<string, Record<string, string | number>>>, + schemaProperties: { + type: Object, + required: true, + }, }); -const title = computed<string>(() => props.parameterGroup["title"]); -const icon = computed<string>(() => props.parameterGroup["fa_icon"]); -const description = computed<string>(() => props.parameterGroup["description"]); +const title = computed<string>(() => parameterGroup.value["title"]); +const icon = computed<string>(() => parameterGroup.value["fa_icon"]); +const description = computed<string>(() => parameterGroup.value["description"]); const groupHidden = computed<boolean>(() => Object.keys(parameters.value).reduce( (acc: boolean, val: string) => acc && parameters.value[val]["hidden"], @@ -43,39 +44,195 @@ const groupHidden = computed<boolean>(() => ), ); const groupRequired = computed<boolean>( - () => (props.parameterGroup["required"] ?? []).length > 0, + () => + (parameterGroup.value["required"] ?? parameterGroup.value["anyOf"] ?? []) + .length > 0, ); const parameters = computed<Record<string, never>>( - () => props.parameterGroup["properties"], + () => parameterGroup.value["properties"], +); + +const parameterGroup = computed( + () => props.schemaProperties[props.parameterGroupName], ); -function parameterRequired( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - parameterGroup: Record<string, any>, - parameterName: string, -): boolean { +/* +Object with parameter name as key and list of parameters that make the parameter required if they are set as value +JSONSchema DependentRequired + */ +const parameterDependenciesPerParameter = computed<Record<string, string[]>>( + () => { + const r: Record<string, string[]> = {}; + for (const groupName of Object.keys(props.schemaProperties)) { + const dep = + props.schemaProperties[groupName]["dependentRequired"] ?? + props.schemaProperties[groupName]["dependencies"] ?? + {}; + for (const paramName of Object.keys(dep)) { + for (const depParam of dep[paramName]) { + if (parameters.value[depParam] != undefined) { + if (r[depParam] == undefined) { + r[depParam] = [paramName]; + } else { + r[depParam].push(depParam); + } + } + } + } + } + return r; + }, +); + +// Object with parameter name as key and boolean flag if the parameter is required as value +const parameterRequired = computed<Record<string, boolean>>(() => { + const r: Record<string, boolean> = {}; + for (const parameterName of Object.keys(parameters.value)) { + r[parameterName] = + parameterDirectlyRequired(parameterName) || // parameter is directly required + parameterDependentRequired(parameterName) || // parameter is required depending on other parameters + parameterAnyOfRequired(parameterName); // parameter is required in a OR parameter group + } + return r; +}); + +// evaluate if the parameter is required directly +function parameterDirectlyRequired(parameterName: string): boolean { + return parameterGroup.value["required"]?.includes(parameterName) ?? false; +} + +// evaluate if a parameter is required due to a anyOf constraint +function parameterDependentRequired(parameterName: string): boolean { + return parameterDependenciesPerParameter.value[parameterName] // parameter is required when another parameter is set + ?.reduce( + (acc: boolean, param: string) => acc || model.value[param] != undefined, + false, + ); +} + +// evaluate of a parameter is required du to a dependentRequired constraint +function parameterAnyOfRequired(parameterName: string): boolean { return ( - parameterGroup["required"]?.includes(parameterName) || // parameter is required - parameterGroup["dependentRequired"]?.[parameterName] // parameter is required when another parameter is set - ?.map((param: string) => model.value[param]) - ?.reduce((acc: boolean, val: string) => acc || val, false) + parameterAnyOfDependenciesPerParameter.value[parameterName] != undefined && + parameterAnyOfDependenciesPerParameter.value[ + parameterName + ].dependencies.reduce( + (acc, groupParam) => acc && model.value[groupParam] == undefined, + true, + ) && + (model.value[parameterName] == undefined || + parameterAnyOfDependenciesPerParameter.value[parameterName].group.reduce( + (acc, groupParam) => acc && model.value[groupParam] == undefined, + true, + )) ); } -function parameterId(parameterName: string): string { - return parameterName.replace(/\./g, ""); +interface ParameterAnyOfDependencies { + group: string[]; // AND group in OR combination + dependencies: string[]; // OR combination to fulfill } + +// object with parameter name as key and anyOf dependencies as value +const parameterAnyOfDependenciesPerParameter = computed< + Record<string, ParameterAnyOfDependencies> +>(() => { + const b: string[][] = + parameterGroup.value["anyOf"] + ?.map((b: Record<string, string[]>) => b["required"] ?? []) + ?.filter((b: string[]) => b.length > 0) ?? []; + const r: Record<string, ParameterAnyOfDependencies> = {}; + for (const paramName of b.flat()) { + r[paramName] = { + group: + b.find((a) => a.includes(paramName))?.filter((a) => a != paramName) ?? + [], + dependencies: b.filter((a) => !a.includes(paramName)).flat(), + }; + } + return r; +}); + +// object with parameter name as key and tooltip string for dependentRequired label as value +const dependentTooltip = computed<Record<string, string>>(() => { + const r: Record<string, string> = {}; + for (const paramName of Object.keys(parameters.value)) { + let labelText = ""; + if (parameterDependenciesPerParameter.value[paramName] != undefined) { + labelText += + "Required when these are set: <ul class='ps-4 mb-0 text-start'>" + + parameterDependenciesPerParameter.value[paramName] + .map((a) => "<li>--" + a + "</li>") + .join("") + + "</ul></li>"; + } + if (labelText.length > 0) { + r[paramName] = labelText; + } + } + return r; +}); + +// object with parameter name as key and tooltip string for anyOf label as value +const anyOfTooltip = computed<Record<string, string>>(() => { + const r: Record<string, string> = {}; + for (const paramName of Object.keys(parameters.value)) { + let labelText = ""; + if (parameterAnyOfDependenciesPerParameter.value[paramName] != undefined) { + labelText += "<ul class='ps-3 ms-0 mb-0 text-start'>"; + if ( + parameterAnyOfDependenciesPerParameter.value[paramName].group.length > 0 + ) { + labelText += + "<li>When this is set, these are also required:<ul >" + + parameterAnyOfDependenciesPerParameter.value[paramName].group + .map((a) => "<li>--" + a + "</li>") + .join("") + + "</ul></li>"; + } + labelText += + "<li>Set this or any of these parameters:<ul>" + + parameterAnyOfDependenciesPerParameter.value[paramName].dependencies + .map((a) => "<li>--" + a + "</li>") + .join("") + + "</ul></li></ul>"; + } + if (labelText.length > 0) { + r[paramName] = labelText; + } + } + return r; +}); + +// object with parameter name as key and id for html attributes as value +const parameterIds = computed<Record<string, string>>(() => { + const r: Record<string, string> = {}; + for (const parameterName of Object.keys(parameters.value)) { + r[parameterName] = md5(parameterName); + } + return r; +}); + +onMounted(() => { + document + ?.querySelector(`#group-${groupId}`) + ?.querySelectorAll("[data-bs-toggle=tooltip]") + .forEach((tooltipTriggerEl) => { + Tooltip.getOrCreateInstance(tooltipTriggerEl); + }); +}); </script> <template> <div + :id="`group-${groupId}`" class="card mb-3" :hidden=" (!props.showHidden && groupHidden) || (!props.showOptional && !groupRequired) " > - <h3 :id="props.parameterGroupName" class="card-header"> + <h3 :id="parameterGroup.valueName" class="card-header"> <font-awesome-icon v-if="icon" :icon="icon" class="me-2" /> {{ title }} </h3> @@ -89,18 +246,50 @@ function parameterId(parameterName: string): string { :hidden=" (!props.showHidden && parameter['hidden']) || (!props.showOptional && - !parameterRequired(props.parameterGroup, parameterName)) + !( + parameterRequired[parameterName] || + parameterAnyOfDependenciesPerParameter[parameterName] != + undefined || + parameterDependenciesPerParameter[parameterName] != undefined + )) " > <code class="p-2 rounded-top border-bottom-0 border bg-secondary-subtle border-secondary" - >--{{ parameter["name"] ?? parameterName }}</code - ><span - v-if="parameterRequired(props.parameterGroup, parameterName)" - class="rounded p-1 bg-warning text-light ms-2" - >required</span > - <div class="input-group"> + --{{ parameter["name"] ?? parameterName }} + </code> + <span + v-if="parameterDirectlyRequired(parameterName)" + class="rounded p-1 bg-warning ms-2" + > + required + </span> + <span + v-if="anyOfTooltip[parameterName] != undefined" + class="rounded p-1 bg-secondary ms-2 label" + data-bs-toggle="tooltip" + data-bs-placement="bottom" + :data-bs-title="anyOfTooltip[parameterName]" + data-bs-custom-class="parameter-form-tooltip" + data-bs-html="true" + >anyOf</span + > + <span + v-if="dependentTooltip[parameterName] != undefined" + class="rounded p-1 bg-secondary ms-2 label" + data-bs-toggle="tooltip" + data-bs-placement="bottom" + :data-bs-title="dependentTooltip[parameterName]" + data-bs-custom-class="parameter-form-tooltip" + data-bs-html="true" + > + Dependent + </span> + <div + class="input-group" + :class="{ 'mb-3': parameter['description'] == undefined }" + > <span v-if="parameter['fa_icon']" class="input-group-text border-end-0 border border-secondary" @@ -108,9 +297,10 @@ function parameterId(parameterName: string): string { <font-awesome-icon :icon="parameter['fa_icon']" /> </span> <parameter-input + :id="parameterIds[parameterName]" v-model="model[parameterName]" :parameter="parameter" - :required="parameterRequired(props.parameterGroup, parameterName)" + :required="parameterRequired[parameterName]" border="secondary" :resource-parameter=" props.resourceParameters?.includes(parameterName) @@ -122,9 +312,9 @@ function parameterId(parameterName: string): string { v-if="parameter['help_text']" class="input-group-text cursor-pointer px-2 border border-secondary" data-bs-toggle="collapse" - :data-bs-target="'#help-collapse-' + parameterId(parameterName)" + :data-bs-target="'#help-collapse-' + parameterIds[parameterName]" aria-expanded="false" - :aria-controls="'help-collapse-' + parameterId(parameterName)" + :aria-controls="'help-collapse-' + parameterIds[parameterName]" > <font-awesome-icon class="cursor-pointer" @@ -132,12 +322,12 @@ function parameterId(parameterName: string): string { /> </span> </div> - <label v-if="parameter['description']"> + <div v-if="parameter['description']" class="d-inline-block"> <markdown-renderer :markdown="parameter['description']" /> - </label> + </div> <div v-if="parameter['help_text']" - :id="'help-collapse-' + parameterId(parameterName)" + :id="'help-collapse-' + parameterIds[parameterName]" class="collapse" > <div class="p-2 pb-0 mx-2 mb-3 flex-shrink-1 border rounded"> @@ -156,7 +346,7 @@ function parameterId(parameterName: string): string { </div> </template> -<style scoped> +<style> div.card-body { backdrop-filter: brightness(1.2); } @@ -164,4 +354,8 @@ div.card-body { span.cursor-pointer:hover { color: var(--bs-info); } + +.label { + cursor: help; +} </style> diff --git a/src/components/parameter-schema/form-mode/ParameterInput.vue b/src/components/parameter-schema/form-mode/ParameterInput.vue index 3e4a76f..72ebea2 100644 --- a/src/components/parameter-schema/form-mode/ParameterInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterInput.vue @@ -14,6 +14,7 @@ const model = defineModel({ }); const rawInput = ref<boolean>(false); +const randomIDSuffix = Math.random().toString(16).substring(2, 8); const props = defineProps<{ // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -25,16 +26,20 @@ const props = defineProps<{ allowRaw?: boolean; forceRawFile?: boolean; mapping?: Record<string, string | number>; + id?: string; }>(); const parameterType = computed<string>( () => props.parameter["type"] ?? "string", ); + +const elemId = computed<string>(() => props.id ?? randomIDSuffix); </script> <template> <parameter-mapping-input v-if="mapping && Object.keys(mapping ?? {}).length > 0 && !rawInput" + :id="elemId" v-model="model as string | number | undefined" :required="required" :size-modifier="sizeModifier" @@ -45,6 +50,7 @@ const parameterType = computed<string>( /> <parameter-number-input v-else-if="parameterType === 'number' || parameterType === 'integer'" + :id="elemId" v-model="model" :parameter="parameter" :required="required" @@ -53,12 +59,15 @@ const parameterType = computed<string>( /> <parameter-boolean-input v-else-if="parameterType === 'boolean'" + :id="elemId" v-model="model" :parameter="parameter" :border="border" + :required="required" /> <parameter-enum-input v-else-if="parameter['enum']" + :id="elemId" v-model="model" :required="required" :parameter="parameter" @@ -68,6 +77,7 @@ const parameterType = computed<string>( <template v-else> <parameter-resource-input v-if="resourceParameter && !rawInput" + :id="elemId" v-model="model" :parameter="parameter" :required="required" @@ -78,6 +88,7 @@ const parameterType = computed<string>( /> <parameter-file-input v-else-if="parameter['format'] && !rawInput && !forceRawFile" + :id="elemId" v-model="model" :required="required" :parameter="parameter" @@ -88,6 +99,7 @@ const parameterType = computed<string>( /> <parameter-string-input v-else + :id="elemId" v-model="model" :parameter="parameter" :required="required" diff --git a/src/components/parameter-schema/form-mode/ParameterMappingInput.vue b/src/components/parameter-schema/form-mode/ParameterMappingInput.vue index d10ddda..837788f 100644 --- a/src/components/parameter-schema/form-mode/ParameterMappingInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterMappingInput.vue @@ -10,6 +10,7 @@ const props = defineProps<{ border?: ExtendedColors; mapping: Record<string, string | number>; allowRaw?: boolean; + id: string; }>(); const emit = defineEmits<{ @@ -30,6 +31,7 @@ const dynamicCssClasses = computed<string[]>(() => { <template> <select + :id="id" v-model="model" class="form-select" :class="dynamicCssClasses" diff --git a/src/components/parameter-schema/form-mode/ParameterNumberInput.vue b/src/components/parameter-schema/form-mode/ParameterNumberInput.vue index 1a37ea7..f717ee7 100644 --- a/src/components/parameter-schema/form-mode/ParameterNumberInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterNumberInput.vue @@ -20,6 +20,7 @@ const props = defineProps({ type: String as PropType<SizeModifierType>, }, border: String as PropType<ExtendedColors>, + id: String, }); const dynamicCssClasses = computed<string[]>(() => { @@ -36,6 +37,7 @@ const dynamicCssClasses = computed<string[]>(() => { <template> <input + :id="id" v-model="model" class="form-control flex-fill" :class="dynamicCssClasses" diff --git a/src/components/parameter-schema/form-mode/ParameterResourceInput.vue b/src/components/parameter-schema/form-mode/ParameterResourceInput.vue index d9dd92e..2081825 100644 --- a/src/components/parameter-schema/form-mode/ParameterResourceInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterResourceInput.vue @@ -17,6 +17,7 @@ const props = defineProps<{ sizeModifier?: SizeModifierType; border?: ExtendedColors; allowRaw?: boolean; + id: string; }>(); const emit = defineEmits<{ @@ -24,7 +25,6 @@ const emit = defineEmits<{ }>(); const resourceRepository = useResourceStore(); -const randomIDSuffix = Math.random().toString(16).substring(2, 8); type ResourcePath = { resource_id: string; @@ -158,6 +158,7 @@ onMounted(() => { <template> <select + :id="id + 'Resource'" class="form-select" :class="selectDynamicClass" :required="props.required" @@ -177,6 +178,7 @@ onMounted(() => { </option> </select> <select + :id="id + 'ResourceVersion'" class="form-select" :class="selectDynamicClass" :required="resource.resource_id.length > 0" @@ -199,6 +201,7 @@ onMounted(() => { </option> </select> <input + :id="id + 'ResourcePath'" v-model="resource.suffix" type="text" class="form-control" @@ -207,9 +210,9 @@ onMounted(() => { minlength="2" maxlength="256" pattern="\/\S*" - :list="'resource-tree-options-' + randomIDSuffix" + :list="'resource-tree-options-' + id" /> - <datalist :id="'resource-tree-options-' + randomIDSuffix"> + <datalist :id="'resource-tree-options-' + id"> <option v-for="file in resourceRepository.resourceTreeList[ resource.resource_version_id diff --git a/src/components/parameter-schema/form-mode/ParameterStringInput.vue b/src/components/parameter-schema/form-mode/ParameterStringInput.vue index 95bab52..97bf021 100644 --- a/src/components/parameter-schema/form-mode/ParameterStringInput.vue +++ b/src/components/parameter-schema/form-mode/ParameterStringInput.vue @@ -21,6 +21,7 @@ const props = defineProps({ border: String as PropType<ExtendedColors>, resourceParameter: Boolean, allowSwitch: Boolean, + id: String, }); const emit = defineEmits<{ @@ -54,6 +55,7 @@ const helpTextPresent = computed<boolean>(() => props.parameter["help_text"]); <template> <input + :id="id" ref="stringInput" v-model="model" class="form-control" diff --git a/src/components/workflows/modals/CreateWorkflowModal.vue b/src/components/workflows/modals/CreateWorkflowModal.vue index 0339257..3a86387 100644 --- a/src/components/workflows/modals/CreateWorkflowModal.vue +++ b/src/components/workflows/modals/CreateWorkflowModal.vue @@ -512,6 +512,7 @@ onMounted(() => { class="form-control" placeholder="v1.0.0" maxlength="10" + required @change="checkVersionValidity" /> <div diff --git a/src/utils/md5.d.ts b/src/utils/md5.d.ts new file mode 100644 index 0000000..db8c804 --- /dev/null +++ b/src/utils/md5.d.ts @@ -0,0 +1,7 @@ +/** + * Calculate MD5 hash of a string + * + * @param {string} d The string to hash. + * @returns {number} The hexdigest. + */ +export declare function md5(d: string): string; diff --git a/src/utils/md5.js b/src/utils/md5.js new file mode 100644 index 0000000..b464d8b --- /dev/null +++ b/src/utils/md5.js @@ -0,0 +1,498 @@ +export function md5(d) { + var r = M(V(Y(X(d), 8 * d.length))); + return r.toLowerCase(); +} + +function M(d) { + for (var _, m = "0123456789ABCDEF", f = "", r = 0; r < d.length; r++) + _ = d.charCodeAt(r); + f += m.charAt((_ >>> 4) & 15) + m.charAt(15 & _); + return f; +} + +function X(d) { + for (var _ = Array(d.length >> 2), m = 0; m < _.length; m++) _[m] = 0; + for (m = 0; m < 8 * d.length; m += 8) + _[m >> 5] |= (255 & d.charCodeAt(m / 8)) << m % 32; + return _; +} + +function V(d) { + for (var _ = "", m = 0; m < 32 * d.length; m += 8) + _ += String.fromCharCode((d[m >> 5] >>> m % 32) & 255); + return _; +} + +function Y(d, _) { + d[_ >> 5] |= 128 << _ % 32; + d[14 + (((_ + 64) >>> 9) << 4)] = _; + for ( + var m = 1732584193, f = -271733879, r = -1732584194, i = 271733878, n = 0; + n < d.length; + n += 16 + ) { + var h = m, + t = f, + g = r, + e = i; + f = md5_ii( + (f = md5_ii( + (f = md5_ii( + (f = md5_ii( + (f = md5_hh( + (f = md5_hh( + (f = md5_hh( + (f = md5_hh( + (f = md5_gg( + (f = md5_gg( + (f = md5_gg( + (f = md5_gg( + (f = md5_ff( + (f = md5_ff( + (f = md5_ff( + (f = md5_ff( + f, + (r = md5_ff( + r, + (i = md5_ff( + i, + (m = md5_ff( + m, + f, + r, + i, + d[n + 0], + 7, + -680876936, + )), + f, + r, + d[n + 1], + 12, + -389564586, + )), + m, + f, + d[n + 2], + 17, + 606105819, + )), + i, + m, + d[n + 3], + 22, + -1044525330, + )), + (r = md5_ff( + r, + (i = md5_ff( + i, + (m = md5_ff( + m, + f, + r, + i, + d[n + 4], + 7, + -176418897, + )), + f, + r, + d[n + 5], + 12, + 1200080426, + )), + m, + f, + d[n + 6], + 17, + -1473231341, + )), + i, + m, + d[n + 7], + 22, + -45705983, + )), + (r = md5_ff( + r, + (i = md5_ff( + i, + (m = md5_ff( + m, + f, + r, + i, + d[n + 8], + 7, + 1770035416, + )), + f, + r, + d[n + 9], + 12, + -1958414417, + )), + m, + f, + d[n + 10], + 17, + -42063, + )), + i, + m, + d[n + 11], + 22, + -1990404162, + )), + (r = md5_ff( + r, + (i = md5_ff( + i, + (m = md5_ff( + m, + f, + r, + i, + d[n + 12], + 7, + 1804603682, + )), + f, + r, + d[n + 13], + 12, + -40341101, + )), + m, + f, + d[n + 14], + 17, + -1502002290, + )), + i, + m, + d[n + 15], + 22, + 1236535329, + )), + (r = md5_gg( + r, + (i = md5_gg( + i, + (m = md5_gg( + m, + f, + r, + i, + d[n + 1], + 5, + -165796510, + )), + f, + r, + d[n + 6], + 9, + -1069501632, + )), + m, + f, + d[n + 11], + 14, + 643717713, + )), + i, + m, + d[n + 0], + 20, + -373897302, + )), + (r = md5_gg( + r, + (i = md5_gg( + i, + (m = md5_gg(m, f, r, i, d[n + 5], 5, -701558691)), + f, + r, + d[n + 10], + 9, + 38016083, + )), + m, + f, + d[n + 15], + 14, + -660478335, + )), + i, + m, + d[n + 4], + 20, + -405537848, + )), + (r = md5_gg( + r, + (i = md5_gg( + i, + (m = md5_gg(m, f, r, i, d[n + 9], 5, 568446438)), + f, + r, + d[n + 14], + 9, + -1019803690, + )), + m, + f, + d[n + 3], + 14, + -187363961, + )), + i, + m, + d[n + 8], + 20, + 1163531501, + )), + (r = md5_gg( + r, + (i = md5_gg( + i, + (m = md5_gg(m, f, r, i, d[n + 13], 5, -1444681467)), + f, + r, + d[n + 2], + 9, + -51403784, + )), + m, + f, + d[n + 7], + 14, + 1735328473, + )), + i, + m, + d[n + 12], + 20, + -1926607734, + )), + (r = md5_hh( + r, + (i = md5_hh( + i, + (m = md5_hh(m, f, r, i, d[n + 5], 4, -378558)), + f, + r, + d[n + 8], + 11, + -2022574463, + )), + m, + f, + d[n + 11], + 16, + 1839030562, + )), + i, + m, + d[n + 14], + 23, + -35309556, + )), + (r = md5_hh( + r, + (i = md5_hh( + i, + (m = md5_hh(m, f, r, i, d[n + 1], 4, -1530992060)), + f, + r, + d[n + 4], + 11, + 1272893353, + )), + m, + f, + d[n + 7], + 16, + -155497632, + )), + i, + m, + d[n + 10], + 23, + -1094730640, + )), + (r = md5_hh( + r, + (i = md5_hh( + i, + (m = md5_hh(m, f, r, i, d[n + 13], 4, 681279174)), + f, + r, + d[n + 0], + 11, + -358537222, + )), + m, + f, + d[n + 3], + 16, + -722521979, + )), + i, + m, + d[n + 6], + 23, + 76029189, + )), + (r = md5_hh( + r, + (i = md5_hh( + i, + (m = md5_hh(m, f, r, i, d[n + 9], 4, -640364487)), + f, + r, + d[n + 12], + 11, + -421815835, + )), + m, + f, + d[n + 15], + 16, + 530742520, + )), + i, + m, + d[n + 2], + 23, + -995338651, + )), + (r = md5_ii( + r, + (i = md5_ii( + i, + (m = md5_ii(m, f, r, i, d[n + 0], 6, -198630844)), + f, + r, + d[n + 7], + 10, + 1126891415, + )), + m, + f, + d[n + 14], + 15, + -1416354905, + )), + i, + m, + d[n + 5], + 21, + -57434055, + )), + (r = md5_ii( + r, + (i = md5_ii( + i, + (m = md5_ii(m, f, r, i, d[n + 12], 6, 1700485571)), + f, + r, + d[n + 3], + 10, + -1894986606, + )), + m, + f, + d[n + 10], + 15, + -1051523, + )), + i, + m, + d[n + 1], + 21, + -2054922799, + )), + (r = md5_ii( + r, + (i = md5_ii( + i, + (m = md5_ii(m, f, r, i, d[n + 8], 6, 1873313359)), + f, + r, + d[n + 15], + 10, + -30611744, + )), + m, + f, + d[n + 6], + 15, + -1560198380, + )), + i, + m, + d[n + 13], + 21, + 1309151649, + )), + (r = md5_ii( + r, + (i = md5_ii( + i, + (m = md5_ii(m, f, r, i, d[n + 4], 6, -145523070)), + f, + r, + d[n + 11], + 10, + -1120210379, + )), + m, + f, + d[n + 2], + 15, + 718787259, + )), + i, + m, + d[n + 9], + 21, + -343485551, + ); + m = safe_add(m, h); + f = safe_add(f, t); + r = safe_add(r, g); + i = safe_add(i, e); + } + return [m, f, r, i]; +} + +function md5_cmn(d, _, m, f, r, i) { + return safe_add(bit_rol(safe_add(safe_add(_, d), safe_add(f, i)), r), m); +} + +function md5_ff(d, _, m, f, r, i, n) { + return md5_cmn((_ & m) | (~_ & f), d, _, r, i, n); +} + +function md5_gg(d, _, m, f, r, i, n) { + return md5_cmn((_ & f) | (m & ~f), d, _, r, i, n); +} + +function md5_hh(d, _, m, f, r, i, n) { + return md5_cmn(_ ^ m ^ f, d, _, r, i, n); +} + +function md5_ii(d, _, m, f, r, i, n) { + return md5_cmn(m ^ (_ | ~f), d, _, r, i, n); +} + +function safe_add(d, _) { + var m = (65535 & d) + (65535 & _); + return (((d >> 16) + (_ >> 16) + (m >> 16)) << 16) | (65535 & m); +} + +function bit_rol(d, _) { + return (d << _) | (d >>> (32 - _)); +} diff --git a/tsconfig.json b/tsconfig.json index 508ccb8..9871f9e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "extends": [ - "@tsconfig/node20/tsconfig.json", + "@tsconfig/node22/tsconfig.json", "@vue/tsconfig/tsconfig.json" ], "include": [ -- GitLab