From 0701e9e13dd66cf595e66a4f9b72dee7e6e8b280 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Fri, 5 Sep 2025 08:53:57 +0200 Subject: [PATCH 01/42] chore!: update to new ESLint config Now nodejs LTS v22 is required. Further changes: - use provenance for npm - add more exports to reduce import size --- .github/workflows/pull.yml | 8 +- bun.lock | 1141 +++++++++--------------------------- eslint.config.mjs | 71 +-- package.json | 45 +- packages/ard/index.js | 2 +- packages/undici/request.js | 4 +- tests/ard.test.mjs | 8 +- tests/strings.test.mjs | 4 +- 8 files changed, 371 insertions(+), 912 deletions(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index fc48bae..6a19b69 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -4,9 +4,6 @@ on: pull_request_target: types: [labeled] -env: - NODE_VERSION: 20 - jobs: security: name: Check permissions for pull request runs @@ -20,6 +17,9 @@ jobs: needs: security name: Run Tests runs-on: ubuntu-latest + strategy: + matrix: + version: [20, 22] steps: - name: 👀 Checkout Code uses: actions/checkout@v4 @@ -27,7 +27,7 @@ jobs: - name: 🏗 Install Node.js uses: actions/setup-node@v4 with: - node-version: ${{ env.NODE_VERSION }} + node-version: ${{ matrix.version }} - name: 🛠 Setup Bun uses: oven-sh/setup-bun@v2 diff --git a/bun.lock b/bun.lock index 27b7fd8..77569a3 100644 --- a/bun.lock +++ b/bun.lock @@ -10,254 +10,33 @@ "undici": "7.13.0", }, "devDependencies": { - "@swrlab/style-guide": "^1.0.3", + "@swrlab/style-guide": "^2.0.7", + "@types/bun": "^1.2.21", "chai": "5.1.2", - "eslint": "^9.33.0", - "eslint-plugin-json": "^4.0.1", - "mocha": "^11.7.1", + "eslint": "^9.34.0", "prettier": "^3.6.2", }, }, }, "packages": { - "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], - "@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], + "@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="], - "@babel/compat-data": ["@babel/compat-data@7.26.2", "", {}, "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg=="], + "@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="], - "@babel/core": ["@babel/core@7.26.0", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.0", "@babel/generator": "^7.26.0", "@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-module-transforms": "^7.26.0", "@babel/helpers": "^7.26.0", "@babel/parser": "^7.26.0", "@babel/template": "^7.25.9", "@babel/traverse": "^7.25.9", "@babel/types": "^7.26.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg=="], + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], - "@babel/eslint-parser": ["@babel/eslint-parser@7.25.9", "", { "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.11.0", "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, "sha512-5UXfgpK0j0Xr/xIdgdLEhOFxaDZ0bRPWJJchRpqOSur/3rZoPbqqki5mm0p4NE2cs28krBEiSM2MB7//afRSQQ=="], + "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.53.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.39.1", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.8.0" } }, "sha512-Wyed8Wfn3vMNVwrZrgLMxmqwmlcCE1/RfUAOHFzMJb3QLH03mi9Yv1iOCZjif0yx5EZUeJ+17VD1MHPka9IQjQ=="], - "@babel/generator": ["@babel/generator@7.26.2", "", { "dependencies": { "@babel/parser": "^7.26.2", "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw=="], - - "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.25.9", "", { "dependencies": { "@babel/types": "^7.25.9" } }, "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g=="], - - "@babel/helper-builder-binary-assignment-operator-visitor": ["@babel/helper-builder-binary-assignment-operator-visitor@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g=="], - - "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.25.9", "", { "dependencies": { "@babel/compat-data": "^7.25.9", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ=="], - - "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.25.9", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-member-expression-to-functions": "^7.25.9", "@babel/helper-optimise-call-expression": "^7.25.9", "@babel/helper-replace-supers": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", "@babel/traverse": "^7.25.9", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ=="], - - "@babel/helper-create-regexp-features-plugin": ["@babel/helper-create-regexp-features-plugin@7.25.9", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "regexpu-core": "^6.1.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw=="], - - "@babel/helper-define-polyfill-provider": ["@babel/helper-define-polyfill-provider@0.6.3", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.22.6", "@babel/helper-plugin-utils": "^7.22.5", "debug": "^4.1.1", "lodash.debounce": "^4.0.8", "resolve": "^1.14.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg=="], - - "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ=="], - - "@babel/helper-module-imports": ["@babel/helper-module-imports@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw=="], - - "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.26.0", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw=="], - - "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.25.9", "", { "dependencies": { "@babel/types": "^7.25.9" } }, "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ=="], - - "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.25.9", "", {}, "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw=="], - - "@babel/helper-remap-async-to-generator": ["@babel/helper-remap-async-to-generator@7.25.9", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-wrap-function": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw=="], - - "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.25.9", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.25.9", "@babel/helper-optimise-call-expression": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ=="], - - "@babel/helper-simple-access": ["@babel/helper-simple-access@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q=="], - - "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.25.9", "", { "dependencies": { "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA=="], - - "@babel/helper-string-parser": ["@babel/helper-string-parser@7.25.9", "", {}, "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="], - - "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], - - "@babel/helper-validator-option": ["@babel/helper-validator-option@7.25.9", "", {}, "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw=="], - - "@babel/helper-wrap-function": ["@babel/helper-wrap-function@7.25.9", "", { "dependencies": { "@babel/template": "^7.25.9", "@babel/traverse": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g=="], - - "@babel/helpers": ["@babel/helpers@7.26.0", "", { "dependencies": { "@babel/template": "^7.25.9", "@babel/types": "^7.26.0" } }, "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw=="], - - "@babel/parser": ["@babel/parser@7.26.2", "", { "dependencies": { "@babel/types": "^7.26.0" }, "bin": "./bin/babel-parser.js" }, "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ=="], - - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": ["@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g=="], - - "@babel/plugin-bugfix-safari-class-field-initializer-scope": ["@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw=="], - - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": ["@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug=="], - - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": ["@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", "@babel/plugin-transform-optional-chaining": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.13.0" } }, "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g=="], - - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": ["@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg=="], - - "@babel/plugin-proposal-decorators": ["@babel/plugin-proposal-decorators@7.24.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.24.7", "@babel/helper-plugin-utils": "^7.24.7", "@babel/plugin-syntax-decorators": "^7.24.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-RL9GR0pUG5Kc8BUWLNDm2T5OpYwSX15r98I0IkgmRQTXuELq/OynH8xtMTMvTJFjXbMWFVTKtYkTaYQsuAwQlQ=="], - - "@babel/plugin-proposal-private-property-in-object": ["@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2", "", { "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w=="], - - "@babel/plugin-syntax-async-generators": ["@babel/plugin-syntax-async-generators@7.8.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw=="], - - "@babel/plugin-syntax-class-properties": ["@babel/plugin-syntax-class-properties@7.12.13", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA=="], - - "@babel/plugin-syntax-class-static-block": ["@babel/plugin-syntax-class-static-block@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw=="], - - "@babel/plugin-syntax-decorators": ["@babel/plugin-syntax-decorators@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg=="], - - "@babel/plugin-syntax-dynamic-import": ["@babel/plugin-syntax-dynamic-import@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ=="], - - "@babel/plugin-syntax-export-namespace-from": ["@babel/plugin-syntax-export-namespace-from@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.3" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q=="], - - "@babel/plugin-syntax-flow": ["@babel/plugin-syntax-flow@7.26.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg=="], - - "@babel/plugin-syntax-import-assertions": ["@babel/plugin-syntax-import-assertions@7.26.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg=="], - - "@babel/plugin-syntax-import-attributes": ["@babel/plugin-syntax-import-attributes@7.26.0", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A=="], - - "@babel/plugin-syntax-import-meta": ["@babel/plugin-syntax-import-meta@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g=="], - - "@babel/plugin-syntax-json-strings": ["@babel/plugin-syntax-json-strings@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA=="], - - "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA=="], - - "@babel/plugin-syntax-logical-assignment-operators": ["@babel/plugin-syntax-logical-assignment-operators@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig=="], - - "@babel/plugin-syntax-nullish-coalescing-operator": ["@babel/plugin-syntax-nullish-coalescing-operator@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ=="], - - "@babel/plugin-syntax-numeric-separator": ["@babel/plugin-syntax-numeric-separator@7.10.4", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug=="], - - "@babel/plugin-syntax-object-rest-spread": ["@babel/plugin-syntax-object-rest-spread@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA=="], - - "@babel/plugin-syntax-optional-catch-binding": ["@babel/plugin-syntax-optional-catch-binding@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q=="], - - "@babel/plugin-syntax-optional-chaining": ["@babel/plugin-syntax-optional-chaining@7.8.3", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg=="], - - "@babel/plugin-syntax-private-property-in-object": ["@babel/plugin-syntax-private-property-in-object@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg=="], - - "@babel/plugin-syntax-top-level-await": ["@babel/plugin-syntax-top-level-await@7.14.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw=="], - - "@babel/plugin-syntax-unicode-sets-regex": ["@babel/plugin-syntax-unicode-sets-regex@7.18.6", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg=="], - - "@babel/plugin-transform-arrow-functions": ["@babel/plugin-transform-arrow-functions@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg=="], - - "@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-remap-async-to-generator": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw=="], - - "@babel/plugin-transform-async-to-generator": ["@babel/plugin-transform-async-to-generator@7.25.9", "", { "dependencies": { "@babel/helper-module-imports": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-remap-async-to-generator": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ=="], - - "@babel/plugin-transform-block-scoped-functions": ["@babel/plugin-transform-block-scoped-functions@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA=="], - - "@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg=="], - - "@babel/plugin-transform-class-properties": ["@babel/plugin-transform-class-properties@7.25.9", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q=="], - - "@babel/plugin-transform-class-static-block": ["@babel/plugin-transform-class-static-block@7.26.0", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ=="], - - "@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.25.9", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-replace-supers": "^7.25.9", "@babel/traverse": "^7.25.9", "globals": "^11.1.0" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg=="], - - "@babel/plugin-transform-computed-properties": ["@babel/plugin-transform-computed-properties@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/template": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA=="], - - "@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ=="], - - "@babel/plugin-transform-dotall-regex": ["@babel/plugin-transform-dotall-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA=="], - - "@babel/plugin-transform-duplicate-keys": ["@babel/plugin-transform-duplicate-keys@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw=="], - - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": ["@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog=="], - - "@babel/plugin-transform-dynamic-import": ["@babel/plugin-transform-dynamic-import@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg=="], - - "@babel/plugin-transform-exponentiation-operator": ["@babel/plugin-transform-exponentiation-operator@7.25.9", "", { "dependencies": { "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA=="], - - "@babel/plugin-transform-export-namespace-from": ["@babel/plugin-transform-export-namespace-from@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww=="], - - "@babel/plugin-transform-flow-strip-types": ["@babel/plugin-transform-flow-strip-types@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/plugin-syntax-flow": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-/VVukELzPDdci7UUsWQaSkhgnjIWXnIyRpM02ldxaVoFK96c41So8JcKT3m0gYjyv7j5FNPGS5vfELrWalkbDA=="], - - "@babel/plugin-transform-for-of": ["@babel/plugin-transform-for-of@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A=="], - - "@babel/plugin-transform-function-name": ["@babel/plugin-transform-function-name@7.25.9", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA=="], - - "@babel/plugin-transform-json-strings": ["@babel/plugin-transform-json-strings@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw=="], - - "@babel/plugin-transform-literals": ["@babel/plugin-transform-literals@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ=="], - - "@babel/plugin-transform-logical-assignment-operators": ["@babel/plugin-transform-logical-assignment-operators@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q=="], - - "@babel/plugin-transform-member-expression-literals": ["@babel/plugin-transform-member-expression-literals@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA=="], - - "@babel/plugin-transform-modules-amd": ["@babel/plugin-transform-modules-amd@7.25.9", "", { "dependencies": { "@babel/helper-module-transforms": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw=="], - - "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.25.9", "", { "dependencies": { "@babel/helper-module-transforms": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-simple-access": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg=="], - - "@babel/plugin-transform-modules-systemjs": ["@babel/plugin-transform-modules-systemjs@7.25.9", "", { "dependencies": { "@babel/helper-module-transforms": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9", "@babel/traverse": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA=="], - - "@babel/plugin-transform-modules-umd": ["@babel/plugin-transform-modules-umd@7.25.9", "", { "dependencies": { "@babel/helper-module-transforms": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw=="], - - "@babel/plugin-transform-named-capturing-groups-regex": ["@babel/plugin-transform-named-capturing-groups-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA=="], - - "@babel/plugin-transform-new-target": ["@babel/plugin-transform-new-target@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ=="], - - "@babel/plugin-transform-nullish-coalescing-operator": ["@babel/plugin-transform-nullish-coalescing-operator@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog=="], - - "@babel/plugin-transform-numeric-separator": ["@babel/plugin-transform-numeric-separator@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q=="], - - "@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.25.9", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/plugin-transform-parameters": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg=="], - - "@babel/plugin-transform-object-super": ["@babel/plugin-transform-object-super@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-replace-supers": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A=="], - - "@babel/plugin-transform-optional-catch-binding": ["@babel/plugin-transform-optional-catch-binding@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g=="], - - "@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A=="], - - "@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g=="], - - "@babel/plugin-transform-private-methods": ["@babel/plugin-transform-private-methods@7.25.9", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw=="], - - "@babel/plugin-transform-private-property-in-object": ["@babel/plugin-transform-private-property-in-object@7.25.9", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw=="], - - "@babel/plugin-transform-property-literals": ["@babel/plugin-transform-property-literals@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA=="], - - "@babel/plugin-transform-react-display-name": ["@babel/plugin-transform-react-display-name@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ=="], - - "@babel/plugin-transform-react-jsx": ["@babel/plugin-transform-react-jsx@7.25.9", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-module-imports": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", "@babel/plugin-syntax-jsx": "^7.25.9", "@babel/types": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw=="], - - "@babel/plugin-transform-react-jsx-development": ["@babel/plugin-transform-react-jsx-development@7.25.9", "", { "dependencies": { "@babel/plugin-transform-react-jsx": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw=="], - - "@babel/plugin-transform-react-pure-annotations": ["@babel/plugin-transform-react-pure-annotations@7.25.9", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg=="], - - "@babel/plugin-transform-regenerator": ["@babel/plugin-transform-regenerator@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "regenerator-transform": "^0.15.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg=="], - - "@babel/plugin-transform-reserved-words": ["@babel/plugin-transform-reserved-words@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg=="], - - "@babel/plugin-transform-shorthand-properties": ["@babel/plugin-transform-shorthand-properties@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng=="], - - "@babel/plugin-transform-spread": ["@babel/plugin-transform-spread@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A=="], - - "@babel/plugin-transform-sticky-regex": ["@babel/plugin-transform-sticky-regex@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA=="], - - "@babel/plugin-transform-template-literals": ["@babel/plugin-transform-template-literals@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw=="], - - "@babel/plugin-transform-typeof-symbol": ["@babel/plugin-transform-typeof-symbol@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA=="], - - "@babel/plugin-transform-unicode-escapes": ["@babel/plugin-transform-unicode-escapes@7.25.9", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q=="], - - "@babel/plugin-transform-unicode-property-regex": ["@babel/plugin-transform-unicode-property-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg=="], - - "@babel/plugin-transform-unicode-regex": ["@babel/plugin-transform-unicode-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA=="], - - "@babel/plugin-transform-unicode-sets-regex": ["@babel/plugin-transform-unicode-sets-regex@7.25.9", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ=="], - - "@babel/preset-env": ["@babel/preset-env@7.25.4", "", { "dependencies": { "@babel/compat-data": "^7.25.4", "@babel/helper-compilation-targets": "^7.25.2", "@babel/helper-plugin-utils": "^7.24.8", "@babel/helper-validator-option": "^7.24.8", "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", "@babel/plugin-syntax-class-static-block": "^7.14.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", "@babel/plugin-syntax-import-assertions": "^7.24.7", "@babel/plugin-syntax-import-attributes": "^7.24.7", "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", "@babel/plugin-transform-arrow-functions": "^7.24.7", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoped-functions": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-class-static-block": "^7.24.7", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-computed-properties": "^7.24.7", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-dotall-regex": "^7.24.7", "@babel/plugin-transform-duplicate-keys": "^7.24.7", "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", "@babel/plugin-transform-dynamic-import": "^7.24.7", "@babel/plugin-transform-exponentiation-operator": "^7.24.7", "@babel/plugin-transform-export-namespace-from": "^7.24.7", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-function-name": "^7.25.1", "@babel/plugin-transform-json-strings": "^7.24.7", "@babel/plugin-transform-literals": "^7.25.2", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-member-expression-literals": "^7.24.7", "@babel/plugin-transform-modules-amd": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-modules-systemjs": "^7.25.0", "@babel/plugin-transform-modules-umd": "^7.24.7", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-new-target": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-numeric-separator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-object-super": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.25.4", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-property-literals": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-reserved-words": "^7.24.7", "@babel/plugin-transform-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-template-literals": "^7.24.7", "@babel/plugin-transform-typeof-symbol": "^7.24.8", "@babel/plugin-transform-unicode-escapes": "^7.24.7", "@babel/plugin-transform-unicode-property-regex": "^7.24.7", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/plugin-transform-unicode-sets-regex": "^7.25.4", "@babel/preset-modules": "0.1.6-no-external-plugins", "babel-plugin-polyfill-corejs2": "^0.4.10", "babel-plugin-polyfill-corejs3": "^0.10.6", "babel-plugin-polyfill-regenerator": "^0.6.1", "core-js-compat": "^3.37.1", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw=="], - - "@babel/preset-flow": ["@babel/preset-flow@7.24.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-validator-option": "^7.24.7", "@babel/plugin-transform-flow-strip-types": "^7.24.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-NL3Lo0NorCU607zU3NwRyJbpaB6E3t0xtd3LfAQKDfkeX4/ggcDXvkmkW42QWT5owUeW/jAe4hn+2qvkV1IbfQ=="], - - "@babel/preset-modules": ["@babel/preset-modules@0.1.6-no-external-plugins", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@babel/types": "^7.4.4", "esutils": "^2.0.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA=="], - - "@babel/preset-react": ["@babel/preset-react@7.24.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.24.7", "@babel/helper-validator-option": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.24.7", "@babel/plugin-transform-react-jsx-development": "^7.24.7", "@babel/plugin-transform-react-pure-annotations": "^7.24.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag=="], - - "@babel/runtime": ["@babel/runtime@7.26.0", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw=="], - - "@babel/template": ["@babel/template@7.25.9", "", { "dependencies": { "@babel/code-frame": "^7.25.9", "@babel/parser": "^7.25.9", "@babel/types": "^7.25.9" } }, "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg=="], - - "@babel/traverse": ["@babel/traverse@7.25.9", "", { "dependencies": { "@babel/code-frame": "^7.25.9", "@babel/generator": "^7.25.9", "@babel/parser": "^7.25.9", "@babel/template": "^7.25.9", "@babel/types": "^7.25.9", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw=="], - - "@babel/types": ["@babel/types@7.26.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.25.9", "@babel/helper-validator-identifier": "^7.25.9" } }, "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA=="], + "@eslint-community/eslint-plugin-eslint-comments": ["@eslint-community/eslint-plugin-eslint-comments@4.5.0", "", { "dependencies": { "escape-string-regexp": "^4.0.0", "ignore": "^5.2.4" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-MAhuTKlr4y/CE3WYX26raZjy+I/kS2PLKSzvfmDCGrBLTFHOYwqROZdr4XwPgXwX3K9rjzMr4pSmUWGnzsUyMg=="], "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA=="], "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], + "@eslint/compat": ["@eslint/compat@1.3.2", "", { "peerDependencies": { "eslint": "^8.40 || 9" }, "optionalPeers": ["eslint"] }, "sha512-jRNwzTbd6p2Rw4sZ1CgWRS8YMtqG15YyZf7zvb6gY2rB2u6n+2Z+ELW0GtL0fQgyl0pr4Y/BzBfng/BdsereRA=="], + "@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="], "@eslint/config-helpers": ["@eslint/config-helpers@0.3.1", "", {}, "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA=="], @@ -266,7 +45,9 @@ "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], - "@eslint/js": ["@eslint/js@9.15.0", "", {}, "sha512-tMTqrY+EzbXmKJR5ToI8lxu7jaN5EdmrBFJpQk5JmSlyLsx6o4t27r883K5xsLuCYCpfKBCGswMSWXsM+jB7lg=="], + "@eslint/js": ["@eslint/js@9.34.0", "", {}, "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw=="], + + "@eslint/markdown": ["@eslint/markdown@7.2.0", "", { "dependencies": { "@eslint/core": "^0.15.2", "@eslint/plugin-kit": "^0.3.5", "github-slugger": "^2.0.0", "mdast-util-from-markdown": "^2.0.2", "mdast-util-frontmatter": "^2.0.1", "mdast-util-gfm": "^3.1.0", "micromark-extension-frontmatter": "^2.0.0", "micromark-extension-gfm": "^3.0.0", "micromark-util-normalize-identifier": "^2.0.1" } }, "sha512-cmDloByulvKzofM0tIkSGWwxMcrKOLsXZC+EM0FLkRIrxKzW+2RkZAt9TAh37EtQRmx1M4vjBEmlC6R0wiGkog=="], "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], @@ -288,19 +69,7 @@ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], - "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], - - "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.5", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg=="], - - "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], - - "@jridgewell/set-array": ["@jridgewell/set-array@1.2.1", "", {}, "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A=="], - - "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.0", "", {}, "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="], - - "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.25", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ=="], - - "@nicolo-ribaudo/eslint-scope-5-internals": ["@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1", "", { "dependencies": { "eslint-scope": "5.1.1" } }, "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -308,109 +77,121 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], - - "@pkgr/core": ["@pkgr/core@0.1.1", "", {}, "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA=="], + "@pkgr/core": ["@pkgr/core@0.2.9", "", {}, "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA=="], - "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="], + "@swrlab/style-guide": ["@swrlab/style-guide@2.0.7", "", { "dependencies": { "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0", "@eslint/js": "^9.34.0", "@eslint/markdown": "^7.2.0", "eslint-config-flat-gitignore": "^2.1.0", "eslint-config-prettier": "^10.1.8", "eslint-flat-config-utils": "^2.1.1", "eslint-plugin-de-morgan": "^1.3.1", "eslint-plugin-import-x": "^4.16.1", "eslint-plugin-jsdoc": "^54.2.1", "eslint-plugin-jsonc": "^2.20.1", "eslint-plugin-n": "^17.21.3", "eslint-plugin-perfectionist": "^4.15.0", "eslint-plugin-pnpm": "^1.1.1", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-regexp": "^2.10.0", "eslint-plugin-security": "^3.0.1", "eslint-plugin-sonarjs": "^3.0.5", "eslint-plugin-testing-library": "^7.6.8", "eslint-plugin-unicorn": "^60.0.0", "eslint-plugin-unused-imports": "^4.2.0", "eslint-plugin-vue": "^10.4.0", "eslint-plugin-vuejs-accessibility": "^2.4.1", "eslint-plugin-yml": "^1.18.0", "globals": "^16.3.0", "jsonc-eslint-parser": "^2.4.0", "local-pkg": "^1.1.2", "prettier": "^3.6.2", "typescript-eslint": "^8.42.0", "vue-eslint-parser": "^10.2.0", "yaml-eslint-parser": "^1.3.0" }, "peerDependencies": { "eslint": "^9.34.0" } }, "sha512-4GHnx/7iiXrT146tIiql8O5cSDvr0IZ17JA7307O+vazeURrJQlVsrW/OITCsooD/gWa9rcnxj2uWSe8OioBdA=="], - "@stylistic/eslint-plugin-js": ["@stylistic/eslint-plugin-js@2.10.1", "", { "dependencies": { "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0" }, "peerDependencies": { "eslint": ">=8.40.0" } }, "sha512-IikL/RKy9Sk2UMDUUpqrEcwDeYzUEt6SaL2/UVCFuVQxKACHSgStT0NxXkxZmBOUforaU52FPf2Su07FYH5s5g=="], + "@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="], - "@swrlab/style-guide": ["@swrlab/style-guide@1.0.3", "", { "dependencies": { "@babel/core": "^7.26.0", "@babel/eslint-parser": "^7.25.9", "@eslint/js": "^9.15.0", "@stylistic/eslint-plugin-js": "^2.10.1", "eslint-config-prettier": "^9.1.0", "eslint-import-resolver-alias": "^1.1.2", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-import-x": "^4.4.2", "eslint-plugin-jsonc": "^2.18.2", "eslint-plugin-n": "^17.13.2", "eslint-plugin-perfectionist": "^3.9.1", "eslint-plugin-prettier": "^5.2.1", "eslint-plugin-security": "^3.0.1", "eslint-plugin-sonarjs": "^2.0.4", "eslint-plugin-testing-library": "^6.4.0", "eslint-plugin-unicorn": "^56.0.0", "eslint-plugin-unused-imports": "^4.1.4", "eslint-plugin-vue": "^9.31.0", "globals": "^15.12.0" }, "peerDependencies": { "eslint": "^9.13.0", "prettier": ">=3.0.0" }, "optionalPeers": ["eslint", "prettier"] }, "sha512-zuwQOiP62NSDhJcrt46w4csY8fJgbhuId7dl0LVaYVrbD5PnbkRMg3RTeAYS2Swhnh4VlBzbN17+3+8OWjjP3g=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], - "@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="], + "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], "@types/caseless": ["@types/caseless@0.12.5", "", {}, "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg=="], + "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], + "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], - "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], + + "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], "@types/node": ["@types/node@18.19.64", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ=="], - "@types/normalize-package-data": ["@types/normalize-package-data@2.4.4", "", {}, "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA=="], + "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], "@types/request": ["@types/request@2.48.12", "", { "dependencies": { "@types/caseless": "*", "@types/node": "*", "@types/tough-cookie": "*", "form-data": "^2.5.0" } }, "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw=="], - "@types/semver": ["@types/semver@7.5.8", "", {}, "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ=="], - "@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="], - "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@7.16.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "7.16.1", "@typescript-eslint/type-utils": "7.16.1", "@typescript-eslint/utils": "7.16.1", "@typescript-eslint/visitor-keys": "7.16.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "@typescript-eslint/parser": "^7.0.0", "eslint": "^8.56.0" } }, "sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A=="], + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], - "@typescript-eslint/parser": ["@typescript-eslint/parser@7.18.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", "@typescript-eslint/typescript-estree": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg=="], + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.42.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/type-utils": "8.42.0", "@typescript-eslint/utils": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.42.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ=="], - "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.14.0", "", { "dependencies": { "@typescript-eslint/types": "8.14.0", "@typescript-eslint/visitor-keys": "8.14.0" } }, "sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw=="], + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.42.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg=="], - "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@7.16.1", "", { "dependencies": { "@typescript-eslint/typescript-estree": "7.16.1", "@typescript-eslint/utils": "7.16.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA=="], + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.42.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.42.0", "@typescript-eslint/types": "^8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg=="], - "@typescript-eslint/types": ["@typescript-eslint/types@8.14.0", "", {}, "sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g=="], + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0" } }, "sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw=="], - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.14.0", "", { "dependencies": { "@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", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" } }, "sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ=="], + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.42.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ=="], - "@typescript-eslint/utils": ["@typescript-eslint/utils@8.14.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "8.14.0", "@typescript-eslint/types": "8.14.0", "@typescript-eslint/typescript-estree": "8.14.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA=="], + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/utils": "8.42.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-9KChw92sbPTYVFw3JLRH1ockhyR3zqqn9lQXol3/YbI6jVxzWoGcT3AsAW0mu1MY0gYtsXnUGV/AKpkAj5tVlQ=="], - "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@7.16.1", "", { "dependencies": { "@typescript-eslint/types": "7.16.1", "eslint-visitor-keys": "^3.4.3" } }, "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg=="], + "@typescript-eslint/types": ["@typescript-eslint/types@8.42.0", "", {}, "sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw=="], - "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.42.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.42.0", "@typescript-eslint/tsconfig-utils": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ=="], - "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.42.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g=="], - "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-3WbiuzoEowaEn8RSnhJBrxSwX8ULYE9CXaPepS2C2W3NSA5NNIvBaslpBSBElPq0UGr0xVJlXFWOAKIkyylydQ=="], - "agent-base": ["agent-base@7.1.1", "", { "dependencies": { "debug": "^4.3.4" } }, "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA=="], + "@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="], - "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + "@unrs/resolver-binding-android-arm64": ["@unrs/resolver-binding-android-arm64@1.11.1", "", { "os": "android", "cpu": "arm64" }, "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g=="], - "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g=="], - "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ=="], - "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "@unrs/resolver-binding-freebsd-x64": ["@unrs/resolver-binding-freebsd-x64@1.11.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw=="], - "aria-query": ["aria-query@5.1.3", "", { "dependencies": { "deep-equal": "^2.0.5" } }, "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ=="], + "@unrs/resolver-binding-linux-arm-gnueabihf": ["@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw=="], - "array-buffer-byte-length": ["array-buffer-byte-length@1.0.1", "", { "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" } }, "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg=="], + "@unrs/resolver-binding-linux-arm-musleabihf": ["@unrs/resolver-binding-linux-arm-musleabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw=="], - "array-includes": ["array-includes@3.1.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" } }, "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ=="], + "@unrs/resolver-binding-linux-arm64-gnu": ["@unrs/resolver-binding-linux-arm64-gnu@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ=="], - "array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="], + "@unrs/resolver-binding-linux-arm64-musl": ["@unrs/resolver-binding-linux-arm64-musl@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w=="], - "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="], + "@unrs/resolver-binding-linux-ppc64-gnu": ["@unrs/resolver-binding-linux-ppc64-gnu@1.11.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA=="], - "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ=="], + "@unrs/resolver-binding-linux-riscv64-gnu": ["@unrs/resolver-binding-linux-riscv64-gnu@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ=="], - "array.prototype.flat": ["array.prototype.flat@1.3.2", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" } }, "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA=="], + "@unrs/resolver-binding-linux-riscv64-musl": ["@unrs/resolver-binding-linux-riscv64-musl@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew=="], - "array.prototype.flatmap": ["array.prototype.flatmap@1.3.2", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" } }, "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ=="], + "@unrs/resolver-binding-linux-s390x-gnu": ["@unrs/resolver-binding-linux-s390x-gnu@1.11.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg=="], - "array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="], + "@unrs/resolver-binding-linux-x64-gnu": ["@unrs/resolver-binding-linux-x64-gnu@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w=="], - "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.3", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", "define-properties": "^1.2.1", "es-abstract": "^1.22.3", "es-errors": "^1.2.1", "get-intrinsic": "^1.2.3", "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" } }, "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A=="], + "@unrs/resolver-binding-linux-x64-musl": ["@unrs/resolver-binding-linux-x64-musl@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA=="], - "arrify": ["arrify@2.0.1", "", {}, "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="], + "@unrs/resolver-binding-wasm32-wasi": ["@unrs/resolver-binding-wasm32-wasi@1.11.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.11" }, "cpu": "none" }, "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ=="], - "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + "@unrs/resolver-binding-win32-arm64-msvc": ["@unrs/resolver-binding-win32-arm64-msvc@1.11.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw=="], - "ast-types-flow": ["ast-types-flow@0.0.8", "", {}, "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ=="], + "@unrs/resolver-binding-win32-ia32-msvc": ["@unrs/resolver-binding-win32-ia32-msvc@1.11.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ=="], - "async-retry": ["async-retry@1.3.3", "", { "dependencies": { "retry": "0.13.1" } }, "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw=="], + "@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g=="], - "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], - "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], + "acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], - "axe-core": ["axe-core@4.10.2", "", {}, "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w=="], + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "agent-base": ["agent-base@7.1.1", "", { "dependencies": { "debug": "^4.3.4" } }, "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA=="], - "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], + "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], - "babel-plugin-polyfill-corejs2": ["babel-plugin-polyfill-corejs2@0.4.12", "", { "dependencies": { "@babel/compat-data": "^7.22.6", "@babel/helper-define-polyfill-provider": "^0.6.3", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og=="], + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], - "babel-plugin-polyfill-corejs3": ["babel-plugin-polyfill-corejs3@0.10.6", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.2", "core-js-compat": "^3.38.0" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA=="], + "are-docs-informative": ["are-docs-informative@0.0.2", "", {}, "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig=="], - "babel-plugin-polyfill-regenerator": ["babel-plugin-polyfill-regenerator@0.6.3", "", { "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.3" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q=="], + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], + + "arrify": ["arrify@2.0.1", "", {}, "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="], + + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + + "async-retry": ["async-retry@1.3.3", "", { "dependencies": { "retry": "0.13.1" } }, "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw=="], + + "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], @@ -424,173 +205,139 @@ "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], - "browser-stdout": ["browser-stdout@1.3.1", "", {}, "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="], - - "browserslist": ["browserslist@4.24.2", "", { "dependencies": { "caniuse-lite": "^1.0.30001669", "electron-to-chromium": "^1.5.41", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg=="], + "browserslist": ["browserslist@4.25.4", "", { "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg=="], "buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="], "builtin-modules": ["builtin-modules@3.3.0", "", {}, "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw=="], - "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], + "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], - "call-bind": ["call-bind@1.0.7", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.1" } }, "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w=="], + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], - "camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="], + "caniuse-lite": ["caniuse-lite@1.0.30001739", "", {}, "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA=="], - "caniuse-lite": ["caniuse-lite@1.0.30001680", "", {}, "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA=="], + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], "chai": ["chai@5.1.2", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], + "change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], + + "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], - "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], - "ci-info": ["ci-info@4.1.0", "", {}, "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A=="], + "ci-info": ["ci-info@4.3.0", "", {}, "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ=="], "clean-regexp": ["clean-regexp@1.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw=="], - "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], - "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + "comment-parser": ["comment-parser@1.4.1", "", {}, "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg=="], + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], - "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], - "core-js-compat": ["core-js-compat@3.39.0", "", { "dependencies": { "browserslist": "^4.24.2" } }, "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw=="], + "core-js-compat": ["core-js-compat@3.45.1", "", { "dependencies": { "browserslist": "^4.25.3" } }, "sha512-tqTt5T4PzsMIZ430XGviK4vzYSoeNJ6CXODi6c/voxOT6IZqBht5/EKaSNnYiEjjRYxjVz7DQIsOsY0XNi8PIA=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], - "damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="], - - "data-view-buffer": ["data-view-buffer@1.0.1", "", { "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA=="], - - "data-view-byte-length": ["data-view-byte-length@1.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ=="], - - "data-view-byte-offset": ["data-view-byte-offset@1.0.0", "", { "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA=="], + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], "debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], - "decamelize": ["decamelize@4.0.0", "", {}, "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ=="], + "decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="], "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], - "deep-equal": ["deep-equal@2.2.3", "", { "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.5", "es-get-iterator": "^1.1.3", "get-intrinsic": "^1.2.2", "is-arguments": "^1.1.1", "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "isarray": "^2.0.5", "object-is": "^1.1.5", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.5.1", "side-channel": "^1.0.4", "which-boxed-primitive": "^1.0.2", "which-collection": "^1.0.1", "which-typed-array": "^1.1.13" } }, "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA=="], - "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], - "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], - - "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], - "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], - "detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], - - "diff": ["diff@7.0.0", "", {}, "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw=="], + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], - "dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="], + "detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], - "doctrine": ["doctrine@3.0.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="], + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], "duplexify": ["duplexify@4.1.3", "", { "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", "stream-shift": "^1.0.2" } }, "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA=="], - "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], - "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], - "electron-to-chromium": ["electron-to-chromium@1.5.62", "", {}, "sha512-t8c+zLmJHa9dJy96yBZRXGQYoiCEnHYgFwn1asvSPZSUdVxnB62A4RASd7k41ytG3ErFBA0TpHlKg9D9SQBmLg=="], + "electron-to-chromium": ["electron-to-chromium@1.5.214", "", {}, "sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q=="], - "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + "emoji-regex": ["emoji-regex@10.5.0", "", {}, "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg=="], + + "empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="], "end-of-stream": ["end-of-stream@1.4.4", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q=="], "enhanced-resolve": ["enhanced-resolve@5.17.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg=="], - "error-ex": ["error-ex@1.3.2", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g=="], - - "es-abstract": ["es-abstract@1.23.5", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", "data-view-buffer": "^1.0.1", "data-view-byte-length": "^1.0.1", "data-view-byte-offset": "^1.0.0", "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", "get-intrinsic": "^1.2.4", "get-symbol-description": "^1.0.2", "globalthis": "^1.0.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "hasown": "^2.0.2", "internal-slot": "^1.0.7", "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", "is-data-view": "^1.0.1", "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.3", "object-keys": "^1.1.1", "object.assign": "^4.1.5", "regexp.prototype.flags": "^1.5.3", "safe-array-concat": "^1.1.2", "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.9", "string.prototype.trimend": "^1.0.8", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.2", "typed-array-byte-length": "^1.0.1", "typed-array-byte-offset": "^1.0.2", "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", "which-typed-array": "^1.1.15" } }, "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ=="], - - "es-define-property": ["es-define-property@1.0.0", "", { "dependencies": { "get-intrinsic": "^1.2.4" } }, "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ=="], - - "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], - - "es-get-iterator": ["es-get-iterator@1.1.3", "", { "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.1.3", "has-symbols": "^1.0.3", "is-arguments": "^1.1.1", "is-map": "^2.0.2", "is-set": "^2.0.2", "is-string": "^1.0.7", "isarray": "^2.0.5", "stop-iteration-iterator": "^1.0.0" } }, "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw=="], - - "es-iterator-helpers": ["es-iterator-helpers@1.2.0", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "globalthis": "^1.0.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", "iterator.prototype": "^1.1.3", "safe-array-concat": "^1.1.2" } }, "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q=="], - - "es-object-atoms": ["es-object-atoms@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw=="], - - "es-set-tostringtag": ["es-set-tostringtag@2.0.3", "", { "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", "hasown": "^2.0.1" } }, "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ=="], - - "es-shim-unscopables": ["es-shim-unscopables@1.0.2", "", { "dependencies": { "hasown": "^2.0.0" } }, "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw=="], - - "es-to-primitive": ["es-to-primitive@1.2.1", "", { "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", "is-symbol": "^1.0.2" } }, "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA=="], - "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - "eslint": ["eslint@9.33.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.33.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA=="], + "eslint": ["eslint@9.34.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.34.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg=="], - "eslint-compat-utils": ["eslint-compat-utils@0.6.3", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-9IDdksh5pUYP2ZLi7mOdROxVjLY8gY2qKxprmrJ/5Dyqud7M/IFKxF3o0VLlRhITm1pK6Fk7NiBxE39M/VlUcw=="], + "eslint-compat-utils": ["eslint-compat-utils@0.6.5", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ=="], - "eslint-config-prettier": ["eslint-config-prettier@9.1.0", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw=="], + "eslint-config-flat-gitignore": ["eslint-config-flat-gitignore@2.1.0", "", { "dependencies": { "@eslint/compat": "^1.2.5" }, "peerDependencies": { "eslint": "^9.5.0" } }, "sha512-cJzNJ7L+psWp5mXM7jBX+fjHtBvvh06RBlcweMhKD8jWqQw0G78hOW5tpVALGHGFPsBV+ot2H+pdDGJy6CV8pA=="], - "eslint-import-resolver-alias": ["eslint-import-resolver-alias@1.1.2", "", { "peerDependencies": { "eslint-plugin-import": ">=1.4.0" } }, "sha512-WdviM1Eu834zsfjHtcGHtGfcu+F30Od3V7I9Fi57uhBEwPkjDcii7/yW8jAT+gOhn4P/vOxxNAXbFAKsrrc15w=="], + "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], - "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="], + "eslint-flat-config-utils": ["eslint-flat-config-utils@2.1.1", "", { "dependencies": { "pathe": "^2.0.3" } }, "sha512-K8eaPkBemHkfbYsZH7z4lZ/tt6gNSsVh535Wh9W9gQBS2WjvfUbbVr2NZR3L1yiRCLuOEimYfPxCxODczD4Opg=="], + + "eslint-import-context": ["eslint-import-context@0.1.9", "", { "dependencies": { "get-tsconfig": "^4.10.1", "stable-hash-x": "^0.2.0" }, "peerDependencies": { "unrs-resolver": "^1.0.0" }, "optionalPeers": ["unrs-resolver"] }, "sha512-K9Hb+yRaGAGUbwjhFNHvSmmkZs9+zbuoe3kFQ4V1wYjrepUFYM2dZAfNtjbbj3qsPfUfsA68Bx/ICWQMi+C8Eg=="], "eslint-json-compat-utils": ["eslint-json-compat-utils@0.2.1", "", { "dependencies": { "esquery": "^1.6.0" }, "peerDependencies": { "eslint": "*", "jsonc-eslint-parser": "^2.4.0" } }, "sha512-YzEodbDyW8DX8bImKhAcCeu/L31Dd/70Bidx2Qex9OFUtgzXLqtfWL4Hr5fM/aCCB8QUZLuJur0S9k6UfgFkfg=="], - "eslint-module-utils": ["eslint-module-utils@2.12.0", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg=="], + "eslint-plugin-de-morgan": ["eslint-plugin-de-morgan@1.3.1", "", { "peerDependencies": { "eslint": ">=8.0.0" } }, "sha512-pB0xqHPXCRgCFnFSLvQDSP/egYrlccYMI0txz4gzBF6RuT2X+4LsZl0JoWAQc7dphEjJBQ3dWyMqXfBgdP2UVg=="], "eslint-plugin-es-x": ["eslint-plugin-es-x@7.8.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.1.2", "@eslint-community/regexpp": "^4.11.0", "eslint-compat-utils": "^0.5.1" }, "peerDependencies": { "eslint": ">=8" } }, "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ=="], - "eslint-plugin-eslint-comments": ["eslint-plugin-eslint-comments@3.2.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5", "ignore": "^5.0.5" }, "peerDependencies": { "eslint": ">=4.19.1" } }, "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ=="], - - "eslint-plugin-import": ["eslint-plugin-import@2.30.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.8", "array.prototype.findlastindex": "^1.2.5", "array.prototype.flat": "^1.3.2", "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.9.0", "hasown": "^2.0.2", "is-core-module": "^2.15.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.0", "semver": "^6.3.1", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, "sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw=="], + "eslint-plugin-import-x": ["eslint-plugin-import-x@4.16.1", "", { "dependencies": { "@typescript-eslint/types": "^8.35.0", "comment-parser": "^1.4.1", "debug": "^4.4.1", "eslint-import-context": "^0.1.9", "is-glob": "^4.0.3", "minimatch": "^9.0.3 || ^10.0.1", "semver": "^7.7.2", "stable-hash-x": "^0.2.0", "unrs-resolver": "^1.9.2" }, "peerDependencies": { "@typescript-eslint/utils": "^8.0.0", "eslint": "^8.57.0 || ^9.0.0", "eslint-import-resolver-node": "*" }, "optionalPeers": ["@typescript-eslint/utils", "eslint-import-resolver-node"] }, "sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ=="], - "eslint-plugin-import-x": ["eslint-plugin-import-x@4.4.2", "", { "dependencies": { "@typescript-eslint/utils": "^8.1.0", "debug": "^4.3.4", "doctrine": "^3.0.0", "eslint-import-resolver-node": "^0.3.9", "get-tsconfig": "^4.7.3", "is-glob": "^4.0.3", "minimatch": "^9.0.3", "semver": "^7.6.3", "stable-hash": "^0.0.4", "tslib": "^2.6.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-mDRXPSLQ0UQZQw91QdG4/qZT6hgeW2MJTczAbgPseUZuPEtIjjdPOolXroRkulnOn3fzj6gNgvk+wchMJiHElg=="], + "eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@54.3.1", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.53.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.4.1", "escape-string-regexp": "^4.0.0", "espree": "^10.4.0", "esquery": "^1.6.0", "parse-imports-exports": "^0.2.4", "semver": "^7.7.2", "spdx-expression-parse": "^4.0.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-6KlEwRCaQfSi1Wsis4cxsqDfOuQDPG56ozSPCkG+N9aISTQpahbo2n0YZs6c7CIVXQzVdYSxuvQ6w31rfeiMhw=="], - "eslint-plugin-json": ["eslint-plugin-json@4.0.1", "", { "dependencies": { "lodash": "^4.17.21", "vscode-json-languageservice": "^4.1.6" } }, "sha512-3An5ISV5dq/kHfXdNyY5TUe2ONC3yXFSkLX2gu+W8xAhKhfvrRvkSAeKXCxZqZ0KJLX15ojBuLPyj+UikQMkOA=="], + "eslint-plugin-jsonc": ["eslint-plugin-jsonc@2.20.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.5.1", "eslint-compat-utils": "^0.6.4", "eslint-json-compat-utils": "^0.2.1", "espree": "^9.6.1 || ^10.3.0", "graphemer": "^1.4.0", "jsonc-eslint-parser": "^2.4.0", "natural-compare": "^1.4.0", "synckit": "^0.6.2 || ^0.7.3 || ^0.11.5" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-gUzIwQHXx7ZPypUoadcyRi4WbHW2TPixDr0kqQ4miuJBU0emJmyGTlnaT3Og9X2a8R1CDayN9BFSq5weGWbTng=="], - "eslint-plugin-jsonc": ["eslint-plugin-jsonc@2.18.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "eslint-compat-utils": "^0.6.0", "eslint-json-compat-utils": "^0.2.1", "espree": "^9.6.1", "graphemer": "^1.4.0", "jsonc-eslint-parser": "^2.0.4", "natural-compare": "^1.4.0", "synckit": "^0.6.0" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-SDhJiSsWt3nItl/UuIv+ti4g3m4gpGkmnUJS9UWR3TrpyNsIcnJoBRD7Kof6cM4Rk3L0wrmY5Tm3z7ZPjR2uGg=="], + "eslint-plugin-n": ["eslint-plugin-n@17.21.3", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.5.0", "enhanced-resolve": "^5.17.1", "eslint-plugin-es-x": "^7.8.0", "get-tsconfig": "^4.8.1", "globals": "^15.11.0", "globrex": "^0.1.2", "ignore": "^5.3.2", "semver": "^7.6.3", "ts-declaration-location": "^1.0.6" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-MtxYjDZhMQgsWRm/4xYLL0i2EhusWT7itDxlJ80l1NND2AL2Vi5Mvneqv/ikG9+zpran0VsVRXTEHrpLmUZRNw=="], - "eslint-plugin-jsx-a11y": ["eslint-plugin-jsx-a11y@6.10.0", "", { "dependencies": { "aria-query": "~5.1.3", "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", "axe-core": "^4.10.0", "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "es-iterator-helpers": "^1.0.19", "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "safe-regex-test": "^1.0.3", "string.prototype.includes": "^2.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "sha512-ySOHvXX8eSN6zz8Bywacm7CvGNhUtdjvqfQDVe6020TUK34Cywkw7m0KsCCk1Qtm9G1FayfTN1/7mMYnYO2Bhg=="], + "eslint-plugin-perfectionist": ["eslint-plugin-perfectionist@4.15.0", "", { "dependencies": { "@typescript-eslint/types": "^8.34.1", "@typescript-eslint/utils": "^8.34.1", "natural-orderby": "^5.0.0" }, "peerDependencies": { "eslint": ">=8.45.0" } }, "sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw=="], - "eslint-plugin-n": ["eslint-plugin-n@17.13.2", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.1", "enhanced-resolve": "^5.17.1", "eslint-plugin-es-x": "^7.8.0", "get-tsconfig": "^4.8.1", "globals": "^15.11.0", "ignore": "^5.3.2", "minimatch": "^9.0.5", "semver": "^7.6.3" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-MhBAKkT01h8cOXcTBTlpuR7bxH5OBUNpUXefsvwSVEy46cY4m/Kzr2osUCQvA3zJFD6KuCeNNDv0+HDuWk/OcA=="], + "eslint-plugin-pnpm": ["eslint-plugin-pnpm@1.1.1", "", { "dependencies": { "empathic": "^2.0.0", "jsonc-eslint-parser": "^2.4.0", "pathe": "^2.0.3", "pnpm-workspace-yaml": "1.1.1", "tinyglobby": "^0.2.14", "yaml-eslint-parser": "^1.3.0" }, "peerDependencies": { "eslint": "^9.0.0" } }, "sha512-gNo+swrLCgvT8L6JX6hVmxuKeuStGK2l8IwVjDxmYIn+wP4SW/d0ORLKyUiYamsp+UxknQo3f2M1irrTpqahCw=="], - "eslint-plugin-perfectionist": ["eslint-plugin-perfectionist@3.9.1", "", { "dependencies": { "@typescript-eslint/types": "^8.9.0", "@typescript-eslint/utils": "^8.9.0", "minimatch": "^9.0.5", "natural-compare-lite": "^1.4.0" }, "peerDependencies": { "astro-eslint-parser": "^1.0.2", "eslint": ">=8.0.0", "svelte": ">=3.0.0", "svelte-eslint-parser": "^0.41.1", "vue-eslint-parser": ">=9.0.0" }, "optionalPeers": ["astro-eslint-parser", "svelte", "svelte-eslint-parser", "vue-eslint-parser"] }, "sha512-9WRzf6XaAxF4Oi5t/3TqKP5zUjERhasHmLFHin2Yw6ZAp/EP/EVA2dr3BhQrrHWCm5SzTMZf0FcjDnBkO2xFkA=="], + "eslint-plugin-prettier": ["eslint-plugin-prettier@5.5.4", "", { "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.11.7" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg=="], - "eslint-plugin-prettier": ["eslint-plugin-prettier@5.2.1", "", { "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.9.1" }, "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", "eslint-config-prettier": "*", "prettier": ">=3.0.0" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw=="], + "eslint-plugin-regexp": ["eslint-plugin-regexp@2.10.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.11.0", "comment-parser": "^1.4.0", "jsdoc-type-pratt-parser": "^4.0.0", "refa": "^0.12.1", "regexp-ast-analysis": "^0.7.1", "scslre": "^0.3.0" }, "peerDependencies": { "eslint": ">=8.44.0" } }, "sha512-ovzQT8ESVn5oOe5a7gIDPD5v9bCSjIFJu57sVPDqgPRXicQzOnYfFN21WoQBQF18vrhT5o7UMKFwJQVVjyJ0ng=="], - "eslint-plugin-react": ["eslint-plugin-react@7.36.1", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.2", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.0.19", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.8", "object.fromentries": "^2.0.8", "object.values": "^1.2.0", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.11", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-/qwbqNXZoq+VP30s1d4Nc1C5GTxjJQjk4Jzs4Wq2qzxFM7dSmuG2UkIjg2USMLh3A/aVcUNrK7v0J5U1XEGGwA=="], + "eslint-plugin-security": ["eslint-plugin-security@3.0.1", "", { "dependencies": { "safe-regex": "^2.1.1" } }, "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q=="], - "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@4.6.2", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" } }, "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ=="], + "eslint-plugin-sonarjs": ["eslint-plugin-sonarjs@3.0.5", "", { "dependencies": { "@eslint-community/regexpp": "4.12.1", "builtin-modules": "3.3.0", "bytes": "3.1.2", "functional-red-black-tree": "1.0.1", "jsx-ast-utils-x": "0.1.0", "lodash.merge": "4.6.2", "minimatch": "9.0.5", "scslre": "0.3.0", "semver": "7.7.2", "typescript": ">=5" }, "peerDependencies": { "eslint": "^8.0.0 || ^9.0.0" } }, "sha512-dI62Ff3zMezUToi161hs2i1HX1ie8Ia2hO0jtNBfdgRBicAG4ydy2WPt0rMTrAe3ZrlqhpAO3w1jcQEdneYoFA=="], - "eslint-plugin-security": ["eslint-plugin-security@3.0.1", "", { "dependencies": { "safe-regex": "^2.1.1" } }, "sha512-XjVGBhtDZJfyuhIxnQ/WMm385RbX3DBu7H1J7HNNhmB2tnGxMeqVSnYv79oAj992ayvIBZghsymwkYFS6cGH4Q=="], + "eslint-plugin-testing-library": ["eslint-plugin-testing-library@7.6.8", "", { "dependencies": { "@typescript-eslint/scope-manager": "^8.15.0", "@typescript-eslint/utils": "^8.15.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-8qvVtc9gzYsBWJd2bMJByAlOdr/GBBH2RZygvp70OTivsJkLkYRxSZFtHq1XQK8k+zNi8DcV7aiSx3avE0rf2w=="], - "eslint-plugin-sonarjs": ["eslint-plugin-sonarjs@2.0.4", "", { "dependencies": { "@babel/core": "7.25.2", "@babel/eslint-parser": "7.25.1", "@babel/plugin-proposal-decorators": "7.24.7", "@babel/preset-env": "7.25.4", "@babel/preset-flow": "7.24.7", "@babel/preset-react": "7.24.7", "@eslint-community/regexpp": "4.11.1", "@typescript-eslint/eslint-plugin": "7.16.1", "@typescript-eslint/utils": "7.16.1", "builtin-modules": "3.3.0", "bytes": "3.1.2", "eslint-plugin-import": "2.30.0", "eslint-plugin-jsx-a11y": "6.10.0", "eslint-plugin-react": "7.36.1", "eslint-plugin-react-hooks": "4.6.2", "eslint-scope": "8.1.0", "functional-red-black-tree": "1.0.1", "jsx-ast-utils": "3.3.5", "minimatch": "10.0.1", "scslre": "0.3.0", "semver": "7.6.3", "typescript": "5.6.2", "vue-eslint-parser": "9.4.3" }, "peerDependencies": { "eslint": "^8.0.0 || ^9.0.0" } }, "sha512-XVVAB/t0WSgHitHNajIcIDmviCO8kB9VSsrjy+4WUEVM3eieY9SDHEtCDaOMTjj6XMtcAr8BFDXCFaP005s+tg=="], + "eslint-plugin-unicorn": ["eslint-plugin-unicorn@60.0.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "@eslint-community/eslint-utils": "^4.7.0", "@eslint/plugin-kit": "^0.3.3", "change-case": "^5.4.4", "ci-info": "^4.3.0", "clean-regexp": "^1.0.0", "core-js-compat": "^3.44.0", "esquery": "^1.6.0", "find-up-simple": "^1.0.1", "globals": "^16.3.0", "indent-string": "^5.0.0", "is-builtin-module": "^5.0.0", "jsesc": "^3.1.0", "pluralize": "^8.0.0", "regexp-tree": "^0.1.27", "regjsparser": "^0.12.0", "semver": "^7.7.2", "strip-indent": "^4.0.0" }, "peerDependencies": { "eslint": ">=9.29.0" } }, "sha512-QUzTefvP8stfSXsqKQ+vBQSEsXIlAiCduS/V1Em+FKgL9c21U/IIm20/e3MFy1jyCf14tHAhqC1sX8OTy6VUCg=="], - "eslint-plugin-testing-library": ["eslint-plugin-testing-library@6.4.0", "", { "dependencies": { "@typescript-eslint/utils": "^5.62.0" }, "peerDependencies": { "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, "sha512-yeWF+YgCgvNyPNI9UKnG0FjeE2sk93N/3lsKqcmR8dSfeXJwFT5irnWo7NjLf152HkRzfoFjh3LsBUrhvFz4eA=="], + "eslint-plugin-unused-imports": ["eslint-plugin-unused-imports@4.2.0", "", { "peerDependencies": { "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", "eslint": "^9.0.0 || ^8.0.0" }, "optionalPeers": ["@typescript-eslint/eslint-plugin"] }, "sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w=="], - "eslint-plugin-unicorn": ["eslint-plugin-unicorn@56.0.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.24.7", "@eslint-community/eslint-utils": "^4.4.0", "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", "core-js-compat": "^3.38.1", "esquery": "^1.6.0", "globals": "^15.9.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", "jsesc": "^3.0.2", "pluralize": "^8.0.0", "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", "regjsparser": "^0.10.0", "semver": "^7.6.3", "strip-indent": "^3.0.0" }, "peerDependencies": { "eslint": ">=8.56.0" } }, "sha512-aXpddVz/PQMmd69uxO98PA4iidiVNvA0xOtbpUoz1WhBd4RxOQQYqN618v68drY0hmy5uU2jy1bheKEVWBjlPw=="], + "eslint-plugin-vue": ["eslint-plugin-vue@10.4.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "^7.6.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", "eslint": "^8.57.0 || ^9.0.0", "vue-eslint-parser": "^10.0.0" }, "optionalPeers": ["@typescript-eslint/parser"] }, "sha512-K6tP0dW8FJVZLQxa2S7LcE1lLw3X8VvB3t887Q6CLrFVxHYBXGANbXvwNzYIu6Ughx1bSJ5BDT0YB3ybPT39lw=="], - "eslint-plugin-unused-imports": ["eslint-plugin-unused-imports@4.1.4", "", { "peerDependencies": { "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", "eslint": "^9.0.0 || ^8.0.0" }, "optionalPeers": ["@typescript-eslint/eslint-plugin"] }, "sha512-YptD6IzQjDardkl0POxnnRBhU1OEePMV0nd6siHaRBbd+lyh6NAhFEobiznKU7kTsSsDeSD62Pe7kAM1b7dAZQ=="], + "eslint-plugin-vuejs-accessibility": ["eslint-plugin-vuejs-accessibility@2.4.1", "", { "dependencies": { "aria-query": "^5.3.0", "emoji-regex": "^10.0.0", "vue-eslint-parser": "^9.0.1" }, "peerDependencies": { "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-ZRZhPdslplZXSF71MtSG+zXYRAT5KiHR4JVuo/DERQf9noAkDvi5W418VOE1qllmJd7wTenndxi1q8XeDMxdHw=="], - "eslint-plugin-vue": ["eslint-plugin-vue@9.31.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "globals": "^13.24.0", "natural-compare": "^1.4.0", "nth-check": "^2.1.1", "postcss-selector-parser": "^6.0.15", "semver": "^7.6.3", "vue-eslint-parser": "^9.4.3", "xml-name-validator": "^4.0.0" }, "peerDependencies": { "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-aYMUCgivhz1o4tLkRHj5oq9YgYPM4/EJc0M7TAKRLCUA5OYxRLAhYEVD2nLtTwLyixEFI+/QXSvKU9ESZFgqjQ=="], + "eslint-plugin-yml": ["eslint-plugin-yml@1.18.0", "", { "dependencies": { "debug": "^4.3.2", "escape-string-regexp": "4.0.0", "eslint-compat-utils": "^0.6.0", "natural-compare": "^1.4.0", "yaml-eslint-parser": "^1.2.1" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-9NtbhHRN2NJa/s3uHchO3qVVZw0vyOIvWlXWGaKCr/6l3Go62wsvJK5byiI6ZoYztDsow4GnS69BZD3GnqH3hA=="], "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], @@ -608,6 +355,8 @@ "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], + "exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="], + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], @@ -624,84 +373,52 @@ "fastq": ["fastq@1.17.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w=="], + "fault": ["fault@2.0.1", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], - "flat": ["flat@5.0.2", "", { "bin": { "flat": "cli.js" } }, "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ=="], + "find-up-simple": ["find-up-simple@1.0.1", "", {}, "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ=="], "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], "flatted": ["flatted@3.3.1", "", {}, "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="], - "for-each": ["for-each@0.3.3", "", { "dependencies": { "is-callable": "^1.1.3" } }, "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw=="], - - "foreground-child": ["foreground-child@3.3.0", "", { "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" } }, "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg=="], - "form-data": ["form-data@2.5.2", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12", "safe-buffer": "^5.2.1" } }, "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q=="], - "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - - "function.prototype.name": ["function.prototype.name@1.1.6", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", "functions-have-names": "^1.2.3" } }, "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg=="], + "format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="], "functional-red-black-tree": ["functional-red-black-tree@1.0.1", "", {}, "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g=="], - "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="], - "gaxios": ["gaxios@6.7.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", "node-fetch": "^2.6.9", "uuid": "^9.0.1" } }, "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ=="], "gcp-metadata": ["gcp-metadata@6.1.0", "", { "dependencies": { "gaxios": "^6.0.0", "json-bigint": "^1.0.0" } }, "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg=="], - "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], - - "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], - - "get-intrinsic": ["get-intrinsic@1.2.4", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" } }, "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ=="], - - "get-symbol-description": ["get-symbol-description@1.0.2", "", { "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4" } }, "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg=="], - "get-tsconfig": ["get-tsconfig@4.8.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg=="], - "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], + "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], - "globals": ["globals@15.12.0", "", {}, "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ=="], - - "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], + "globals": ["globals@16.3.0", "", {}, "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ=="], - "globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="], + "globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="], "google-auth-library": ["google-auth-library@9.15.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^6.1.1", "gcp-metadata": "^6.1.0", "gtoken": "^7.0.0", "jws": "^4.0.0" } }, "sha512-7ccSEJFDFO7exFbO6NRyC+xH8/mZ1GZGG2xxx9iHxZWcjUjJpjWxIMw3cofAKcueZ6DATiukmmprD7yavQHOyQ=="], - "gopd": ["gopd@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.1.3" } }, "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA=="], - "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], "gtoken": ["gtoken@7.1.0", "", { "dependencies": { "gaxios": "^6.0.0", "jws": "^4.0.0" } }, "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw=="], - "has-bigints": ["has-bigints@1.0.2", "", {}, "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ=="], - "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], - "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], - - "has-proto": ["has-proto@1.0.3", "", {}, "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q=="], - - "has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="], - - "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], - - "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], - - "he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="], - - "hosted-git-info": ["hosted-git-info@2.8.9", "", {}, "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="], - "html-entities": ["html-entities@2.5.2", "", {}, "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA=="], "http-proxy-agent": ["http-proxy-agent@5.0.0", "", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="], @@ -714,141 +431,147 @@ "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], - "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + "indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="], "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - "internal-slot": ["internal-slot@1.0.7", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", "side-channel": "^1.0.4" } }, "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g=="], + "is-builtin-module": ["is-builtin-module@5.0.0", "", { "dependencies": { "builtin-modules": "^5.0.0" } }, "sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA=="], - "is-arguments": ["is-arguments@1.1.1", "", { "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" } }, "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA=="], + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], - "is-array-buffer": ["is-array-buffer@3.0.4", "", { "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" } }, "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw=="], + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], - "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], - "is-async-function": ["is-async-function@2.0.0", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA=="], + "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], - "is-bigint": ["is-bigint@1.0.4", "", { "dependencies": { "has-bigints": "^1.0.1" } }, "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg=="], + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], - "is-boolean-object": ["is-boolean-object@1.1.2", "", { "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" } }, "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA=="], + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], - "is-builtin-module": ["is-builtin-module@3.2.1", "", { "dependencies": { "builtin-modules": "^3.3.0" } }, "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A=="], + "jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@4.8.0", "", {}, "sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw=="], - "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], - "is-core-module": ["is-core-module@2.15.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ=="], + "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], - "is-data-view": ["is-data-view@1.0.1", "", { "dependencies": { "is-typed-array": "^1.1.13" } }, "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w=="], + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], - "is-date-object": ["is-date-object@1.0.5", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ=="], + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], - "is-finalizationregistry": ["is-finalizationregistry@1.0.2", "", { "dependencies": { "call-bind": "^1.0.2" } }, "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw=="], + "jsonc-eslint-parser": ["jsonc-eslint-parser@2.4.0", "", { "dependencies": { "acorn": "^8.5.0", "eslint-visitor-keys": "^3.0.0", "espree": "^9.0.0", "semver": "^7.3.5" } }, "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg=="], - "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + "jsx-ast-utils-x": ["jsx-ast-utils-x@0.1.0", "", {}, "sha512-eQQBjBnsVtGacsG9uJNB8qOr3yA8rga4wAaGG1qRcBzSIvfhERLrWxMAM1hp5fcS6Abo8M4+bUBTekYR0qTPQw=="], - "is-generator-function": ["is-generator-function@1.0.10", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A=="], + "jwa": ["jwa@2.0.0", "", { "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA=="], - "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + "jws": ["jws@4.0.0", "", { "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg=="], - "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], - "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="], + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], - "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + "local-pkg": ["local-pkg@1.1.2", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.3.0", "quansync": "^0.2.11" } }, "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A=="], - "is-number-object": ["is-number-object@1.0.7", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ=="], + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], - "is-plain-obj": ["is-plain-obj@2.1.0", "", {}, "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="], + "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], - "is-regex": ["is-regex@1.1.4", "", { "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" } }, "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg=="], + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], - "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="], + "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], - "is-shared-array-buffer": ["is-shared-array-buffer@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7" } }, "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg=="], + "loupe": ["loupe@3.1.2", "", {}, "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg=="], - "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + "luxon": ["luxon@3.7.1", "", {}, "sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg=="], - "is-string": ["is-string@1.0.7", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg=="], + "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], - "is-symbol": ["is-symbol@1.0.4", "", { "dependencies": { "has-symbols": "^1.0.2" } }, "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg=="], + "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], - "is-typed-array": ["is-typed-array@1.1.13", "", { "dependencies": { "which-typed-array": "^1.1.14" } }, "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw=="], + "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA=="], - "is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="], + "mdast-util-frontmatter": ["mdast-util-frontmatter@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "escape-string-regexp": "^5.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-extension-frontmatter": "^2.0.0" } }, "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA=="], - "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="], + "mdast-util-gfm": ["mdast-util-gfm@3.1.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ=="], - "is-weakref": ["is-weakref@1.0.2", "", { "dependencies": { "call-bind": "^1.0.2" } }, "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ=="], + "mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ=="], - "is-weakset": ["is-weakset@2.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4" } }, "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ=="], + "mdast-util-gfm-footnote": ["mdast-util-gfm-footnote@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0" } }, "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ=="], - "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], + "mdast-util-gfm-strikethrough": ["mdast-util-gfm-strikethrough@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg=="], - "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + "mdast-util-gfm-table": ["mdast-util-gfm-table@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "markdown-table": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg=="], - "iterator.prototype": ["iterator.prototype@1.1.3", "", { "dependencies": { "define-properties": "^1.2.1", "get-intrinsic": "^1.2.1", "has-symbols": "^1.0.3", "reflect.getprototypeof": "^1.0.4", "set-function-name": "^2.0.1" } }, "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ=="], + "mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="], - "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + "mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="], - "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + "mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="], - "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], + "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="], - "jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], - "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], + "micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="], - "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="], - "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + "micromark-extension-frontmatter": ["micromark-extension-frontmatter@2.0.0", "", { "dependencies": { "fault": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg=="], - "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + "micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="], - "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + "micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="], - "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + "micromark-extension-gfm-footnote": ["micromark-extension-gfm-footnote@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw=="], - "jsonc-eslint-parser": ["jsonc-eslint-parser@2.4.0", "", { "dependencies": { "acorn": "^8.5.0", "eslint-visitor-keys": "^3.0.0", "espree": "^9.0.0", "semver": "^7.3.5" } }, "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg=="], + "micromark-extension-gfm-strikethrough": ["micromark-extension-gfm-strikethrough@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw=="], - "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], + "micromark-extension-gfm-table": ["micromark-extension-gfm-table@2.1.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg=="], - "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="], + "micromark-extension-gfm-tagfilter": ["micromark-extension-gfm-tagfilter@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg=="], - "jwa": ["jwa@2.0.0", "", { "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA=="], + "micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw=="], - "jws": ["jws@4.0.0", "", { "dependencies": { "jwa": "^2.0.0", "safe-buffer": "^5.0.1" } }, "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg=="], + "micromark-factory-destination": ["micromark-factory-destination@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA=="], - "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + "micromark-factory-label": ["micromark-factory-label@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg=="], - "language-subtag-registry": ["language-subtag-registry@0.3.23", "", {}, "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ=="], + "micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="], - "language-tags": ["language-tags@1.0.9", "", { "dependencies": { "language-subtag-registry": "^0.3.20" } }, "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA=="], + "micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="], - "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + "micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ=="], - "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], - "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + "micromark-util-chunked": ["micromark-util-chunked@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA=="], - "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], + "micromark-util-classify-character": ["micromark-util-classify-character@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q=="], - "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], + "micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.1", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg=="], - "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + "micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.2", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw=="], - "log-symbols": ["log-symbols@4.1.0", "", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="], + "micromark-util-decode-string": ["micromark-util-decode-string@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ=="], - "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], + "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="], - "loupe": ["loupe@3.1.2", "", {}, "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg=="], + "micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.1", "", {}, "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="], - "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + "micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q=="], - "luxon": ["luxon@3.7.1", "", {}, "sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg=="], + "micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.1", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg=="], - "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="], + + "micromark-util-subtokenize": ["micromark-util-subtokenize@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA=="], + + "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], @@ -862,46 +585,24 @@ "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], - - "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], - - "mocha": ["mocha@11.7.1", "", { "dependencies": { "browser-stdout": "^1.3.1", "chokidar": "^4.0.1", "debug": "^4.3.5", "diff": "^7.0.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", "glob": "^10.4.5", "he": "^1.2.0", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", "minimatch": "^9.0.5", "ms": "^2.1.3", "picocolors": "^1.1.1", "serialize-javascript": "^6.0.2", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", "workerpool": "^9.2.0", "yargs": "^17.7.2", "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "bin": { "mocha": "bin/mocha.js", "_mocha": "bin/_mocha" } }, "sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A=="], + "mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "napi-postinstall": ["napi-postinstall@0.3.3", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow=="], + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], - "natural-compare-lite": ["natural-compare-lite@1.4.0", "", {}, "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g=="], + "natural-orderby": ["natural-orderby@5.0.0", "", {}, "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg=="], "node-crc": ["node-crc@github:swrlab/node-crc#92864dc", { "dependencies": { "@types/node": "^18.11.17", "detect-libc": "^2.0.1" } }, "swrlab-node-crc-92864dc"], "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], - "node-releases": ["node-releases@2.0.18", "", {}, "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="], - - "normalize-package-data": ["normalize-package-data@2.5.0", "", { "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA=="], + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], - "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], - - "object-inspect": ["object-inspect@1.13.3", "", {}, "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA=="], - - "object-is": ["object-is@1.1.6", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1" } }, "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q=="], - - "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], - - "object.assign": ["object.assign@4.1.5", "", { "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ=="], - - "object.entries": ["object.entries@1.1.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ=="], - - "object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="], - - "object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="], - - "object.values": ["object.values@1.2.0", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ=="], - "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], @@ -910,33 +611,29 @@ "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], - "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], - - "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], - "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], - "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], + "parse-imports-exports": ["parse-imports-exports@0.2.4", "", { "dependencies": { "parse-statements": "1.0.11" } }, "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ=="], + + "parse-statements": ["parse-statements@1.0.11", "", {}, "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA=="], "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], - "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], - - "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], - - "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="], + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "pathval": ["pathval@2.0.0", "", {}, "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA=="], "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "pkg-types": ["pkg-types@2.3.0", "", { "dependencies": { "confbox": "^0.2.2", "exsolve": "^1.0.7", "pathe": "^2.0.3" } }, "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig=="], "pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="], - "possible-typed-array-names": ["possible-typed-array-names@1.0.0", "", {}, "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q=="], + "pnpm-workspace-yaml": ["pnpm-workspace-yaml@1.1.1", "", { "dependencies": { "yaml": "^2.8.1" } }, "sha512-nGBB7h3Ped3g9dBrR6d3YNwXCKYsEg8K9J3GMmSrwGEXq3RHeGW44/B4MZW51p4FRMnyxJzTY5feSBbUjRhIHQ=="], "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], @@ -946,51 +643,21 @@ "prettier-linter-helpers": ["prettier-linter-helpers@1.0.0", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w=="], - "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], - - "randombytes": ["randombytes@2.1.0", "", { "dependencies": { "safe-buffer": "^5.1.0" } }, "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ=="], - - "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], - - "read-pkg": ["read-pkg@5.2.0", "", { "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", "parse-json": "^5.0.0", "type-fest": "^0.6.0" } }, "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg=="], + "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], - "read-pkg-up": ["read-pkg-up@7.0.1", "", { "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", "type-fest": "^0.8.1" } }, "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg=="], + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], - "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], - "refa": ["refa@0.12.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.8.0" } }, "sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g=="], - "reflect.getprototypeof": ["reflect.getprototypeof@1.0.6", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.1", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", "which-builtin-type": "^1.1.3" } }, "sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg=="], - - "regenerate": ["regenerate@1.4.2", "", {}, "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A=="], - - "regenerate-unicode-properties": ["regenerate-unicode-properties@10.2.0", "", { "dependencies": { "regenerate": "^1.4.2" } }, "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA=="], - - "regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="], - - "regenerator-transform": ["regenerator-transform@0.15.2", "", { "dependencies": { "@babel/runtime": "^7.8.4" } }, "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg=="], - "regexp-ast-analysis": ["regexp-ast-analysis@0.7.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.8.0", "refa": "^0.12.1" } }, "sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A=="], "regexp-tree": ["regexp-tree@0.1.27", "", { "bin": { "regexp-tree": "bin/regexp-tree" } }, "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA=="], - "regexp.prototype.flags": ["regexp.prototype.flags@1.5.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "set-function-name": "^2.0.2" } }, "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ=="], - - "regexpu-core": ["regexpu-core@6.1.1", "", { "dependencies": { "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.2.0", "regjsgen": "^0.8.0", "regjsparser": "^0.11.0", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" } }, "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw=="], - - "regjsgen": ["regjsgen@0.8.0", "", {}, "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q=="], - - "regjsparser": ["regjsparser@0.10.0", "", { "dependencies": { "jsesc": "~0.5.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA=="], - - "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], - - "resolve": ["resolve@1.22.8", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw=="], + "regjsparser": ["regjsparser@0.12.0", "", { "dependencies": { "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ=="], "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], @@ -1004,75 +671,33 @@ "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], - "safe-array-concat": ["safe-array-concat@1.1.2", "", { "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" } }, "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q=="], - "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], "safe-regex": ["safe-regex@2.1.1", "", { "dependencies": { "regexp-tree": "~0.1.1" } }, "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A=="], - "safe-regex-test": ["safe-regex-test@1.0.3", "", { "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", "is-regex": "^1.1.4" } }, "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw=="], - "scslre": ["scslre@0.3.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.8.0", "refa": "^0.12.0", "regexp-ast-analysis": "^0.7.0" } }, "sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ=="], - "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "serialize-javascript": ["serialize-javascript@6.0.2", "", { "dependencies": { "randombytes": "^2.1.0" } }, "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g=="], - - "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], - - "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="], + "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], - "side-channel": ["side-channel@1.0.6", "", { "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" } }, "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA=="], - - "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - - "slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], - - "spdx-correct": ["spdx-correct@3.2.0", "", { "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA=="], - "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], - "spdx-expression-parse": ["spdx-expression-parse@3.0.1", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="], + "spdx-expression-parse": ["spdx-expression-parse@4.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ=="], "spdx-license-ids": ["spdx-license-ids@3.0.20", "", {}, "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw=="], - "stable-hash": ["stable-hash@0.0.4", "", {}, "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g=="], - - "stop-iteration-iterator": ["stop-iteration-iterator@1.0.0", "", { "dependencies": { "internal-slot": "^1.0.4" } }, "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ=="], + "stable-hash-x": ["stable-hash-x@0.2.0", "", {}, "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ=="], "stream-events": ["stream-events@1.0.5", "", { "dependencies": { "stubs": "^3.0.0" } }, "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg=="], "stream-shift": ["stream-shift@1.0.3", "", {}, "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="], - "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - - "string.prototype.includes": ["string.prototype.includes@2.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3" } }, "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg=="], - - "string.prototype.matchall": ["string.prototype.matchall@4.0.11", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", "regexp.prototype.flags": "^1.5.2", "set-function-name": "^2.0.2", "side-channel": "^1.0.6" } }, "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg=="], - - "string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="], - - "string.prototype.trim": ["string.prototype.trim@1.2.9", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.0", "es-object-atoms": "^1.0.0" } }, "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw=="], - - "string.prototype.trimend": ["string.prototype.trimend@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ=="], - - "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="], - "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], - "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], - - "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], + "strip-indent": ["strip-indent@4.0.0", "", { "dependencies": { "min-indent": "^1.0.1" } }, "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA=="], "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], @@ -1080,57 +705,49 @@ "stubs": ["stubs@3.0.0", "", {}, "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw=="], - "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - - "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "synckit": ["synckit@0.6.2", "", { "dependencies": { "tslib": "^2.3.1" } }, "sha512-Vhf+bUa//YSTYKseDiiEuQmhGCoIF3CVBhunm3r/DQnYiGT4JssmnKQc44BIyOZRK2pKjXXAgbhfmbeoC9CJpA=="], + "synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="], "tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="], "teeny-request": ["teeny-request@9.0.0", "", { "dependencies": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.9", "stream-events": "^1.0.5", "uuid": "^9.0.0" } }, "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g=="], + "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], - "ts-api-utils": ["ts-api-utils@1.4.0", "", { "peerDependencies": { "typescript": ">=4.2.0" } }, "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ=="], + "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], - "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="], + "ts-declaration-location": ["ts-declaration-location@1.0.7", "", { "dependencies": { "picomatch": "^4.0.2" }, "peerDependencies": { "typescript": ">=4.0.0" } }, "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "tsutils": ["tsutils@3.21.0", "", { "dependencies": { "tslib": "^1.8.1" }, "peerDependencies": { "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA=="], - "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], - "type-fest": ["type-fest@0.8.1", "", {}, "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="], - - "typed-array-buffer": ["typed-array-buffer@1.0.2", "", { "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", "is-typed-array": "^1.1.13" } }, "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ=="], - - "typed-array-byte-length": ["typed-array-byte-length@1.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-proto": "^1.0.3", "is-typed-array": "^1.1.13" } }, "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw=="], - - "typed-array-byte-offset": ["typed-array-byte-offset@1.0.2", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-proto": "^1.0.3", "is-typed-array": "^1.1.13" } }, "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA=="], - - "typed-array-length": ["typed-array-length@1.0.6", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0" } }, "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g=="], - "typescript": ["typescript@5.6.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw=="], - "unbox-primitive": ["unbox-primitive@1.0.2", "", { "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } }, "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw=="], + "typescript-eslint": ["typescript-eslint@8.42.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.42.0", "@typescript-eslint/parser": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/utils": "8.42.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ozR/rQn+aQXQxh1YgbCzQWDFrsi9mcg+1PM3l/z5o1+20P7suOIaNg515bpr/OYt6FObz/NHcBstydDLHWeEKg=="], + + "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], "undici": ["undici@7.13.0", "", {}, "sha512-l+zSMssRqrzDcb3fjMkjjLGmuiiK2pMIcV++mJaAc9vhjSGpvM7h43QgP+OAMb1GImHmbPyG2tBXeuyG5iY4gA=="], "undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], - "unicode-canonical-property-names-ecmascript": ["unicode-canonical-property-names-ecmascript@2.0.1", "", {}, "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg=="], + "unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], + + "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], - "unicode-match-property-ecmascript": ["unicode-match-property-ecmascript@2.0.0", "", { "dependencies": { "unicode-canonical-property-names-ecmascript": "^2.0.0", "unicode-property-aliases-ecmascript": "^2.0.0" } }, "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q=="], + "unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="], - "unicode-match-property-value-ecmascript": ["unicode-match-property-value-ecmascript@2.2.0", "", {}, "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg=="], + "unist-util-visit-parents": ["unist-util-visit-parents@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw=="], - "unicode-property-aliases-ecmascript": ["unicode-property-aliases-ecmascript@2.1.0", "", {}, "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w=="], + "unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="], - "update-browserslist-db": ["update-browserslist-db@1.1.1", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.0" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A=="], + "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], @@ -1138,19 +755,7 @@ "uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], - "validate-npm-package-license": ["validate-npm-package-license@3.0.4", "", { "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew=="], - - "vscode-json-languageservice": ["vscode-json-languageservice@4.2.1", "", { "dependencies": { "jsonc-parser": "^3.0.0", "vscode-languageserver-textdocument": "^1.0.3", "vscode-languageserver-types": "^3.16.0", "vscode-nls": "^5.0.0", "vscode-uri": "^3.0.3" } }, "sha512-xGmv9QIWs2H8obGbWg+sIPI/3/pFgj/5OWBhNzs00BkYQ9UaB2F6JJaGB/2/YOZJ3BvLXQTC4Q7muqU25QgAhA=="], - - "vscode-languageserver-textdocument": ["vscode-languageserver-textdocument@1.0.12", "", {}, "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA=="], - - "vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], - - "vscode-nls": ["vscode-nls@5.2.0", "", {}, "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng=="], - - "vscode-uri": ["vscode-uri@3.0.8", "", {}, "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw=="], - - "vue-eslint-parser": ["vue-eslint-parser@9.4.3", "", { "dependencies": { "debug": "^4.3.4", "eslint-scope": "^7.1.1", "eslint-visitor-keys": "^3.3.0", "espree": "^9.3.1", "esquery": "^1.4.0", "lodash": "^4.17.21", "semver": "^7.3.6" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg=="], + "vue-eslint-parser": ["vue-eslint-parser@10.2.0", "", { "dependencies": { "debug": "^4.4.0", "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.6.0", "semver": "^7.6.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw=="], "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], @@ -1158,43 +763,21 @@ "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], - "which-boxed-primitive": ["which-boxed-primitive@1.0.2", "", { "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", "is-number-object": "^1.0.4", "is-string": "^1.0.5", "is-symbol": "^1.0.3" } }, "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg=="], - - "which-builtin-type": ["which-builtin-type@1.1.4", "", { "dependencies": { "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.0.5", "is-finalizationregistry": "^1.0.2", "is-generator-function": "^1.0.10", "is-regex": "^1.1.4", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.0.2", "which-collection": "^1.0.2", "which-typed-array": "^1.1.15" } }, "sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w=="], - - "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="], - - "which-typed-array": ["which-typed-array@1.1.15", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-tostringtag": "^1.0.2" } }, "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA=="], - "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], - "workerpool": ["workerpool@9.3.3", "", {}, "sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw=="], - - "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - - "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], "xml-name-validator": ["xml-name-validator@4.0.0", "", {}, "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw=="], - "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], - - "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + "yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="], - "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - - "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], - - "yargs-unparser": ["yargs-unparser@2.0.0", "", { "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", "flat": "^5.0.2", "is-plain-obj": "^2.1.0" } }, "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA=="], + "yaml-eslint-parser": ["yaml-eslint-parser@1.3.0", "", { "dependencies": { "eslint-visitor-keys": "^3.0.0", "yaml": "^2.0.0" } }, "sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA=="], "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - "@babel/eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@2.1.0", "", {}, "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw=="], - - "@babel/plugin-transform-classes/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], - "@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], + "@es-joy/jsdoccomment/@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -1202,117 +785,63 @@ "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], - "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], - - "@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], - - "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], - - "@nicolo-ribaudo/eslint-scope-5-internals/eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], - - "@stylistic/eslint-plugin-js/eslint-visitor-keys": ["eslint-visitor-keys@4.2.0", "", {}, "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw=="], - - "@stylistic/eslint-plugin-js/espree": ["espree@10.3.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.0" } }, "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg=="], - "@types/request/@types/node": ["@types/node@22.9.0", "", { "dependencies": { "undici-types": "~6.19.8" } }, "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ=="], - "@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@7.16.1", "", { "dependencies": { "@typescript-eslint/types": "7.16.1", "@typescript-eslint/visitor-keys": "7.16.1" } }, "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils": ["@typescript-eslint/utils@7.16.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "7.16.1", "@typescript-eslint/types": "7.16.1", "@typescript-eslint/typescript-estree": "7.16.1" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA=="], + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - "@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0" } }, "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA=="], + "@typescript-eslint/parser/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@7.18.0", "", {}, "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ=="], + "@typescript-eslint/project-service/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "@typescript-eslint/parser/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" } }, "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA=="], + "@typescript-eslint/type-utils/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "eslint-visitor-keys": "^3.4.3" } }, "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg=="], - - "@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.14.0", "", { "dependencies": { "@typescript-eslint/types": "8.14.0", "eslint-visitor-keys": "^3.4.3" } }, "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@7.16.1", "", { "dependencies": { "@typescript-eslint/types": "7.16.1", "@typescript-eslint/visitor-keys": "7.16.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" } }, "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ=="], - - "@typescript-eslint/type-utils/@typescript-eslint/utils": ["@typescript-eslint/utils@7.16.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "7.16.1", "@typescript-eslint/types": "7.16.1", "@typescript-eslint/typescript-estree": "7.16.1" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA=="], - - "@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.14.0", "", { "dependencies": { "@typescript-eslint/types": "8.14.0", "eslint-visitor-keys": "^3.4.3" } }, "sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ=="], + "@typescript-eslint/typescript-estree/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "@typescript-eslint/typescript-estree/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - - "@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@7.16.1", "", {}, "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ=="], - - "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@typescript-eslint/utils/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], - "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "bun-types/@types/node": ["@types/node@22.9.0", "", { "dependencies": { "undici-types": "~6.19.8" } }, "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ=="], "clean-regexp/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - "eslint/@eslint/js": ["@eslint/js@9.33.0", "", {}, "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A=="], - - "eslint-compat-utils/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - - "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], - - "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], + "eslint-import-context/get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], "eslint-plugin-es-x/eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="], - "eslint-plugin-eslint-comments/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - - "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], - - "eslint-plugin-import/doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], - - "eslint-plugin-import-x/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "eslint-plugin-import-x/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - - "eslint-plugin-jsonc/espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], - - "eslint-plugin-n/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "eslint-plugin-n/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - - "eslint-plugin-perfectionist/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "eslint-plugin-prettier/synckit": ["synckit@0.9.2", "", { "dependencies": { "@pkgr/core": "^0.1.0", "tslib": "^2.6.2" } }, "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw=="], + "eslint-plugin-import-x/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "eslint-plugin-react/doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], + "eslint-plugin-import-x/minimatch": ["minimatch@10.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="], - "eslint-plugin-react/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="], + "eslint-plugin-jsdoc/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "eslint-plugin-sonarjs/@babel/core": ["@babel/core@7.25.2", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.0", "@babel/helper-compilation-targets": "^7.25.2", "@babel/helper-module-transforms": "^7.25.2", "@babel/helpers": "^7.25.0", "@babel/parser": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.2", "@babel/types": "^7.25.2", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA=="], + "eslint-plugin-jsonc/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], - "eslint-plugin-sonarjs/@babel/eslint-parser": ["@babel/eslint-parser@7.25.1", "", { "dependencies": { "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", "eslint-visitor-keys": "^2.1.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.11.0", "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" } }, "sha512-Y956ghgTT4j7rKesabkh5WeqgSFZVFwaPR0IWFm7KFHFmmJ4afbG49SmfW4S+GyRPx0Dy5jxEWA5t0rpxfElWg=="], + "eslint-plugin-n/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], - "eslint-plugin-sonarjs/@eslint-community/regexpp": ["@eslint-community/regexpp@4.11.1", "", {}, "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q=="], + "eslint-plugin-n/globals": ["globals@15.12.0", "", {}, "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ=="], - "eslint-plugin-sonarjs/@typescript-eslint/utils": ["@typescript-eslint/utils@7.16.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "7.16.1", "@typescript-eslint/types": "7.16.1", "@typescript-eslint/typescript-estree": "7.16.1" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA=="], + "eslint-plugin-regexp/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], - "eslint-plugin-sonarjs/eslint-scope": ["eslint-scope@8.1.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw=="], + "eslint-plugin-sonarjs/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "eslint-plugin-sonarjs/minimatch": ["minimatch@10.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="], + "eslint-plugin-unicorn/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], - "eslint-plugin-sonarjs/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - - "eslint-plugin-testing-library/@typescript-eslint/utils": ["@typescript-eslint/utils@5.62.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", "@typescript-eslint/scope-manager": "5.62.0", "@typescript-eslint/types": "5.62.0", "@typescript-eslint/typescript-estree": "5.62.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ=="], + "eslint-plugin-vue/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - "eslint-plugin-unicorn/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "eslint-plugin-vuejs-accessibility/vue-eslint-parser": ["vue-eslint-parser@9.4.3", "", { "dependencies": { "debug": "^4.3.4", "eslint-scope": "^7.1.1", "eslint-visitor-keys": "^3.3.0", "espree": "^9.3.1", "esquery": "^1.4.0", "lodash": "^4.17.21", "semver": "^7.3.6" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg=="], - "eslint-plugin-vue/globals": ["globals@13.24.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ=="], + "eslint-plugin-yml/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "eslint-plugin-vue/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "espree/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "gaxios/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], - "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], - "jsonc-eslint-parser/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + "is-builtin-module/builtin-modules": ["builtin-modules@5.0.0", "", {}, "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg=="], "jsonc-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -1320,152 +849,62 @@ "jsonc-eslint-parser/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - "mocha/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - "normalize-package-data/semver": ["semver@5.7.2", "", { "bin": { "semver": "bin/semver" } }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + "mdast-util-frontmatter/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "micromark/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "read-pkg/type-fest": ["type-fest@0.6.0", "", {}, "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg=="], + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "read-pkg-up/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], + "mlly/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], - "regexpu-core/regjsparser": ["regjsparser@0.11.2", "", { "dependencies": { "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA=="], + "mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], - "regjsparser/jsesc": ["jsesc@0.5.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA=="], - - "string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + "regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], "teeny-request/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], "teeny-request/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], - "tsconfig-paths/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], - - "tsutils/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], - - "vue-eslint-parser/eslint-scope": ["eslint-scope@7.2.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg=="], - - "vue-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "vue-eslint-parser/espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], + "vue-eslint-parser/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "vue-eslint-parser/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], - - "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], - - "@nicolo-ribaudo/eslint-scope-5-internals/eslint-scope/estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], - - "@stylistic/eslint-plugin-js/espree/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + "yaml-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "@types/request/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], - "@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@7.16.1", "", {}, "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@7.16.1", "", {}, "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@7.16.1", "", { "dependencies": { "@typescript-eslint/types": "7.16.1", "@typescript-eslint/visitor-keys": "7.16.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" } }, "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ=="], - - "@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "@typescript-eslint/parser/@typescript-eslint/typescript-estree/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - - "@typescript-eslint/parser/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@7.16.1", "", {}, "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - - "@typescript-eslint/type-utils/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@7.16.1", "", { "dependencies": { "@typescript-eslint/types": "7.16.1", "@typescript-eslint/visitor-keys": "7.16.1" } }, "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw=="], - - "@typescript-eslint/type-utils/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@7.16.1", "", {}, "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@typescript-eslint/utils/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + "bun-types/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], "eslint-plugin-es-x/eslint-compat-utils/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], "eslint-plugin-import-x/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "eslint-plugin-jsonc/espree/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + "eslint-plugin-jsonc/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "eslint-plugin-jsonc/espree/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "eslint-plugin-n/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "eslint-plugin-n/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "eslint-plugin-perfectionist/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "eslint-plugin-sonarjs/@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "eslint-plugin-sonarjs/@babel/eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@2.1.0", "", {}, "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw=="], - - "eslint-plugin-sonarjs/@babel/eslint-parser/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "eslint-plugin-sonarjs/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@7.16.1", "", { "dependencies": { "@typescript-eslint/types": "7.16.1", "@typescript-eslint/visitor-keys": "7.16.1" } }, "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw=="], - - "eslint-plugin-sonarjs/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@7.16.1", "", {}, "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ=="], - - "eslint-plugin-sonarjs/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@7.16.1", "", { "dependencies": { "@typescript-eslint/types": "7.16.1", "@typescript-eslint/visitor-keys": "7.16.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" } }, "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ=="], + "eslint-plugin-regexp/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "eslint-plugin-sonarjs/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "eslint-plugin-testing-library/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@5.62.0", "", { "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0" } }, "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w=="], + "eslint-plugin-unicorn/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "eslint-plugin-testing-library/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@5.62.0", "", {}, "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ=="], + "eslint-plugin-vuejs-accessibility/vue-eslint-parser/eslint-scope": ["eslint-scope@7.2.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg=="], - "eslint-plugin-testing-library/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@5.62.0", "", { "dependencies": { "@typescript-eslint/types": "5.62.0", "@typescript-eslint/visitor-keys": "5.62.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", "semver": "^7.3.7", "tsutils": "^3.21.0" } }, "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA=="], + "eslint-plugin-vuejs-accessibility/vue-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "eslint-plugin-testing-library/@typescript-eslint/utils/eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], + "eslint-plugin-vuejs-accessibility/vue-eslint-parser/espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], - "eslint-plugin-testing-library/@typescript-eslint/utils/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "eslint-plugin-vuejs-accessibility/vue-eslint-parser/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - "eslint-plugin-vue/globals/type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="], - - "glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "mocha/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "read-pkg-up/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], + "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], "teeny-request/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], - - "vue-eslint-parser/espree/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], - - "@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "eslint-plugin-sonarjs/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - - "eslint-plugin-testing-library/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@5.62.0", "", { "dependencies": { "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" } }, "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw=="], - - "eslint-plugin-testing-library/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@5.62.0", "", { "dependencies": { "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" } }, "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw=="], - - "eslint-plugin-testing-library/@typescript-eslint/utils/eslint-scope/estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], - - "read-pkg-up/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], - - "@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "eslint-plugin-sonarjs/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - - "eslint-plugin-testing-library/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "eslint-plugin-testing-library/@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "read-pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], } } diff --git a/eslint.config.mjs b/eslint.config.mjs index 88c9df3..822186f 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,54 +1,41 @@ -import { audiolab } from '@swrlab/style-guide/eslint/presets' +import { audiolab } from '@swrlab/style-guide/eslint.js' export default audiolab( + { + prettier: false, + comments: true, + }, [ { ignores: [], }, { + name: 'node-utils/disabled-rules', rules: { - 'n/no-missing-import': 'off', - 'n/no-path-concat': 'off', - // 'vue/no-unused-component': 'off', - 'vue/no-unused-components': 'off', - 'n/no-unsupported-features/node-builtins': 'off', - 'n/no-missing-require': 'off', - 'no-unused-vars': 'off', - eqeqeq: 'off', - 'no-undef': 'off', - // 'prefer-const': 'off', - 'import/no-extraneous-dependencies': 'off', - 'n/no-extraneous-require': 'off', - - 'vue/no-deprecated-destroyed-lifecycle': 'off', - 'prefer-template': 'off', - 'sonarjs/cognitive-complexity': 'off', - - // fixable - 'one-var': 'off', - 'prefer-const': 'off', - 'no-var': 'off', - - // should be fixed / easy to fix - 'prefer-promise-reject-errors': 'off', - 'n/prefer-global/process': 'off', - 'n/prefer-global/buffer': 'off', - 'n/no-process-exit': 'off', - 'n/no-unpublished-import': 'off', - 'n/no-unpublished-require': 'off', - 'eslint-comments/require-description': 'off', - // could be fixed when converting to ESM - 'import/order': 'off', - // a bit more complex to fix (but nice idea in general) - 'import/no-default-export': 'off', - 'no-console': 'off', - 'func-names': 'off', + 'unicorn/prefer-string-slice': 'off', + 'perfectionist/sort-imports': 'off', + 'unicorn/prefer-string-replace-all': 'off', + 'node/prefer-global/buffer': 'off', + '@eslint-community/eslint-comments/require-description': 'off', 'jsonc/sort-keys': 'off', + 'no-console': 'off', + 'node/prefer-global/process': 'off', + 'prefer-template': 'off', + 'require-await': 'off', + 'security/detect-non-literal-fs-filename': 'off', + 'security/detect-non-literal-regexp': 'off', + 'security/detect-object-injection': 'off', + 'sonarjs/no-ignored-exceptions': 'off', + 'sonarjs/os-command': 'off', + 'sonarjs/pseudo-random': 'off', + 'sonarjs/slow-regex': 'off', + 'unicorn/no-instanceof-builtins': 'off', + 'unicorn/prefer-date-now': 'off', + 'unicorn/prefer-includes': 'off', + 'unicorn/prefer-optional-catch-binding': 'off', + 'unicorn/prefer-prototype-methods': 'off', + 'unused-imports/no-unused-vars': 'off', }, }, - ], - { - prettier: false, - comments: true, - } + ] ) diff --git a/package.json b/package.json index 87492a1..ec4645f 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,11 @@ "main": "./index.js", "scripts": { "ard:coreId": "node ./scripts/ard/coreId.js", - "lint": "eslint .", - "test": "bunx --bun mocha tests/**.mjs" + "format": "prettier --write .", + "lint": "eslint", + "lint:fix": "eslint --fix", + "test": "bun test tests/**.mjs", + "test:node": "node --test tests/**.mjs" }, "dependencies": { "@google-cloud/storage": "^7.16.0", @@ -22,15 +25,41 @@ "undici": "7.13.0" }, "devDependencies": { - "@swrlab/style-guide": "^1.0.3", + "@swrlab/style-guide": "^2.0.7", + "@types/bun": "^1.2.21", "chai": "5.1.2", - "eslint": "^9.33.0", - "eslint-plugin-json": "^4.0.1", - "mocha": "^11.7.1", + "eslint": "^9.34.0", "prettier": "^3.6.2" }, + "devEngines": { + "runtime": { + "name": "node", + "version": "^22.18.0 || >= 24.6", + "onFail": "warn" + }, + "packageManager": { + "name": "bun", + "onFail": "ignore" + } + }, "engines": { - "node": ">=20" + "node": ">=20 || ^22.18.0 || ^24.6.0" }, - "prettier": "@swrlab/style-guide/prettier" + "prettier": "@swrlab/style-guide/prettier.js", + "publishConfig": { + "access": "public", + "provenance": true, + "main": "./dist/index.js", + "module": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.mts", + "default": "./dist/index.js" + }, + "/ard.js": { + "types": "./dist/ard/index.d.mts", + "default": "./dist/ard/index.js" + } + } + } } diff --git a/packages/ard/index.js b/packages/ard/index.js index d41ff46..9f75ef8 100644 --- a/packages/ard/index.js +++ b/packages/ard/index.js @@ -1,5 +1,5 @@ // import packages -const createHashedId = require('../../utils/ard/createHashedId') +const createHashedId = require('../../utils/ard/createHashedId.js') // export packages module.exports = { diff --git a/packages/undici/request.js b/packages/undici/request.js index c207fc1..711ba94 100644 --- a/packages/undici/request.js +++ b/packages/undici/request.js @@ -1,5 +1,4 @@ // load node utils -// eslint-disable-next-line unicorn/prefer-node-protocol const undici = require('undici') const AbortController = require('abort-controller') @@ -43,7 +42,8 @@ module.exports = async (url, options) => { const { string, buffer } = await convertReadableStream(body) // detect/ set redirect - const redirect = statusCode >= 300 && statusCode < 400 && headers.location ? new URL(headers.location, url) : null + const redirect = + statusCode >= 300 && statusCode < 400 && headers.location ? new URL(headers.location, url) : null // fetch header vars const contentType = headers['content-type'] diff --git a/tests/ard.test.mjs b/tests/ard.test.mjs index 1ce140a..05a236b 100644 --- a/tests/ard.test.mjs +++ b/tests/ard.test.mjs @@ -5,14 +5,16 @@ */ -import { expect } from 'chai' -import { createHashedId } from '../packages/ard' +// import { expect } from 'chai' +import assert from 'node:assert' +import { describe, it } from 'node:test' +import { createHashedId } from '../packages/ard/index.js' // Test ARD Package describe('Test ARD Package', () => { describe('Test ARD-CoreID Hash', () => { it("createHashedId('test') = 0c171b2e54a30c11", () => { - expect(createHashedId('test')).to.equal('0c171b2e54a30c11') + assert.equal(createHashedId('test'), '0c171b2e54a30c11') }) }) }) diff --git a/tests/strings.test.mjs b/tests/strings.test.mjs index 728c069..32fec12 100644 --- a/tests/strings.test.mjs +++ b/tests/strings.test.mjs @@ -175,7 +175,9 @@ describe('Test Strings Package', () => { }) it("removeDoubleSpaces('hello world once again')) = 'hello world once again'", () => { - expect(strings.removeDoubleSpaces('hello world once again')).to.equal('hello world once again') + expect(strings.removeDoubleSpaces('hello world once again')).to.equal( + 'hello world once again' + ) }) }) From 9eccbbd906f478d20fdb3baff04fe67b92011a83 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Fri, 5 Sep 2025 09:13:44 +0200 Subject: [PATCH 02/42] refact(tests): move to plain `assert` - remove chai in favour of `node:assert` module - this module is supported by other runtimes like bun and deno as well run node tests: $ node --test tests/*.mjs run bun tests: $ bun test tests/*.mjs or to use the `test` command from `package.json`: bun test --- bun.lock | 13 ------ eslint.config.mjs | 1 + package.json | 1 - tests/ard.test.mjs | 9 ---- tests/date.test.mjs | 39 ++++++++---------- tests/helpers.test.mjs | 26 ++++-------- tests/numbers.test.mjs | 62 ++++++++++++---------------- tests/strings.test.mjs | 93 ++++++++++++++++++++---------------------- 8 files changed, 95 insertions(+), 149 deletions(-) diff --git a/bun.lock b/bun.lock index 77569a3..283e437 100644 --- a/bun.lock +++ b/bun.lock @@ -12,7 +12,6 @@ "devDependencies": { "@swrlab/style-guide": "^2.0.7", "@types/bun": "^1.2.21", - "chai": "5.1.2", "eslint": "^9.34.0", "prettier": "^3.6.2", }, @@ -187,8 +186,6 @@ "arrify": ["arrify@2.0.1", "", {}, "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="], - "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], - "async-retry": ["async-retry@1.3.3", "", { "dependencies": { "retry": "0.13.1" } }, "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw=="], "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], @@ -221,16 +218,12 @@ "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], - "chai": ["chai@5.1.2", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw=="], - "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], - "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], - "ci-info": ["ci-info@4.3.0", "", {}, "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ=="], "clean-regexp": ["clean-regexp@1.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw=="], @@ -259,8 +252,6 @@ "decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="], - "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], - "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], @@ -483,8 +474,6 @@ "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], - "loupe": ["loupe@3.1.2", "", {}, "sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg=="], - "luxon": ["luxon@3.7.1", "", {}, "sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg=="], "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], @@ -623,8 +612,6 @@ "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], - "pathval": ["pathval@2.0.0", "", {}, "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA=="], - "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], diff --git a/eslint.config.mjs b/eslint.config.mjs index 822186f..594b2e4 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -10,6 +10,7 @@ export default audiolab( ignores: [], }, { + files: ['./packages/**/*.js', './utils/**/*.js'], name: 'node-utils/disabled-rules', rules: { 'unicorn/prefer-string-slice': 'off', diff --git a/package.json b/package.json index ec4645f..a2e79fc 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "devDependencies": { "@swrlab/style-guide": "^2.0.7", "@types/bun": "^1.2.21", - "chai": "5.1.2", "eslint": "^9.34.0", "prettier": "^3.6.2" }, diff --git a/tests/ard.test.mjs b/tests/ard.test.mjs index 05a236b..9c1f396 100644 --- a/tests/ard.test.mjs +++ b/tests/ard.test.mjs @@ -1,16 +1,7 @@ -/* - - by SWR Audio Lab - tests with mocha and chai - -*/ - -// import { expect } from 'chai' import assert from 'node:assert' import { describe, it } from 'node:test' import { createHashedId } from '../packages/ard/index.js' -// Test ARD Package describe('Test ARD Package', () => { describe('Test ARD-CoreID Hash', () => { it("createHashedId('test') = 0c171b2e54a30c11", () => { diff --git a/tests/date.test.mjs b/tests/date.test.mjs index 9387a44..79b9708 100644 --- a/tests/date.test.mjs +++ b/tests/date.test.mjs @@ -1,68 +1,61 @@ -/* - - by SWR Audio Lab - tests with mocha and chai - -*/ - -// Add eslint exceptions for chai -/* global describe it */ - -import { expect } from 'chai' -import * as date from '../packages/date' +import assert from 'node:assert' +import { describe, it } from 'node:test' +import * as date from '../packages/date/index.js' const testDate = '2038-01-19T03:14:08.000' -const relativeTime = 2147483647000 - new Date().getTime() -const relativeYears = Number.parseInt(relativeTime / (1000 * 60 * 60 * 24 * 365), 10) +const relativeTime = 2147483647000 - Date.now() +const relativeYears = Number.parseInt( + relativeTime / (1000 * 60 * 60 * 24 * 365), + 10 +) -// Test DateTime Package describe('Test DateTime Package', () => { describe('Test getDateHourMinutes', () => { const testResult = 'Di, 19. Januar 2038 - 03:14 Uhr' it(`getDateHourMinutes('${testDate}') = '${testResult}'`, () => { - expect(date.getDateHourMinutes(testDate)).to.equal(testResult) + assert.equal(date.getDateHourMinutes(testDate), testResult) }) }) describe('Test getDayMonthYear', () => { const testResult = 'Di, 19. Januar 2038' it(`getDayMonthYear('${testDate}') = '${testResult}'`, () => { - expect(date.getDayMonthYear(testDate)).to.equal(testResult) + assert.equal(date.getDayMonthYear(testDate), testResult) }) }) describe('Test getFullRelativeTime', () => { const testResult = `Di, 19. Januar 2038 - 03:14 Uhr (in ${relativeYears} Jahren)` it(`getFullRelativeTime('${testDate}') = '${testResult}'`, () => { - expect(date.getFullRelativeTime(testDate)).to.equal(testResult) + assert.equal(date.getFullRelativeTime(testDate), testResult) }) }) describe('Test getHourMinutes', () => { const testResult = '03:14' it(`getHourMinutes('${testDate}') = '${testResult}'`, () => { - expect(date.getHourMinutes(testDate)).to.equal(testResult) + assert.equal(date.getHourMinutes(testDate), testResult) }) }) describe('Test getIsoRelativeTime', () => { const testResult = `${testDate} (in ${relativeYears} Jahren)` it(`getIsoRelativeTime('${testDate}') = '${testResult}'`, () => { - expect(date.getIsoRelativeTime(testDate)).to.equal(testResult) + assert.equal(date.getIsoRelativeTime(testDate), testResult) }) }) describe('Test getRelativeTime', () => { const testResult = `in ${relativeYears} Jahren` it(`getRelativeTime('${testDate}') = '${testResult}'`, () => { - expect(date.getRelativeTime(testDate)).to.equal(testResult) + assert.equal(date.getRelativeTime(testDate), testResult) }) }) describe('Test getYearMonthDay', () => { const testResult = '20380119' it(`getYearMonthDay('${testDate}') = '${testResult}'`, () => { - expect(date.getYearMonthDay(testDate)).to.equal(testResult) + assert.equal(date.getYearMonthDay(testDate), testResult) }) }) @@ -70,7 +63,7 @@ describe('Test DateTime Package', () => { const test = '20380119' const testResult = '19012038' it(`revYearMonthDay('${test}') = '${testResult}'`, () => { - expect(date.revYearMonthDay(test)).to.equal(testResult) + assert.equal(date.revYearMonthDay(test), testResult) }) }) }) diff --git a/tests/helpers.test.mjs b/tests/helpers.test.mjs index 590cac9..a1540b0 100644 --- a/tests/helpers.test.mjs +++ b/tests/helpers.test.mjs @@ -1,25 +1,15 @@ -/* +import assert from 'node:assert' +import { describe, it } from 'node:test' +import * as helpers from '../packages/helpers/index.js' - by SWR Audio Lab - tests with mocha and chai - -*/ - -// Add eslint exceptions for chai -/* global describe it */ - -import { expect } from 'chai' -import * as helpers from '../packages/helpers' - -// Test Helpers Package describe('Test Helpers Package', () => { describe('Test arrayToObjectCount', () => { it("arrayToObjectCount(['foo', 'bar', 'bar']) = { bar: 2, foo: 1 }", () => { const test = ['foo', 'bar', 'bar'] const result = { bar: 2, foo: 1 } const testResult = helpers.arrayToObjectCount(test) - expect(testResult.bar).to.equal(result.bar) - expect(testResult.foo).to.equal(result.foo) + assert.equal(testResult.bar, result.bar) + assert.equal(testResult.foo, result.foo) }) }) @@ -28,8 +18,8 @@ describe('Test Helpers Package', () => { const test = { hello: 'world', foo: 'bar' } const result = ['hello', 'foo'] const testResult = helpers.getJsonKeys(test) - expect(testResult[0]).to.equal(result[0]) - expect(testResult[1]).to.equal(result[1]) + assert.equal(testResult[0], result[0]) + assert.equal(testResult[1], result[1]) }) }) @@ -39,7 +29,7 @@ describe('Test Helpers Package', () => { const before = Date.now() await helpers.sleep(time) const after = Date.now() - expect(after - before).to.be.greaterThanOrEqual(time) + assert(after - before >= time) }) }) }) diff --git a/tests/numbers.test.mjs b/tests/numbers.test.mjs index 2045b86..f2b5d6f 100644 --- a/tests/numbers.test.mjs +++ b/tests/numbers.test.mjs @@ -1,127 +1,117 @@ -/* +import assert from 'node:assert' +import { describe, it } from 'node:test' +import * as numbers from '../packages/numbers/index.js' - by SWR Audio Lab - tests with mocha and chai - -*/ - -// Add eslint exceptions for chai -/* global describe it */ - -import { expect } from 'chai' -import * as numbers from '../packages/numbers' - -// Test Numbers Package describe('Test Numbers Package', () => { describe('Test addLeadingZero', () => { it("addLeadingZero(1) = '01'", () => { - expect(numbers.addLeadingZero(1)).to.equal('01') + assert.equal(numbers.addLeadingZero(1), '01') }) it("addLeadingZero(10) = '10'", () => { - expect(numbers.addLeadingZero(10)).to.equal('10') + assert.equal(numbers.addLeadingZero(10), '10') }) }) describe('Test addTrailingZeros', () => { it("addTrailingZeros(1, 5) = '1.00000'", () => { - expect(numbers.addTrailingZeros(1, 5)).to.equal('1.00000') + assert.equal(numbers.addTrailingZeros(1, 5), '1.00000') }) it("addTrailingZeros(1.1, 5) = '1.10000'", () => { - expect(numbers.addTrailingZeros(1.1, 5)).to.equal('1.10000') + assert.equal(numbers.addTrailingZeros(1.1, 5), '1.10000') }) it("addTrailingZeros('1.2', 5) = '1.20000'", () => { - expect(numbers.addTrailingZeros('1.2', 5)).to.equal('1.20000') + assert.equal(numbers.addTrailingZeros('1.2', 5), '1.20000') }) it("addTrailingZeros(2, 2, ',') = '2,00'", () => { - expect(numbers.addTrailingZeros(2, 2, ',')).to.equal('2,00') + assert.equal(numbers.addTrailingZeros(2, 2, ','), '2,00') }) it("addTrailingZeros(2.1, 2, ',') = '2,10'", () => { - expect(numbers.addTrailingZeros(2.1, 2, ',')).to.equal('2,10') + assert.equal(numbers.addTrailingZeros(2.1, 2, ','), '2,10') }) it("addTrailingZeros('2,2', 2, ','') = '2,20'", () => { - expect(numbers.addTrailingZeros('2,2', 2, ',')).to.equal('2,20') + assert.equal(numbers.addTrailingZeros('2,2', 2, ','), '2,20') }) }) describe('Test getAverage', () => { it('getAverage([1, 2, 3]) = 2', () => { - expect(numbers.getAverage([1, 2, 3])).to.equal(2) + assert.equal(numbers.getAverage([1, 2, 3]), 2) }) it('getAverage([1.2, 2.4, 3.6], 1) = 2.4', () => { - expect(numbers.getAverage([1.2, 2.4, 3.6], 1)).to.equal(2.4) + assert.equal(numbers.getAverage([1.2, 2.4, 3.6], 1), 2.4) }) }) describe('Test getDiff', () => { it('getDiff(2, 1) = 1', () => { - expect(numbers.getDiff(2, 1)).to.equal(1) + assert.equal(numbers.getDiff(2, 1), 1) }) it('getDiff(1, 2) = -1', () => { - expect(numbers.getDiff(1, 2)).to.equal(-1) + assert.equal(numbers.getDiff(1, 2), -1) }) }) describe('Test getRandomInRange', () => { it('getRandomInRange(1, 5) = 1,2,3,4 or 5', () => { - expect([1, 2, 3, 4, 5]).to.include(numbers.getRandomInRange(1, 5)) + assert([1, 2, 3, 4, 5].includes(numbers.getRandomInRange(1, 5))) }) it('getRandomInRange(5, 9) = 5,6,7,8 or 9', () => { - expect([5, 6, 7, 8, 9]).to.include(numbers.getRandomInRange(5, 9)) + assert([5, 6, 7, 8, 9].includes(numbers.getRandomInRange(5, 9))) }) }) describe('Test getSum', () => { it('getSum([1, 2, 3]) = 6', () => { - expect(numbers.getSum([1, 2, 3])).to.equal(6) + assert.equal(numbers.getSum([1, 2, 3]), 6) }) it('getSum([1.2, 2.4, 3.6], 1) = 7.2', () => { - expect(numbers.getSum([1.2, 2.4, 3.6], 1)).to.equal(7.2) + assert.equal(numbers.getSum([1.2, 2.4, 3.6], 1), 7.2) }) }) describe('Test isEven', () => { it('isEven(2) = true', () => { - expect(numbers.isEven(2)).to.equal(true) + assert.equal(numbers.isEven(2), true) }) it('isEven(1) = false', () => { - expect(numbers.isEven(1)).to.equal(false) + assert.equal(numbers.isEven(1), false) }) }) describe('Test normalize', () => { it('normalize(2, 100) = 0.02', () => { - expect(numbers.normalize(2, 100)).to.equal(0.02) + assert.equal(numbers.normalize(2, 100), 0.02) }) it('normalize(80, 100) = 0.8', () => { - expect(numbers.normalize(80, 100)).to.equal(0.8) + assert.equal(numbers.normalize(80, 100), 0.8) }) }) describe('Test roundTo', () => { it('roundTo(1.23456) = 1.23', () => { - expect(numbers.roundTo(1.23456)).to.equal(1.23) + assert.equal(numbers.roundTo(1.23456), 1.23) }) it('roundTo(1.23456, 4) = 1.2346', () => { - expect(numbers.roundTo(1.23456, 4)).to.equal(1.2346) + assert.equal(numbers.roundTo(1.23456, 4), 1.2346) }) }) describe('Test toReadable', () => { it("toReadable(1234567) = '1.234.567'", () => { - expect(numbers.toReadable(1234567)).to.equal('1.234.567') + assert.equal(numbers.toReadable(1234567), '1.234.567') }) }) }) diff --git a/tests/strings.test.mjs b/tests/strings.test.mjs index 32fec12..7b16f40 100644 --- a/tests/strings.test.mjs +++ b/tests/strings.test.mjs @@ -1,181 +1,176 @@ -/* +import assert from 'node:assert' +import { describe, it } from 'node:test' +import * as strings from '../packages/strings/index.js' - by SWR Audio Lab - tests with mocha and chai - -*/ - -// Add eslint exceptions for chai -/* global describe it */ - -import { expect } from 'chai' -import * as strings from '../packages/strings' - -// Test Strings Package describe('Test Strings Package', () => { describe('Test capitalize', () => { it("capitalize('a') = 'A'", () => { - expect(strings.capitalize('a')).to.equal('A') + assert.equal(strings.capitalize('a'), 'A') }) it("capitalize('apple') = 'Apple'", () => { - expect(strings.capitalize('apple')).to.equal('Apple') + assert.equal(strings.capitalize('apple'), 'Apple') }) }) describe('Test getObjectLength', () => { it("getObjectLength({ hello: 'world' }) = 1", () => { - expect(strings.getObjectLength({ hello: 'world' })).to.equal(1) + assert.equal(strings.getObjectLength({ hello: 'world' }), 1) }) it("getObjectLength({ hello: 'world', foo: 'bar' }) = 2", () => { - expect( + assert.equal( strings.getObjectLength({ hello: 'world', foo: 'bar', - }) - ).to.equal(2) + }), + 2 + ) }) }) describe('Test isArray', () => { it("isArray(['hello world']) = true", () => { - expect(strings.isArray(['hello world'])).to.equal(true) + assert.equal(strings.isArray(['hello world']), true) }) it("isArray({ hello: 'world' }) = false", () => { - expect(strings.isArray({ hello: 'world' })).to.equal(false) + assert.equal(strings.isArray({ hello: 'world' }), false) }) }) describe('Test isEmptyArray', () => { it('isEmptyArray([]) = true', () => { - expect(strings.isEmptyArray([])).to.equal(true) + assert.equal(strings.isEmptyArray([]), true) }) it("isEmptyArray(['hello world']) = false", () => { - expect(strings.isEmptyArray(['hello world'])).to.equal(false) + assert.equal(strings.isEmptyArray(['hello world']), false) }) }) describe('Test isEmptyObject', () => { it('isEmptyObject({}) = true', () => { - expect(strings.isEmptyObject({})).to.equal(true) + assert.equal(strings.isEmptyObject({}), true) }) it("isEmptyObject({ hello: 'world' }) = false", () => { - expect(strings.isEmptyObject({ hello: 'world' })).to.equal(false) + assert.equal(strings.isEmptyObject({ hello: 'world' }), false) }) }) describe('Test isEmptyString', () => { it("isEmptyString('') = true", () => { - expect(strings.isEmptyString('')).to.equal(true) + assert.equal(strings.isEmptyString(''), true) }) it("isEmptyString('hello world') = false", () => { - expect(strings.isEmptyString('hello world')).to.equal(false) + assert.equal(strings.isEmptyString('hello world'), false) }) }) describe('Test isIncluded', () => { it("isIncluded('hello world', 'hello') = true", () => { - expect(strings.isIncluded('hello world', 'hello')).to.equal(true) + assert.equal(strings.isIncluded('hello world', 'hello'), true) }) it("isIncluded('hello world', 'earth') = false", () => { - expect(strings.isIncluded('hello world', 'earth')).to.equal(false) + assert.equal(strings.isIncluded('hello world', 'earth'), false) }) }) describe('Test isNull', () => { it('isNull(null) = true', () => { - expect(strings.isNull(null)).to.equal(true) + assert.equal(strings.isNull(null), true) }) it('isNull(undefined) = false', () => { - expect(strings.isNull(undefined)).to.equal(false) + assert.equal(strings.isNull(undefined), false) }) }) describe('Test isObject', () => { it("isObject({ hello: 'world' }) = true", () => { - expect(strings.isObject({ hello: 'world' })).to.equal(true) + assert.equal(strings.isObject({ hello: 'world' }), true) }) it("isObject('hello world') = false", () => { - expect(strings.isObject('hello world')).to.equal(false) + assert.equal(strings.isObject('hello world'), false) }) }) describe('Test isUndefined', () => { it('isUndefined(undefined) = true', () => { - expect(strings.isUndefined(undefined)).to.equal(true) + assert.equal(strings.isUndefined(undefined), true) }) it('isUndefined(null) = false', () => { - expect(strings.isUndefined(null)).to.equal(false) + assert.equal(strings.isUndefined(null), false) }) }) describe('Test notEmptyArray', () => { it("notEmptyArray(['hello world']) = true", () => { - expect(strings.notEmptyArray(['hello world'])).to.equal(true) + assert.equal(strings.notEmptyArray(['hello world']), true) }) it('notEmptyArray([]) = false', () => { - expect(strings.notEmptyArray([])).to.equal(false) + assert.equal(strings.notEmptyArray([]), false) }) }) describe('Test notEmptyObject', () => { it("notEmptyObject({ hello: 'world' }) = true", () => { - expect(strings.notEmptyObject({ hello: 'world' })).to.equal(true) + assert.equal(strings.notEmptyObject({ hello: 'world' }), true) }) it('notEmptyObject({}) = false', () => { - expect(strings.notEmptyObject({})).to.equal(false) + assert.equal(strings.notEmptyObject({}), false) }) }) describe('Test notNullOrUndefined', () => { it("notNullOrUndefined('hello world') = true", () => { - expect(strings.notNullOrUndefined('hello world')).to.equal(true) + assert.equal(strings.notNullOrUndefined('hello world'), true) }) it('notNullOrUndefined(null) = false', () => { - expect(strings.notNullOrUndefined(null)).to.equal(false) + assert.equal(strings.notNullOrUndefined(null), false) }) it('notNullOrUndefined(undefined) = false', () => { - expect(strings.notNullOrUndefined(undefined)).to.equal(false) + assert.equal(strings.notNullOrUndefined(undefined), false) }) }) describe('Test pluralize', () => { it("pluralize(1, 'Apple') = '1 Apple'", () => { - expect(strings.pluralize(1, 'Apple')).to.equal('1 Apple') + assert.equal(strings.pluralize(1, 'Apple'), '1 Apple') }) it("pluralize(1000, 'Apple') = '1.000 Apples'", () => { - expect(strings.pluralize(1000, 'Apple')).to.equal('1.000 Apples') + assert.equal(strings.pluralize(1000, 'Apple'), '1.000 Apples') }) it("pluralize(1, 'Child', 'Children') = '1 Child'", () => { - expect(strings.pluralize(1, 'Child', 'Children')).to.equal('1 Child') + assert.equal(strings.pluralize(1, 'Child', 'Children'), '1 Child') }) it("pluralize(1000, 'Child', 'Children') = '1.000 Children'", () => { - expect(strings.pluralize(1000, 'Child', 'Children')).to.equal('1.000 Children') + assert.equal( + strings.pluralize(1000, 'Child', 'Children'), + '1.000 Children' + ) }) }) describe('Test removeDoubleSpaces', () => { it("removeDoubleSpaces('hello world')) = 'hello world'", () => { - expect(strings.removeDoubleSpaces('hello world')).to.equal('hello world') + assert.equal(strings.removeDoubleSpaces('hello world'), 'hello world') }) it("removeDoubleSpaces('hello world once again')) = 'hello world once again'", () => { - expect(strings.removeDoubleSpaces('hello world once again')).to.equal( + assert.equal( + strings.removeDoubleSpaces('hello world once again'), 'hello world once again' ) }) @@ -183,7 +178,7 @@ describe('Test Strings Package', () => { describe('Test toHex', () => { it("toHex('hello world')) = '68656c6c6f20776f726c64'", () => { - expect(strings.toHex('hello world')).to.equal('68656c6c6f20776f726c64') + assert.equal(strings.toHex('hello world'), '68656c6c6f20776f726c64') }) }) }) From 2c3755a49d7e1ce71566813fc970af5b51bf5530 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Fri, 5 Sep 2025 09:31:38 +0200 Subject: [PATCH 03/42] chore: format files and fix linting errors also add a bun test example. --- package.json | 36 ++++++++++++++++++------------------ scripts/ard/coreId.js | 24 +++++++----------------- tests/ard.bun.test.ts | 13 +++++++++++++ tests/date.test.mjs | 5 +---- tests/strings.test.mjs | 10 ++-------- 5 files changed, 41 insertions(+), 47 deletions(-) create mode 100644 tests/ard.bun.test.ts diff --git a/package.json b/package.json index a2e79fc..71e4e3d 100644 --- a/package.json +++ b/package.json @@ -2,13 +2,29 @@ "name": "@swrlab/utils", "version": "2.2.0", "description": "Wrapping common SWR Audio Lab utils", + "license": "MIT", "repository": { "type": "git", "url": "https://github.com/swrlab/node-utils" }, "author": "SWR Audio Lab ", - "license": "MIT", "main": "./index.js", + "publishConfig": { + "access": "public", + "provenance": true, + "main": "./dist/index.js", + "module": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.mts", + "default": "./dist/index.js" + }, + "/ard.js": { + "types": "./dist/ard/index.d.mts", + "default": "./dist/ard/index.js" + } + } + }, "scripts": { "ard:coreId": "node ./scripts/ard/coreId.js", "format": "prettier --write .", @@ -44,21 +60,5 @@ "engines": { "node": ">=20 || ^22.18.0 || ^24.6.0" }, - "prettier": "@swrlab/style-guide/prettier.js", - "publishConfig": { - "access": "public", - "provenance": true, - "main": "./dist/index.js", - "module": "./dist/index.js", - "exports": { - ".": { - "types": "./dist/index.d.mts", - "default": "./dist/index.js" - }, - "/ard.js": { - "types": "./dist/ard/index.d.mts", - "default": "./dist/ard/index.js" - } - } - } + "prettier": "@swrlab/style-guide/prettier.js" } diff --git a/scripts/ard/coreId.js b/scripts/ard/coreId.js index 6833711..23282b4 100644 --- a/scripts/ard/coreId.js +++ b/scripts/ard/coreId.js @@ -1,20 +1,10 @@ -/* - - by SWR audio lab - - this file creates a CLI for hashing ids - -*/ - -// load utils +const process = require('node:process') const createHashedId = require('../../utils/ard/createHashedId') -// parse input -const input = process.argv[2] +const input = process.argv.slice(2) -// log output -console.log('INPUT:') -console.log(input) -console.log(' ') -console.log('OUTPUT (CRC64-ECMA182):') -console.log(createHashedId(input)) +console.info('INPUT:') +console.info(input) +console.info(' ') +console.info('OUTPUT (CRC64-ECMA182):') +console.info(createHashedId(input)) diff --git a/tests/ard.bun.test.ts b/tests/ard.bun.test.ts new file mode 100644 index 0000000..c0e27ec --- /dev/null +++ b/tests/ard.bun.test.ts @@ -0,0 +1,13 @@ +/** + * @fileoverview A port of the ard test to bun using bun's `expect` (that behaves like jest). + */ +import { describe, expect, it } from 'bun:test' +import { createHashedId } from '../packages/ard/index.js' + +describe('Test ARD Package', () => { + describe('Test ARD-CoreID Hash', () => { + it("createHashedId('test') = 0c171b2e54a30c11", () => { + expect(createHashedId('test')).toEqual('0c171b2e54a30c11') + }) + }) +}) diff --git a/tests/date.test.mjs b/tests/date.test.mjs index 79b9708..9573f83 100644 --- a/tests/date.test.mjs +++ b/tests/date.test.mjs @@ -4,10 +4,7 @@ import * as date from '../packages/date/index.js' const testDate = '2038-01-19T03:14:08.000' const relativeTime = 2147483647000 - Date.now() -const relativeYears = Number.parseInt( - relativeTime / (1000 * 60 * 60 * 24 * 365), - 10 -) +const relativeYears = Number.parseInt(relativeTime / (1000 * 60 * 60 * 24 * 365), 10) describe('Test DateTime Package', () => { describe('Test getDateHourMinutes', () => { diff --git a/tests/strings.test.mjs b/tests/strings.test.mjs index 7b16f40..b2e137d 100644 --- a/tests/strings.test.mjs +++ b/tests/strings.test.mjs @@ -156,10 +156,7 @@ describe('Test Strings Package', () => { }) it("pluralize(1000, 'Child', 'Children') = '1.000 Children'", () => { - assert.equal( - strings.pluralize(1000, 'Child', 'Children'), - '1.000 Children' - ) + assert.equal(strings.pluralize(1000, 'Child', 'Children'), '1.000 Children') }) }) @@ -169,10 +166,7 @@ describe('Test Strings Package', () => { }) it("removeDoubleSpaces('hello world once again')) = 'hello world once again'", () => { - assert.equal( - strings.removeDoubleSpaces('hello world once again'), - 'hello world once again' - ) + assert.equal(strings.removeDoubleSpaces('hello world once again'), 'hello world once again') }) }) From 60b57a5101062c1c2799ee87c2bbb73bbfa0c3c9 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Fri, 5 Sep 2025 09:35:22 +0200 Subject: [PATCH 04/42] chore: improve dev linting --- eslint.config.mjs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 594b2e4..3081a34 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -2,16 +2,16 @@ import { audiolab } from '@swrlab/style-guide/eslint.js' export default audiolab( { - prettier: false, + prettier: true, comments: true, }, [ { - ignores: [], - }, - { - files: ['./packages/**/*.js', './utils/**/*.js'], name: 'node-utils/disabled-rules', + // because we disable some rules, there might be complaints about unused disable directives + linterOptions: { + reportUnusedDisableDirectives: false, + }, rules: { 'unicorn/prefer-string-slice': 'off', 'perfectionist/sort-imports': 'off', From 1af2814557bdfee3f048da42ff9f8ab25d50a4fd Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Fri, 5 Sep 2025 21:06:56 +0200 Subject: [PATCH 05/42] refact: start moving to Typescript - migrate ard - start migrating date -> dates --- README.md | 9 ++ bun.lock | 105 +++++++++++++++++- eslint.config.mjs | 3 +- package.json | 10 +- packages/ard/index.js | 7 -- packages/date/index.js | 21 ---- src/ard/createHashedId.ts | 18 +++ src/ard/index.ts | 1 + src/dates/getDateHourMinutes.ts | 39 +++++++ src/dates/getDayMonthYear.ts | 37 ++++++ .../date => src/dates}/getFullRelativeTime.js | 0 {utils/date => src/dates}/getHourMinutes.js | 0 .../date => src/dates}/getIsoRelativeTime.js | 0 {utils/date => src/dates}/getRelativeTime.js | 0 {utils/date => src/dates}/getYearMonthDay.js | 0 src/dates/index.ts | 8 ++ {utils/date => src/dates}/revYearMonthDay.js | 0 src/dates/utils.ts | 38 +++++++ tests/ard.bun.test.ts | 2 +- tests/ard.test.mjs | 2 +- tests/date.test.mjs | 2 +- tests/date.utils.test.mjs | 60 ++++++++++ tsconfig.json | 44 ++++++++ tsdown.config.ts | 9 ++ utils/ard/createHashedId.js | 15 --- utils/date/getDateHourMinutes.js | 5 - utils/date/getDayMonthYear.js | 4 - 27 files changed, 378 insertions(+), 61 deletions(-) delete mode 100644 packages/ard/index.js delete mode 100644 packages/date/index.js create mode 100644 src/ard/createHashedId.ts create mode 100644 src/ard/index.ts create mode 100644 src/dates/getDateHourMinutes.ts create mode 100644 src/dates/getDayMonthYear.ts rename {utils/date => src/dates}/getFullRelativeTime.js (100%) rename {utils/date => src/dates}/getHourMinutes.js (100%) rename {utils/date => src/dates}/getIsoRelativeTime.js (100%) rename {utils/date => src/dates}/getRelativeTime.js (100%) rename {utils/date => src/dates}/getYearMonthDay.js (100%) create mode 100644 src/dates/index.ts rename {utils/date => src/dates}/revYearMonthDay.js (100%) create mode 100644 src/dates/utils.ts create mode 100644 tests/date.utils.test.mjs create mode 100644 tsconfig.json create mode 100644 tsdown.config.ts delete mode 100644 utils/ard/createHashedId.js delete mode 100644 utils/date/getDateHourMinutes.js delete mode 100644 utils/date/getDayMonthYear.js diff --git a/README.md b/README.md index 32f8dde..9356aab 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,15 @@ Then run the desired script. - [Strings](./packages/strings) - Common string, array, object encoding and getter helpers - [Undici](./packages/undici) - Provides the latest install of [`undici-wrapper`](https://github.com/frytg/undici-wrapper), a wrapper around the [`undici`](https://undici.nodejs.org/) HTTP library +### ARD + +```js +import { createHashedId } from '@swrlab/utils/ard.js' + +// or globally +import { ard } from '@swrlab/utils' +``` + ## Scripts ### ARD Core ID generator diff --git a/bun.lock b/bun.lock index 283e437..1a0be38 100644 --- a/bun.lock +++ b/bun.lock @@ -12,14 +12,25 @@ "devDependencies": { "@swrlab/style-guide": "^2.0.7", "@types/bun": "^1.2.21", + "@types/luxon": "^3.7.1", "eslint": "^9.34.0", "prettier": "^3.6.2", + "tsdown": "^0.14.2", + "typescript": "^5.9.2", }, }, }, "packages": { + "@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.27.1", "", {}, "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow=="], + "@babel/parser": ["@babel/parser@7.28.3", "", { "dependencies": { "@babel/types": "^7.28.2" }, "bin": "./bin/babel-parser.js" }, "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA=="], + + "@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="], + "@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="], "@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="], @@ -68,7 +79,15 @@ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="], + + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.3", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@tybys/wasm-util": "^0.10.0" } }, "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -76,8 +95,44 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + "@oxc-project/runtime": ["@oxc-project/runtime@0.82.3", "", {}, "sha512-LNh5GlJvYHAnMurO+EyA8jJwN1rki7l3PSHuosDh2I7h00T6/u9rCkUjg/SvPmT1CZzvhuW0y+gf7jcqUy/Usg=="], + + "@oxc-project/types": ["@oxc-project/types@0.82.3", "", {}, "sha512-6nCUxBnGX0c6qfZW5MaF6/fmu5dHJDMiMPaioKHKs5mi5+8/FHQ7WGjgQIz1zxpmceMYfdIXkOaLYE+ejbuOtA=="], + "@pkgr/core": ["@pkgr/core@0.2.9", "", {}, "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA=="], + "@quansync/fs": ["@quansync/fs@0.1.5", "", { "dependencies": { "quansync": "^0.2.11" } }, "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA=="], + + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-beta.35", "", { "os": "android", "cpu": "arm64" }, "sha512-zVTg0544Ib1ldJSWwjy8URWYHlLFJ98rLnj+2FIj5fRs4KqGKP4VgH/pVUbXNGxeLFjItie6NSK1Un7nJixneQ=="], + + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.35", "", { "os": "darwin", "cpu": "arm64" }, "sha512-WPy0qx22CABTKDldEExfpYHWHulRoPo+m/YpyxP+6ODUPTQexWl8Wp12fn1CVP0xi0rOBj7ugs6+kKMAJW56wQ=="], + + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-beta.35", "", { "os": "darwin", "cpu": "x64" }, "sha512-3k1TabJafF/GgNubXMkfp93d5p30SfIMOmQ5gm1tFwO+baMxxVPwDs3FDvSl+feCWwXxBA+bzemgkaDlInmp1Q=="], + + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-beta.35", "", { "os": "freebsd", "cpu": "x64" }, "sha512-GAiapN5YyIocnBVNEiOxMfWO9NqIeEKKWohj1sPLGc61P+9N1meXOOCiAPbLU+adXq0grtbYySid+Or7f2q+Mg=="], + + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.35", "", { "os": "linux", "cpu": "arm" }, "sha512-okPKKIE73qkUMvq7dxDyzD0VIysdV4AirHqjf8tGTjuNoddUAl3WAtMYbuZCEKJwUyI67UINKO1peFVlYEb+8w=="], + + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-beta.35", "", { "os": "linux", "cpu": "arm64" }, "sha512-Nky8Q2cxyKVkEETntrvcmlzNir5khQbDfX3PflHPbZY7XVZalllRqw7+MW5vn+jTsk5BfKVeLsvrF4344IU55g=="], + + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-beta.35", "", { "os": "linux", "cpu": "arm64" }, "sha512-8aHpWVSfZl3Dy2VNFG9ywmlCPAJx45g0z+qdOeqmYceY7PBAT4QGzii9ig1hPb1pY8K45TXH44UzQwr2fx352Q=="], + + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-beta.35", "", { "os": "linux", "cpu": "x64" }, "sha512-1r1Ac/vTcm1q4kRiX/NB6qtorF95PhjdCxKH3Z5pb+bWMDZnmcz18fzFlT/3C6Qpj/ZqUF+EUrG4QEDXtVXGgg=="], + + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-beta.35", "", { "os": "linux", "cpu": "x64" }, "sha512-AFl1LnuhUBDfX2j+cE6DlVGROv4qG7GCPDhR1kJqi2+OuXGDkeEjqRvRQOFErhKz1ckkP/YakvN7JheLJ2PKHQ=="], + + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-beta.35", "", { "os": "none", "cpu": "arm64" }, "sha512-Tuwb8vPs+TVJlHhyLik+nwln/burvIgaPDgg6wjNZ23F1ttjZi0w0rQSZfAgsX4jaUbylwCETXQmTp3w6vcJMw=="], + + "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-beta.35", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.3" }, "cpu": "none" }, "sha512-rG0OozgqNUYcpu50MpICMlJflexRVtQfjlN9QYf6hoel46VvY0FbKGwBKoeUp2K5D4i8lV04DpEMfTZlzRjeiA=="], + + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-beta.35", "", { "os": "win32", "cpu": "arm64" }, "sha512-WeOfAZrycFo9+ZqTDp3YDCAOLolymtKGwImrr9n+OW0lpwI2UKyKXbAwGXRhydAYbfrNmuqWyfyoAnLh3X9Hjg=="], + + "@rolldown/binding-win32-ia32-msvc": ["@rolldown/binding-win32-ia32-msvc@1.0.0-beta.35", "", { "os": "win32", "cpu": "ia32" }, "sha512-XkLT7ikKGiUDvLh7qtJHRukbyyP1BIrD1xb7A+w4PjIiOKeOH8NqZ+PBaO4plT7JJnLxx+j9g/3B7iylR1nTFQ=="], + + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-beta.35", "", { "os": "win32", "cpu": "x64" }, "sha512-rftASFKVzjbcQHTCYHaBIDrnQFzbeV50tm4hVugG3tPjd435RHZC2pbeGV5IPdKEqyJSuurM/GfbV3kLQ3LY/A=="], + + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.35", "", {}, "sha512-slYrCpoxJUqzFDDNlvrOYRazQUNRvWPjXA17dAOISY3rDMxX6k8K4cj2H+hEYMHF81HO3uNd5rHVigAWRM5dSg=="], + "@swrlab/style-guide": ["@swrlab/style-guide@2.0.7", "", { "dependencies": { "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0", "@eslint/js": "^9.34.0", "@eslint/markdown": "^7.2.0", "eslint-config-flat-gitignore": "^2.1.0", "eslint-config-prettier": "^10.1.8", "eslint-flat-config-utils": "^2.1.1", "eslint-plugin-de-morgan": "^1.3.1", "eslint-plugin-import-x": "^4.16.1", "eslint-plugin-jsdoc": "^54.2.1", "eslint-plugin-jsonc": "^2.20.1", "eslint-plugin-n": "^17.21.3", "eslint-plugin-perfectionist": "^4.15.0", "eslint-plugin-pnpm": "^1.1.1", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-regexp": "^2.10.0", "eslint-plugin-security": "^3.0.1", "eslint-plugin-sonarjs": "^3.0.5", "eslint-plugin-testing-library": "^7.6.8", "eslint-plugin-unicorn": "^60.0.0", "eslint-plugin-unused-imports": "^4.2.0", "eslint-plugin-vue": "^10.4.0", "eslint-plugin-vuejs-accessibility": "^2.4.1", "eslint-plugin-yml": "^1.18.0", "globals": "^16.3.0", "jsonc-eslint-parser": "^2.4.0", "local-pkg": "^1.1.2", "prettier": "^3.6.2", "typescript-eslint": "^8.42.0", "vue-eslint-parser": "^10.2.0", "yaml-eslint-parser": "^1.3.0" }, "peerDependencies": { "eslint": "^9.34.0" } }, "sha512-4GHnx/7iiXrT146tIiql8O5cSDvr0IZ17JA7307O+vazeURrJQlVsrW/OITCsooD/gWa9rcnxj2uWSe8OioBdA=="], "@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="], @@ -94,6 +149,8 @@ "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + "@types/luxon": ["@types/luxon@3.7.1", "", {}, "sha512-H3iskjFIAn5SlJU7OuxUmTEpebK6TKB8rxZShDslBMZJ5u9S//KM1sbdAisiSrqwLQncVjnpi2OK2J51h+4lsg=="], + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], @@ -178,6 +235,8 @@ "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + "ansis": ["ansis@4.1.0", "", {}, "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w=="], + "are-docs-informative": ["are-docs-informative@0.0.2", "", {}, "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig=="], "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], @@ -186,6 +245,8 @@ "arrify": ["arrify@2.0.1", "", {}, "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="], + "ast-kit": ["ast-kit@2.1.2", "", { "dependencies": { "@babel/parser": "^7.28.0", "pathe": "^2.0.3" } }, "sha512-cl76xfBQM6pztbrFWRnxbrDm9EOqDr1BF6+qQnnDZG2Co2LjyUktkN9GTJfBAfdae+DbT2nJf2nCGAdDDN7W2g=="], + "async-retry": ["async-retry@1.3.3", "", { "dependencies": { "retry": "0.13.1" } }, "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw=="], "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], @@ -196,6 +257,8 @@ "bignumber.js": ["bignumber.js@9.1.2", "", {}, "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug=="], + "birpc": ["birpc@2.5.0", "", {}, "sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ=="], + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], @@ -212,6 +275,8 @@ "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], "caniuse-lite": ["caniuse-lite@1.0.30001739", "", {}, "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA=="], @@ -224,6 +289,8 @@ "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + "ci-info": ["ci-info@4.3.0", "", {}, "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ=="], "clean-regexp": ["clean-regexp@1.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw=="], @@ -254,6 +321,8 @@ "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], @@ -262,6 +331,10 @@ "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], + + "dts-resolver": ["dts-resolver@2.1.2", "", { "peerDependencies": { "oxc-resolver": ">=11.0.0" }, "optionalPeers": ["oxc-resolver"] }, "sha512-xeXHBQkn2ISSXxbJWD828PFjtyg+/UrMDo7W4Ffcs7+YWCquxU8YjV1KoxuiL+eJ5pg3ll+bC6flVv61L3LKZg=="], + "duplexify": ["duplexify@4.1.3", "", { "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", "stream-shift": "^1.0.2" } }, "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA=="], "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], @@ -410,6 +483,8 @@ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], + "html-entities": ["html-entities@2.5.2", "", {}, "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA=="], "http-proxy-agent": ["http-proxy-agent@5.0.0", "", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="], @@ -438,6 +513,8 @@ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + "jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], "jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@4.8.0", "", {}, "sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw=="], @@ -638,6 +715,8 @@ "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], + "refa": ["refa@0.12.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.8.0" } }, "sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g=="], "regexp-ast-analysis": ["regexp-ast-analysis@0.7.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.8.0", "refa": "^0.12.1" } }, "sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A=="], @@ -656,6 +735,10 @@ "reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="], + "rolldown": ["rolldown@1.0.0-beta.35", "", { "dependencies": { "@oxc-project/runtime": "=0.82.3", "@oxc-project/types": "=0.82.3", "@rolldown/pluginutils": "1.0.0-beta.35", "ansis": "^4.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.35", "@rolldown/binding-darwin-arm64": "1.0.0-beta.35", "@rolldown/binding-darwin-x64": "1.0.0-beta.35", "@rolldown/binding-freebsd-x64": "1.0.0-beta.35", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.35", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.35", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.35", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.35", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.35", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.35", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.35", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.35", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.35", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.35" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-gJATyqcsJe0Cs8RMFO8XgFjfTc0lK1jcSvirDQDSIfsJE+vt53QH/Ob+OBSJsXb98YtZXHfP/bHpELpPwCprow=="], + + "rolldown-plugin-dts": ["rolldown-plugin-dts@0.15.10", "", { "dependencies": { "@babel/generator": "^7.28.3", "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "ast-kit": "^2.1.2", "birpc": "^2.5.0", "debug": "^4.4.1", "dts-resolver": "^2.1.2", "get-tsconfig": "^4.10.1" }, "peerDependencies": { "@typescript/native-preview": ">=7.0.0-dev.20250601.1", "rolldown": "^1.0.0-beta.9", "typescript": "^5.0.0", "vue-tsc": "~3.0.3" }, "optionalPeers": ["@typescript/native-preview", "typescript", "vue-tsc"] }, "sha512-8cPVAVQUo9tYAoEpc3jFV9RxSil13hrRRg8cHC9gLXxRMNtWPc1LNMSDXzjyD+5Vny49sDZH77JlXp/vlc4I3g=="], + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], @@ -700,26 +783,34 @@ "teeny-request": ["teeny-request@9.0.0", "", { "dependencies": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.9", "stream-events": "^1.0.5", "uuid": "^9.0.0" } }, "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g=="], + "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], + "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], "tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], "ts-declaration-location": ["ts-declaration-location@1.0.7", "", { "dependencies": { "picomatch": "^4.0.2" }, "peerDependencies": { "typescript": ">=4.0.0" } }, "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA=="], + "tsdown": ["tsdown@0.14.2", "", { "dependencies": { "ansis": "^4.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "debug": "^4.4.1", "diff": "^8.0.2", "empathic": "^2.0.0", "hookable": "^5.5.3", "rolldown": "latest", "rolldown-plugin-dts": "^0.15.8", "semver": "^7.7.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.14", "tree-kill": "^1.2.2", "unconfig": "^7.3.3" }, "peerDependencies": { "@arethetypeswrong/core": "^0.18.1", "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0" }, "optionalPeers": ["@arethetypeswrong/core", "publint", "typescript", "unplugin-lightningcss", "unplugin-unused"], "bin": { "tsdown": "dist/run.mjs" } }, "sha512-6ThtxVZoTlR5YJov5rYvH8N1+/S/rD/pGfehdCLGznGgbxz+73EASV1tsIIZkLw2n+SXcERqHhcB/OkyxdKv3A=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], - "typescript": ["typescript@5.6.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw=="], + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], "typescript-eslint": ["typescript-eslint@8.42.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.42.0", "@typescript-eslint/parser": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/utils": "8.42.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ozR/rQn+aQXQxh1YgbCzQWDFrsi9mcg+1PM3l/z5o1+20P7suOIaNg515bpr/OYt6FObz/NHcBstydDLHWeEKg=="], "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], + "unconfig": ["unconfig@7.3.3", "", { "dependencies": { "@quansync/fs": "^0.1.5", "defu": "^6.1.4", "jiti": "^2.5.1", "quansync": "^0.2.11" } }, "sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA=="], + "undici": ["undici@7.13.0", "", {}, "sha512-l+zSMssRqrzDcb3fjMkjjLGmuiiK2pMIcV++mJaAc9vhjSGpvM7h43QgP+OAMb1GImHmbPyG2tBXeuyG5iY4gA=="], "undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], @@ -788,6 +879,8 @@ "@typescript-eslint/utils/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], + "@unrs/resolver-binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], + "bun-types/@types/node": ["@types/node@22.9.0", "", { "dependencies": { "undici-types": "~6.19.8" } }, "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ=="], "clean-regexp/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], @@ -812,6 +905,8 @@ "eslint-plugin-sonarjs/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "eslint-plugin-sonarjs/typescript": ["typescript@5.6.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw=="], + "eslint-plugin-unicorn/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], "eslint-plugin-vue/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], @@ -850,10 +945,16 @@ "regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], + "rolldown-plugin-dts/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "rolldown-plugin-dts/get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], + "teeny-request/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], "teeny-request/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + "tsdown/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "vue-eslint-parser/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "vue-eslint-parser/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], diff --git a/eslint.config.mjs b/eslint.config.mjs index 3081a34..442e5ee 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -2,12 +2,13 @@ import { audiolab } from '@swrlab/style-guide/eslint.js' export default audiolab( { - prettier: true, + prettier: false, comments: true, }, [ { name: 'node-utils/disabled-rules', + files: ['packages/**', 'utils/**'], // because we disable some rules, there might be complaints about unused disable directives linterOptions: { reportUnusedDisableDirectives: false, diff --git a/package.json b/package.json index 71e4e3d..b8fb0f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "@swrlab/utils", - "version": "2.2.0", + "version": "3.0.0", + "type": "module", "description": "Wrapping common SWR Audio Lab utils", "license": "MIT", "repository": { @@ -8,7 +9,7 @@ "url": "https://github.com/swrlab/node-utils" }, "author": "SWR Audio Lab ", - "main": "./index.js", + "main": "./src/index.ts", "publishConfig": { "access": "public", "provenance": true, @@ -43,8 +44,11 @@ "devDependencies": { "@swrlab/style-guide": "^2.0.7", "@types/bun": "^1.2.21", + "@types/luxon": "^3.7.1", "eslint": "^9.34.0", - "prettier": "^3.6.2" + "prettier": "^3.6.2", + "tsdown": "^0.14.2", + "typescript": "^5.9.2" }, "devEngines": { "runtime": { diff --git a/packages/ard/index.js b/packages/ard/index.js deleted file mode 100644 index 9f75ef8..0000000 --- a/packages/ard/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// import packages -const createHashedId = require('../../utils/ard/createHashedId.js') - -// export packages -module.exports = { - createHashedId, -} diff --git a/packages/date/index.js b/packages/date/index.js deleted file mode 100644 index 4ab424e..0000000 --- a/packages/date/index.js +++ /dev/null @@ -1,21 +0,0 @@ -// import packages -const getDateHourMinutes = require('../../utils/date/getDateHourMinutes') -const getDayMonthYear = require('../../utils/date/getDayMonthYear') -const getFullRelativeTime = require('../../utils/date/getFullRelativeTime') -const getHourMinutes = require('../../utils/date/getHourMinutes') -const getIsoRelativeTime = require('../../utils/date/getIsoRelativeTime') -const getRelativeTime = require('../../utils/date/getRelativeTime') -const getYearMonthDay = require('../../utils/date/getYearMonthDay') -const revYearMonthDay = require('../../utils/date/revYearMonthDay') - -// export packages -module.exports = { - getDateHourMinutes, - getDayMonthYear, - getFullRelativeTime, - getHourMinutes, - getIsoRelativeTime, - getRelativeTime, - getYearMonthDay, - revYearMonthDay, -} diff --git a/src/ard/createHashedId.ts b/src/ard/createHashedId.ts new file mode 100644 index 0000000..9833401 --- /dev/null +++ b/src/ard/createHashedId.ts @@ -0,0 +1,18 @@ +import { Buffer } from 'node:buffer' +import crc from 'node-crc' + +/** + * Create a a CRC64-ECMA182-compliant hash + * + * @module ard + * @category ard + * @param input - utf-8 encoded input string + * @returns CRC64-ECMA182-compliant hashed input + * + * @example + * ``` + * // Prints: '6a80b80f748c9b50' + * ard.createHashedId('my-string-to-encode') + * ``` + */ +export const createHashedId = (input: string): string => crc.crc64(Buffer.from(input, 'utf-8')).toString('hex') diff --git a/src/ard/index.ts b/src/ard/index.ts new file mode 100644 index 0000000..5b11cd8 --- /dev/null +++ b/src/ard/index.ts @@ -0,0 +1 @@ +export { createHashedId } from './createHashedId.ts' diff --git a/src/dates/getDateHourMinutes.ts b/src/dates/getDateHourMinutes.ts new file mode 100644 index 0000000..e93b679 --- /dev/null +++ b/src/dates/getDateHourMinutes.ts @@ -0,0 +1,39 @@ +import { DateTime } from 'luxon' +import { formatDateString, type ISODateString } from './utils.ts' + +const DEFAULT_LOCALE = 'de' + +const dayHourMinutesFormat = 'ccc, d. LLLL yyyy - HH:mm' +// const dayHourMinutesFormatDateFNS = 'PPPP - kk:mm' +/** + * Get a date string with full date including weekday and hours with minutes. + * + * @module dates + * @category dates + * + * @returns A string like 'Di, 19. Januar 2038 - 03:14 Uhr'. + */ +export const getDateHourMinutesLegacy = (date: ISODateString) => + `${DateTime.fromISO(date).setLocale(DEFAULT_LOCALE).toFormat(dayHourMinutesFormat)} Uhr` + +/** + * Get a date string with full date including weekday and hours with minutes. + * + * @module dates + * @category dates + * @param date + * @returns german formatted date string + */ +export function getDateHourMinutes(date: ISODateString): string { + const options: Intl.DateTimeFormatOptions = { + weekday: 'short', + month: 'long', + day: 'numeric', + year: 'numeric', + hour: 'numeric', + minute: 'numeric', + hour12: false, + timeZone: 'Europe/Berlin', + } + return formatDateString(new Intl.DateTimeFormat('de-DE', options).format(Date.parse(date))) +} diff --git a/src/dates/getDayMonthYear.ts b/src/dates/getDayMonthYear.ts new file mode 100644 index 0000000..7146408 --- /dev/null +++ b/src/dates/getDayMonthYear.ts @@ -0,0 +1,37 @@ +import { DateTime } from 'luxon' +import { formatDateString, type ISODateString } from './utils.ts' + +const DEFAULT_LOCALE = 'de' + +const dateFormat = 'ccc, d. LLLL yyyy' +/** + * Get weekday, day, month and year in german locale. + * + * @category dates + * + * @param date - input Date + * @param locale - defaults to `de` + * + * @returns 'Do, 1. Januar 1970' + */ +export const getDayMonthYearLegacy = (date: ISODateString, locale: string = DEFAULT_LOCALE): string => + DateTime.fromISO(date).setLocale(locale).toFormat(dateFormat) + +const options: Intl.DateTimeFormatOptions = { + weekday: 'short', + day: 'numeric', + month: 'long', + year: 'numeric', +} +/** + * Get weekday, day, month and year in german locale. + * + * @category dates + * + * @param date - input Date + * @param locale - defaults to `de` + * + * @returns 'Do, 1. Januar 1970' + */ +export const getDayMonthYear = (date: ISODateString, locale: string = 'de-DE'): string => + formatDateString(new Intl.DateTimeFormat(locale, options).format(Date.parse(date))) diff --git a/utils/date/getFullRelativeTime.js b/src/dates/getFullRelativeTime.js similarity index 100% rename from utils/date/getFullRelativeTime.js rename to src/dates/getFullRelativeTime.js diff --git a/utils/date/getHourMinutes.js b/src/dates/getHourMinutes.js similarity index 100% rename from utils/date/getHourMinutes.js rename to src/dates/getHourMinutes.js diff --git a/utils/date/getIsoRelativeTime.js b/src/dates/getIsoRelativeTime.js similarity index 100% rename from utils/date/getIsoRelativeTime.js rename to src/dates/getIsoRelativeTime.js diff --git a/utils/date/getRelativeTime.js b/src/dates/getRelativeTime.js similarity index 100% rename from utils/date/getRelativeTime.js rename to src/dates/getRelativeTime.js diff --git a/utils/date/getYearMonthDay.js b/src/dates/getYearMonthDay.js similarity index 100% rename from utils/date/getYearMonthDay.js rename to src/dates/getYearMonthDay.js diff --git a/src/dates/index.ts b/src/dates/index.ts new file mode 100644 index 0000000..0f80ab8 --- /dev/null +++ b/src/dates/index.ts @@ -0,0 +1,8 @@ +export { getDateHourMinutes } from './getDateHourMinutes.ts' +export { getDayMonthYear } from './getDayMonthYear.ts' +// import { getFullRelativeTime } from '../../utils/date/getFullRelativeTime' +// import { getHourMinutes } from './utils/date/getHourMinutes' +// import { getIsoRelativeTime } from './utils/date/getIsoRelativeTime' +// import { getRelativeTime } from './utils/date/getRelativeTime' +// import { getYearMonthDay } from './utils/date/getYearMonthDay' +// import { revYearMonthDay } from './utils/date/revYearMonthDay.ts' diff --git a/utils/date/revYearMonthDay.js b/src/dates/revYearMonthDay.js similarity index 100% rename from utils/date/revYearMonthDay.js rename to src/dates/revYearMonthDay.js diff --git a/src/dates/utils.ts b/src/dates/utils.ts new file mode 100644 index 0000000..f631c09 --- /dev/null +++ b/src/dates/utils.ts @@ -0,0 +1,38 @@ +// used as luxon DateTime.fromISO input +/** ISO Date String, like `2038-01-19T03:14:08.000`. */ +export type ISODateString = `${string}T${string}` + +/** append ` Uhr` suffix */ +const addOClock = (str: string) => `${str} Uhr` + +type FormatOptions = { + /** remove the dot after the short weekday */ + weekdayWithoutDot?: boolean + /** replaces `um` or `at` with provided string or `-` if `true` */ + timePrefix?: string | true + /** add ` Uhr` suffix after the time */ + addOClockSuffix?: boolean +} +/** + * Format Date String and modify smaller issues. + * + * @param str - input string + * @param options - FormatOptions + * + * @returns formatted date string + */ +export const formatDateString = (str: string, options: FormatOptions = {}): string => { + const { weekdayWithoutDot = true, timePrefix = true, addOClockSuffix = true } = options + let formatted = str + if (weekdayWithoutDot) { + formatted = formatted.replace('.,', ',') + } + if (timePrefix) { + const prefix = timePrefix !== true ? timePrefix : '-' + formatted = formatted.replace(/ um /, ` ${prefix} `) + } + if (addOClockSuffix) { + formatted = addOClock(formatted) + } + return formatted +} diff --git a/tests/ard.bun.test.ts b/tests/ard.bun.test.ts index c0e27ec..d73f90c 100644 --- a/tests/ard.bun.test.ts +++ b/tests/ard.bun.test.ts @@ -2,7 +2,7 @@ * @fileoverview A port of the ard test to bun using bun's `expect` (that behaves like jest). */ import { describe, expect, it } from 'bun:test' -import { createHashedId } from '../packages/ard/index.js' +import { createHashedId } from '../src/ard/index.ts' describe('Test ARD Package', () => { describe('Test ARD-CoreID Hash', () => { diff --git a/tests/ard.test.mjs b/tests/ard.test.mjs index 9c1f396..a038a2c 100644 --- a/tests/ard.test.mjs +++ b/tests/ard.test.mjs @@ -1,6 +1,6 @@ import assert from 'node:assert' import { describe, it } from 'node:test' -import { createHashedId } from '../packages/ard/index.js' +import { createHashedId } from '../src/ard/index.ts' describe('Test ARD Package', () => { describe('Test ARD-CoreID Hash', () => { diff --git a/tests/date.test.mjs b/tests/date.test.mjs index 9573f83..57deda1 100644 --- a/tests/date.test.mjs +++ b/tests/date.test.mjs @@ -1,6 +1,6 @@ import assert from 'node:assert' import { describe, it } from 'node:test' -import * as date from '../packages/date/index.js' +import * as date from '../src/dates/index.ts' const testDate = '2038-01-19T03:14:08.000' const relativeTime = 2147483647000 - Date.now() diff --git a/tests/date.utils.test.mjs b/tests/date.utils.test.mjs new file mode 100644 index 0000000..5b752b6 --- /dev/null +++ b/tests/date.utils.test.mjs @@ -0,0 +1,60 @@ +import assert from 'node:assert' +import { test } from 'node:test' +import { formatDateString } from '../src/dates/utils.ts' + +/** german formatted date string */ +const date = 'Mo., 19. Januar 2038 um 14:08' +const formattedDate = 'Mo, 19. Januar 2038 - 14:08 Uhr' + +test('formatDateString()', (t) => { + t.test('default values', () => { + assert.strictEqual(formatDateString(''), ' Uhr') + assert.strictEqual(formatDateString(' um '), ' - Uhr') + assert.strictEqual(formatDateString('So., 20'), 'So, 20 Uhr') + assert.strictEqual(formatDateString(date), formattedDate) + }) + t.test('no modifications', () => { + const options = { + addOClockSuffix: false, + timePrefix: false, + weekdayWithoutDot: false, + } + assert.strictEqual(formatDateString('', options), '') + assert.strictEqual(formatDateString(date, options), date) + }) + t.test('addOClockSuffix', () => { + assert.strictEqual(formatDateString('', { addOClockSuffix: false }), '') + assert.strictEqual( + formatDateString(date, { addOClockSuffix: false }), + formattedDate.replace(' Uhr', '') + ) + assert(!formatDateString(date, { addOClockSuffix: false }).includes('Uhr')) + }) + t.test('other timePrefix', () => { + const prefix = 'hello' + assert.strictEqual(formatDateString('', { timePrefix: prefix }), ' Uhr') + assert.strictEqual( + formatDateString(' um ', { timePrefix: prefix, addOClockSuffix: false }), + ` ${prefix} ` + ) + assert(formatDateString(date, { timePrefix: prefix }).includes(prefix)) + }) + t.test('weekday with dot', () => { + assert.strictEqual( + formatDateString('.,', { + weekdayWithoutDot: false, + addOClockSuffix: false, + }), + '.,' + ) + assert.strictEqual( + formatDateString('.,', { + weekdayWithoutDot: true, + addOClockSuffix: false, + }), + ',' + ) + assert(formatDateString(date, { weekdayWithoutDot: false }).includes('.,')) + assert(!formatDateString(date, { weekdayWithoutDot: true }).includes('.,')) + }) +}) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..5fc09ea --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,44 @@ +{ + "compilerOptions": { + "target": "esnext", + "rootDir": "src", + "module": "nodenext", + // "lib": ["esnext"], + // "types": ["node"], + "resolveJsonModule": true, + + "allowImportingTsExtensions": true, + + // "noPropertyAccessFromIndexSignature": true, + + // Recommended Options + "strict": true, + "exactOptionalPropertyTypes": true, + + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + // Style Options + "noImplicitReturns": true, + // "noEmit": true, + + // Stricter Typechecking Options + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "declaration": true, + "declarationMap": true, + "isolatedDeclarations": true, + "outDir": "dist", + // Other Outputs + "sourceMap": true, + "erasableSyntaxOnly": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, // --> isolatedModules + "rewriteRelativeImportExtensions": true, + // "jsx": "react-jsx", + // "moduleDetection": "force", + "skipLibCheck": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src/**/*"] +} diff --git a/tsdown.config.ts b/tsdown.config.ts new file mode 100644 index 0000000..549ae6c --- /dev/null +++ b/tsdown.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsdown' + +export default defineConfig({ + entry: { + index: 'src/index.ts', + eslint: 'src/eslint/index.ts', + prettier: 'src/prettier/index.js', + }, +}) diff --git a/utils/ard/createHashedId.js b/utils/ard/createHashedId.js deleted file mode 100644 index ae2b1a2..0000000 --- a/utils/ard/createHashedId.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - - by SWR Audio Lab - - this file creates a CRC64-ECMA182-compliant hash - based on an utf-8 encoded input string - -*/ - -// load node utils -const crc = require('node-crc') - -module.exports = (input) => { - return crc.crc64(Buffer.from(input, 'utf-8')).toString('hex') -} diff --git a/utils/date/getDateHourMinutes.js b/utils/date/getDateHourMinutes.js deleted file mode 100644 index fcc9704..0000000 --- a/utils/date/getDateHourMinutes.js +++ /dev/null @@ -1,5 +0,0 @@ -const { DateTime } = require('luxon') - -// returns 'Di, 19. Januar 2038 - 03:14 Uhr' -const dayHourMinutes = 'ccc, d. LLLL yyyy - HH:mm' -module.exports = (date) => `${DateTime.fromISO(date).setLocale('de').toFormat(dayHourMinutes)} Uhr` diff --git a/utils/date/getDayMonthYear.js b/utils/date/getDayMonthYear.js deleted file mode 100644 index cc387c8..0000000 --- a/utils/date/getDayMonthYear.js +++ /dev/null @@ -1,4 +0,0 @@ -const { DateTime } = require('luxon') - -// returns 'Do, 1. Januar 1970' -module.exports = (date) => DateTime.fromISO(date).setLocale('de').toFormat('ccc, d. LLLL yyyy') From eb64f496841bac59fa673b7d5680ef4892fa0afc Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Fri, 5 Sep 2025 22:10:07 +0200 Subject: [PATCH 06/42] refact(dates): adjust tests --- src/dates/getDateHourMinutes.ts | 11 ++--- src/dates/getDayMonthYear.ts | 16 +++---- src/dates/getFullRelativeTime.js | 5 --- src/dates/index.ts | 24 +++++++++- src/dates/utils.ts | 39 +++++++++++++++-- tests/date.test.mjs | 24 +++++++--- tests/date.utils.test.mjs | 75 ++++++++++++++++++++++---------- 7 files changed, 136 insertions(+), 58 deletions(-) delete mode 100644 src/dates/getFullRelativeTime.js diff --git a/src/dates/getDateHourMinutes.ts b/src/dates/getDateHourMinutes.ts index e93b679..bdec7a5 100644 --- a/src/dates/getDateHourMinutes.ts +++ b/src/dates/getDateHourMinutes.ts @@ -1,7 +1,4 @@ -import { DateTime } from 'luxon' -import { formatDateString, type ISODateString } from './utils.ts' - -const DEFAULT_LOCALE = 'de' +import { type ISODateString, parseDate, parseDateWithLuxon } from './utils.ts' const dayHourMinutesFormat = 'ccc, d. LLLL yyyy - HH:mm' // const dayHourMinutesFormatDateFNS = 'PPPP - kk:mm' @@ -14,7 +11,7 @@ const dayHourMinutesFormat = 'ccc, d. LLLL yyyy - HH:mm' * @returns A string like 'Di, 19. Januar 2038 - 03:14 Uhr'. */ export const getDateHourMinutesLegacy = (date: ISODateString) => - `${DateTime.fromISO(date).setLocale(DEFAULT_LOCALE).toFormat(dayHourMinutesFormat)} Uhr` + `${parseDateWithLuxon(date).toFormat(dayHourMinutesFormat)} Uhr` /** * Get a date string with full date including weekday and hours with minutes. @@ -33,7 +30,7 @@ export function getDateHourMinutes(date: ISODateString): string { hour: 'numeric', minute: 'numeric', hour12: false, - timeZone: 'Europe/Berlin', + // timeZone: 'Europe/Berlin', } - return formatDateString(new Intl.DateTimeFormat('de-DE', options).format(Date.parse(date))) + return new Intl.DateTimeFormat('de-DE', options).format(parseDate(date)) } diff --git a/src/dates/getDayMonthYear.ts b/src/dates/getDayMonthYear.ts index 7146408..8b7581a 100644 --- a/src/dates/getDayMonthYear.ts +++ b/src/dates/getDayMonthYear.ts @@ -1,21 +1,16 @@ -import { DateTime } from 'luxon' -import { formatDateString, type ISODateString } from './utils.ts' +import { DEFAULT_LOCALE, type ISODateString, parseDate, parseDateWithLuxon } from './utils.ts' -const DEFAULT_LOCALE = 'de' - -const dateFormat = 'ccc, d. LLLL yyyy' +const luxonDateFormat = 'ccc, d. LLLL yyyy' /** * Get weekday, day, month and year in german locale. * * @category dates * * @param date - input Date - * @param locale - defaults to `de` * * @returns 'Do, 1. Januar 1970' */ -export const getDayMonthYearLegacy = (date: ISODateString, locale: string = DEFAULT_LOCALE): string => - DateTime.fromISO(date).setLocale(locale).toFormat(dateFormat) +export const getDayMonthYearLegacy = (date: ISODateString): string => parseDateWithLuxon(date).toFormat(luxonDateFormat) const options: Intl.DateTimeFormatOptions = { weekday: 'short', @@ -23,6 +18,7 @@ const options: Intl.DateTimeFormatOptions = { month: 'long', year: 'numeric', } + /** * Get weekday, day, month and year in german locale. * @@ -33,5 +29,5 @@ const options: Intl.DateTimeFormatOptions = { * * @returns 'Do, 1. Januar 1970' */ -export const getDayMonthYear = (date: ISODateString, locale: string = 'de-DE'): string => - formatDateString(new Intl.DateTimeFormat(locale, options).format(Date.parse(date))) +export const getDayMonthYear = (date: ISODateString, locale: string = DEFAULT_LOCALE): string => + new Intl.DateTimeFormat(locale, options).format(parseDate(date)) diff --git a/src/dates/getFullRelativeTime.js b/src/dates/getFullRelativeTime.js deleted file mode 100644 index edcab2d..0000000 --- a/src/dates/getFullRelativeTime.js +++ /dev/null @@ -1,5 +0,0 @@ -const getDateHourMinutes = require('./getDateHourMinutes') -const getRelativeTime = require('./getRelativeTime') - -// returns 'Do, 1. Januar 1970 - 00:00 Uhr (in YY Jahren)' -module.exports = (date) => `${getDateHourMinutes(date)} (${getRelativeTime(date)})` diff --git a/src/dates/index.ts b/src/dates/index.ts index 0f80ab8..9305f59 100644 --- a/src/dates/index.ts +++ b/src/dates/index.ts @@ -1,8 +1,28 @@ -export { getDateHourMinutes } from './getDateHourMinutes.ts' -export { getDayMonthYear } from './getDayMonthYear.ts' +/** + * @fileoverview Date formatting utilities. + */ + +import { getDateHourMinutes } from './getDateHourMinutes.ts' +import { getDayMonthYear } from './getDayMonthYear.ts' +import { addOClock, type ISODateString, shortenWeekday } from './utils.ts' // import { getFullRelativeTime } from '../../utils/date/getFullRelativeTime' // import { getHourMinutes } from './utils/date/getHourMinutes' // import { getIsoRelativeTime } from './utils/date/getIsoRelativeTime' // import { getRelativeTime } from './utils/date/getRelativeTime' // import { getYearMonthDay } from './utils/date/getYearMonthDay' // import { revYearMonthDay } from './utils/date/revYearMonthDay.ts' + +export { getDateHourMinutes } +export { getDayMonthYear } + +export { getDateHourMinutesLegacy } from './getDateHourMinutes.ts' + +/** + * Legacy date exports to be compatible with the previous format. + */ +export const legacy = { + getDateHourMinutes(date: ISODateString): string { + return addOClock(date) + }, + getDayMonthYear: (date: ISODateString): string => shortenWeekday(getDayMonthYear(date)), +} diff --git a/src/dates/utils.ts b/src/dates/utils.ts index f631c09..c05616c 100644 --- a/src/dates/utils.ts +++ b/src/dates/utils.ts @@ -1,27 +1,58 @@ +import { DateTime } from 'luxon' + +/** Default date locale for german */ +export const DEFAULT_LOCALE = 'de-DE' + // used as luxon DateTime.fromISO input /** ISO Date String, like `2038-01-19T03:14:08.000`. */ export type ISODateString = `${string}T${string}` +export const parseDateWithLuxon = (date: ISODateString): DateTime => DateTime.fromISO(date).setLocale(DEFAULT_LOCALE) + +export const parseDate = (date: ISODateString): Date => new Date(date) +// in the future we can use the Temporal API +// export const parseDate = (date: ISODateString): Temporal.PlainDateTime => new Temporal.PlainDateTime.from(date) + /** append ` Uhr` suffix */ -const addOClock = (str: string) => `${str} Uhr` +export const addOClock = (str: string) => `${str} Uhr` -type FormatOptions = { +/** removing the trailing `.` form a short weekname before a comma like so: `Mo.,` -> `Mo,` */ +export const shortenWeekday = (str: string): string => str.replace('.,', ',') + +type OptionsWeekdayDot = { /** remove the dot after the short weekday */ weekdayWithoutDot?: boolean +} +type FormatOptions = OptionsWeekdayDot & { /** replaces `um` or `at` with provided string or `-` if `true` */ timePrefix?: string | true /** add ` Uhr` suffix after the time */ addOClockSuffix?: boolean } /** - * Format Date String and modify smaller issues. + * Format date string and modify smaller issues. * * @param str - input string * @param options - FormatOptions * * @returns formatted date string */ -export const formatDateString = (str: string, options: FormatOptions = {}): string => { +export const formatDateString = (str: string, options: OptionsWeekdayDot = { weekdayWithoutDot: true }): string => { + if (options.weekdayWithoutDot) { + return shortenWeekday(str) + } + return str +} + +/** + * Format date time string and modify smaller issues. + * + * @param str - input string + * @param options - FormatOptions + * + * @returns formatted date time string + */ +export const formatDateTimeString = (str: string, options: FormatOptions = {}): string => { const { weekdayWithoutDot = true, timePrefix = true, addOClockSuffix = true } = options let formatted = str if (weekdayWithoutDot) { diff --git a/tests/date.test.mjs b/tests/date.test.mjs index 57deda1..99125b1 100644 --- a/tests/date.test.mjs +++ b/tests/date.test.mjs @@ -2,22 +2,34 @@ import assert from 'node:assert' import { describe, it } from 'node:test' import * as date from '../src/dates/index.ts' +const date2 = 'Fri Sep 05 2025 21:44:37 GMT+0200 (Central European Summer Time)' +const date2date = new Date(date2) +const date2iso = '2025-09-05T19:44:37.000Z' + const testDate = '2038-01-19T03:14:08.000' const relativeTime = 2147483647000 - Date.now() const relativeYears = Number.parseInt(relativeTime / (1000 * 60 * 60 * 24 * 365), 10) describe('Test DateTime Package', () => { describe('Test getDateHourMinutes', () => { - const testResult = 'Di, 19. Januar 2038 - 03:14 Uhr' - it(`getDateHourMinutes('${testDate}') = '${testResult}'`, () => { - assert.equal(date.getDateHourMinutes(testDate), testResult) + const newFormat = 'Di., 19. Januar 2038 um 03:14' + const testLegacyResult = 'Di, 19. Januar 2038 - 03:14 Uhr' + it(`getDateHourMinutes('${testDate}') = '${testLegacyResult}'`, () => { + assert.equal(date.getDateHourMinutesLegacy(testDate), testLegacyResult) + }) + it(`getDateHourMinutes('${testDate}') = '${newFormat}'`, () => { + assert.equal(date.getDateHourMinutes(testDate), newFormat) }) }) describe('Test getDayMonthYear', () => { - const testResult = 'Di, 19. Januar 2038' - it(`getDayMonthYear('${testDate}') = '${testResult}'`, () => { - assert.equal(date.getDayMonthYear(testDate), testResult) + const newFormat = 'Di., 19. Januar 2038' + it(`getDayMonthYear('${testDate}') = '${newFormat}'`, () => { + assert.equal(date.getDayMonthYear(testDate), newFormat) + }) + const testLegacyFormat = 'Di, 19. Januar 2038' + it(`getDayMonthYear('${testDate}') = '${testLegacyFormat}'`, () => { + assert.equal(date.legacy.getDayMonthYear(testDate), testLegacyFormat) }) }) diff --git a/tests/date.utils.test.mjs b/tests/date.utils.test.mjs index 5b752b6..9e6afac 100644 --- a/tests/date.utils.test.mjs +++ b/tests/date.utils.test.mjs @@ -1,60 +1,87 @@ import assert from 'node:assert' -import { test } from 'node:test' -import { formatDateString } from '../src/dates/utils.ts' +import { describe, test } from 'node:test' +import { formatDateString, formatDateTimeString } from '../src/dates/utils.ts' /** german formatted date string */ const date = 'Mo., 19. Januar 2038 um 14:08' const formattedDate = 'Mo, 19. Januar 2038 - 14:08 Uhr' -test('formatDateString()', (t) => { - t.test('default values', () => { - assert.strictEqual(formatDateString(''), ' Uhr') - assert.strictEqual(formatDateString(' um '), ' - Uhr') - assert.strictEqual(formatDateString('So., 20'), 'So, 20 Uhr') - assert.strictEqual(formatDateString(date), formattedDate) +describe('formatDateString(): ', () => { + test('formatDateString(): default values', () => { + assert.strictEqual(formatDateString(''), '') + assert.strictEqual(formatDateString('So., 20'), 'So, 20') + assert.strictEqual(formatDateString(date), date.replace('.,', ',')) }) - t.test('no modifications', () => { + test('formatDateString(): weekday with dot', () => { + assert.strictEqual( + formatDateString('.,', { + weekdayWithoutDot: false, + }), + '.,' + ) + assert.strictEqual( + formatDateString('.,', { + weekdayWithoutDot: true, + }), + ',' + ) + assert(formatDateString(date, { weekdayWithoutDot: false }).includes('.,')) + assert(!formatDateString(date, { weekdayWithoutDot: true }).includes('.,')) + }) +}) + +describe('formatDateTimeString(): ', () => { + test('formatDateTimeString(): default values', () => { + assert.strictEqual(formatDateTimeString(''), ' Uhr') + assert.strictEqual(formatDateTimeString(' um '), ' - Uhr') + assert.strictEqual(formatDateTimeString('So., 20'), 'So, 20 Uhr') + assert.strictEqual(formatDateTimeString(date), formattedDate) + }) + test('formatDateTimeString(): no modifications', () => { const options = { addOClockSuffix: false, timePrefix: false, weekdayWithoutDot: false, } - assert.strictEqual(formatDateString('', options), '') - assert.strictEqual(formatDateString(date, options), date) + assert.strictEqual(formatDateTimeString('', options), '') + assert.strictEqual(formatDateTimeString(date, options), date) }) - t.test('addOClockSuffix', () => { - assert.strictEqual(formatDateString('', { addOClockSuffix: false }), '') + test('formatDateTimeString(): addOClockSuffix', () => { + assert.strictEqual(formatDateTimeString('', { addOClockSuffix: false }), '') assert.strictEqual( - formatDateString(date, { addOClockSuffix: false }), + formatDateTimeString(date, { addOClockSuffix: false }), formattedDate.replace(' Uhr', '') ) - assert(!formatDateString(date, { addOClockSuffix: false }).includes('Uhr')) + assert(!formatDateTimeString(date, { addOClockSuffix: false }).includes('Uhr')) }) - t.test('other timePrefix', () => { + test('formatDateTimeString(): other timePrefix', () => { const prefix = 'hello' - assert.strictEqual(formatDateString('', { timePrefix: prefix }), ' Uhr') + assert.strictEqual(formatDateTimeString('', { timePrefix: prefix }), ' Uhr') assert.strictEqual( - formatDateString(' um ', { timePrefix: prefix, addOClockSuffix: false }), + formatDateTimeString(' um ', { + timePrefix: prefix, + addOClockSuffix: false, + }), ` ${prefix} ` ) - assert(formatDateString(date, { timePrefix: prefix }).includes(prefix)) + assert(formatDateTimeString(date, { timePrefix: prefix }).includes(prefix)) }) - t.test('weekday with dot', () => { + test('formatDateTimeString(): weekday with dot', () => { assert.strictEqual( - formatDateString('.,', { + formatDateTimeString('.,', { weekdayWithoutDot: false, addOClockSuffix: false, }), '.,' ) assert.strictEqual( - formatDateString('.,', { + formatDateTimeString('.,', { weekdayWithoutDot: true, addOClockSuffix: false, }), ',' ) - assert(formatDateString(date, { weekdayWithoutDot: false }).includes('.,')) - assert(!formatDateString(date, { weekdayWithoutDot: true }).includes('.,')) + assert(formatDateTimeString(date, { weekdayWithoutDot: false }).includes('.,')) + assert(!formatDateTimeString(date, { weekdayWithoutDot: true }).includes('.,')) }) }) From d8192561fd3ba99bd5a2bae6c39161bcf304d6d8 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Fri, 5 Sep 2025 22:43:03 +0200 Subject: [PATCH 07/42] refact(dates): migrate getRelativeTime and getFullRelativeTime --- package.json | 2 +- src/dates/getFullRelativeTime.ts | 20 ++++++++++++++++++++ src/dates/getRelativeTime.js | 4 ---- src/dates/getRelativeTime.ts | 9 +++++++++ src/dates/index.ts | 20 +++++++++++--------- src/dates/revYearMonthDay.js | 6 +++--- tests/date.test.mjs | 17 ++++++++++++----- 7 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 src/dates/getFullRelativeTime.ts delete mode 100644 src/dates/getRelativeTime.js create mode 100644 src/dates/getRelativeTime.ts diff --git a/package.json b/package.json index b8fb0f5..e469389 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "@swrlab/utils", "version": "3.0.0", - "type": "module", "description": "Wrapping common SWR Audio Lab utils", + "type": "module", "license": "MIT", "repository": { "type": "git", diff --git a/src/dates/getFullRelativeTime.ts b/src/dates/getFullRelativeTime.ts new file mode 100644 index 0000000..679373f --- /dev/null +++ b/src/dates/getFullRelativeTime.ts @@ -0,0 +1,20 @@ +import { getDateHourMinutes } from './getDateHourMinutes.ts' +import { getRelativeTime } from './getRelativeTime.ts' +import { formatDateTimeString, type ISODateString } from './utils.ts' + +/** + * Get full relative time. + * + * @param date - ISO date string + * @returns formatted date string like: 'Do., 1. Januar 1970 um 00:00 (in YY Jahren)' + */ +export const getFullRelativeTime = (date: ISODateString) => `${getDateHourMinutes(date)} (${getRelativeTime(date)})` + +/** + * Get full relative time. + * + * @param date - ISO date string + * @returns formatted date string like: 'Do, 1. Januar 1970 - 00:00 Uhr (in YY Jahren)' + */ +export const getFullRelativeTimeLegacy = (date: ISODateString) => + `${formatDateTimeString(getDateHourMinutes(date))} (${getRelativeTime(date)})` diff --git a/src/dates/getRelativeTime.js b/src/dates/getRelativeTime.js deleted file mode 100644 index 0df4aa8..0000000 --- a/src/dates/getRelativeTime.js +++ /dev/null @@ -1,4 +0,0 @@ -const { DateTime } = require('luxon') - -// get relative years (returns 'in YY Jahren') -module.exports = (date) => DateTime.fromISO(date).setLocale('de').toRelative() diff --git a/src/dates/getRelativeTime.ts b/src/dates/getRelativeTime.ts new file mode 100644 index 0000000..1931b9a --- /dev/null +++ b/src/dates/getRelativeTime.ts @@ -0,0 +1,9 @@ +import { type ISODateString, parseDateWithLuxon } from './utils.ts' + +/** + * Get relative years. + * + * @param date - ISO date string + * @returns date string in format 'in YY Jahren' or 'vor 12 Tagen' + */ +export const getRelativeTime = (date: ISODateString): string | null => parseDateWithLuxon(date).toRelative() diff --git a/src/dates/index.ts b/src/dates/index.ts index 9305f59..1cf981c 100644 --- a/src/dates/index.ts +++ b/src/dates/index.ts @@ -4,25 +4,27 @@ import { getDateHourMinutes } from './getDateHourMinutes.ts' import { getDayMonthYear } from './getDayMonthYear.ts' -import { addOClock, type ISODateString, shortenWeekday } from './utils.ts' -// import { getFullRelativeTime } from '../../utils/date/getFullRelativeTime' -// import { getHourMinutes } from './utils/date/getHourMinutes' -// import { getIsoRelativeTime } from './utils/date/getIsoRelativeTime' -// import { getRelativeTime } from './utils/date/getRelativeTime' +import { getFullRelativeTime, getFullRelativeTimeLegacy } from './getFullRelativeTime.ts' // import { getYearMonthDay } from './utils/date/getYearMonthDay' // import { revYearMonthDay } from './utils/date/revYearMonthDay.ts' +import { formatDateTimeString, type ISODateString, shortenWeekday } from './utils.ts' + +export { getDateHourMinutesLegacy } from './getDateHourMinutes.ts' export { getDateHourMinutes } export { getDayMonthYear } +export { getFullRelativeTime } -export { getDateHourMinutesLegacy } from './getDateHourMinutes.ts' +// import { getHourMinutes } from './utils/date/getHourMinutes' +// import { getIsoRelativeTime } from './utils/date/getIsoRelativeTime' +export { getRelativeTime } from './getRelativeTime.ts' /** * Legacy date exports to be compatible with the previous format. */ export const legacy = { - getDateHourMinutes(date: ISODateString): string { - return addOClock(date) - }, + getDateHourMinutes: (date: ISODateString): string => formatDateTimeString(getDateHourMinutes(date)), getDayMonthYear: (date: ISODateString): string => shortenWeekday(getDayMonthYear(date)), + getFullRelativeTime: (date: ISODateString): string => getFullRelativeTimeLegacy(date), } +// TODO: consider adding all functions to legacy diff --git a/src/dates/revYearMonthDay.js b/src/dates/revYearMonthDay.js index b80e671..449f7f1 100644 --- a/src/dates/revYearMonthDay.js +++ b/src/dates/revYearMonthDay.js @@ -1,7 +1,7 @@ // get DDMMYYYY from YYYYMMDD module.exports = (date) => { - const year = date.substring(0, 4) - const month = date.substring(4, 6) - const day = date.substring(6, 8) + const year = date.slice(0, 4) + const month = date.slice(4, 6) + const day = date.slice(6, 8) return `${day}${month}${year}` } diff --git a/tests/date.test.mjs b/tests/date.test.mjs index 99125b1..067fa1e 100644 --- a/tests/date.test.mjs +++ b/tests/date.test.mjs @@ -14,9 +14,12 @@ describe('Test DateTime Package', () => { describe('Test getDateHourMinutes', () => { const newFormat = 'Di., 19. Januar 2038 um 03:14' const testLegacyResult = 'Di, 19. Januar 2038 - 03:14 Uhr' - it(`getDateHourMinutes('${testDate}') = '${testLegacyResult}'`, () => { + it(`getDateHourMinutesLegacy('${testDate}') = '${testLegacyResult}'`, () => { assert.equal(date.getDateHourMinutesLegacy(testDate), testLegacyResult) }) + it(`legacy.getDateHourMinutes('${testDate}') = '${testLegacyResult}'`, () => { + assert.equal(date.legacy.getDateHourMinutes(testDate), testLegacyResult) + }) it(`getDateHourMinutes('${testDate}') = '${newFormat}'`, () => { assert.equal(date.getDateHourMinutes(testDate), newFormat) }) @@ -28,15 +31,19 @@ describe('Test DateTime Package', () => { assert.equal(date.getDayMonthYear(testDate), newFormat) }) const testLegacyFormat = 'Di, 19. Januar 2038' - it(`getDayMonthYear('${testDate}') = '${testLegacyFormat}'`, () => { + it(`legacy.getDayMonthYear('${testDate}') = '${testLegacyFormat}'`, () => { assert.equal(date.legacy.getDayMonthYear(testDate), testLegacyFormat) }) }) describe('Test getFullRelativeTime', () => { - const testResult = `Di, 19. Januar 2038 - 03:14 Uhr (in ${relativeYears} Jahren)` - it(`getFullRelativeTime('${testDate}') = '${testResult}'`, () => { - assert.equal(date.getFullRelativeTime(testDate), testResult) + const legacyResult = `Di, 19. Januar 2038 - 03:14 Uhr (in ${relativeYears} Jahren)` + it(`legacy.getFullRelativeTime('${testDate}') = '${legacyResult}'`, () => { + assert.equal(date.legacy.getFullRelativeTime(testDate), legacyResult) + }) + const newResult = `Di., 19. Januar 2038 um 03:14 (in ${relativeYears} Jahren)` + it(`getFullRelativeTime('${testDate}') = '${newResult}'`, () => { + assert.equal(date.getFullRelativeTime(testDate), newResult) }) }) From 28a536c82334e6dea471c79f6498803156efb6ab Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Fri, 5 Sep 2025 23:03:06 +0200 Subject: [PATCH 08/42] refact(dates): migrate getYearMonthDay --- src/dates/getDateHourMinutes.ts | 9 +++++---- src/dates/getDayMonthYear.ts | 9 +++------ src/dates/getYearMonthDay.js | 4 ---- src/dates/getYearMonthDay.ts | 9 +++++++++ src/dates/index.ts | 9 +++++---- src/dates/utils.ts | 4 ++++ 6 files changed, 26 insertions(+), 18 deletions(-) delete mode 100644 src/dates/getYearMonthDay.js create mode 100644 src/dates/getYearMonthDay.ts diff --git a/src/dates/getDateHourMinutes.ts b/src/dates/getDateHourMinutes.ts index bdec7a5..f677a1e 100644 --- a/src/dates/getDateHourMinutes.ts +++ b/src/dates/getDateHourMinutes.ts @@ -1,4 +1,4 @@ -import { type ISODateString, parseDate, parseDateWithLuxon } from './utils.ts' +import { addOClock, intlFormat, type ISODateString, luxonFormat } from './utils.ts' const dayHourMinutesFormat = 'ccc, d. LLLL yyyy - HH:mm' // const dayHourMinutesFormatDateFNS = 'PPPP - kk:mm' @@ -10,8 +10,8 @@ const dayHourMinutesFormat = 'ccc, d. LLLL yyyy - HH:mm' * * @returns A string like 'Di, 19. Januar 2038 - 03:14 Uhr'. */ -export const getDateHourMinutesLegacy = (date: ISODateString) => - `${parseDateWithLuxon(date).toFormat(dayHourMinutesFormat)} Uhr` +export const getDateHourMinutesLegacy = (date: ISODateString): string => + addOClock(luxonFormat(date, dayHourMinutesFormat)) /** * Get a date string with full date including weekday and hours with minutes. @@ -30,7 +30,8 @@ export function getDateHourMinutes(date: ISODateString): string { hour: 'numeric', minute: 'numeric', hour12: false, + // setting timezone can cause some trouble // timeZone: 'Europe/Berlin', } - return new Intl.DateTimeFormat('de-DE', options).format(parseDate(date)) + return intlFormat(date, options) } diff --git a/src/dates/getDayMonthYear.ts b/src/dates/getDayMonthYear.ts index 8b7581a..48b52bb 100644 --- a/src/dates/getDayMonthYear.ts +++ b/src/dates/getDayMonthYear.ts @@ -1,4 +1,4 @@ -import { DEFAULT_LOCALE, type ISODateString, parseDate, parseDateWithLuxon } from './utils.ts' +import { intlFormat, type ISODateString, luxonFormat } from './utils.ts' const luxonDateFormat = 'ccc, d. LLLL yyyy' /** @@ -10,7 +10,7 @@ const luxonDateFormat = 'ccc, d. LLLL yyyy' * * @returns 'Do, 1. Januar 1970' */ -export const getDayMonthYearLegacy = (date: ISODateString): string => parseDateWithLuxon(date).toFormat(luxonDateFormat) +export const getDayMonthYearLegacy = (date: ISODateString): string => luxonFormat(date, luxonDateFormat) const options: Intl.DateTimeFormatOptions = { weekday: 'short', @@ -18,16 +18,13 @@ const options: Intl.DateTimeFormatOptions = { month: 'long', year: 'numeric', } - /** * Get weekday, day, month and year in german locale. * * @category dates * * @param date - input Date - * @param locale - defaults to `de` * * @returns 'Do, 1. Januar 1970' */ -export const getDayMonthYear = (date: ISODateString, locale: string = DEFAULT_LOCALE): string => - new Intl.DateTimeFormat(locale, options).format(parseDate(date)) +export const getDayMonthYear = (date: ISODateString): string => intlFormat(date, options) diff --git a/src/dates/getYearMonthDay.js b/src/dates/getYearMonthDay.js deleted file mode 100644 index 1b778a8..0000000 --- a/src/dates/getYearMonthDay.js +++ /dev/null @@ -1,4 +0,0 @@ -const { DateTime } = require('luxon') - -// get YYYYMMDD (returns '19700101') -module.exports = (date) => DateTime.fromISO(date).setLocale('de').toFormat('yyyyLLdd') diff --git a/src/dates/getYearMonthDay.ts b/src/dates/getYearMonthDay.ts new file mode 100644 index 0000000..64a40c4 --- /dev/null +++ b/src/dates/getYearMonthDay.ts @@ -0,0 +1,9 @@ +import { type ISODateString, luxonFormat } from './utils.ts' + +/** + * Get YYYYMMDD. + * + * @param date - ISO date string + * @returns date string formatted like '19700101' + */ +export const getYearMonthDay = (date: ISODateString): string => luxonFormat(date, 'yyyyLLdd') diff --git a/src/dates/index.ts b/src/dates/index.ts index 1cf981c..0fb3f8f 100644 --- a/src/dates/index.ts +++ b/src/dates/index.ts @@ -5,19 +5,20 @@ import { getDateHourMinutes } from './getDateHourMinutes.ts' import { getDayMonthYear } from './getDayMonthYear.ts' import { getFullRelativeTime, getFullRelativeTimeLegacy } from './getFullRelativeTime.ts' -// import { getYearMonthDay } from './utils/date/getYearMonthDay' // import { revYearMonthDay } from './utils/date/revYearMonthDay.ts' import { formatDateTimeString, type ISODateString, shortenWeekday } from './utils.ts' +// import { getHourMinutes } from './utils/date/getHourMinutes' +// import { getIsoRelativeTime } from './utils/date/getIsoRelativeTime' + export { getDateHourMinutesLegacy } from './getDateHourMinutes.ts' +export { getRelativeTime } from './getRelativeTime.ts' export { getDateHourMinutes } export { getDayMonthYear } export { getFullRelativeTime } -// import { getHourMinutes } from './utils/date/getHourMinutes' -// import { getIsoRelativeTime } from './utils/date/getIsoRelativeTime' -export { getRelativeTime } from './getRelativeTime.ts' +export { getYearMonthDay } from './getYearMonthDay.ts' /** * Legacy date exports to be compatible with the previous format. diff --git a/src/dates/utils.ts b/src/dates/utils.ts index c05616c..4c54834 100644 --- a/src/dates/utils.ts +++ b/src/dates/utils.ts @@ -8,11 +8,15 @@ export const DEFAULT_LOCALE = 'de-DE' export type ISODateString = `${string}T${string}` export const parseDateWithLuxon = (date: ISODateString): DateTime => DateTime.fromISO(date).setLocale(DEFAULT_LOCALE) +export const luxonFormat = (date: ISODateString, format: string): string => parseDateWithLuxon(date).toFormat(format) export const parseDate = (date: ISODateString): Date => new Date(date) // in the future we can use the Temporal API // export const parseDate = (date: ISODateString): Temporal.PlainDateTime => new Temporal.PlainDateTime.from(date) +export const intlFormat = (date: ISODateString, options: Intl.DateTimeFormatOptions): string => + new Intl.DateTimeFormat(DEFAULT_LOCALE, options).format(parseDate(date)) + /** append ` Uhr` suffix */ export const addOClock = (str: string) => `${str} Uhr` From e7e9655203bb3ef18bf1dfb487c6ae9ffa4701db Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Fri, 5 Sep 2025 23:11:31 +0200 Subject: [PATCH 09/42] refact(dates): migrate getHourMinutes and getIsoRelativeTime --- src/dates/getDateHourMinutes.ts | 2 ++ src/dates/getDayMonthYear.ts | 2 ++ src/dates/getFullRelativeTime.ts | 8 ++++++++ src/dates/getHourMinutes.js | 4 ---- src/dates/getHourMinutes.ts | 10 ++++++++++ src/dates/getIsoRelativeTime.js | 4 ---- src/dates/getIsoRelativeTime.ts | 14 ++++++++++++++ src/dates/getRelativeTime.ts | 6 +++++- src/dates/getYearMonthDay.ts | 4 ++++ src/dates/index.ts | 6 ++---- 10 files changed, 47 insertions(+), 13 deletions(-) delete mode 100644 src/dates/getHourMinutes.js create mode 100644 src/dates/getHourMinutes.ts delete mode 100644 src/dates/getIsoRelativeTime.js create mode 100644 src/dates/getIsoRelativeTime.ts diff --git a/src/dates/getDateHourMinutes.ts b/src/dates/getDateHourMinutes.ts index f677a1e..0c3859b 100644 --- a/src/dates/getDateHourMinutes.ts +++ b/src/dates/getDateHourMinutes.ts @@ -18,7 +18,9 @@ export const getDateHourMinutesLegacy = (date: ISODateString): string => * * @module dates * @category dates + * * @param date + * * @returns german formatted date string */ export function getDateHourMinutes(date: ISODateString): string { diff --git a/src/dates/getDayMonthYear.ts b/src/dates/getDayMonthYear.ts index 48b52bb..b3dcca8 100644 --- a/src/dates/getDayMonthYear.ts +++ b/src/dates/getDayMonthYear.ts @@ -4,6 +4,7 @@ const luxonDateFormat = 'ccc, d. LLLL yyyy' /** * Get weekday, day, month and year in german locale. * + * @module dates * @category dates * * @param date - input Date @@ -21,6 +22,7 @@ const options: Intl.DateTimeFormatOptions = { /** * Get weekday, day, month and year in german locale. * + * @module dates * @category dates * * @param date - input Date diff --git a/src/dates/getFullRelativeTime.ts b/src/dates/getFullRelativeTime.ts index 679373f..930b356 100644 --- a/src/dates/getFullRelativeTime.ts +++ b/src/dates/getFullRelativeTime.ts @@ -5,7 +5,11 @@ import { formatDateTimeString, type ISODateString } from './utils.ts' /** * Get full relative time. * + * @module dates + * @category dates + * * @param date - ISO date string + * * @returns formatted date string like: 'Do., 1. Januar 1970 um 00:00 (in YY Jahren)' */ export const getFullRelativeTime = (date: ISODateString) => `${getDateHourMinutes(date)} (${getRelativeTime(date)})` @@ -13,7 +17,11 @@ export const getFullRelativeTime = (date: ISODateString) => `${getDateHourMinute /** * Get full relative time. * + * @module dates + * @category dates + * * @param date - ISO date string + * * @returns formatted date string like: 'Do, 1. Januar 1970 - 00:00 Uhr (in YY Jahren)' */ export const getFullRelativeTimeLegacy = (date: ISODateString) => diff --git a/src/dates/getHourMinutes.js b/src/dates/getHourMinutes.js deleted file mode 100644 index 5a3fa3f..0000000 --- a/src/dates/getHourMinutes.js +++ /dev/null @@ -1,4 +0,0 @@ -const { DateTime } = require('luxon') - -// get hours and minutes (returns '12:34') -module.exports = (date) => DateTime.fromISO(date).toFormat('HH:mm') diff --git a/src/dates/getHourMinutes.ts b/src/dates/getHourMinutes.ts new file mode 100644 index 0000000..dc5956b --- /dev/null +++ b/src/dates/getHourMinutes.ts @@ -0,0 +1,10 @@ +import { type ISODateString, luxonFormat } from './utils.ts' + +/** + * Get hours and minutes (returns ) + * + * @param date - ISO date string + * + * @returns in _HH:mm_ format (example: `12:34` or `09:03`) + */ +export const getHourMinutes = (date: ISODateString): string => luxonFormat(date, 'HH:mm') diff --git a/src/dates/getIsoRelativeTime.js b/src/dates/getIsoRelativeTime.js deleted file mode 100644 index 57a8656..0000000 --- a/src/dates/getIsoRelativeTime.js +++ /dev/null @@ -1,4 +0,0 @@ -const getRelativeTime = require('./getRelativeTime') - -// get iso date with relative years -module.exports = (date) => `${date} (${getRelativeTime(date)})` diff --git a/src/dates/getIsoRelativeTime.ts b/src/dates/getIsoRelativeTime.ts new file mode 100644 index 0000000..714bfcb --- /dev/null +++ b/src/dates/getIsoRelativeTime.ts @@ -0,0 +1,14 @@ +import type { ISODateString } from './utils.ts' +import { getRelativeTime } from './getRelativeTime.ts' + +/** + * Get iso date with relative years. + * + * @module dates + * @category dates + * + * @param date - ISO date string + * + * @returns ISO date string with relative time suffix + */ +export const getIsoRelativeTime = (date: ISODateString) => `${date} (${getRelativeTime(date)})` diff --git a/src/dates/getRelativeTime.ts b/src/dates/getRelativeTime.ts index 1931b9a..d8cbb93 100644 --- a/src/dates/getRelativeTime.ts +++ b/src/dates/getRelativeTime.ts @@ -3,7 +3,11 @@ import { type ISODateString, parseDateWithLuxon } from './utils.ts' /** * Get relative years. * + * @module dates + * @category dates + * * @param date - ISO date string - * @returns date string in format 'in YY Jahren' or 'vor 12 Tagen' + * + * @returns german formatted date string: 'in YY Jahren' or 'vor 12 Tagen' */ export const getRelativeTime = (date: ISODateString): string | null => parseDateWithLuxon(date).toRelative() diff --git a/src/dates/getYearMonthDay.ts b/src/dates/getYearMonthDay.ts index 64a40c4..70eb67b 100644 --- a/src/dates/getYearMonthDay.ts +++ b/src/dates/getYearMonthDay.ts @@ -3,7 +3,11 @@ import { type ISODateString, luxonFormat } from './utils.ts' /** * Get YYYYMMDD. * + * @module dates + * @category dates + * * @param date - ISO date string + * * @returns date string formatted like '19700101' */ export const getYearMonthDay = (date: ISODateString): string => luxonFormat(date, 'yyyyLLdd') diff --git a/src/dates/index.ts b/src/dates/index.ts index 0fb3f8f..91f0850 100644 --- a/src/dates/index.ts +++ b/src/dates/index.ts @@ -8,10 +8,9 @@ import { getFullRelativeTime, getFullRelativeTimeLegacy } from './getFullRelativ // import { revYearMonthDay } from './utils/date/revYearMonthDay.ts' import { formatDateTimeString, type ISODateString, shortenWeekday } from './utils.ts' -// import { getHourMinutes } from './utils/date/getHourMinutes' -// import { getIsoRelativeTime } from './utils/date/getIsoRelativeTime' - export { getDateHourMinutesLegacy } from './getDateHourMinutes.ts' +export { getHourMinutes } from './getHourMinutes.ts' +export { getIsoRelativeTime } from './getIsoRelativeTime.ts' export { getRelativeTime } from './getRelativeTime.ts' export { getDateHourMinutes } @@ -28,4 +27,3 @@ export const legacy = { getDayMonthYear: (date: ISODateString): string => shortenWeekday(getDayMonthYear(date)), getFullRelativeTime: (date: ISODateString): string => getFullRelativeTimeLegacy(date), } -// TODO: consider adding all functions to legacy From 5249830aea749491d9db2e635ebc033ae8527137 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Fri, 5 Sep 2025 23:32:56 +0200 Subject: [PATCH 10/42] refact(dates): migrate revYearMonthDay and finish dates --- .gitignore | 4 ++-- eslint.config.mjs => eslint.config.js | 0 package.json | 5 ++-- src/dates/index.ts | 8 +++++-- src/dates/revYearMonthDay.js | 7 ------ src/dates/revYearMonthDay.ts | 24 +++++++++++++++++++ src/index.ts | 2 ++ tests/{ard.test.mjs => ard.test.ts} | 0 tests/{date.test.mjs => date.test.ts} | 11 +++++---- ...date.utils.test.mjs => date.utils.test.ts} | 0 tsdown.config.ts | 4 ++-- 11 files changed, 45 insertions(+), 20 deletions(-) rename eslint.config.mjs => eslint.config.js (100%) delete mode 100644 src/dates/revYearMonthDay.js create mode 100644 src/dates/revYearMonthDay.ts create mode 100644 src/index.ts rename tests/{ard.test.mjs => ard.test.ts} (100%) rename tests/{date.test.mjs => date.test.ts} (91%) rename tests/{date.utils.test.mjs => date.utils.test.ts} (100%) diff --git a/.gitignore b/.gitignore index 837a99e..1dda601 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ +dist/ + # Logs logs *.log npm-debug.log* -yarn-debug.log* -yarn-error.log* .DS_Store .env diff --git a/eslint.config.mjs b/eslint.config.js similarity index 100% rename from eslint.config.mjs rename to eslint.config.js diff --git a/package.json b/package.json index e469389..d050657 100644 --- a/package.json +++ b/package.json @@ -28,11 +28,12 @@ }, "scripts": { "ard:coreId": "node ./scripts/ard/coreId.js", + "build": "tsdown", "format": "prettier --write .", "lint": "eslint", "lint:fix": "eslint --fix", - "test": "bun test tests/**.mjs", - "test:node": "node --test tests/**.mjs" + "test": "bun test tests/**/*.ts", + "test:node": "node --test tests/**/*.ts" }, "dependencies": { "@google-cloud/storage": "^7.16.0", diff --git a/src/dates/index.ts b/src/dates/index.ts index 91f0850..bfb1d8d 100644 --- a/src/dates/index.ts +++ b/src/dates/index.ts @@ -5,7 +5,7 @@ import { getDateHourMinutes } from './getDateHourMinutes.ts' import { getDayMonthYear } from './getDayMonthYear.ts' import { getFullRelativeTime, getFullRelativeTimeLegacy } from './getFullRelativeTime.ts' -// import { revYearMonthDay } from './utils/date/revYearMonthDay.ts' +import { toDayMonthYear } from './revYearMonthDay.ts' import { formatDateTimeString, type ISODateString, shortenWeekday } from './utils.ts' export { getDateHourMinutesLegacy } from './getDateHourMinutes.ts' @@ -16,8 +16,12 @@ export { getRelativeTime } from './getRelativeTime.ts' export { getDateHourMinutes } export { getDayMonthYear } export { getFullRelativeTime } - export { getYearMonthDay } from './getYearMonthDay.ts' +// new name +export { toDayMonthYear } +// export old name +/** @deprecated please use `toDayMonthYear` */ +export { toDayMonthYear as revYearMonthDay } /** * Legacy date exports to be compatible with the previous format. diff --git a/src/dates/revYearMonthDay.js b/src/dates/revYearMonthDay.js deleted file mode 100644 index 449f7f1..0000000 --- a/src/dates/revYearMonthDay.js +++ /dev/null @@ -1,7 +0,0 @@ -// get DDMMYYYY from YYYYMMDD -module.exports = (date) => { - const year = date.slice(0, 4) - const month = date.slice(4, 6) - const day = date.slice(6, 8) - return `${day}${month}${year}` -} diff --git a/src/dates/revYearMonthDay.ts b/src/dates/revYearMonthDay.ts new file mode 100644 index 0000000..4aa3a36 --- /dev/null +++ b/src/dates/revYearMonthDay.ts @@ -0,0 +1,24 @@ +import type { ISODateString } from './utils.ts' + +/** + * Format a YearMonthDay (english) date into DayMonthYear (german). + * + * @param date - ISO date string + * + * @returns date string in `DDMMYYYY` format. + */ +export const toDayMonthYear = (date: ISODateString): string => { + const year = date.slice(0, 4) + const month = date.slice(4, 6) + const day = date.slice(6, 8) + return `${day}${month}${year}` +} + +/** + * Get DDMMYYYY from YYYYMMDD. + * + * @param date - ISO date string + * + * @returns date string in `DDMMYYYY` format. + */ +export const revYearMonthDay: (date: ISODateString) => string = toDayMonthYear diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..ba7c6dd --- /dev/null +++ b/src/index.ts @@ -0,0 +1,2 @@ +export * from './ard/index.ts' +export * from './dates/index.ts' diff --git a/tests/ard.test.mjs b/tests/ard.test.ts similarity index 100% rename from tests/ard.test.mjs rename to tests/ard.test.ts diff --git a/tests/date.test.mjs b/tests/date.test.ts similarity index 91% rename from tests/date.test.mjs rename to tests/date.test.ts index 067fa1e..2ec7806 100644 --- a/tests/date.test.mjs +++ b/tests/date.test.ts @@ -2,13 +2,14 @@ import assert from 'node:assert' import { describe, it } from 'node:test' import * as date from '../src/dates/index.ts' -const date2 = 'Fri Sep 05 2025 21:44:37 GMT+0200 (Central European Summer Time)' -const date2date = new Date(date2) -const date2iso = '2025-09-05T19:44:37.000Z' - +const ONE_YEAR_IN_MS = 1000 * 60 * 60 * 24 * 365 const testDate = '2038-01-19T03:14:08.000' const relativeTime = 2147483647000 - Date.now() -const relativeYears = Number.parseInt(relativeTime / (1000 * 60 * 60 * 24 * 365), 10) +const relativeYears = Math.floor(relativeTime / ONE_YEAR_IN_MS) + +// const date2 = 'Fri Sep 05 2025 21:44:37 GMT+0200 (Central European Summer Time)' +// const date2date = new Date(date2) +// const date2iso = '2025-09-05T19:44:37.000Z' describe('Test DateTime Package', () => { describe('Test getDateHourMinutes', () => { diff --git a/tests/date.utils.test.mjs b/tests/date.utils.test.ts similarity index 100% rename from tests/date.utils.test.mjs rename to tests/date.utils.test.ts diff --git a/tsdown.config.ts b/tsdown.config.ts index 549ae6c..36a0514 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -3,7 +3,7 @@ import { defineConfig } from 'tsdown' export default defineConfig({ entry: { index: 'src/index.ts', - eslint: 'src/eslint/index.ts', - prettier: 'src/prettier/index.js', + ard: 'src/ard/index.ts', + dates: 'src/dates/index.ts', }, }) From 13b6cf35f5fd0a9b77e9ea138bb6aed529e4226a Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Sat, 6 Sep 2025 00:00:28 +0200 Subject: [PATCH 11/42] refact: migrate helpers --- packages/helpers/index.js | 11 ----------- src/dates/revYearMonthDay.ts | 15 ++------------- src/dates/utils.ts | 2 +- src/helpers/arrayToObjectCount.ts | 12 ++++++++++++ src/helpers/getJsonKeys.ts | 18 ++++++++++++++++++ src/helpers/index.ts | 6 ++++++ src/helpers/sleep.ts | 6 ++++++ tests/{helpers.test.mjs => helpers.test.ts} | 6 +++++- utils/helpers/arrayToObjectCount.js | 7 ------- utils/helpers/getJsonKeys.js | 10 ---------- utils/helpers/sleep.js | 6 ------ 11 files changed, 50 insertions(+), 49 deletions(-) delete mode 100644 packages/helpers/index.js create mode 100644 src/helpers/arrayToObjectCount.ts create mode 100644 src/helpers/getJsonKeys.ts create mode 100644 src/helpers/index.ts create mode 100644 src/helpers/sleep.ts rename tests/{helpers.test.mjs => helpers.test.ts} (82%) delete mode 100644 utils/helpers/arrayToObjectCount.js delete mode 100644 utils/helpers/getJsonKeys.js delete mode 100644 utils/helpers/sleep.js diff --git a/packages/helpers/index.js b/packages/helpers/index.js deleted file mode 100644 index 8efd1c2..0000000 --- a/packages/helpers/index.js +++ /dev/null @@ -1,11 +0,0 @@ -// import packages -const arrayToObjectCount = require('../../utils/helpers/arrayToObjectCount') -const getJsonKeys = require('../../utils/helpers/getJsonKeys') -const sleep = require('../../utils/helpers/sleep') - -// export packages -module.exports = { - arrayToObjectCount, - getJsonKeys, - sleep, -} diff --git a/src/dates/revYearMonthDay.ts b/src/dates/revYearMonthDay.ts index 4aa3a36..8b8f256 100644 --- a/src/dates/revYearMonthDay.ts +++ b/src/dates/revYearMonthDay.ts @@ -1,24 +1,13 @@ -import type { ISODateString } from './utils.ts' - /** * Format a YearMonthDay (english) date into DayMonthYear (german). * - * @param date - ISO date string + * @param date - date string * * @returns date string in `DDMMYYYY` format. */ -export const toDayMonthYear = (date: ISODateString): string => { +export const toDayMonthYear = (date: string): string => { const year = date.slice(0, 4) const month = date.slice(4, 6) const day = date.slice(6, 8) return `${day}${month}${year}` } - -/** - * Get DDMMYYYY from YYYYMMDD. - * - * @param date - ISO date string - * - * @returns date string in `DDMMYYYY` format. - */ -export const revYearMonthDay: (date: ISODateString) => string = toDayMonthYear diff --git a/src/dates/utils.ts b/src/dates/utils.ts index 4c54834..69b978d 100644 --- a/src/dates/utils.ts +++ b/src/dates/utils.ts @@ -29,7 +29,7 @@ type OptionsWeekdayDot = { } type FormatOptions = OptionsWeekdayDot & { /** replaces `um` or `at` with provided string or `-` if `true` */ - timePrefix?: string | true + timePrefix?: string | boolean /** add ` Uhr` suffix after the time */ addOClockSuffix?: boolean } diff --git a/src/helpers/arrayToObjectCount.ts b/src/helpers/arrayToObjectCount.ts new file mode 100644 index 0000000..4f4c29b --- /dev/null +++ b/src/helpers/arrayToObjectCount.ts @@ -0,0 +1,12 @@ +/** + * Reduce array elements to object with count + * + * @param array + * @returns object with elements and their count. + */ +export const arrayToObjectCount = (array: string[]): Record => + array.reduce((obj: Record, name: string) => { + // eslint-disable-next-line security/detect-object-injection -- this seems safe + obj[name] = obj[name] ? ++obj[name] : 1 + return obj + }, {}) diff --git a/src/helpers/getJsonKeys.ts b/src/helpers/getJsonKeys.ts new file mode 100644 index 0000000..85d1143 --- /dev/null +++ b/src/helpers/getJsonKeys.ts @@ -0,0 +1,18 @@ +/** + * Get all keys of given json. + * + * @deprecated use `Object.keys` instead + * + * @param json + * + * @returns array + */ +export const getJsonKeys = (json: any): string[] => { + const keys = [] + for (const key in json) { + if (Object.prototype.hasOwnProperty.call(json, key)) { + keys.push(key) + } + } + return keys +} diff --git a/src/helpers/index.ts b/src/helpers/index.ts new file mode 100644 index 0000000..51ba901 --- /dev/null +++ b/src/helpers/index.ts @@ -0,0 +1,6 @@ +/** + * @fileoverview General helper functions. + */ +export { arrayToObjectCount } from './arrayToObjectCount.ts' +export { getJsonKeys } from './getJsonKeys.ts' +export { sleep } from './sleep.ts' diff --git a/src/helpers/sleep.ts b/src/helpers/sleep.ts new file mode 100644 index 0000000..4e56a2a --- /dev/null +++ b/src/helpers/sleep.ts @@ -0,0 +1,6 @@ +/** + * Sleep the given time in ms (async). + * + * @param ms - miliseconds to sleep + */ +export const sleep = (ms: number): Promise => new Promise((resolve) => setTimeout(resolve, ms)) diff --git a/tests/helpers.test.mjs b/tests/helpers.test.ts similarity index 82% rename from tests/helpers.test.mjs rename to tests/helpers.test.ts index a1540b0..97520c8 100644 --- a/tests/helpers.test.mjs +++ b/tests/helpers.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert' import { describe, it } from 'node:test' -import * as helpers from '../packages/helpers/index.js' +import * as helpers from '../src/helpers/index.ts' describe('Test Helpers Package', () => { describe('Test arrayToObjectCount', () => { @@ -20,6 +20,10 @@ describe('Test Helpers Package', () => { const testResult = helpers.getJsonKeys(test) assert.equal(testResult[0], result[0]) assert.equal(testResult[1], result[1]) + // just using `Object.keys` + const testResultSimple = Object.keys(test) + assert.equal(testResultSimple[0], result[0]) + assert.equal(testResultSimple[1], result[1]) }) }) diff --git a/utils/helpers/arrayToObjectCount.js b/utils/helpers/arrayToObjectCount.js deleted file mode 100644 index eec2222..0000000 --- a/utils/helpers/arrayToObjectCount.js +++ /dev/null @@ -1,7 +0,0 @@ -// reduce array elements to object with count -module.exports = (array) => { - return array.reduce((obj, name) => { - obj[name] = obj[name] ? ++obj[name] : 1 - return obj - }, {}) -} diff --git a/utils/helpers/getJsonKeys.js b/utils/helpers/getJsonKeys.js deleted file mode 100644 index 43b1f14..0000000 --- a/utils/helpers/getJsonKeys.js +++ /dev/null @@ -1,10 +0,0 @@ -// get all keys of given json -module.exports = (json) => { - const keys = [] - for (const key in json) { - if ({}.hasOwnProperty.call(json, key)) { - keys.push(key) - } - } - return keys -} diff --git a/utils/helpers/sleep.js b/utils/helpers/sleep.js deleted file mode 100644 index aa96726..0000000 --- a/utils/helpers/sleep.js +++ /dev/null @@ -1,6 +0,0 @@ -// sleep the given time in ms (async) -module.exports = (ms) => { - return new Promise((resolve) => { - setTimeout(resolve, ms) - }) -} From c5d38607f6333ad1f8615c976d190d46f30bdf87 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Sat, 6 Sep 2025 15:01:22 +0200 Subject: [PATCH 12/42] refact(numbers): migrate all number utils --- packages/numbers/index.js | 25 ------------- src/index.ts | 2 ++ src/numbers/addLeadingZero.ts | 7 ++++ .../numbers/addTrailingZeros.ts | 4 +-- src/numbers/getAverage.ts | 17 +++++++++ src/numbers/getDiff.ts | 11 ++++++ src/numbers/getRandomInRange.ts | 35 +++++++++++++++++++ src/numbers/getSum.ts | 17 +++++++++ src/numbers/index.ts | 10 ++++++ src/numbers/isEven.ts | 9 +++++ src/numbers/normalize.ts | 12 +++++++ src/numbers/roundTo.ts | 9 +++++ src/numbers/toReadable.ts | 10 ++++++ tests/{numbers.test.mjs => numbers.test.ts} | 16 ++++++++- utils/numbers/addLeadingZero.js | 2 -- utils/numbers/getAverage.js | 4 --- utils/numbers/getDiff.js | 2 -- utils/numbers/getRandomInRange.js | 5 --- utils/numbers/getSum.js | 4 --- utils/numbers/isEven.js | 2 -- utils/numbers/normalize.js | 2 -- utils/numbers/roundTo.js | 5 --- utils/numbers/toReadable.js | 2 -- utils/strings/pluralize.js | 4 +-- 24 files changed, 158 insertions(+), 58 deletions(-) delete mode 100644 packages/numbers/index.js create mode 100644 src/numbers/addLeadingZero.ts rename utils/numbers/addTrailingZeros.js => src/numbers/addTrailingZeros.ts (67%) create mode 100644 src/numbers/getAverage.ts create mode 100644 src/numbers/getDiff.ts create mode 100644 src/numbers/getRandomInRange.ts create mode 100644 src/numbers/getSum.ts create mode 100644 src/numbers/index.ts create mode 100644 src/numbers/isEven.ts create mode 100644 src/numbers/normalize.ts create mode 100644 src/numbers/roundTo.ts create mode 100644 src/numbers/toReadable.ts rename tests/{numbers.test.mjs => numbers.test.ts} (85%) delete mode 100644 utils/numbers/addLeadingZero.js delete mode 100644 utils/numbers/getAverage.js delete mode 100644 utils/numbers/getDiff.js delete mode 100644 utils/numbers/getRandomInRange.js delete mode 100644 utils/numbers/getSum.js delete mode 100644 utils/numbers/isEven.js delete mode 100644 utils/numbers/normalize.js delete mode 100644 utils/numbers/roundTo.js delete mode 100644 utils/numbers/toReadable.js diff --git a/packages/numbers/index.js b/packages/numbers/index.js deleted file mode 100644 index 4a0c2e4..0000000 --- a/packages/numbers/index.js +++ /dev/null @@ -1,25 +0,0 @@ -// import packages -const addLeadingZero = require('../../utils/numbers/addLeadingZero') -const addTrailingZeros = require('../../utils/numbers/addTrailingZeros') -const getAverage = require('../../utils/numbers/getAverage') -const getDiff = require('../../utils/numbers/getDiff') -const getRandomInRange = require('../../utils/numbers/getRandomInRange') -const getSum = require('../../utils/numbers/getSum') -const isEven = require('../../utils/numbers/isEven') -const normalize = require('../../utils/numbers/normalize') -const roundTo = require('../../utils/numbers/roundTo') -const toReadable = require('../../utils/numbers/toReadable') - -// export packages -module.exports = { - addLeadingZero, - addTrailingZeros, - getAverage, - getDiff, - getRandomInRange, - getSum, - isEven, - normalize, - roundTo, - toReadable, -} diff --git a/src/index.ts b/src/index.ts index ba7c6dd..4054330 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,4 @@ export * from './ard/index.ts' export * from './dates/index.ts' +export * from './helpers/index.ts' +export * from './numbers/index.ts' diff --git a/src/numbers/addLeadingZero.ts b/src/numbers/addLeadingZero.ts new file mode 100644 index 0000000..654344f --- /dev/null +++ b/src/numbers/addLeadingZero.ts @@ -0,0 +1,7 @@ +/** + * Add leading zero if not existent. + * + * @param value number + * @returns number string + */ +export const addLeadingZero = (value: number): string => value.toString().padStart(2, '0') diff --git a/utils/numbers/addTrailingZeros.js b/src/numbers/addTrailingZeros.ts similarity index 67% rename from utils/numbers/addTrailingZeros.js rename to src/numbers/addTrailingZeros.ts index 1fdb2f3..928aecc 100644 --- a/utils/numbers/addTrailingZeros.js +++ b/src/numbers/addTrailingZeros.ts @@ -1,8 +1,8 @@ // add given number of trailing zeros -module.exports = (num, length, delimiter = '.') => { +export const addTrailingZeros = (num: number | string, length: number, delimiter = '.') => { // https://bobbyhadz.com/blog/javascript-add-trailing-zeros-to-number const string = String(num) const splitter = string.includes('.') ? '.' : delimiter - const parts = String(num).split(splitter) + const parts = string.split(splitter) return `${parts[0]}${delimiter}${(parts[1] ?? '').padEnd(length, '0')}` } diff --git a/src/numbers/getAverage.ts b/src/numbers/getAverage.ts new file mode 100644 index 0000000..649a56d --- /dev/null +++ b/src/numbers/getAverage.ts @@ -0,0 +1,17 @@ +import { getSum as sum } from './getSum.ts' +import { roundTo } from './roundTo.ts' + +/** + * Get average from array of values. + * + * @param arr + * @param decimals + * + * @returns average value + */ +export const getAverage = (arr: number[], decimals = 2): number => sum(arr, decimals) / arr.length + +// The rounding should occur afterwards to reduce the error. +// And ideally, the rounding is done by the caller themself. +export const getAverageNew = (arr: number[], decimals = 2): number => + roundTo(arr.reduce((sum, num) => sum + num, 0) / arr.length, decimals) diff --git a/src/numbers/getDiff.ts b/src/numbers/getDiff.ts new file mode 100644 index 0000000..ba6e7cb --- /dev/null +++ b/src/numbers/getDiff.ts @@ -0,0 +1,11 @@ +/** + * Get difference of two values. + * + * @deprecated Just do the diference youself. It's not that hard. + * + * @param a + * @param b + * + * @returns the difference of `a` and `b`. + */ +export const getDiff = (a: number, b: number): number => a - b diff --git a/src/numbers/getRandomInRange.ts b/src/numbers/getRandomInRange.ts new file mode 100644 index 0000000..f473c21 --- /dev/null +++ b/src/numbers/getRandomInRange.ts @@ -0,0 +1,35 @@ +import crypto from 'node:crypto' +/** + * Returns a random integer between min (inclusive) and max (inclusive). + * + * @deprecated use the newer version that uses the crypto api. + * + * @param min + * @param max + * + * @returns random integer + */ +export const getRandomInRangLegacy = (min: number, max: number): number => { + // Using Math.round() will give you a non-uniform distribution! + // eslint-disable-next-line sonarjs/pseudo-random -- here it's ok + return Math.floor(Math.random() * (max - min + 1)) + min +} + +/** + * Generate a random integer in range using `crypto.getRandomValues()`. + * + * @param {number} min - Minimum value (inclusive) + * @param {number} max - Maximum value (inclusive) + * + * @returns {number} Random integer in range + */ +export const getRandomInRange = (min: number, max: number): number => { + const range = max - min + 1 + // const buf = new Uint32Array(1) + // crypto.getRandomValues(buf) + const buf = crypto.randomBytes(1) + + const octet: number = buf[0] ?? 1 + // Convert to 0-1 range, then scale to our range + return Math.floor((octet / (0xffffffff + 1)) * range) + min +} diff --git a/src/numbers/getSum.ts b/src/numbers/getSum.ts new file mode 100644 index 0000000..e694178 --- /dev/null +++ b/src/numbers/getSum.ts @@ -0,0 +1,17 @@ +import { roundTo } from './roundTo.js' + +/** + * Get sum of number array. + * The values are rounded to the 2nd decimal position by default. + * + * @param arr - number array + * @param decimals - default is `2` + * @returns sum of all elements + */ +export const getSum = (arr: number[], decimals = 2): number => arr.reduce((sum, n) => roundTo(sum + n, decimals), 0) + +export const getSumNew = (arr: number[], decimals = 2): number => + roundTo( + arr.reduce((sum, n) => sum + n, 0), + decimals + ) diff --git a/src/numbers/index.ts b/src/numbers/index.ts new file mode 100644 index 0000000..4e66ea9 --- /dev/null +++ b/src/numbers/index.ts @@ -0,0 +1,10 @@ +export { addLeadingZero } from './addLeadingZero.ts' +export { addTrailingZeros } from './addTrailingZeros.ts' +export { getAverage } from './getAverage.ts' +export { getDiff } from './getDiff.ts' +export { getRandomInRange } from './getRandomInRange.ts' +export { getSum } from './getSum.ts' +export { isEven } from './isEven.ts' +export { normalize } from './normalize.ts' +export { roundTo } from './roundTo.ts' +export { toReadable } from './toReadable.ts' diff --git a/src/numbers/isEven.ts b/src/numbers/isEven.ts new file mode 100644 index 0000000..b6a71d8 --- /dev/null +++ b/src/numbers/isEven.ts @@ -0,0 +1,9 @@ +/** + * Check if a number is even. + * + * @deprecated use a plain `value % 2 === 0` yourself. + * + * @param value - input number + * @returns `true` if even; `false` otherwise. + */ +export const isEven = (value: number): boolean => value % 2 === 0 diff --git a/src/numbers/normalize.ts b/src/numbers/normalize.ts new file mode 100644 index 0000000..66227cc --- /dev/null +++ b/src/numbers/normalize.ts @@ -0,0 +1,12 @@ +/** + * Normalize value by division of a maximum value. + * + * @deprecated just use a plain division. + * + * @param value + * + * @param maximumValue + * + * @returns normalized value. + */ +export const normalize = (value: number, maximumValue: number): number => value / maximumValue diff --git a/src/numbers/roundTo.ts b/src/numbers/roundTo.ts new file mode 100644 index 0000000..48c0894 --- /dev/null +++ b/src/numbers/roundTo.ts @@ -0,0 +1,9 @@ +// https://gist.github.com/djD-REK/068cba3d430cf7abfddfd32a5d7903c3 +/** + * + * @param number + * @param decimals - default is `2` + * + * @returns rounded number + */ +export const roundTo = (number: number, decimals = 2): number => Number.parseFloat(number.toFixed(decimals)) diff --git a/src/numbers/toReadable.ts b/src/numbers/toReadable.ts new file mode 100644 index 0000000..fc70e91 --- /dev/null +++ b/src/numbers/toReadable.ts @@ -0,0 +1,10 @@ +import { DEFAULT_LOCALE } from '../dates/utils.ts' + +/** + * Return a number in german readable format. + * + * @param value - number + * + * @returns readable number string + */ +export const toReadable = (value: number): string => value.toLocaleString(DEFAULT_LOCALE) diff --git a/tests/numbers.test.mjs b/tests/numbers.test.ts similarity index 85% rename from tests/numbers.test.mjs rename to tests/numbers.test.ts index f2b5d6f..730bfc6 100644 --- a/tests/numbers.test.mjs +++ b/tests/numbers.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert' import { describe, it } from 'node:test' -import * as numbers from '../packages/numbers/index.js' +import * as numbers from '../src/numbers/index.ts' describe('Test Numbers Package', () => { describe('Test addLeadingZero', () => { @@ -107,6 +107,20 @@ describe('Test Numbers Package', () => { it('roundTo(1.23456, 4) = 1.2346', () => { assert.equal(numbers.roundTo(1.23456, 4), 1.2346) }) + + it('roundTo(234.23456, 4) = 234.2346', () => { + assert.equal(numbers.roundTo(234.23456, 4), 234.2346) + }) + + it('roundTo(234.2345671, 4) = 234.2346', () => { + assert.equal(numbers.roundTo(234.2345671, 4), 234.2346) + }) + it('roundTo(234.2344671, 3) = 234.234', () => { + assert.equal(numbers.roundTo(234.2344671, 3), 234.234) + }) + it('roundTo(234.2343671, 3) = 234.234', () => { + assert.equal(numbers.roundTo(234.2343671, 3), 234.234) + }) }) describe('Test toReadable', () => { diff --git a/utils/numbers/addLeadingZero.js b/utils/numbers/addLeadingZero.js deleted file mode 100644 index 481e7fc..0000000 --- a/utils/numbers/addLeadingZero.js +++ /dev/null @@ -1,2 +0,0 @@ -// add leading zero if not existent -module.exports = (value) => (value < 10 ? `0${value}` : value).toString() diff --git a/utils/numbers/getAverage.js b/utils/numbers/getAverage.js deleted file mode 100644 index 5d09ed0..0000000 --- a/utils/numbers/getAverage.js +++ /dev/null @@ -1,4 +0,0 @@ -// get average from array of values -const sum = require('./getSum') - -module.exports = (arr, decimals = 2) => sum(arr, decimals) / arr.length diff --git a/utils/numbers/getDiff.js b/utils/numbers/getDiff.js deleted file mode 100644 index eb80d8f..0000000 --- a/utils/numbers/getDiff.js +++ /dev/null @@ -1,2 +0,0 @@ -// get difference of two values -module.exports = (a, b) => a - b diff --git a/utils/numbers/getRandomInRange.js b/utils/numbers/getRandomInRange.js deleted file mode 100644 index f299ac3..0000000 --- a/utils/numbers/getRandomInRange.js +++ /dev/null @@ -1,5 +0,0 @@ -// Returns a random integer between min (inclusive) and max (inclusive) -module.exports = (min, max) => { - // Using Math.round() will give you a non-uniform distribution! - return Math.floor(Math.random() * (max - min + 1)) + min -} diff --git a/utils/numbers/getSum.js b/utils/numbers/getSum.js deleted file mode 100644 index f91273e..0000000 --- a/utils/numbers/getSum.js +++ /dev/null @@ -1,4 +0,0 @@ -// get sum from array of values -const roundTo = require('./roundTo') - -module.exports = (arr, decimals = 2) => arr.reduce((a, b) => roundTo(a + b, decimals), 0) diff --git a/utils/numbers/isEven.js b/utils/numbers/isEven.js deleted file mode 100644 index 5221267..0000000 --- a/utils/numbers/isEven.js +++ /dev/null @@ -1,2 +0,0 @@ -// check if a variable is even -module.exports = (value) => value % 2 === 0 diff --git a/utils/numbers/normalize.js b/utils/numbers/normalize.js deleted file mode 100644 index 0cd910a..0000000 --- a/utils/numbers/normalize.js +++ /dev/null @@ -1,2 +0,0 @@ -// normalize value by division of a maximum value -module.exports = (value, maximumValue) => value / maximumValue diff --git a/utils/numbers/roundTo.js b/utils/numbers/roundTo.js deleted file mode 100644 index 20a8964..0000000 --- a/utils/numbers/roundTo.js +++ /dev/null @@ -1,5 +0,0 @@ -// eslint-disable-file prefer-template -// https://gist.github.com/djD-REK/068cba3d430cf7abfddfd32a5d7903c3 -module.exports = (number, decimal = 2) => { - return Number(Math.round(number + 'e' + decimal) + 'e-' + decimal) -} diff --git a/utils/numbers/toReadable.js b/utils/numbers/toReadable.js deleted file mode 100644 index cd2f132..0000000 --- a/utils/numbers/toReadable.js +++ /dev/null @@ -1,2 +0,0 @@ -// return a number in readable format -module.exports = (value) => value.toLocaleString('de-DE') diff --git a/utils/strings/pluralize.js b/utils/strings/pluralize.js index e461c7f..af6afb5 100644 --- a/utils/strings/pluralize.js +++ b/utils/strings/pluralize.js @@ -1,7 +1,7 @@ -const toReadable = require('../numbers/toReadable') +import { toReadable } from '../../src/numbers/toReadable.ts' // pluralize value to values or use custom plural -module.exports = (count, singular, plural) => { +export const pluralize = (count, singular, plural) => { const multi = plural ?? `${singular}s` return `${toReadable(count)} ${count !== 1 ? multi : singular}` } From 87e688a38d9a6fcc736c9e2fe9f751a84a1237ab Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Sat, 6 Sep 2025 17:44:33 +0200 Subject: [PATCH 13/42] refact(strings): migrate all string utils --- .editorconfig | 2 +- eslint.config.js | 2 +- index.js | 17 ------- package.json | 5 ++- packages/strings/index.js | 37 --------------- packages/undici/request.js | 3 +- scripts/ard/coreId.js | 4 +- src/numbers/getSum.ts | 2 +- src/strings/capitalize.ts | 14 ++++++ src/strings/getObjectLength.ts | 7 +++ src/strings/index.ts | 16 +++++++ src/strings/isArray.ts | 10 +++++ src/strings/isEmptyArray.ts | 12 +++++ src/strings/isEmptyObject.ts | 10 +++++ src/strings/isEmptyString.ts | 7 +++ src/strings/isIncluded.ts | 13 ++++++ src/strings/isNull.ts | 7 +++ src/strings/isObject.ts | 22 +++++++++ src/strings/isUndefined.ts | 14 ++++++ src/strings/notEmptyArray.ts | 7 +++ src/strings/notEmptyObject.ts | 4 ++ src/strings/notNullOrUndefined.ts | 10 +++++ src/strings/pluralize.ts | 14 ++++++ src/strings/removeDoubleSpaces.ts | 7 +++ src/strings/toHex.ts | 9 ++++ tests/{ard.bun.test.ts => ard.test.bun.ts} | 0 tests/date.utils.test.ts | 5 +-- tests/{strings.test.mjs => strings.test.ts} | 50 +++++++++++++++++++-- utils/strings/capitalize.js | 2 - utils/strings/getObjectLength.js | 2 - utils/strings/isArray.js | 4 -- utils/strings/isEmptyArray.js | 4 -- utils/strings/isEmptyObject.js | 5 --- utils/strings/isEmptyString.js | 2 - utils/strings/isIncluded.js | 2 - utils/strings/isNull.js | 2 - utils/strings/isObject.js | 6 --- utils/strings/isUndefined.js | 2 - utils/strings/notEmptyArray.js | 4 -- utils/strings/notEmptyObject.js | 5 --- utils/strings/notNullOrUndefined.js | 5 --- utils/strings/pluralize.js | 7 --- utils/strings/removeDoubleSpaces.js | 2 - utils/strings/toHex.js | 2 - 44 files changed, 239 insertions(+), 127 deletions(-) delete mode 100644 packages/strings/index.js create mode 100644 src/strings/capitalize.ts create mode 100644 src/strings/getObjectLength.ts create mode 100644 src/strings/index.ts create mode 100644 src/strings/isArray.ts create mode 100644 src/strings/isEmptyArray.ts create mode 100644 src/strings/isEmptyObject.ts create mode 100644 src/strings/isEmptyString.ts create mode 100644 src/strings/isIncluded.ts create mode 100644 src/strings/isNull.ts create mode 100644 src/strings/isObject.ts create mode 100644 src/strings/isUndefined.ts create mode 100644 src/strings/notEmptyArray.ts create mode 100644 src/strings/notEmptyObject.ts create mode 100644 src/strings/notNullOrUndefined.ts create mode 100644 src/strings/pluralize.ts create mode 100644 src/strings/removeDoubleSpaces.ts create mode 100644 src/strings/toHex.ts rename tests/{ard.bun.test.ts => ard.test.bun.ts} (100%) rename tests/{strings.test.mjs => strings.test.ts} (76%) delete mode 100644 utils/strings/capitalize.js delete mode 100644 utils/strings/getObjectLength.js delete mode 100644 utils/strings/isArray.js delete mode 100644 utils/strings/isEmptyArray.js delete mode 100644 utils/strings/isEmptyObject.js delete mode 100644 utils/strings/isEmptyString.js delete mode 100644 utils/strings/isIncluded.js delete mode 100644 utils/strings/isNull.js delete mode 100644 utils/strings/isObject.js delete mode 100644 utils/strings/isUndefined.js delete mode 100644 utils/strings/notEmptyArray.js delete mode 100644 utils/strings/notEmptyObject.js delete mode 100644 utils/strings/notNullOrUndefined.js delete mode 100644 utils/strings/pluralize.js delete mode 100644 utils/strings/removeDoubleSpaces.js delete mode 100644 utils/strings/toHex.js diff --git a/.editorconfig b/.editorconfig index 866cda1..c58e4f2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,7 +8,7 @@ root = true charset = utf-8 end_of_line = lf indent_style = tab -indent_size = 8 +indent_size = 4 max_line_length = 120 trim_trailing_whitespace = true insert_final_newline = true diff --git a/eslint.config.js b/eslint.config.js index 442e5ee..533adc4 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -2,7 +2,7 @@ import { audiolab } from '@swrlab/style-guide/eslint.js' export default audiolab( { - prettier: false, + prettier: true, comments: true, }, [ diff --git a/index.js b/index.js index d388bbb..3d8d6da 100644 --- a/index.js +++ b/index.js @@ -1,24 +1,7 @@ -/* - - node-utils by SWR audio lab - frequently used node-packages and helpers - -*/ - -// import packages -const ard = require('./packages/ard') -const helpers = require('./packages/helpers') -const numbers = require('./packages/numbers') const storage = require('./packages/storage-wrapper') -const strings = require('./packages/strings') const undici = require('./packages/undici') -// export packages module.exports = { - ard, - helpers, - numbers, storage, - strings, undici, } diff --git a/package.json b/package.json index d050657..3d4ce21 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,9 @@ "format": "prettier --write .", "lint": "eslint", "lint:fix": "eslint --fix", - "test": "bun test tests/**/*.ts", - "test:node": "node --test tests/**/*.ts" + "test": "bun run test:bun", + "test:bun": "bun test ./tests/**test*.ts", + "test:node": "node --test ./tests/**/*.test.ts" }, "dependencies": { "@google-cloud/storage": "^7.16.0", diff --git a/packages/strings/index.js b/packages/strings/index.js deleted file mode 100644 index d33f6f3..0000000 --- a/packages/strings/index.js +++ /dev/null @@ -1,37 +0,0 @@ -// import packages -const capitalize = require('../../utils/strings/capitalize') -const getObjectLength = require('../../utils/strings/getObjectLength') -const isArray = require('../../utils/strings/isArray') -const isEmptyArray = require('../../utils/strings/isEmptyArray') -const isEmptyObject = require('../../utils/strings/isEmptyObject') -const isEmptyString = require('../../utils/strings/isEmptyString') -const isIncluded = require('../../utils/strings/isIncluded') -const isNull = require('../../utils/strings/isNull') -const isObject = require('../../utils/strings/isObject') -const isUndefined = require('../../utils/strings/isUndefined') -const notEmptyArray = require('../../utils/strings/notEmptyArray') -const notEmptyObject = require('../../utils/strings/notEmptyObject') -const notNullOrUndefined = require('../../utils/strings/notNullOrUndefined') -const pluralize = require('../../utils/strings/pluralize') -const removeDoubleSpaces = require('../../utils/strings/removeDoubleSpaces') -const toHex = require('../../utils/strings/toHex') - -// export packages -module.exports = { - capitalize, - getObjectLength, - isArray, - isEmptyArray, - isEmptyObject, - isEmptyString, - isIncluded, - isNull, - isObject, - isUndefined, - notEmptyArray, - notEmptyObject, - notNullOrUndefined, - pluralize, - removeDoubleSpaces, - toHex, -} diff --git a/packages/undici/request.js b/packages/undici/request.js index 711ba94..fa890e0 100644 --- a/packages/undici/request.js +++ b/packages/undici/request.js @@ -42,8 +42,7 @@ module.exports = async (url, options) => { const { string, buffer } = await convertReadableStream(body) // detect/ set redirect - const redirect = - statusCode >= 300 && statusCode < 400 && headers.location ? new URL(headers.location, url) : null + const redirect = statusCode >= 300 && statusCode < 400 && headers.location ? new URL(headers.location, url) : null // fetch header vars const contentType = headers['content-type'] diff --git a/scripts/ard/coreId.js b/scripts/ard/coreId.js index 23282b4..689d4a8 100644 --- a/scripts/ard/coreId.js +++ b/scripts/ard/coreId.js @@ -1,5 +1,5 @@ -const process = require('node:process') -const createHashedId = require('../../utils/ard/createHashedId') +import process from 'node:process' +import { createHashedId } from '../../src/ard/index.ts' const input = process.argv.slice(2) diff --git a/src/numbers/getSum.ts b/src/numbers/getSum.ts index e694178..619cafa 100644 --- a/src/numbers/getSum.ts +++ b/src/numbers/getSum.ts @@ -1,4 +1,4 @@ -import { roundTo } from './roundTo.js' +import { roundTo } from './roundTo.ts' /** * Get sum of number array. diff --git a/src/strings/capitalize.ts b/src/strings/capitalize.ts new file mode 100644 index 0000000..d37d941 --- /dev/null +++ b/src/strings/capitalize.ts @@ -0,0 +1,14 @@ +type Capitalized = T extends `${infer FL}${infer Rest}` ? `${Uppercase}${Rest}` : T +/** + * Converts the first character of string to upper case. + * + * @template T - Literal type of the string. + * @param {T} str - The string to be converted to uppercase. + * @returns {Capitalized} - The capitalized string. + * + * @example + * const result = capitalize('apple') // returns 'Apple' + * const result2 = capitalize('ABC') // returns 'ABC' + */ +export const capitalize = (str: T): Capitalized => + !str ? (str as Capitalized) : ((str.charAt(0).toUpperCase() + str.slice(1)) as Capitalized) diff --git a/src/strings/getObjectLength.ts b/src/strings/getObjectLength.ts new file mode 100644 index 0000000..26d82d3 --- /dev/null +++ b/src/strings/getObjectLength.ts @@ -0,0 +1,7 @@ +/** + * Returns the size (legth of keys) of the given object. + * + * @param {Record} object - The object. + * @returns - The length of the object. + */ +export const getObjectLength = (object: Record): number => object && Object.keys(object).length diff --git a/src/strings/index.ts b/src/strings/index.ts new file mode 100644 index 0000000..e9aea3e --- /dev/null +++ b/src/strings/index.ts @@ -0,0 +1,16 @@ +export { capitalize } from './capitalize.ts' +export { getObjectLength } from './getObjectLength.ts' +export { isArray } from './isArray.ts' +export { isEmptyArray } from './isEmptyArray.ts' +export { isEmptyObject } from './isEmptyObject.ts' +export { isEmptyString } from './isEmptyString.ts' +export { isIncluded } from './isIncluded.ts' +export { isNull } from './isNull.ts' +export { isObject, isPlainObject } from './isObject.ts' +export { isUndefined } from './isUndefined.ts' +export { notEmptyArray } from './notEmptyArray.ts' +export { notEmptyObject } from './notEmptyObject.ts' +export { notNullOrUndefined } from './notNullOrUndefined.ts' +export { pluralize } from './pluralize.ts' +export { removeDoubleSpaces } from './removeDoubleSpaces.ts' +export { toHex } from './toHex.ts' diff --git a/src/strings/isArray.ts b/src/strings/isArray.ts new file mode 100644 index 0000000..12dd152 --- /dev/null +++ b/src/strings/isArray.ts @@ -0,0 +1,10 @@ +/** + * Checks if the given value is an array. + * + * @deprecated Use `Array.isArray(value)` instead. + * + * @param {any} value - The value to be cheked. + * + * @returns {boolean} - `true` if the value is an array, `false` otherwise. + */ +export const isArray = (value?: any): value is any[] => Array.isArray(value) diff --git a/src/strings/isEmptyArray.ts b/src/strings/isEmptyArray.ts new file mode 100644 index 0000000..21041e1 --- /dev/null +++ b/src/strings/isEmptyArray.ts @@ -0,0 +1,12 @@ +/** + * Checks if the given value is an empty array. + * + * @param {unknown} [value] - The value to check. + * @returns {boolean} `true` if the value is empty, `false` otherwise. + * + * @example + * isEmptyArray() // false + * isEmptyArray([]) // true + * isEmptyArray([0]) // false + */ +export const isEmptyArray = (value?: unknown): boolean => Array.isArray(value) && value.length === 0 diff --git a/src/strings/isEmptyObject.ts b/src/strings/isEmptyObject.ts new file mode 100644 index 0000000..3026206 --- /dev/null +++ b/src/strings/isEmptyObject.ts @@ -0,0 +1,10 @@ +import { getObjectLength } from './getObjectLength.ts' +import { isPlainObject } from './isObject.ts' + +/** + * Checks if a given value is an empty object. + * + * @param {unknown} [value] - The value to check. + * @returns `true` if the value is an empty object, `false` otherwise. + */ +export const isEmptyObject = (value?: unknown): boolean => isPlainObject(value) && getObjectLength(value) === 0 diff --git a/src/strings/isEmptyString.ts b/src/strings/isEmptyString.ts new file mode 100644 index 0000000..c877b14 --- /dev/null +++ b/src/strings/isEmptyString.ts @@ -0,0 +1,7 @@ +/** + * Checks if a given string is empty. + * + * @param {string} string - The string to check. + * @returns `true` if the string is empty, `false` otherwise. + */ +export const isEmptyString = (string: string): string is '' => string === '' diff --git a/src/strings/isIncluded.ts b/src/strings/isIncluded.ts new file mode 100644 index 0000000..01972d2 --- /dev/null +++ b/src/strings/isIncluded.ts @@ -0,0 +1,13 @@ +/** + * Checks if a string contains a searchTerm. + * + * @deprecated Use `string.includes(searchTerm)` instead of `isIncluded(string, searchTerm)`. + * + * @param {string} string - The string to search in. + * @param {string} searchTerm - The sub-string to search in the string. + * @returns `true` if the string contains the searchTerm, `false` otherwise. + */ +export const isIncluded = (string: string, searchTerm: string): boolean => string.includes(searchTerm) + +// Array version: +// export const isIncluded = (array: T[], searchElement: T): boolean => array.includes(searchElement) diff --git a/src/strings/isNull.ts b/src/strings/isNull.ts new file mode 100644 index 0000000..aaecc4f --- /dev/null +++ b/src/strings/isNull.ts @@ -0,0 +1,7 @@ +/** + * Checks if the given value is null. + * + * @param value - The value to check. + * @returns `true`, if the value is null, `false` otherwise. + */ +export const isNull = (value: unknown): value is null => value === null diff --git a/src/strings/isObject.ts b/src/strings/isObject.ts new file mode 100644 index 0000000..ba84066 --- /dev/null +++ b/src/strings/isObject.ts @@ -0,0 +1,22 @@ +// import { isArray } from './isArray.ts' +// import { notNullOrUndefined } from './notNullOrUndefined.ts' + +/** + * Checks if a given value is a plain object. + * + * @param {unknown} [value] - The value to check. + * @returns `true` if the value is an object, `false` otherwise. + */ +export const isPlainObject = (value?: unknown): value is Record => + value !== null && typeof value === 'object' && !Array.isArray(value) + +// export for legacy name +/** + * Checks if a given value is a (plain) object. + * + * @deprecated Use `isPlainObject instead` + * + * @param {unknown} [value] - The value to check. + * @returns `true` if the value is an object, `false` otherwise. + */ +export const isObject: (value?: unknown) => value is Record = isPlainObject diff --git a/src/strings/isUndefined.ts b/src/strings/isUndefined.ts new file mode 100644 index 0000000..bff0c50 --- /dev/null +++ b/src/strings/isUndefined.ts @@ -0,0 +1,14 @@ +/** + * Checks if the given value is undefined. + * + * @param {unknown} x - The value to check. + * @returns {x is undefined} `true` if the value is undefined, `false` otherwise. + * + * @example + * isUndefined(undefined) // true + * isUndefined(null) // false + * isUndefined("") // false + * isUndefined(false) // false + * isUndefined([]) // false + */ +export const isUndefined = (x: any): x is undefined => x === undefined diff --git a/src/strings/notEmptyArray.ts b/src/strings/notEmptyArray.ts new file mode 100644 index 0000000..82aaeeb --- /dev/null +++ b/src/strings/notEmptyArray.ts @@ -0,0 +1,7 @@ +/** + * Checks if the given value is a non-empty array. + * + * @param {unknown[]} [value] - The value to check. + * @returns `true` if the value is a non-empty array, `false` otherwise. + */ +export const notEmptyArray = (value?: unknown[]): boolean => Array.isArray(value) && value.length > 0 diff --git a/src/strings/notEmptyObject.ts b/src/strings/notEmptyObject.ts new file mode 100644 index 0000000..0628dd7 --- /dev/null +++ b/src/strings/notEmptyObject.ts @@ -0,0 +1,4 @@ +import { getObjectLength } from './getObjectLength.ts' +import { isPlainObject } from './isObject.ts' + +export const notEmptyObject = (value: Record): boolean => isPlainObject(value) && getObjectLength(value) > 0 diff --git a/src/strings/notNullOrUndefined.ts b/src/strings/notNullOrUndefined.ts new file mode 100644 index 0000000..7daee5b --- /dev/null +++ b/src/strings/notNullOrUndefined.ts @@ -0,0 +1,10 @@ +import { isNull } from './isNull.ts' +import { isUndefined } from './isUndefined.ts' + +/** + * Checks if a given value is not `null` and not `undefined`. + * + * @param {unknown} [value] - The value to check. + * @returns `true` if the value is neither `null` nor `undefined`, `false otherwise`. + */ +export const notNullOrUndefined = (value?: unknown): boolean => !isNull(value) && !isUndefined(value) diff --git a/src/strings/pluralize.ts b/src/strings/pluralize.ts new file mode 100644 index 0000000..2b0bdea --- /dev/null +++ b/src/strings/pluralize.ts @@ -0,0 +1,14 @@ +import { toReadable } from '../numbers/toReadable.ts' + +/** + * Covert a number to a readable value with a description term. + * + * @param {number} count - The number to be used. + * @param singular - The singular term, if the number is 1. + * @param plural - The plural term, if the number is not 1. Optional. If not provided the singular term is used with an `s` appended. + * @returns {string} - The pluralized string. + */ +export const pluralize = (count: number, singular: string, plural?: string): string => { + const term = count === 1 ? singular : (plural ?? `${singular}s`) + return `${toReadable(count)} ${term}` +} diff --git a/src/strings/removeDoubleSpaces.ts b/src/strings/removeDoubleSpaces.ts new file mode 100644 index 0000000..3dea0df --- /dev/null +++ b/src/strings/removeDoubleSpaces.ts @@ -0,0 +1,7 @@ +/** + * Remove all duplicate spaces from the given string. + * + * @param string - The string that may contain multiple spaces. + * @returns {string} - The trimmed string. + */ +export const removeDoubleSpaces = (string: string): string => string.replaceAll(/ +(?= )/g, '') diff --git a/src/strings/toHex.ts b/src/strings/toHex.ts new file mode 100644 index 0000000..1e69fd0 --- /dev/null +++ b/src/strings/toHex.ts @@ -0,0 +1,9 @@ +import { Buffer } from 'node:buffer' + +/** + * Converts the given string into a hexadecimal string. + * + * @param value - The string to be converted. + * @returns {string} - The hex value of the string. + */ +export const toHex = (value: string): string => Buffer.from(value).toString('hex') diff --git a/tests/ard.bun.test.ts b/tests/ard.test.bun.ts similarity index 100% rename from tests/ard.bun.test.ts rename to tests/ard.test.bun.ts diff --git a/tests/date.utils.test.ts b/tests/date.utils.test.ts index 9e6afac..b0cdb6c 100644 --- a/tests/date.utils.test.ts +++ b/tests/date.utils.test.ts @@ -48,10 +48,7 @@ describe('formatDateTimeString(): ', () => { }) test('formatDateTimeString(): addOClockSuffix', () => { assert.strictEqual(formatDateTimeString('', { addOClockSuffix: false }), '') - assert.strictEqual( - formatDateTimeString(date, { addOClockSuffix: false }), - formattedDate.replace(' Uhr', '') - ) + assert.strictEqual(formatDateTimeString(date, { addOClockSuffix: false }), formattedDate.replace(' Uhr', '')) assert(!formatDateTimeString(date, { addOClockSuffix: false }).includes('Uhr')) }) test('formatDateTimeString(): other timePrefix', () => { diff --git a/tests/strings.test.mjs b/tests/strings.test.ts similarity index 76% rename from tests/strings.test.mjs rename to tests/strings.test.ts index b2e137d..67aac49 100644 --- a/tests/strings.test.mjs +++ b/tests/strings.test.ts @@ -1,14 +1,15 @@ import assert from 'node:assert' -import { describe, it } from 'node:test' -import * as strings from '../packages/strings/index.js' +import { describe, it, test } from 'node:test' +import * as strings from '../src/strings/index.ts' +import { capitalize } from '../src/strings/index.ts' describe('Test Strings Package', () => { describe('Test capitalize', () => { it("capitalize('a') = 'A'", () => { - assert.equal(strings.capitalize('a'), 'A') + assert.equal(capitalize('a'), 'A') }) it("capitalize('apple') = 'Apple'", () => { - assert.equal(strings.capitalize('apple'), 'Apple') + assert.equal(capitalize('apple'), 'Apple') }) }) @@ -36,6 +37,21 @@ describe('Test Strings Package', () => { it("isArray({ hello: 'world' }) = false", () => { assert.equal(strings.isArray({ hello: 'world' }), false) }) + + test('valid arrays', () => { + assert(strings.isArray([])) + assert(strings.isArray([0])) + assert(strings.isArray([false])) + }) + test('non arrays', () => { + assert(!strings.isArray(true)) + assert(!strings.isArray(false)) + assert(!strings.isArray('')) + assert(!strings.isArray('[]')) + assert(!strings.isArray(null)) + assert(!strings.isArray()) + assert(!strings.isArray(undefined)) + }) }) describe('Test isEmptyArray', () => { @@ -98,6 +114,19 @@ describe('Test Strings Package', () => { }) }) + describe('Test isPlainObject', () => { + it('is true with objects', () => { + assert(strings.isPlainObject({})) + assert(strings.isPlainObject(Object.create(null))) + assert(strings.isPlainObject({ hello: 'world' })) + }) + + it('is false with invalid objects', () => { + assert.equal(strings.isPlainObject([]), false) + assert.equal(strings.isPlainObject('hello world'), false) + }) + }) + describe('Test isUndefined', () => { it('isUndefined(undefined) = true', () => { assert.equal(strings.isUndefined(undefined), true) @@ -106,6 +135,10 @@ describe('Test Strings Package', () => { it('isUndefined(null) = false', () => { assert.equal(strings.isUndefined(null), false) }) + + it('isUndefined(false) = false', () => { + assert.equal(strings.isUndefined(false), false) + }) }) describe('Test notEmptyArray', () => { @@ -165,9 +198,18 @@ describe('Test Strings Package', () => { assert.equal(strings.removeDoubleSpaces('hello world'), 'hello world') }) + it("removeDoubleSpaces('hello world')) = 'hello world'", () => { + assert.equal(strings.removeDoubleSpaces('hello world'), 'hello world') + }) + it("removeDoubleSpaces('hello world once again')) = 'hello world once again'", () => { assert.equal(strings.removeDoubleSpaces('hello world once again'), 'hello world once again') }) + + it('does not remove normal spaces', () => { + assert.equal(strings.removeDoubleSpaces('hello world'), 'hello world') + assert.equal(strings.removeDoubleSpaces(' hello world '), ' hello world ') + }) }) describe('Test toHex', () => { diff --git a/utils/strings/capitalize.js b/utils/strings/capitalize.js deleted file mode 100644 index e75a87b..0000000 --- a/utils/strings/capitalize.js +++ /dev/null @@ -1,2 +0,0 @@ -// capitalize value to Value -module.exports = (value) => `${value[0].toUpperCase()}${value.slice(1)}` diff --git a/utils/strings/getObjectLength.js b/utils/strings/getObjectLength.js deleted file mode 100644 index fdf73d7..0000000 --- a/utils/strings/getObjectLength.js +++ /dev/null @@ -1,2 +0,0 @@ -// get the length (count of keys) of an object -module.exports = (value) => value && Object.keys(value).length diff --git a/utils/strings/isArray.js b/utils/strings/isArray.js deleted file mode 100644 index 4ea4453..0000000 --- a/utils/strings/isArray.js +++ /dev/null @@ -1,4 +0,0 @@ -const notNullOrUndefined = require('./notNullOrUndefined') - -// check if a variable is really an array -module.exports = (value) => notNullOrUndefined(value) && value instanceof Array diff --git a/utils/strings/isEmptyArray.js b/utils/strings/isEmptyArray.js deleted file mode 100644 index 6595737..0000000 --- a/utils/strings/isEmptyArray.js +++ /dev/null @@ -1,4 +0,0 @@ -const isArray = require('./isArray') - -// check if a variable is an empty array -module.exports = (value) => isArray(value) && value.length === 0 diff --git a/utils/strings/isEmptyObject.js b/utils/strings/isEmptyObject.js deleted file mode 100644 index cc4ec28..0000000 --- a/utils/strings/isEmptyObject.js +++ /dev/null @@ -1,5 +0,0 @@ -const isObject = require('./isObject') -const getObjectLength = require('./getObjectLength') - -// check if a variable is an empty object -module.exports = (value) => isObject(value) && getObjectLength(value) === 0 diff --git a/utils/strings/isEmptyString.js b/utils/strings/isEmptyString.js deleted file mode 100644 index 7d1045f..0000000 --- a/utils/strings/isEmptyString.js +++ /dev/null @@ -1,2 +0,0 @@ -// check if a variable is an empty string -module.exports = (value) => value === '' diff --git a/utils/strings/isIncluded.js b/utils/strings/isIncluded.js deleted file mode 100644 index 0b74ff2..0000000 --- a/utils/strings/isIncluded.js +++ /dev/null @@ -1,2 +0,0 @@ -// check if a variable (haystack) includes a needle -module.exports = (haystack, needle) => haystack.indexOf(needle) !== -1 diff --git a/utils/strings/isNull.js b/utils/strings/isNull.js deleted file mode 100644 index 9e32efe..0000000 --- a/utils/strings/isNull.js +++ /dev/null @@ -1,2 +0,0 @@ -// check if a variable is null -module.exports = (value) => value === null diff --git a/utils/strings/isObject.js b/utils/strings/isObject.js deleted file mode 100644 index 086ace1..0000000 --- a/utils/strings/isObject.js +++ /dev/null @@ -1,6 +0,0 @@ -// import utils -const isArray = require('./isArray') -const notNullOrUndefined = require('./notNullOrUndefined') - -// check if a variable is really an object -module.exports = (value) => notNullOrUndefined(value) && value instanceof Object && !isArray(value) diff --git a/utils/strings/isUndefined.js b/utils/strings/isUndefined.js deleted file mode 100644 index ff200a6..0000000 --- a/utils/strings/isUndefined.js +++ /dev/null @@ -1,2 +0,0 @@ -// check if a variable is undefined -module.exports = (value) => value === undefined diff --git a/utils/strings/notEmptyArray.js b/utils/strings/notEmptyArray.js deleted file mode 100644 index d4b88b6..0000000 --- a/utils/strings/notEmptyArray.js +++ /dev/null @@ -1,4 +0,0 @@ -const isArray = require('./isArray') - -// check if a variable is an empty array -module.exports = (value) => isArray(value) && value.length > 0 diff --git a/utils/strings/notEmptyObject.js b/utils/strings/notEmptyObject.js deleted file mode 100644 index 803a15e..0000000 --- a/utils/strings/notEmptyObject.js +++ /dev/null @@ -1,5 +0,0 @@ -const isObject = require('./isObject') -const getObjectLength = require('./getObjectLength') - -// check if a variable is an empty object -module.exports = (value) => isObject(value) && getObjectLength(value) > 0 diff --git a/utils/strings/notNullOrUndefined.js b/utils/strings/notNullOrUndefined.js deleted file mode 100644 index 44e45aa..0000000 --- a/utils/strings/notNullOrUndefined.js +++ /dev/null @@ -1,5 +0,0 @@ -const isNull = require('./isNull') -const isUndefined = require('./isUndefined') - -// check if a variable is neither null nor undefined -module.exports = (value) => !isNull(value) && !isUndefined(value) diff --git a/utils/strings/pluralize.js b/utils/strings/pluralize.js deleted file mode 100644 index af6afb5..0000000 --- a/utils/strings/pluralize.js +++ /dev/null @@ -1,7 +0,0 @@ -import { toReadable } from '../../src/numbers/toReadable.ts' - -// pluralize value to values or use custom plural -export const pluralize = (count, singular, plural) => { - const multi = plural ?? `${singular}s` - return `${toReadable(count)} ${count !== 1 ? multi : singular}` -} diff --git a/utils/strings/removeDoubleSpaces.js b/utils/strings/removeDoubleSpaces.js deleted file mode 100644 index 29764a2..0000000 --- a/utils/strings/removeDoubleSpaces.js +++ /dev/null @@ -1,2 +0,0 @@ -// remove duplicate spaces from a string -module.exports = (value) => value.replace(/ +(?= )/g, '') diff --git a/utils/strings/toHex.js b/utils/strings/toHex.js deleted file mode 100644 index 85ac640..0000000 --- a/utils/strings/toHex.js +++ /dev/null @@ -1,2 +0,0 @@ -// convert input to hex value -module.exports = (value) => Buffer.from(value).toString('hex') From be2df3ce37fd39e901038f517d1f612c9fc35ef5 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Sat, 6 Sep 2025 18:00:12 +0200 Subject: [PATCH 14/42] chore: clean up directory structure --- package.json | 5 +- src/ard/createHashedId.ts | 7 ++- src/{dates => date}/getDateHourMinutes.ts | 0 src/{dates => date}/getDayMonthYear.ts | 0 src/{dates => date}/getFullRelativeTime.ts | 0 src/{dates => date}/getHourMinutes.ts | 0 src/{dates => date}/getIsoRelativeTime.ts | 0 src/{dates => date}/getRelativeTime.ts | 0 src/{dates => date}/getYearMonthDay.ts | 0 src/{dates => date}/index.ts | 0 src/{dates => date}/revYearMonthDay.ts | 0 src/{dates => date}/utils.ts | 0 src/index.ts | 5 +- src/legacy.ts | 4 ++ src/{numbers => number}/addLeadingZero.ts | 0 src/{numbers => number}/addTrailingZeros.ts | 0 src/{numbers => number}/getAverage.ts | 0 src/{numbers => number}/getDiff.ts | 0 src/{numbers => number}/getRandomInRange.ts | 0 src/{numbers => number}/getSum.ts | 0 src/{numbers => number}/index.ts | 0 src/{numbers => number}/isEven.ts | 0 src/{numbers => number}/normalize.ts | 0 src/{numbers => number}/roundTo.ts | 0 src/number/toReadable.ts | 10 ++++ src/numbers/toReadable.ts | 10 ---- src/{strings => string}/capitalize.ts | 0 src/{strings => string}/getObjectLength.ts | 0 src/{strings => string}/index.ts | 0 src/{strings => string}/isArray.ts | 0 src/{strings => string}/isEmptyArray.ts | 0 src/{strings => string}/isEmptyObject.ts | 0 src/{strings => string}/isEmptyString.ts | 0 src/{strings => string}/isIncluded.ts | 0 src/{strings => string}/isNull.ts | 0 src/{strings => string}/isObject.ts | 0 src/{strings => string}/isUndefined.ts | 0 src/{strings => string}/notEmptyArray.ts | 0 src/{strings => string}/notEmptyObject.ts | 0 src/{strings => string}/notNullOrUndefined.ts | 0 src/string/pluralize.ts | 14 +++++ src/{strings => string}/removeDoubleSpaces.ts | 0 src/{strings => string}/toHex.ts | 0 src/strings/pluralize.ts | 14 ----- tests/ard.test.bun.ts | 1 + tests/date.test.ts | 2 +- tests/date.utils.test.ts | 2 +- tests/{numbers.test.ts => number.test.ts} | 56 +++++++++---------- tests/{strings.test.ts => string.test.ts} | 4 +- 49 files changed, 71 insertions(+), 63 deletions(-) rename src/{dates => date}/getDateHourMinutes.ts (100%) rename src/{dates => date}/getDayMonthYear.ts (100%) rename src/{dates => date}/getFullRelativeTime.ts (100%) rename src/{dates => date}/getHourMinutes.ts (100%) rename src/{dates => date}/getIsoRelativeTime.ts (100%) rename src/{dates => date}/getRelativeTime.ts (100%) rename src/{dates => date}/getYearMonthDay.ts (100%) rename src/{dates => date}/index.ts (100%) rename src/{dates => date}/revYearMonthDay.ts (100%) rename src/{dates => date}/utils.ts (100%) create mode 100644 src/legacy.ts rename src/{numbers => number}/addLeadingZero.ts (100%) rename src/{numbers => number}/addTrailingZeros.ts (100%) rename src/{numbers => number}/getAverage.ts (100%) rename src/{numbers => number}/getDiff.ts (100%) rename src/{numbers => number}/getRandomInRange.ts (100%) rename src/{numbers => number}/getSum.ts (100%) rename src/{numbers => number}/index.ts (100%) rename src/{numbers => number}/isEven.ts (100%) rename src/{numbers => number}/normalize.ts (100%) rename src/{numbers => number}/roundTo.ts (100%) create mode 100644 src/number/toReadable.ts delete mode 100644 src/numbers/toReadable.ts rename src/{strings => string}/capitalize.ts (100%) rename src/{strings => string}/getObjectLength.ts (100%) rename src/{strings => string}/index.ts (100%) rename src/{strings => string}/isArray.ts (100%) rename src/{strings => string}/isEmptyArray.ts (100%) rename src/{strings => string}/isEmptyObject.ts (100%) rename src/{strings => string}/isEmptyString.ts (100%) rename src/{strings => string}/isIncluded.ts (100%) rename src/{strings => string}/isNull.ts (100%) rename src/{strings => string}/isObject.ts (100%) rename src/{strings => string}/isUndefined.ts (100%) rename src/{strings => string}/notEmptyArray.ts (100%) rename src/{strings => string}/notEmptyObject.ts (100%) rename src/{strings => string}/notNullOrUndefined.ts (100%) create mode 100644 src/string/pluralize.ts rename src/{strings => string}/removeDoubleSpaces.ts (100%) rename src/{strings => string}/toHex.ts (100%) delete mode 100644 src/strings/pluralize.ts rename tests/{numbers.test.ts => number.test.ts} (55%) rename tests/{strings.test.ts => string.test.ts} (98%) diff --git a/package.json b/package.json index 3d4ce21..fbc66e3 100644 --- a/package.json +++ b/package.json @@ -32,9 +32,10 @@ "format": "prettier --write .", "lint": "eslint", "lint:fix": "eslint --fix", - "test": "bun run test:bun", + "test": "bun run typecheck && bun run test:bun", "test:bun": "bun test ./tests/**test*.ts", - "test:node": "node --test ./tests/**/*.test.ts" + "test:node": "node --test ./tests/**/*.test.ts", + "typecheck": "tsc --noEmit" }, "dependencies": { "@google-cloud/storage": "^7.16.0", diff --git a/src/ard/createHashedId.ts b/src/ard/createHashedId.ts index 9833401..dbda734 100644 --- a/src/ard/createHashedId.ts +++ b/src/ard/createHashedId.ts @@ -2,12 +2,13 @@ import { Buffer } from 'node:buffer' import crc from 'node-crc' /** - * Create a a CRC64-ECMA182-compliant hash + * Create a a CRC64-ECMA182-compliant hash from given input. * * @module ard * @category ard - * @param input - utf-8 encoded input string - * @returns CRC64-ECMA182-compliant hashed input + * + * @param {string} input - The utf-8 encoded input string. + * @returns {string} - CRC64-ECMA182-compliant hashed input * * @example * ``` diff --git a/src/dates/getDateHourMinutes.ts b/src/date/getDateHourMinutes.ts similarity index 100% rename from src/dates/getDateHourMinutes.ts rename to src/date/getDateHourMinutes.ts diff --git a/src/dates/getDayMonthYear.ts b/src/date/getDayMonthYear.ts similarity index 100% rename from src/dates/getDayMonthYear.ts rename to src/date/getDayMonthYear.ts diff --git a/src/dates/getFullRelativeTime.ts b/src/date/getFullRelativeTime.ts similarity index 100% rename from src/dates/getFullRelativeTime.ts rename to src/date/getFullRelativeTime.ts diff --git a/src/dates/getHourMinutes.ts b/src/date/getHourMinutes.ts similarity index 100% rename from src/dates/getHourMinutes.ts rename to src/date/getHourMinutes.ts diff --git a/src/dates/getIsoRelativeTime.ts b/src/date/getIsoRelativeTime.ts similarity index 100% rename from src/dates/getIsoRelativeTime.ts rename to src/date/getIsoRelativeTime.ts diff --git a/src/dates/getRelativeTime.ts b/src/date/getRelativeTime.ts similarity index 100% rename from src/dates/getRelativeTime.ts rename to src/date/getRelativeTime.ts diff --git a/src/dates/getYearMonthDay.ts b/src/date/getYearMonthDay.ts similarity index 100% rename from src/dates/getYearMonthDay.ts rename to src/date/getYearMonthDay.ts diff --git a/src/dates/index.ts b/src/date/index.ts similarity index 100% rename from src/dates/index.ts rename to src/date/index.ts diff --git a/src/dates/revYearMonthDay.ts b/src/date/revYearMonthDay.ts similarity index 100% rename from src/dates/revYearMonthDay.ts rename to src/date/revYearMonthDay.ts diff --git a/src/dates/utils.ts b/src/date/utils.ts similarity index 100% rename from src/dates/utils.ts rename to src/date/utils.ts diff --git a/src/index.ts b/src/index.ts index 4054330..102244b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ export * from './ard/index.ts' -export * from './dates/index.ts' +export * from './date/index.ts' export * from './helpers/index.ts' -export * from './numbers/index.ts' +export * from './number/index.ts' +export * from './string/index.ts' diff --git a/src/legacy.ts b/src/legacy.ts new file mode 100644 index 0000000..7ba5eef --- /dev/null +++ b/src/legacy.ts @@ -0,0 +1,4 @@ +/** + * @fileoverview Provide all the legacy exports so pre-existing export names and behaviour is still present + * and does not break any code. + */ diff --git a/src/numbers/addLeadingZero.ts b/src/number/addLeadingZero.ts similarity index 100% rename from src/numbers/addLeadingZero.ts rename to src/number/addLeadingZero.ts diff --git a/src/numbers/addTrailingZeros.ts b/src/number/addTrailingZeros.ts similarity index 100% rename from src/numbers/addTrailingZeros.ts rename to src/number/addTrailingZeros.ts diff --git a/src/numbers/getAverage.ts b/src/number/getAverage.ts similarity index 100% rename from src/numbers/getAverage.ts rename to src/number/getAverage.ts diff --git a/src/numbers/getDiff.ts b/src/number/getDiff.ts similarity index 100% rename from src/numbers/getDiff.ts rename to src/number/getDiff.ts diff --git a/src/numbers/getRandomInRange.ts b/src/number/getRandomInRange.ts similarity index 100% rename from src/numbers/getRandomInRange.ts rename to src/number/getRandomInRange.ts diff --git a/src/numbers/getSum.ts b/src/number/getSum.ts similarity index 100% rename from src/numbers/getSum.ts rename to src/number/getSum.ts diff --git a/src/numbers/index.ts b/src/number/index.ts similarity index 100% rename from src/numbers/index.ts rename to src/number/index.ts diff --git a/src/numbers/isEven.ts b/src/number/isEven.ts similarity index 100% rename from src/numbers/isEven.ts rename to src/number/isEven.ts diff --git a/src/numbers/normalize.ts b/src/number/normalize.ts similarity index 100% rename from src/numbers/normalize.ts rename to src/number/normalize.ts diff --git a/src/numbers/roundTo.ts b/src/number/roundTo.ts similarity index 100% rename from src/numbers/roundTo.ts rename to src/number/roundTo.ts diff --git a/src/number/toReadable.ts b/src/number/toReadable.ts new file mode 100644 index 0000000..665946a --- /dev/null +++ b/src/number/toReadable.ts @@ -0,0 +1,10 @@ +import { DEFAULT_LOCALE } from '../date/utils.ts' + +/** + * Converts the given number into a german readable format. + * + * @param {number} number - The number to be converted. + * + * @returns {string} - Ther readable string. + */ +export const toReadable = (number: number): string => number.toLocaleString(DEFAULT_LOCALE) diff --git a/src/numbers/toReadable.ts b/src/numbers/toReadable.ts deleted file mode 100644 index fc70e91..0000000 --- a/src/numbers/toReadable.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { DEFAULT_LOCALE } from '../dates/utils.ts' - -/** - * Return a number in german readable format. - * - * @param value - number - * - * @returns readable number string - */ -export const toReadable = (value: number): string => value.toLocaleString(DEFAULT_LOCALE) diff --git a/src/strings/capitalize.ts b/src/string/capitalize.ts similarity index 100% rename from src/strings/capitalize.ts rename to src/string/capitalize.ts diff --git a/src/strings/getObjectLength.ts b/src/string/getObjectLength.ts similarity index 100% rename from src/strings/getObjectLength.ts rename to src/string/getObjectLength.ts diff --git a/src/strings/index.ts b/src/string/index.ts similarity index 100% rename from src/strings/index.ts rename to src/string/index.ts diff --git a/src/strings/isArray.ts b/src/string/isArray.ts similarity index 100% rename from src/strings/isArray.ts rename to src/string/isArray.ts diff --git a/src/strings/isEmptyArray.ts b/src/string/isEmptyArray.ts similarity index 100% rename from src/strings/isEmptyArray.ts rename to src/string/isEmptyArray.ts diff --git a/src/strings/isEmptyObject.ts b/src/string/isEmptyObject.ts similarity index 100% rename from src/strings/isEmptyObject.ts rename to src/string/isEmptyObject.ts diff --git a/src/strings/isEmptyString.ts b/src/string/isEmptyString.ts similarity index 100% rename from src/strings/isEmptyString.ts rename to src/string/isEmptyString.ts diff --git a/src/strings/isIncluded.ts b/src/string/isIncluded.ts similarity index 100% rename from src/strings/isIncluded.ts rename to src/string/isIncluded.ts diff --git a/src/strings/isNull.ts b/src/string/isNull.ts similarity index 100% rename from src/strings/isNull.ts rename to src/string/isNull.ts diff --git a/src/strings/isObject.ts b/src/string/isObject.ts similarity index 100% rename from src/strings/isObject.ts rename to src/string/isObject.ts diff --git a/src/strings/isUndefined.ts b/src/string/isUndefined.ts similarity index 100% rename from src/strings/isUndefined.ts rename to src/string/isUndefined.ts diff --git a/src/strings/notEmptyArray.ts b/src/string/notEmptyArray.ts similarity index 100% rename from src/strings/notEmptyArray.ts rename to src/string/notEmptyArray.ts diff --git a/src/strings/notEmptyObject.ts b/src/string/notEmptyObject.ts similarity index 100% rename from src/strings/notEmptyObject.ts rename to src/string/notEmptyObject.ts diff --git a/src/strings/notNullOrUndefined.ts b/src/string/notNullOrUndefined.ts similarity index 100% rename from src/strings/notNullOrUndefined.ts rename to src/string/notNullOrUndefined.ts diff --git a/src/string/pluralize.ts b/src/string/pluralize.ts new file mode 100644 index 0000000..a12a807 --- /dev/null +++ b/src/string/pluralize.ts @@ -0,0 +1,14 @@ +import { toReadable } from '../number/toReadable.ts' + +/** + * Coverts the given number to a readable value with a description term. + * + * @param {number} count - The number to be used. + * @param {string} singular - The singular term, if the number is 1. + * @param {string} plural - The plural term, if the number is not 1. Optional. If not provided the singular term is used with an `s` appended. + * @returns {string} - The pluralized string. + */ +export const pluralize = (count: number, singular: string, plural?: string): string => { + const term = count === 1 ? singular : (plural ?? `${singular}s`) + return `${toReadable(count)} ${term}` +} diff --git a/src/strings/removeDoubleSpaces.ts b/src/string/removeDoubleSpaces.ts similarity index 100% rename from src/strings/removeDoubleSpaces.ts rename to src/string/removeDoubleSpaces.ts diff --git a/src/strings/toHex.ts b/src/string/toHex.ts similarity index 100% rename from src/strings/toHex.ts rename to src/string/toHex.ts diff --git a/src/strings/pluralize.ts b/src/strings/pluralize.ts deleted file mode 100644 index 2b0bdea..0000000 --- a/src/strings/pluralize.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { toReadable } from '../numbers/toReadable.ts' - -/** - * Covert a number to a readable value with a description term. - * - * @param {number} count - The number to be used. - * @param singular - The singular term, if the number is 1. - * @param plural - The plural term, if the number is not 1. Optional. If not provided the singular term is used with an `s` appended. - * @returns {string} - The pluralized string. - */ -export const pluralize = (count: number, singular: string, plural?: string): string => { - const term = count === 1 ? singular : (plural ?? `${singular}s`) - return `${toReadable(count)} ${term}` -} diff --git a/tests/ard.test.bun.ts b/tests/ard.test.bun.ts index d73f90c..7d01f99 100644 --- a/tests/ard.test.bun.ts +++ b/tests/ard.test.bun.ts @@ -1,5 +1,6 @@ /** * @fileoverview A port of the ard test to bun using bun's `expect` (that behaves like jest). + * NOTE: This file cannot be run in nodejs, since node does not know `bun:test`. */ import { describe, expect, it } from 'bun:test' import { createHashedId } from '../src/ard/index.ts' diff --git a/tests/date.test.ts b/tests/date.test.ts index 2ec7806..d134569 100644 --- a/tests/date.test.ts +++ b/tests/date.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert' import { describe, it } from 'node:test' -import * as date from '../src/dates/index.ts' +import * as date from '../src/date/index.ts' const ONE_YEAR_IN_MS = 1000 * 60 * 60 * 24 * 365 const testDate = '2038-01-19T03:14:08.000' diff --git a/tests/date.utils.test.ts b/tests/date.utils.test.ts index b0cdb6c..2de7b34 100644 --- a/tests/date.utils.test.ts +++ b/tests/date.utils.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert' import { describe, test } from 'node:test' -import { formatDateString, formatDateTimeString } from '../src/dates/utils.ts' +import { formatDateString, formatDateTimeString } from '../src/date/utils.ts' /** german formatted date string */ const date = 'Mo., 19. Januar 2038 um 14:08' diff --git a/tests/numbers.test.ts b/tests/number.test.ts similarity index 55% rename from tests/numbers.test.ts rename to tests/number.test.ts index 730bfc6..c3c3533 100644 --- a/tests/numbers.test.ts +++ b/tests/number.test.ts @@ -1,131 +1,131 @@ import assert from 'node:assert' import { describe, it } from 'node:test' -import * as numbers from '../src/numbers/index.ts' +import * as number from '../src/number/index.ts' describe('Test Numbers Package', () => { describe('Test addLeadingZero', () => { it("addLeadingZero(1) = '01'", () => { - assert.equal(numbers.addLeadingZero(1), '01') + assert.equal(number.addLeadingZero(1), '01') }) it("addLeadingZero(10) = '10'", () => { - assert.equal(numbers.addLeadingZero(10), '10') + assert.equal(number.addLeadingZero(10), '10') }) }) describe('Test addTrailingZeros', () => { it("addTrailingZeros(1, 5) = '1.00000'", () => { - assert.equal(numbers.addTrailingZeros(1, 5), '1.00000') + assert.equal(number.addTrailingZeros(1, 5), '1.00000') }) it("addTrailingZeros(1.1, 5) = '1.10000'", () => { - assert.equal(numbers.addTrailingZeros(1.1, 5), '1.10000') + assert.equal(number.addTrailingZeros(1.1, 5), '1.10000') }) it("addTrailingZeros('1.2', 5) = '1.20000'", () => { - assert.equal(numbers.addTrailingZeros('1.2', 5), '1.20000') + assert.equal(number.addTrailingZeros('1.2', 5), '1.20000') }) it("addTrailingZeros(2, 2, ',') = '2,00'", () => { - assert.equal(numbers.addTrailingZeros(2, 2, ','), '2,00') + assert.equal(number.addTrailingZeros(2, 2, ','), '2,00') }) it("addTrailingZeros(2.1, 2, ',') = '2,10'", () => { - assert.equal(numbers.addTrailingZeros(2.1, 2, ','), '2,10') + assert.equal(number.addTrailingZeros(2.1, 2, ','), '2,10') }) it("addTrailingZeros('2,2', 2, ','') = '2,20'", () => { - assert.equal(numbers.addTrailingZeros('2,2', 2, ','), '2,20') + assert.equal(number.addTrailingZeros('2,2', 2, ','), '2,20') }) }) describe('Test getAverage', () => { it('getAverage([1, 2, 3]) = 2', () => { - assert.equal(numbers.getAverage([1, 2, 3]), 2) + assert.equal(number.getAverage([1, 2, 3]), 2) }) it('getAverage([1.2, 2.4, 3.6], 1) = 2.4', () => { - assert.equal(numbers.getAverage([1.2, 2.4, 3.6], 1), 2.4) + assert.equal(number.getAverage([1.2, 2.4, 3.6], 1), 2.4) }) }) describe('Test getDiff', () => { it('getDiff(2, 1) = 1', () => { - assert.equal(numbers.getDiff(2, 1), 1) + assert.equal(number.getDiff(2, 1), 1) }) it('getDiff(1, 2) = -1', () => { - assert.equal(numbers.getDiff(1, 2), -1) + assert.equal(number.getDiff(1, 2), -1) }) }) describe('Test getRandomInRange', () => { it('getRandomInRange(1, 5) = 1,2,3,4 or 5', () => { - assert([1, 2, 3, 4, 5].includes(numbers.getRandomInRange(1, 5))) + assert([1, 2, 3, 4, 5].includes(number.getRandomInRange(1, 5))) }) it('getRandomInRange(5, 9) = 5,6,7,8 or 9', () => { - assert([5, 6, 7, 8, 9].includes(numbers.getRandomInRange(5, 9))) + assert([5, 6, 7, 8, 9].includes(number.getRandomInRange(5, 9))) }) }) describe('Test getSum', () => { it('getSum([1, 2, 3]) = 6', () => { - assert.equal(numbers.getSum([1, 2, 3]), 6) + assert.equal(number.getSum([1, 2, 3]), 6) }) it('getSum([1.2, 2.4, 3.6], 1) = 7.2', () => { - assert.equal(numbers.getSum([1.2, 2.4, 3.6], 1), 7.2) + assert.equal(number.getSum([1.2, 2.4, 3.6], 1), 7.2) }) }) describe('Test isEven', () => { it('isEven(2) = true', () => { - assert.equal(numbers.isEven(2), true) + assert.equal(number.isEven(2), true) }) it('isEven(1) = false', () => { - assert.equal(numbers.isEven(1), false) + assert.equal(number.isEven(1), false) }) }) describe('Test normalize', () => { it('normalize(2, 100) = 0.02', () => { - assert.equal(numbers.normalize(2, 100), 0.02) + assert.equal(number.normalize(2, 100), 0.02) }) it('normalize(80, 100) = 0.8', () => { - assert.equal(numbers.normalize(80, 100), 0.8) + assert.equal(number.normalize(80, 100), 0.8) }) }) describe('Test roundTo', () => { it('roundTo(1.23456) = 1.23', () => { - assert.equal(numbers.roundTo(1.23456), 1.23) + assert.equal(number.roundTo(1.23456), 1.23) }) it('roundTo(1.23456, 4) = 1.2346', () => { - assert.equal(numbers.roundTo(1.23456, 4), 1.2346) + assert.equal(number.roundTo(1.23456, 4), 1.2346) }) it('roundTo(234.23456, 4) = 234.2346', () => { - assert.equal(numbers.roundTo(234.23456, 4), 234.2346) + assert.equal(number.roundTo(234.23456, 4), 234.2346) }) it('roundTo(234.2345671, 4) = 234.2346', () => { - assert.equal(numbers.roundTo(234.2345671, 4), 234.2346) + assert.equal(number.roundTo(234.2345671, 4), 234.2346) }) it('roundTo(234.2344671, 3) = 234.234', () => { - assert.equal(numbers.roundTo(234.2344671, 3), 234.234) + assert.equal(number.roundTo(234.2344671, 3), 234.234) }) it('roundTo(234.2343671, 3) = 234.234', () => { - assert.equal(numbers.roundTo(234.2343671, 3), 234.234) + assert.equal(number.roundTo(234.2343671, 3), 234.234) }) }) describe('Test toReadable', () => { it("toReadable(1234567) = '1.234.567'", () => { - assert.equal(numbers.toReadable(1234567), '1.234.567') + assert.equal(number.toReadable(1234567), '1.234.567') }) }) }) diff --git a/tests/strings.test.ts b/tests/string.test.ts similarity index 98% rename from tests/strings.test.ts rename to tests/string.test.ts index 67aac49..13bef5c 100644 --- a/tests/strings.test.ts +++ b/tests/string.test.ts @@ -1,7 +1,7 @@ import assert from 'node:assert' import { describe, it, test } from 'node:test' -import * as strings from '../src/strings/index.ts' -import { capitalize } from '../src/strings/index.ts' +import * as strings from '../src/string/index.ts' +import { capitalize } from '../src/string/index.ts' describe('Test Strings Package', () => { describe('Test capitalize', () => { From 7328bd963a5c3b9a544ccae230eb8f60ad9ff4c9 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Sat, 6 Sep 2025 18:02:58 +0200 Subject: [PATCH 15/42] chore: upgrade dependencies --- bun.lock | 86 +++++++++++++++++++----------------------------- package.json | 10 +++--- tsdown.config.ts | 4 ++- 3 files changed, 41 insertions(+), 59 deletions(-) diff --git a/bun.lock b/bun.lock index 1a0be38..16d348c 100644 --- a/bun.lock +++ b/bun.lock @@ -3,17 +3,17 @@ "workspaces": { "": { "dependencies": { - "@google-cloud/storage": "^7.16.0", + "@google-cloud/storage": "^7.17.0", "abort-controller": "^3.0.0", - "luxon": "3.7.1", + "luxon": "3.7.2", "node-crc": "https://github.com/swrlab/node-crc#v2.1.0", - "undici": "7.13.0", + "undici": "7.15.0", }, "devDependencies": { "@swrlab/style-guide": "^2.0.7", "@types/bun": "^1.2.21", "@types/luxon": "^3.7.1", - "eslint": "^9.34.0", + "eslint": "^9.35.0", "prettier": "^3.6.2", "tsdown": "^0.14.2", "typescript": "^5.9.2", @@ -41,7 +41,7 @@ "@eslint-community/eslint-plugin-eslint-comments": ["@eslint-community/eslint-plugin-eslint-comments@4.5.0", "", { "dependencies": { "escape-string-regexp": "^4.0.0", "ignore": "^5.2.4" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-MAhuTKlr4y/CE3WYX26raZjy+I/kS2PLKSzvfmDCGrBLTFHOYwqROZdr4XwPgXwX3K9rjzMr4pSmUWGnzsUyMg=="], - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA=="], + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], @@ -69,7 +69,7 @@ "@google-cloud/promisify": ["@google-cloud/promisify@4.0.0", "", {}, "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g=="], - "@google-cloud/storage": ["@google-cloud/storage@7.16.0", "", { "dependencies": { "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", "@google-cloud/promisify": "<4.1.0", "abort-controller": "^3.0.0", "async-retry": "^1.3.3", "duplexify": "^4.1.3", "fast-xml-parser": "^4.4.1", "gaxios": "^6.0.2", "google-auth-library": "^9.6.3", "html-entities": "^2.5.2", "mime": "^3.0.0", "p-limit": "^3.0.1", "retry-request": "^7.0.0", "teeny-request": "^9.0.0", "uuid": "^8.0.0" } }, "sha512-7/5LRgykyOfQENcm6hDKP8SX/u9XxE5YOiWOkgkwcoO+cG8xT/cyOvp9wwN3IxfdYgpHs8CE7Nq2PKX2lNaEXw=="], + "@google-cloud/storage": ["@google-cloud/storage@7.17.0", "", { "dependencies": { "@google-cloud/paginator": "^5.0.0", "@google-cloud/projectify": "^4.0.0", "@google-cloud/promisify": "<4.1.0", "abort-controller": "^3.0.0", "async-retry": "^1.3.3", "duplexify": "^4.1.3", "fast-xml-parser": "^4.4.1", "gaxios": "^6.0.2", "google-auth-library": "^9.6.3", "html-entities": "^2.5.2", "mime": "^3.0.0", "p-limit": "^3.0.1", "retry-request": "^7.0.0", "teeny-request": "^9.0.0", "uuid": "^8.0.0" } }, "sha512-5m9GoZqKh52a1UqkxDBu/+WVFDALNtHg5up5gNmNbXQWBcV813tzJKsyDtKjOPrlR1em1TxtD7NSPCrObH7koQ=="], "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], @@ -145,7 +145,7 @@ "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], - "@types/estree": ["@types/estree@1.0.6", "", {}, "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="], + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], @@ -315,7 +315,7 @@ "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], - "debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="], @@ -353,7 +353,7 @@ "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - "eslint": ["eslint@9.34.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.34.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg=="], + "eslint": ["eslint@9.35.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.1", "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.35.0", "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg=="], "eslint-compat-utils": ["eslint-compat-utils@0.6.5", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-vAUHYzue4YAa2hNACjB8HvUQj5yehAZgiClyFVVom9cP8z5NSFq3PwB/TtJslN2zAMgRX6FCFCjYBbQh71g5RQ=="], @@ -551,7 +551,7 @@ "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], - "luxon": ["luxon@3.7.1", "", {}, "sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg=="], + "luxon": ["luxon@3.7.2", "", {}, "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew=="], "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], @@ -811,7 +811,7 @@ "unconfig": ["unconfig@7.3.3", "", { "dependencies": { "@quansync/fs": "^0.1.5", "defu": "^6.1.4", "jiti": "^2.5.1", "quansync": "^0.2.11" } }, "sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA=="], - "undici": ["undici@7.13.0", "", {}, "sha512-l+zSMssRqrzDcb3fjMkjjLGmuiiK2pMIcV++mJaAc9vhjSGpvM7h43QgP+OAMb1GImHmbPyG2tBXeuyG5iY4gA=="], + "undici": ["undici@7.15.0", "", {}, "sha512-7oZJCPvvMvTd0OlqWsIxTuItTpJBpU1tcbVl24FMn3xt3+VSunwUasmfPJRE57oNO1KsZ4PgA1xTdAX4hq8NyQ=="], "undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], @@ -855,10 +855,12 @@ "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], - "@es-joy/jsdoccomment/@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], - "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@eslint/config-array/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], + + "@eslint/eslintrc/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], + "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], @@ -867,54 +869,38 @@ "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - "@typescript-eslint/parser/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - - "@typescript-eslint/project-service/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - - "@typescript-eslint/type-utils/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - - "@typescript-eslint/typescript-estree/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], - "@typescript-eslint/utils/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], - "@unrs/resolver-binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], + "agent-base/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], + "bun-types/@types/node": ["@types/node@22.9.0", "", { "dependencies": { "undici-types": "~6.19.8" } }, "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ=="], "clean-regexp/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], + "eslint/@eslint/js": ["@eslint/js@9.35.0", "", {}, "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw=="], + "eslint-import-context/get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], - "eslint-plugin-es-x/eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="], + "eslint-plugin-es-x/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA=="], - "eslint-plugin-import-x/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "eslint-plugin-es-x/eslint-compat-utils": ["eslint-compat-utils@0.5.1", "", { "dependencies": { "semver": "^7.5.4" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q=="], "eslint-plugin-import-x/minimatch": ["minimatch@10.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="], - "eslint-plugin-jsdoc/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - - "eslint-plugin-jsonc/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], - - "eslint-plugin-n/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], - "eslint-plugin-n/globals": ["globals@15.12.0", "", {}, "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ=="], - "eslint-plugin-regexp/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], - "eslint-plugin-sonarjs/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "eslint-plugin-sonarjs/typescript": ["typescript@5.6.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw=="], - "eslint-plugin-unicorn/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.8.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-MJQFqrZgcW0UNYLGOuQpey/oTN59vyWwplvCGZztn1cKz9agZPPYpJB7h2OMmuu7VLqkvEjN8feFZJmxNF9D+Q=="], + "eslint-plugin-vue/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA=="], "eslint-plugin-vue/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], "eslint-plugin-vuejs-accessibility/vue-eslint-parser": ["vue-eslint-parser@9.4.3", "", { "dependencies": { "debug": "^4.3.4", "eslint-scope": "^7.1.1", "eslint-visitor-keys": "^3.3.0", "espree": "^9.3.1", "esquery": "^1.4.0", "lodash": "^4.17.21", "semver": "^7.3.6" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg=="], - "eslint-plugin-yml/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "espree/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], @@ -923,6 +909,10 @@ "http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + "http-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], + + "https-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], + "is-builtin-module/builtin-modules": ["builtin-modules@5.0.0", "", {}, "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg=="], "jsonc-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -935,8 +925,6 @@ "mdast-util-frontmatter/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], - "micromark/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "mlly/acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], @@ -945,18 +933,12 @@ "regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], - "rolldown-plugin-dts/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "rolldown-plugin-dts/get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], "teeny-request/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], "teeny-request/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], - "tsdown/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - - "vue-eslint-parser/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "vue-eslint-parser/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], "yaml-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -965,23 +947,19 @@ "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "@typescript-eslint/utils/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "bun-types/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], + "eslint-plugin-es-x/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "eslint-plugin-es-x/eslint-compat-utils/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], "eslint-plugin-import-x/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "eslint-plugin-jsonc/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "eslint-plugin-n/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - - "eslint-plugin-regexp/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "eslint-plugin-sonarjs/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], - "eslint-plugin-unicorn/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "eslint-plugin-vue/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "eslint-plugin-vuejs-accessibility/vue-eslint-parser/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], "eslint-plugin-vuejs-accessibility/vue-eslint-parser/eslint-scope": ["eslint-scope@7.2.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg=="], @@ -994,5 +972,7 @@ "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], "teeny-request/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "teeny-request/https-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], } } diff --git a/package.json b/package.json index fbc66e3..190528e 100644 --- a/package.json +++ b/package.json @@ -38,17 +38,17 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@google-cloud/storage": "^7.16.0", + "@google-cloud/storage": "^7.17.0", "abort-controller": "^3.0.0", - "luxon": "3.7.1", + "luxon": "3.7.2", "node-crc": "https://github.com/swrlab/node-crc#v2.1.0", - "undici": "7.13.0" + "undici": "7.15.0" }, "devDependencies": { "@swrlab/style-guide": "^2.0.7", "@types/bun": "^1.2.21", "@types/luxon": "^3.7.1", - "eslint": "^9.34.0", + "eslint": "^9.35.0", "prettier": "^3.6.2", "tsdown": "^0.14.2", "typescript": "^5.9.2" @@ -65,7 +65,7 @@ } }, "engines": { - "node": ">=20 || ^22.18.0 || ^24.6.0" + "node": "^22.18.0 || ^24.6.0" }, "prettier": "@swrlab/style-guide/prettier.js" } diff --git a/tsdown.config.ts b/tsdown.config.ts index 36a0514..43c624b 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -4,6 +4,8 @@ export default defineConfig({ entry: { index: 'src/index.ts', ard: 'src/ard/index.ts', - dates: 'src/dates/index.ts', + dates: 'src/date/index.ts', + string: 'src/string/index.ts', + number: 'src/number/index.ts', }, }) From e16752d3735bd3ed98888bb5a93b2f2c6c5aa398 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Sat, 6 Sep 2025 23:54:37 +0200 Subject: [PATCH 16/42] refact(storage): migrate all storage utils --- packages/storage-wrapper/createUri.js | 18 ---- packages/storage-wrapper/createUrl.js | 35 ------- packages/storage-wrapper/delete.js | 39 -------- packages/storage-wrapper/index.js | 36 ------- packages/storage-wrapper/list.js | 36 ------- packages/storage-wrapper/load.js | 52 ---------- packages/storage-wrapper/move.js | 42 -------- packages/storage-wrapper/save.js | 70 ------------- src/storage/createUri.ts | 23 +++++ src/storage/createUrl.ts | 0 src/storage/delete.ts | 0 src/storage/google.ts | 115 +++++++++++++++++++++ src/storage/index.ts | 137 ++++++++++++++++++++++++++ src/storage/list.ts | 0 src/storage/load.ts | 0 src/storage/local.ts | 13 +++ src/storage/move.ts | 0 src/storage/save.ts | 0 src/storage/utils.ts | 62 ++++++++++++ tests/storage/utils.test.ts | 50 ++++++++++ 20 files changed, 400 insertions(+), 328 deletions(-) delete mode 100644 packages/storage-wrapper/createUri.js delete mode 100644 packages/storage-wrapper/createUrl.js delete mode 100644 packages/storage-wrapper/delete.js delete mode 100644 packages/storage-wrapper/index.js delete mode 100644 packages/storage-wrapper/list.js delete mode 100644 packages/storage-wrapper/load.js delete mode 100644 packages/storage-wrapper/move.js delete mode 100644 packages/storage-wrapper/save.js create mode 100644 src/storage/createUri.ts create mode 100644 src/storage/createUrl.ts create mode 100644 src/storage/delete.ts create mode 100644 src/storage/google.ts create mode 100644 src/storage/index.ts create mode 100644 src/storage/list.ts create mode 100644 src/storage/load.ts create mode 100644 src/storage/local.ts create mode 100644 src/storage/move.ts create mode 100644 src/storage/save.ts create mode 100644 src/storage/utils.ts create mode 100644 tests/storage/utils.test.ts diff --git a/packages/storage-wrapper/createUri.js b/packages/storage-wrapper/createUri.js deleted file mode 100644 index 9d0340b..0000000 --- a/packages/storage-wrapper/createUri.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - - node-storage-wrapper - - This module provides easy access to combine bucket + path to unique URIs - -*/ - -module.exports = { - s3: (bucket, path) => { - // return data - return ['s3:/', bucket, path].join('/') - }, - gs: (bucket, path) => { - // return data - return ['gs:/', bucket, path].join('/') - }, -} diff --git a/packages/storage-wrapper/createUrl.js b/packages/storage-wrapper/createUrl.js deleted file mode 100644 index ad3eb36..0000000 --- a/packages/storage-wrapper/createUrl.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - - node-storage-wrapper - - This module provides easy access to combine bucket + path to unique URIs - -*/ - -module.exports = async function (uri, ttl) { - if (uri.substr(0, 5).toLowerCase() === 'gs://') { - // google cloud storage - const structure = uri.substr(5).split('/') - const bucket = structure.shift() - const path = structure.join('/') - - // set config - const config = { - action: 'read', - expires: Date.now() + ttl, - } - - // create link - const [url] = await this.sdk.gs.bucket(bucket).file(path).getSignedUrl(config) - - // return link - return Promise.resolve(url) - } - - if (uri.substr(0, 7).toLowerCase() === 'http://' || uri.substr(0, 8).toLowerCase() === 'https://') { - // return link - return Promise.resolve(uri) - } - - return Promise.reject(new Error('not implemented')) -} diff --git a/packages/storage-wrapper/delete.js b/packages/storage-wrapper/delete.js deleted file mode 100644 index 991f71f..0000000 --- a/packages/storage-wrapper/delete.js +++ /dev/null @@ -1,39 +0,0 @@ -/* - - node-storage-wrapper - -*/ - -const deleteLocalFile = (that, filePath) => - new Promise((resolve, reject) => { - that.sdk.fs.unlink(filePath, (err) => { - if (err) reject(err) - else resolve() - }) - }) - -module.exports = async function (uri) { - if (uri.substr(0, 5).toLowerCase() === 'gs://') { - // google cloud storage - const structure = uri.substr(5).split('/') - const bucket = structure.shift() - const path = structure.join('/') - - // delete from gcp - await this.sdk.gs.bucket(bucket).file(path).delete(path) - - // return ok - return Promise.resolve() - } - - if (uri.substr(0, 7).toLowerCase() === 'http://' || uri.substr(0, 8).toLowerCase() === 'https://') { - // return ok - return Promise.resolve() - } - - // delete file - await deleteLocalFile(this, uri) - - // return ok - return Promise.resolve() -} diff --git a/packages/storage-wrapper/index.js b/packages/storage-wrapper/index.js deleted file mode 100644 index 362e0c4..0000000 --- a/packages/storage-wrapper/index.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - - node-storage-wrapper - -*/ - -// load node utils -const fs = require('node:fs') -const { Storage } = require('@google-cloud/storage') - -// create wrapper -function StorageWrapper(config) { - // check config - if (!config || !config.gs) return Promise.reject(new Error('storage config invalid')) - - // enable SDKs - this.sdk = {} - - // load node utils - this.sdk.fs = fs - - // load google cloud storage sdk - this.sdk.gs = new Storage(config.gs) - - // import functions - this.createUri = require('./createUri') - this.createUrl = require('./createUrl') - this.delete = require('./delete') - this.list = require('./list') - this.load = require('./load') - this.move = require('./move') - this.save = require('./save') -} - -// export -module.exports = StorageWrapper diff --git a/packages/storage-wrapper/list.js b/packages/storage-wrapper/list.js deleted file mode 100644 index c7a3158..0000000 --- a/packages/storage-wrapper/list.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - - node-storage-wrapper - -*/ - -const listLocalFiles = (that, uri) => - new Promise((resolve, reject) => { - that.sdk.fs.readdir(uri, 'utf8', (err, data) => { - if (err) reject(err) - else resolve(data) - }) - }) - -module.exports = async function (uri) { - if (uri.substr(0, 5).toLowerCase() === 'gs://') { - // google cloud storage - const structure = uri.substr(5).split('/') - const bucket = structure.shift() - const path = structure.join('/') - - // load file - const file = await this.sdk.gs.bucket(bucket).getFiles({ - prefix: path, - }) - - // return list - return Promise.resolve(file[0]) - } - - // local file - const file = await listLocalFiles(this, uri) - - // return list - return Promise.resolve(file) -} diff --git a/packages/storage-wrapper/load.js b/packages/storage-wrapper/load.js deleted file mode 100644 index e38c3f8..0000000 --- a/packages/storage-wrapper/load.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - - node-storage-wrapper - -*/ - -// load node utils -const undici = require('../../utils/undici') - -const loadLocalFile = (that, uri) => - new Promise((resolve, reject) => { - that.sdk.fs.readFile(uri, (err, data) => { - if (err) reject(err) - else resolve(data) - }) - }) - -module.exports = async function (uri, _logPrefix, options) { - if (uri.substr(0, 5).toLowerCase() === 'gs://') { - // google cloud storage - const structure = uri.substr(5).split('/') - const bucket = structure.shift() - const path = structure.join('/') - - // load file - const file = await this.sdk.gs.bucket(bucket).file(path).download() - - // return file - return Promise.resolve(file[0]) - } - - if (uri.substr(0, 7).toLowerCase() === 'http://' || uri.substr(0, 8).toLowerCase() === 'https://') { - // public http(s) endpoint - const file = await undici(uri, { - timeout: options?.timeout, - method: 'GET', - headers: { 'User-Agent': 'node-storage-wrapper' }, - }) - - if (file.ok) { - return Promise.resolve(file.buffer) - } - - return Promise.reject(new Error(`fetching url failed with status > ${file.statusCode}`)) - } - - // local file - const file = await loadLocalFile(this, uri) - - // return file - return Promise.resolve(file) -} diff --git a/packages/storage-wrapper/move.js b/packages/storage-wrapper/move.js deleted file mode 100644 index c7b212b..0000000 --- a/packages/storage-wrapper/move.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - - node-storage-wrapper - -*/ - -module.exports = async function (sourceUri, destinationUri, keepOriginal) { - if (sourceUri.substr(0, 5).toLowerCase() === 'gs://' && destinationUri.substr(0, 5).toLowerCase() === 'gs://') { - // google to google transfer - - // parse source - const structure = sourceUri.substr(5).split('/') - const bucket = structure.shift() - const path = structure.join('/') - - // move file within gcs - if (keepOriginal !== true) { - // move file - await this.sdk.gs.bucket(bucket).file(path).move(destinationUri) - } else { - // copy file - await this.sdk.gs.bucket(bucket).file(path).copy(destinationUri) - } - - // return ok - return Promise.resolve() - } - - // download file - const blob = await this.load(sourceUri) - - // save file to destination - await this.save(destinationUri, blob) - - // delete file if in production - if (keepOriginal !== true) { - await this.delete(sourceUri) - } - - // return ok - return Promise.resolve() -} diff --git a/packages/storage-wrapper/save.js b/packages/storage-wrapper/save.js deleted file mode 100644 index 640c2c7..0000000 --- a/packages/storage-wrapper/save.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - - node-storage-wrapper - -*/ - -// load node utils -const os = require('node:os') -const pathUtil = require('node:path') -const { randomUUID } = require('node:crypto') - -const saveLocalFile = (that, uri, buffer) => - new Promise((resolve, reject) => { - that.sdk.fs.writeFile(uri, buffer, (err) => { - if (err) reject(err) - else resolve() - }) - }) - -const deleteLocalFile = (that, filePath) => - new Promise((resolve, reject) => { - that.sdk.fs.unlink(filePath, (err) => { - if (err) reject(err) - else resolve() - }) - }) - -module.exports = async function (uri, buffer, _logPrefix, resumable) { - let structure, bucket, path - - if (uri.substr(0, 5).toLowerCase() === 'gs://') { - // google cloud storage - structure = uri.substr(5).split('/') - bucket = structure.shift() - path = structure.join('/') - - // save to local file - const tempFilePath = pathUtil.resolve(os.tmpdir(), randomUUID()) - await saveLocalFile(this, tempFilePath, buffer) - - // create default bucket config - const bucketConfig = { - gzip: false, - destination: path, - metadata: {}, - } - - // update bucket config with resumable flag if set - if (resumable !== undefined && resumable !== null) { - bucketConfig.resumable = resumable - } - - // upload file to gcs - await this.sdk.gs.bucket(bucket).upload(tempFilePath, bucketConfig) - - // delete local temp file - await deleteLocalFile(this, tempFilePath) - - // return ok - return Promise.resolve() - } - - // local file - - // save file - const file = await saveLocalFile(this, uri, buffer) - - // return ok - return Promise.resolve(file) -} diff --git a/src/storage/createUri.ts b/src/storage/createUri.ts new file mode 100644 index 0000000..135b998 --- /dev/null +++ b/src/storage/createUri.ts @@ -0,0 +1,23 @@ +/** + * @fileoverview This module provides easy access to combine bucket + path to unique URIs. + * @module storage + */ + +export type CloudStorageURI = { + type: 's3' | 'gs' + bucket: string + path: string +} + +export const s3 = (bucket: string, path: string): CloudStorageURI => ({ type: 's3', bucket, path }) + +export const gs = (bucket: string, path: string): CloudStorageURI => ({ type: 'gs', bucket, path }) + +type S3Uri = `s3:/${B}${P}` +type GoogleStorageUri = `s3:/${B}${P}` + +export const s3Legacy = (bucket: B, path: P): S3Uri => + ['s3:/', bucket, path].join('/') as S3Uri + +export const gsLegacy = (bucket: B, path: P): GoogleStorageUri => + ['gs:/', bucket, path].join('/') as GoogleStorageUri diff --git a/src/storage/createUrl.ts b/src/storage/createUrl.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/storage/delete.ts b/src/storage/delete.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/storage/google.ts b/src/storage/google.ts new file mode 100644 index 0000000..70dd48b --- /dev/null +++ b/src/storage/google.ts @@ -0,0 +1,115 @@ +import type { Bucket, File, GetSignedUrlConfig, StorageOptions, UploadOptions } from '@google-cloud/storage' +import type { Buffer } from 'node:buffer' +import type { CloudStorageUrl } from './utils.ts' +import { Storage } from '@google-cloud/storage' + +let storage: Storage | undefined = undefined + +const parseURI = (uri: string): { bucket: string; file: string } => { + const structure = uri.slice(5).split('/') + const bucket = structure.shift() as string + const file = structure.join('/') + // version 2 (might be better) + // const url = new URL(uri) + // const bucket = url.hostname + // const file = url.pathname + return { bucket, file } +} + +const getBucket = (uri: string): Bucket => { + if (!storage) { + throw new Error('Storage instance is missing') + } + const { bucket } = parseURI(uri) + return storage.bucket(bucket) +} + +const getFile = (uri: string): File => { + if (!storage) { + throw new Error('Storage instance is missing') + } + const { bucket, file } = parseURI(uri) + return storage.bucket(bucket).file(file) +} + +// Public API: + +export const initialize = (config: StorageOptions): void => { + storage = new Storage(config) +} + +export const createSignedUrl = async (uri: string, ttl: number): Promise => { + // assert(storage, 'Storage must be initialized before') + if (!storage) { + throw new Error('Storage instance is missing') + } + // const structure = inputUrl.slice(5).split('/') + // const bucket = structure.shift() as string + // const path = structure.join('/') + + const config: GetSignedUrlConfig = { + action: 'read', + expires: Date.now() + ttl, + } + const [signedUrl] = await getFile(uri).getSignedUrl(config) + return signedUrl +} + +export const deleteFile = async (uri: string): Promise => { + await getFile(uri).delete() +} + +export const listFiles = async (uri: string): Promise => { + const [list] = await getBucket(uri).getFiles({ + prefix: parseURI(uri).file, + }) + return list +} + +/** + * Download file from Google Storage. + * + * @param {string} uri - The Google Storage URI to be downloaded. + * @returns Contents of the file. + */ +export const download = async (uri: string): Promise> => { + const [contents] = await getFile(uri).download() + return contents +} + +export const move = async ( + sourceUri: CloudStorageUrl, + destinationUri: CloudStorageUrl, + keepOriginal: boolean = false +): Promise => { + const source = getFile(sourceUri) + if (keepOriginal === true) { + // copy only, if the original file should be kept. + await source.copy(destinationUri) + return + } + // otherwise move the file within GCS. + await source.move(destinationUri) +} + +/** + * Upload the file to Google Cloud Storage (GCS). + * + * @param {string} uri - The Google Storage URI to the uploaded file. + * @param {string} filePath - Full path to the file to be uploaded. + * @param {boolean} resumable - Set to `true` if the upload should be resumable. + */ +export const upload = async (uri: string, filePath: string, resumable?: boolean): Promise => { + const destination = parseURI(uri).file + const options: UploadOptions = { + gzip: false, + destination, + metadata: {}, + } + + if (resumable !== undefined) { + options.resumable = resumable + } + + await getBucket(uri).upload(filePath, options) +} diff --git a/src/storage/index.ts b/src/storage/index.ts new file mode 100644 index 0000000..7f78ae9 --- /dev/null +++ b/src/storage/index.ts @@ -0,0 +1,137 @@ +import type { File } from '@google-cloud/storage' +/** + * @fileoverview API for Storage. + */ +import type { Buffer } from 'node:buffer' +import type { StorageConfig, StorageWrapperInstance } from './utils.ts' +import { randomUUID } from 'node:crypto' +import os from 'node:os' +import path from 'node:path' +import * as createUri from './createUri.ts' +import * as google from './google.ts' +import * as localFs from './local.ts' +import { isCloudStorageUrl, isHttpUrl, validateUrl } from './utils.ts' + +const createUrl = async (url: string, ttl: number): Promise => { + validateUrl(url) + return isCloudStorageUrl(url) ? await google.createSignedUrl(url, ttl) : Promise.resolve(url) +} + +const deleteFile = async (url: string): Promise => { + if (isCloudStorageUrl(url)) { + await google.deleteFile(url) + } + // abort for http(s):// urls + if (isHttpUrl(url)) { + return + } + // here we should have a local path + await localFs.deleteFile(url) +} + +const list = async (url: string): Promise<(File | string)[]> => { + if (isCloudStorageUrl(url)) { + return await google.listFiles(url) + } + // abort for http(s):// urls + if (isHttpUrl(url)) { + return Promise.reject(new Error('http(s) urls are not supported for listing files')) + } + + return await localFs.listFiles(url) +} + +const fetchContents = async (url: string, timeout?: number): Promise => { + const requestInit: RequestInit = { + method: 'GET', + headers: { 'User-Agent': 'node-storage-wrapper' }, + } + if (timeout) { + requestInit.signal = AbortSignal.timeout(timeout) + } + const response = await fetch(url, requestInit) + + if (response.ok) { + return response.arrayBuffer() + } + + throw new Error(`fetching url failed with status > ${response.status}`) +} + +const load = async (uri: string): Promise | ArrayBufferLike | string> => { + if (isCloudStorageUrl(uri)) { + return await google.download(uri) + } + if (isHttpUrl(uri)) { + return fetchContents(uri) + } + + return await localFs.readFile(uri) +} + +const createTempFile = async (contents: any): Promise => { + const filePath = path.resolve(os.tmpdir(), randomUUID()) + await localFs.writeFile(filePath, contents) + return filePath +} + +const save = async ( + uri: string, + contents: Buffer | ArrayBufferLike | string, + _logPrefix?: string, + resumable?: boolean +): Promise => { + if (isCloudStorageUrl(uri)) { + const filePath = await createTempFile(contents) + await google.upload(uri, filePath, resumable) + await localFs.deleteFile(filePath) + } + if (isHttpUrl(uri)) { + return + } + localFs.writeFile(uri, contents.toString()) +} + +const move = async (sourceUri: string, destinationUri: string, keepOriginal: boolean = false): Promise => { + if (isCloudStorageUrl(sourceUri) && isCloudStorageUrl(destinationUri)) { + return await google.move(sourceUri, destinationUri, keepOriginal) + } + + // (down)load file (from web or local) + const blob = await load(sourceUri) + + // save file to destination + await save(destinationUri, blob) + + // delete file if in production + if (keepOriginal !== true) { + await deleteFile(sourceUri) + } +} + +// legacy export +/** + * Create a Google Cloud Storage Wrapper. + * @deprecated + * + * @param config - Storage Config. + * @returns A StorageWrapper + */ +export function StorageWrapper(config: StorageConfig): Promise | StorageWrapperInstance { + // TODO: just throw the Error and make an async function + if (!config || !config.gs) return Promise.reject(new Error('storage config invalid')) + + google.initialize(config.gs) + + const api: StorageWrapperInstance = { + createUri, + createUrl, + delete: deleteFile, + list, + load, + save, + move, + } + + return api +} diff --git a/src/storage/list.ts b/src/storage/list.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/storage/load.ts b/src/storage/load.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/storage/local.ts b/src/storage/local.ts new file mode 100644 index 0000000..3e926cd --- /dev/null +++ b/src/storage/local.ts @@ -0,0 +1,13 @@ +import fs from 'node:fs/promises' + +/* eslint-disable security/detect-non-literal-fs-filename -- it's assumed to be fine */ +export const deleteFile = async (filePath: string): Promise => await fs.unlink(filePath) + +export const listFiles = async (path: string): Promise => await fs.readdir(path, 'utf-8') + +export const readFile = async (uri: string): Promise => await fs.readFile(uri, 'utf-8') + +export const writeFile = async (uri: string, contents: string): Promise => + await fs.writeFile(uri, contents, 'utf-8') + +/* eslint-enable security/detect-non-literal-fs-filename -- let's run again */ diff --git a/src/storage/move.ts b/src/storage/move.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/storage/save.ts b/src/storage/save.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/storage/utils.ts b/src/storage/utils.ts new file mode 100644 index 0000000..fa9e9c3 --- /dev/null +++ b/src/storage/utils.ts @@ -0,0 +1,62 @@ +import type { StorageOptions } from '@google-cloud/storage' +import type { Buffer } from 'node:buffer' +import type { CloudStorageURI } from './createUri.ts' +import assert from 'node:assert' + +// Types +export type StorageConfig = { + gs: StorageOptions +} + +type CreateUrlFn = (inputUrl: string, ttl: number) => Promise + +export type StorageWrapperInstance = { + createUri: Record<'s3' | 'gs', (bucket: string, path: string) => CloudStorageURI> + createUrl: CreateUrlFn + delete: (url: string) => Promise + list: (url: string) => Promise<(File | string)[]> + load: (uri: string) => Promise | ArrayBufferLike | string> + save: ( + uri: string, + contents: Buffer | ArrayBufferLike | string, + _logPrefix?: string, + resumable?: boolean + ) => Promise + move: (sourceUri: string, destinationUri: string, keepOriginal: boolean) => Promise +} + +// URL Helpers + +export type StartsWith = `${Prefix}{string}` +export type Protocol = `${string}:` +export type CloudStorageUrl = StartsWith<'gs://'> +export type HttpUrl = StartsWith<'https://' | 'http://'> +export type KnownURL = CloudStorageUrl & HttpUrl + +export const isHttp = (protocol: Protocol): boolean => protocol === 'https:' || protocol === 'http:' +export const isCloudStorage = (protocol: Protocol): boolean => protocol === 'gs:' + +export const isValidUrl = (urlString: string): urlString is KnownURL => { + const url = new URL(urlString) + const protocol = url.protocol as Protocol + assert(protocol.endsWith(':'), 'The URL protocol does not end with `:`.') + return isHttp(protocol) || isCloudStorage(protocol) +} + +export const validateUrl = (url: string): void | never => { + if (!isValidUrl(url)) { + throw new Error('not implemented') + } +} + +/** + * Checks if the given url starts with `http(s)://` or `gs://`. + * + * @param {string} url - input url + * @returns {boolean} - `true` if the url is a valid cloud or fs url, `false` otherwise. + */ +export const isCloudStorageUrl = (url: string): url is CloudStorageUrl => { + return isCloudStorage(new URL(url).protocol as Protocol) +} + +export const isHttpUrl = (url: string): url is HttpUrl => url.startsWith('http://') || url.startsWith('https://') diff --git a/tests/storage/utils.test.ts b/tests/storage/utils.test.ts new file mode 100644 index 0000000..814f5e1 --- /dev/null +++ b/tests/storage/utils.test.ts @@ -0,0 +1,50 @@ +import assert from 'node:assert' +import { describe, test } from 'node:test' +import { isCloudStorage, isHttp, isValidUrl } from '../../src/storage/utils.ts' + +describe('storage utils', () => { + describe('isHttp protocol', () => { + test('valid http protocols', () => { + assert(isHttp('http:')) + assert(isHttp('https:')) + }) + test('invalid http protocols', () => { + assert.equal(isHttp(''), false) + assert(!isHttp('http')) + assert(!isHttp('https')) + assert(!isHttp('http://')) + assert(!isHttp('https://')) + }) + }) + + describe('isCloudStorage protocol', () => { + test('valid Cloud Storage protocols', () => { + assert(isCloudStorage('gs:')) + }) + test('invalid Cloud Storage protocols', () => { + assert(!isCloudStorage('gs')) + assert(!isCloudStorage('gs:/')) + assert(!isCloudStorage('http:')) + assert(!isCloudStorage('https:')) + }) + }) + + describe('isValidUrl', () => { + test('valid urls', () => { + assert(isValidUrl('gs://google-storage/test.html')) + assert(isValidUrl('http://insecure:pass@test.localhost')) + assert(isValidUrl('https://test.localhost/')) + }) + test('invalid urls', () => { + try { + isValidUrl('gs') + } catch (error) { + assert.equal(error.code, 'ERR_INVALID_URL') + } + }) + test('invalid stoarge urls', () => { + assert(!isValidUrl('file:///tmp/test.html')) + assert(!isValidUrl('sftp://test.html')) + }) + }) +}) From 8fafba5683773f2bce4b18a96abede1bb31b898d Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Sun, 7 Sep 2025 00:19:31 +0200 Subject: [PATCH 17/42] refact(helpers): add request helper but I don't think we need it. The fetch api should be sufficient nowadays. --- src/helpers/request.ts | 98 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/helpers/request.ts diff --git a/src/helpers/request.ts b/src/helpers/request.ts new file mode 100644 index 0000000..b1dbf61 --- /dev/null +++ b/src/helpers/request.ts @@ -0,0 +1,98 @@ +import { Buffer } from 'node:buffer' +import process from 'node:process' + +import pkg from '../../package.json' with { type: 'json' } +const convertReadableStream = async (readable: any) => { + // create output details + let string = '' + const chunks = [] + + // handle each chunk + for await (const chunk of readable) { + string += chunk + chunks.push(chunk) + } + + // reformat buffer + const buffer = Buffer.concat(chunks) + + // return data + return { string, buffer } +} +const { name, version } = pkg + +const userAgent = `${name.replace('@', '')}/${version}` + +const defaultOptions: RequestInit = { + method: 'GET', + // keepAliveTimeout: 30e3, + // headersTimeout: 0, + // bodyTimeout: 0, + headers: { + 'user-agent': process.env.USER_AGENT || userAgent, + }, +} + +/** 7 seconds (as milliseconds) */ +const DEFAULT_TIMEOUT = 7e3 + +type OptionsTimeout = { timeout: number } +type OptionsReject = { reject: boolean } + +export const request = async ( + url: string, + options: RequestInit & OptionsTimeout & OptionsReject +): Promise> => { + const requestOptions: RequestInit = { + ...defaultOptions, + method: options?.method || 'GET', + body: options?.body || undefined, + signal: AbortSignal.timeout(options?.timeout || DEFAULT_TIMEOUT), + } + if (options?.headers) + requestOptions.headers = { + ...requestOptions.headers, + ...options.headers, + } + + // make actual request + const { status, headers, body, ok, redirected } = await fetch(url, requestOptions) + const statusCode = status + + // const ok = statusCode >= 200 && statusCode < 300 + if (!ok && (!options || options?.reject !== false)) return Promise.reject({ statusCode, ok, headers, url }) + + // turn stream into string + const { string, buffer } = await convertReadableStream(body) + + // detect/ set redirect + + const redirect = statusCode >= 300 && statusCode < 400 && headers.location ? new URL(headers.location, url) : null + + // fetch header vars + const contentType = headers.get('content-type') + + // parse json if set + let json + try { + json = contentType?.includes('application/json') ? JSON.parse(string) : null + } catch { + json = null + } + + // return data + return Promise.resolve({ + statusCode, + ok, + redirect, + headers, + contentType, + /** @deprecated */ + trailers: new Error('not supported any longer'), + body, + status, + string, + buffer, + json, + }) +} From ee1126beac3184b89ce79bcf78fee516bfcb13e3 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Sun, 7 Sep 2025 00:27:58 +0200 Subject: [PATCH 18/42] fix(linting): ignore redirected for now --- src/helpers/request.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/request.ts b/src/helpers/request.ts index b1dbf61..7acdfd7 100644 --- a/src/helpers/request.ts +++ b/src/helpers/request.ts @@ -56,7 +56,7 @@ export const request = async ( } // make actual request - const { status, headers, body, ok, redirected } = await fetch(url, requestOptions) + const { status, headers, body, ok, redirected: _redirected } = await fetch(url, requestOptions) const statusCode = status // const ok = statusCode >= 200 && statusCode < 300 From e2379fa7271e1e672840879f357143e4ef8604d2 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Sun, 7 Sep 2025 00:36:23 +0200 Subject: [PATCH 19/42] fix(request): address type issues --- src/helpers/request.ts | 9 ++++----- src/storage/utils.ts | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/helpers/request.ts b/src/helpers/request.ts index 7acdfd7..98ac50e 100644 --- a/src/helpers/request.ts +++ b/src/helpers/request.ts @@ -43,7 +43,7 @@ export const request = async ( url: string, options: RequestInit & OptionsTimeout & OptionsReject ): Promise> => { - const requestOptions: RequestInit = { + const requestOptions = { ...defaultOptions, method: options?.method || 'GET', body: options?.body || undefined, @@ -56,7 +56,7 @@ export const request = async ( } // make actual request - const { status, headers, body, ok, redirected: _redirected } = await fetch(url, requestOptions) + const { status, headers, url: finalUrl, body, ok, redirected } = await fetch(url, requestOptions as RequestInit) const statusCode = status // const ok = statusCode >= 200 && statusCode < 300 @@ -66,8 +66,7 @@ export const request = async ( const { string, buffer } = await convertReadableStream(body) // detect/ set redirect - - const redirect = statusCode >= 300 && statusCode < 400 && headers.location ? new URL(headers.location, url) : null + // const redirect = statusCode >= 300 && statusCode < 400 && headers.location ? new URL(headers.location, url) : null // fetch header vars const contentType = headers.get('content-type') @@ -84,7 +83,7 @@ export const request = async ( return Promise.resolve({ statusCode, ok, - redirect, + redirect: redirected ? finalUrl : undefined, headers, contentType, /** @deprecated */ diff --git a/src/storage/utils.ts b/src/storage/utils.ts index fa9e9c3..43e2c02 100644 --- a/src/storage/utils.ts +++ b/src/storage/utils.ts @@ -1,4 +1,4 @@ -import type { StorageOptions } from '@google-cloud/storage' +import type { File, StorageOptions } from '@google-cloud/storage' import type { Buffer } from 'node:buffer' import type { CloudStorageURI } from './createUri.ts' import assert from 'node:assert' From c670bfac8817ade9f3c9beb1437116f15e050970 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Sun, 7 Sep 2025 00:40:36 +0200 Subject: [PATCH 20/42] chore(ci): add more node versions --- .github/workflows/pull.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index 6a19b69..a318348 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - version: [20, 22] + version: [20, 22, 24] steps: - name: 👀 Checkout Code uses: actions/checkout@v4 @@ -44,4 +44,10 @@ jobs: run: bun run test - name: 🧪 Run Tests (in Node) + run: node --run test:node + + - name: 🧪 Run Tests (in via npm in Bun) run: npm run test + + - name: 🧪 Run Tests (in via npm in Node) + run: npm run test:node From 0661a5dd3d0e18520112c4296038c201755b1b41 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Tue, 9 Sep 2025 17:51:04 +0200 Subject: [PATCH 21/42] chore: clean up tests --- package.json | 2 +- src/ard/createHashedId.ts | 2 +- src/ard/index.ts | 5 + src/{helpers => array}/arrayToObjectCount.ts | 0 src/array/index.ts | 13 ++ src/array/isEmptyArray.ts | 14 ++ src/array/notEmptyArray.ts | 7 + src/date/index.ts | 2 + src/helpers/index.ts | 6 +- src/helpers/request.ts | 9 + src/helpers/sleep.ts | 5 +- src/number/addLeadingZero.ts | 4 +- src/number/addTrailingZeros.ts | 11 +- src/number/index.ts | 6 + src/{helpers => object}/getJsonKeys.ts | 0 src/{string => object}/getObjectLength.ts | 2 + src/object/index.ts | 11 + src/{string => object}/isEmptyObject.ts | 6 +- src/object/notEmptyObject.ts | 12 + src/predicate/index.ts | 12 + src/{string => predicate}/isArray.ts | 6 +- src/predicate/isNull.ts | 9 + src/{string => predicate}/isObject.ts | 14 +- src/{string => predicate}/isUndefined.ts | 5 + .../notNullOrUndefined.ts | 6 +- src/string/capitalize.ts | 2 + src/string/index.ts | 16 +- src/string/isEmptyArray.ts | 12 - src/string/isNull.ts | 7 - src/string/notEmptyArray.ts | 7 - src/string/notEmptyObject.ts | 4 - tests/ard.test.ts | 10 +- tests/array.test.ts | 28 +++ tests/date.test.ts | 18 +- tests/date.utils.test.ts | 145 ++++++------ tests/helpers.test.ts | 34 +-- tests/number.test.ts | 36 +-- tests/object.test.ts | 74 +++++++ tests/predicate.test.ts | 98 +++++++++ tests/string.test.ts | 206 +++--------------- 40 files changed, 498 insertions(+), 368 deletions(-) rename src/{helpers => array}/arrayToObjectCount.ts (100%) create mode 100644 src/array/index.ts create mode 100644 src/array/isEmptyArray.ts create mode 100644 src/array/notEmptyArray.ts rename src/{helpers => object}/getJsonKeys.ts (100%) rename src/{string => object}/getObjectLength.ts (92%) create mode 100644 src/object/index.ts rename src/{string => object}/isEmptyObject.ts (63%) create mode 100644 src/object/notEmptyObject.ts create mode 100644 src/predicate/index.ts rename src/{string => predicate}/isArray.ts (54%) create mode 100644 src/predicate/isNull.ts rename src/{string => predicate}/isObject.ts (58%) rename src/{string => predicate}/isUndefined.ts (86%) rename src/{string => predicate}/notNullOrUndefined.ts (57%) delete mode 100644 src/string/isEmptyArray.ts delete mode 100644 src/string/isNull.ts delete mode 100644 src/string/notEmptyArray.ts delete mode 100644 src/string/notEmptyObject.ts create mode 100644 tests/array.test.ts create mode 100644 tests/object.test.ts create mode 100644 tests/predicate.test.ts diff --git a/package.json b/package.json index 190528e..a7be610 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "lint:fix": "eslint --fix", "test": "bun run typecheck && bun run test:bun", "test:bun": "bun test ./tests/**test*.ts", - "test:node": "node --test ./tests/**/*.test.ts", + "test:node": "node --test ./tests/**.test.ts", "typecheck": "tsc --noEmit" }, "dependencies": { diff --git a/src/ard/createHashedId.ts b/src/ard/createHashedId.ts index dbda734..3422cae 100644 --- a/src/ard/createHashedId.ts +++ b/src/ard/createHashedId.ts @@ -8,7 +8,7 @@ import crc from 'node-crc' * @category ard * * @param {string} input - The utf-8 encoded input string. - * @returns {string} - CRC64-ECMA182-compliant hashed input + * @returns {string} - CRC64-ECMA182-compliant hashed input. * * @example * ``` diff --git a/src/ard/index.ts b/src/ard/index.ts index 5b11cd8..84a6f79 100644 --- a/src/ard/index.ts +++ b/src/ard/index.ts @@ -1 +1,6 @@ +/** + * @fileoverview ARD utilitties. + * @category ard + * @module ard + */ export { createHashedId } from './createHashedId.ts' diff --git a/src/helpers/arrayToObjectCount.ts b/src/array/arrayToObjectCount.ts similarity index 100% rename from src/helpers/arrayToObjectCount.ts rename to src/array/arrayToObjectCount.ts diff --git a/src/array/index.ts b/src/array/index.ts new file mode 100644 index 0000000..a0f35c9 --- /dev/null +++ b/src/array/index.ts @@ -0,0 +1,13 @@ +/** + * @fileoverview Array utilities + */ + +/** + * Array utilities. + * @category array + * @module array + */ + +export { arrayToObjectCount } from './arrayToObjectCount.ts' +export { isEmptyArray } from './isEmptyArray.ts' +export { notEmptyArray } from './notEmptyArray.ts' diff --git a/src/array/isEmptyArray.ts b/src/array/isEmptyArray.ts new file mode 100644 index 0000000..284387c --- /dev/null +++ b/src/array/isEmptyArray.ts @@ -0,0 +1,14 @@ +/** + * Checks if the given array is an empty array. + * + * @module array + * + * @param {unknown} [arr] - The array to check. + * @returns {boolean} - `true` if the arr is empty, `false` otherwise. + * + * @example + * isEmptyArray() // false + * isEmptyArray([]) // true + * isEmptyArray([0]) // false + */ +export const isEmptyArray = (arr?: unknown): boolean => Array.isArray(arr) && arr.length === 0 diff --git a/src/array/notEmptyArray.ts b/src/array/notEmptyArray.ts new file mode 100644 index 0000000..d30ea03 --- /dev/null +++ b/src/array/notEmptyArray.ts @@ -0,0 +1,7 @@ +/** + * Checks if the given array is a non-empty array. + * + * @param {unknown[]} [arr] - The array to check. + * @returns {boolean} - `true` if the array is a not empty, `false` otherwise. + */ +export const notEmptyArray = (arr?: unknown[]): boolean => Array.isArray(arr) && arr.length > 0 diff --git a/src/date/index.ts b/src/date/index.ts index bfb1d8d..cb208bb 100644 --- a/src/date/index.ts +++ b/src/date/index.ts @@ -1,5 +1,7 @@ /** * @fileoverview Date formatting utilities. + * @category date + * @module date */ import { getDateHourMinutes } from './getDateHourMinutes.ts' diff --git a/src/helpers/index.ts b/src/helpers/index.ts index 51ba901..016c7d2 100644 --- a/src/helpers/index.ts +++ b/src/helpers/index.ts @@ -1,6 +1,8 @@ /** * @fileoverview General helper functions. + * @category helpers + * @module helpers */ -export { arrayToObjectCount } from './arrayToObjectCount.ts' -export { getJsonKeys } from './getJsonKeys.ts' + +export { request } from './request.ts' export { sleep } from './sleep.ts' diff --git a/src/helpers/request.ts b/src/helpers/request.ts index 98ac50e..b16d68b 100644 --- a/src/helpers/request.ts +++ b/src/helpers/request.ts @@ -39,6 +39,15 @@ const DEFAULT_TIMEOUT = 7e3 type OptionsTimeout = { timeout: number } type OptionsReject = { reject: boolean } +/** + * Create a fetchrequest. + * + * @deprecated Use `fetch` or `ofetch` instead. + * + * @param {string} url - URL + * @param options - fetch options + * @returns - Custom fetch object. + */ export const request = async ( url: string, options: RequestInit & OptionsTimeout & OptionsReject diff --git a/src/helpers/sleep.ts b/src/helpers/sleep.ts index 4e56a2a..d8831a4 100644 --- a/src/helpers/sleep.ts +++ b/src/helpers/sleep.ts @@ -1,6 +1,7 @@ /** - * Sleep the given time in ms (async). + * Sleep or wairt for a given time. * - * @param ms - miliseconds to sleep + * @param {number} ms - miliseconds to sleep + * @returns {Promise} - Sleep Promise. */ export const sleep = (ms: number): Promise => new Promise((resolve) => setTimeout(resolve, ms)) diff --git a/src/number/addLeadingZero.ts b/src/number/addLeadingZero.ts index 654344f..d8706e5 100644 --- a/src/number/addLeadingZero.ts +++ b/src/number/addLeadingZero.ts @@ -1,7 +1,7 @@ /** * Add leading zero if not existent. * - * @param value number - * @returns number string + * @param {number} value - The number value. + * @returns {string} - The number as string with a leading zero prepended if needed. */ export const addLeadingZero = (value: number): string => value.toString().padStart(2, '0') diff --git a/src/number/addTrailingZeros.ts b/src/number/addTrailingZeros.ts index 928aecc..7423961 100644 --- a/src/number/addTrailingZeros.ts +++ b/src/number/addTrailingZeros.ts @@ -1,5 +1,12 @@ -// add given number of trailing zeros -export const addTrailingZeros = (num: number | string, length: number, delimiter = '.') => { +/** + * Add a given number of trailing zeros to a number. + * + * @param {number | string} num - The number to be appended zeros. + * @param {number} length - The final number length. + * @param {string} [delimiter] - Number delimeter. Defaults to `.`. + * @returns {string} - A string of the input number with appended zeros. + */ +export const addTrailingZeros = (num: number | string, length: number, delimiter = '.'): string => { // https://bobbyhadz.com/blog/javascript-add-trailing-zeros-to-number const string = String(num) const splitter = string.includes('.') ? '.' : delimiter diff --git a/src/number/index.ts b/src/number/index.ts index 4e66ea9..1b97b91 100644 --- a/src/number/index.ts +++ b/src/number/index.ts @@ -1,3 +1,9 @@ +/** + * @fileoverview Number utilities. + * @category number + * @module number + */ + export { addLeadingZero } from './addLeadingZero.ts' export { addTrailingZeros } from './addTrailingZeros.ts' export { getAverage } from './getAverage.ts' diff --git a/src/helpers/getJsonKeys.ts b/src/object/getJsonKeys.ts similarity index 100% rename from src/helpers/getJsonKeys.ts rename to src/object/getJsonKeys.ts diff --git a/src/string/getObjectLength.ts b/src/object/getObjectLength.ts similarity index 92% rename from src/string/getObjectLength.ts rename to src/object/getObjectLength.ts index 26d82d3..8107393 100644 --- a/src/string/getObjectLength.ts +++ b/src/object/getObjectLength.ts @@ -1,6 +1,8 @@ /** * Returns the size (legth of keys) of the given object. * + * @module object + * * @param {Record} object - The object. * @returns - The length of the object. */ diff --git a/src/object/index.ts b/src/object/index.ts new file mode 100644 index 0000000..3b10cf4 --- /dev/null +++ b/src/object/index.ts @@ -0,0 +1,11 @@ +/** + * @fileoverview + * Object utilities. + * @category object + * @module object + */ + +export { getJsonKeys } from './getJsonKeys.ts' +export { getObjectLength } from './getObjectLength.ts' +export { isEmptyObject } from './isEmptyObject.ts' +export { notEmptyObject } from './notEmptyObject.ts' diff --git a/src/string/isEmptyObject.ts b/src/object/isEmptyObject.ts similarity index 63% rename from src/string/isEmptyObject.ts rename to src/object/isEmptyObject.ts index 3026206..ccab637 100644 --- a/src/string/isEmptyObject.ts +++ b/src/object/isEmptyObject.ts @@ -1,10 +1,12 @@ +import { isPlainObject } from '../predicate/isObject.ts' import { getObjectLength } from './getObjectLength.ts' -import { isPlainObject } from './isObject.ts' /** * Checks if a given value is an empty object. * + * @module object + * * @param {unknown} [value] - The value to check. - * @returns `true` if the value is an empty object, `false` otherwise. + * @returns {boolean} - `true` if the value is an empty object, `false` otherwise. */ export const isEmptyObject = (value?: unknown): boolean => isPlainObject(value) && getObjectLength(value) === 0 diff --git a/src/object/notEmptyObject.ts b/src/object/notEmptyObject.ts new file mode 100644 index 0000000..ddcb04c --- /dev/null +++ b/src/object/notEmptyObject.ts @@ -0,0 +1,12 @@ +import { isPlainObject } from '../predicate/isObject.ts' +import { getObjectLength } from './getObjectLength.ts' + +/** + * Checks if a given value is an object and not empty. + * + * @module object + * + * @param {unknown} [value] - The value to check. + * @returns {boolean} - `true` if the value is an non-empty object, `false` otherwise. + */ +export const notEmptyObject = (value: Record): boolean => isPlainObject(value) && getObjectLength(value) > 0 diff --git a/src/predicate/index.ts b/src/predicate/index.ts new file mode 100644 index 0000000..03d03e8 --- /dev/null +++ b/src/predicate/index.ts @@ -0,0 +1,12 @@ +/** + * Predicate utilities. + * @fileoverview Predicate utilities + * @category predicate + * @module predicate + */ + +export { isArray } from './isArray.ts' +export { isNull } from './isNull.ts' +export { isObject, isPlainObject } from './isObject.ts' +export { isUndefined } from './isUndefined.ts' +export { notNullOrUndefined } from './notNullOrUndefined.ts' diff --git a/src/string/isArray.ts b/src/predicate/isArray.ts similarity index 54% rename from src/string/isArray.ts rename to src/predicate/isArray.ts index 12dd152..a5bdfeb 100644 --- a/src/string/isArray.ts +++ b/src/predicate/isArray.ts @@ -1,10 +1,12 @@ /** * Checks if the given value is an array. * + * @module predicate + * * @deprecated Use `Array.isArray(value)` instead. * - * @param {any} value - The value to be cheked. + * @param {any} [value] - The value to be cheked. * - * @returns {boolean} - `true` if the value is an array, `false` otherwise. + * @returns {value is any[]} - `true` if the value is an array, `false` otherwise. */ export const isArray = (value?: any): value is any[] => Array.isArray(value) diff --git a/src/predicate/isNull.ts b/src/predicate/isNull.ts new file mode 100644 index 0000000..e9ed289 --- /dev/null +++ b/src/predicate/isNull.ts @@ -0,0 +1,9 @@ +/** + * Checks if the given value is null. + * + * @module predicate + * + * @param {unknown} value - The value to check. + * @returns {value is null} - `true`, if the value is null, `false` otherwise. + */ +export const isNull = (value: unknown): value is null => value === null diff --git a/src/string/isObject.ts b/src/predicate/isObject.ts similarity index 58% rename from src/string/isObject.ts rename to src/predicate/isObject.ts index ba84066..08ec159 100644 --- a/src/string/isObject.ts +++ b/src/predicate/isObject.ts @@ -1,8 +1,8 @@ -// import { isArray } from './isArray.ts' -// import { notNullOrUndefined } from './notNullOrUndefined.ts' - /** * Checks if a given value is a plain object. + * This excludes Arrays and Functions. + * + * @module predicate * * @param {unknown} [value] - The value to check. * @returns `true` if the value is an object, `false` otherwise. @@ -12,11 +12,13 @@ export const isPlainObject = (value?: unknown): value is Record value is Record = isPlainObject +export const isObject = (value?: unknown): value is object => + value !== null && (typeof value === 'object' || typeof value === 'function') diff --git a/src/string/isUndefined.ts b/src/predicate/isUndefined.ts similarity index 86% rename from src/string/isUndefined.ts rename to src/predicate/isUndefined.ts index bff0c50..1e86164 100644 --- a/src/string/isUndefined.ts +++ b/src/predicate/isUndefined.ts @@ -1,14 +1,19 @@ /** * Checks if the given value is undefined. * + * @module predicate + * * @param {unknown} x - The value to check. * @returns {x is undefined} `true` if the value is undefined, `false` otherwise. * * @example + * ```js * isUndefined(undefined) // true * isUndefined(null) // false * isUndefined("") // false * isUndefined(false) // false * isUndefined([]) // false + * isUndefined(0) // false + * ``` */ export const isUndefined = (x: any): x is undefined => x === undefined diff --git a/src/string/notNullOrUndefined.ts b/src/predicate/notNullOrUndefined.ts similarity index 57% rename from src/string/notNullOrUndefined.ts rename to src/predicate/notNullOrUndefined.ts index 7daee5b..9b82a3e 100644 --- a/src/string/notNullOrUndefined.ts +++ b/src/predicate/notNullOrUndefined.ts @@ -2,9 +2,11 @@ import { isNull } from './isNull.ts' import { isUndefined } from './isUndefined.ts' /** - * Checks if a given value is not `null` and not `undefined`. + * Checks if a given value is neither `null` nor `undefined`. + * + * @module predicate * * @param {unknown} [value] - The value to check. - * @returns `true` if the value is neither `null` nor `undefined`, `false otherwise`. + * @returns {boolean} - `true` if the value is neither null nor undefined, `false` otherwise. */ export const notNullOrUndefined = (value?: unknown): boolean => !isNull(value) && !isUndefined(value) diff --git a/src/string/capitalize.ts b/src/string/capitalize.ts index d37d941..300be51 100644 --- a/src/string/capitalize.ts +++ b/src/string/capitalize.ts @@ -1,4 +1,5 @@ type Capitalized = T extends `${infer FL}${infer Rest}` ? `${Uppercase}${Rest}` : T + /** * Converts the first character of string to upper case. * @@ -8,6 +9,7 @@ type Capitalized = T extends `${infer FL}${infer Rest}` ? `${U * * @example * const result = capitalize('apple') // returns 'Apple' + * const result = capitalize('Apple') // returns 'Apple' * const result2 = capitalize('ABC') // returns 'ABC' */ export const capitalize = (str: T): Capitalized => diff --git a/src/string/index.ts b/src/string/index.ts index e9aea3e..ef4da1a 100644 --- a/src/string/index.ts +++ b/src/string/index.ts @@ -1,16 +1,12 @@ +/** + * @fileoverview String utilities. + * @category string + * @module string + */ + export { capitalize } from './capitalize.ts' -export { getObjectLength } from './getObjectLength.ts' -export { isArray } from './isArray.ts' -export { isEmptyArray } from './isEmptyArray.ts' -export { isEmptyObject } from './isEmptyObject.ts' export { isEmptyString } from './isEmptyString.ts' export { isIncluded } from './isIncluded.ts' -export { isNull } from './isNull.ts' -export { isObject, isPlainObject } from './isObject.ts' -export { isUndefined } from './isUndefined.ts' -export { notEmptyArray } from './notEmptyArray.ts' -export { notEmptyObject } from './notEmptyObject.ts' -export { notNullOrUndefined } from './notNullOrUndefined.ts' export { pluralize } from './pluralize.ts' export { removeDoubleSpaces } from './removeDoubleSpaces.ts' export { toHex } from './toHex.ts' diff --git a/src/string/isEmptyArray.ts b/src/string/isEmptyArray.ts deleted file mode 100644 index 21041e1..0000000 --- a/src/string/isEmptyArray.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * Checks if the given value is an empty array. - * - * @param {unknown} [value] - The value to check. - * @returns {boolean} `true` if the value is empty, `false` otherwise. - * - * @example - * isEmptyArray() // false - * isEmptyArray([]) // true - * isEmptyArray([0]) // false - */ -export const isEmptyArray = (value?: unknown): boolean => Array.isArray(value) && value.length === 0 diff --git a/src/string/isNull.ts b/src/string/isNull.ts deleted file mode 100644 index aaecc4f..0000000 --- a/src/string/isNull.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Checks if the given value is null. - * - * @param value - The value to check. - * @returns `true`, if the value is null, `false` otherwise. - */ -export const isNull = (value: unknown): value is null => value === null diff --git a/src/string/notEmptyArray.ts b/src/string/notEmptyArray.ts deleted file mode 100644 index 82aaeeb..0000000 --- a/src/string/notEmptyArray.ts +++ /dev/null @@ -1,7 +0,0 @@ -/** - * Checks if the given value is a non-empty array. - * - * @param {unknown[]} [value] - The value to check. - * @returns `true` if the value is a non-empty array, `false` otherwise. - */ -export const notEmptyArray = (value?: unknown[]): boolean => Array.isArray(value) && value.length > 0 diff --git a/src/string/notEmptyObject.ts b/src/string/notEmptyObject.ts deleted file mode 100644 index 0628dd7..0000000 --- a/src/string/notEmptyObject.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { getObjectLength } from './getObjectLength.ts' -import { isPlainObject } from './isObject.ts' - -export const notEmptyObject = (value: Record): boolean => isPlainObject(value) && getObjectLength(value) > 0 diff --git a/tests/ard.test.ts b/tests/ard.test.ts index a038a2c..7fd0c76 100644 --- a/tests/ard.test.ts +++ b/tests/ard.test.ts @@ -1,11 +1,9 @@ import assert from 'node:assert' -import { describe, it } from 'node:test' +import { describe, test } from 'node:test' import { createHashedId } from '../src/ard/index.ts' -describe('Test ARD Package', () => { - describe('Test ARD-CoreID Hash', () => { - it("createHashedId('test') = 0c171b2e54a30c11", () => { - assert.equal(createHashedId('test'), '0c171b2e54a30c11') - }) +describe('ard utils', () => { + test('createHashedId', () => { + assert.equal(createHashedId('test'), '0c171b2e54a30c11', 'expected hash for the input `test` does not match.') }) }) diff --git a/tests/array.test.ts b/tests/array.test.ts new file mode 100644 index 0000000..2434916 --- /dev/null +++ b/tests/array.test.ts @@ -0,0 +1,28 @@ +import assert from 'node:assert' +import { describe, test } from 'node:test' +import { arrayToObjectCount, isEmptyArray, notEmptyArray } from '../src/array/index.ts' + +describe('array utils', () => { + test('arrayToObjectCount', () => { + const test = ['foo', 'bar', 'bar'] + const result = { bar: 2, foo: 1 } + const testResult = arrayToObjectCount(test) + assert.equal(testResult.bar, result.bar) + assert.equal(testResult.foo, result.foo) + }) + + describe('isEmptyArray', () => { + test('an empty array', () => { + assert(isEmptyArray([])) + }) + + test('non-empty array', () => { + assert.equal(isEmptyArray(['hello world']), false) + }) + }) + + test('notEmptyArray', () => { + assert(notEmptyArray(['hello world']), '`true` was expected for a non-empty array') + assert(!notEmptyArray([]), '`false` was expected for an empty array.') + }) +}) diff --git a/tests/date.test.ts b/tests/date.test.ts index d134569..f55aa69 100644 --- a/tests/date.test.ts +++ b/tests/date.test.ts @@ -11,8 +11,8 @@ const relativeYears = Math.floor(relativeTime / ONE_YEAR_IN_MS) // const date2date = new Date(date2) // const date2iso = '2025-09-05T19:44:37.000Z' -describe('Test DateTime Package', () => { - describe('Test getDateHourMinutes', () => { +describe('date utils', () => { + describe('getDateHourMinutes', () => { const newFormat = 'Di., 19. Januar 2038 um 03:14' const testLegacyResult = 'Di, 19. Januar 2038 - 03:14 Uhr' it(`getDateHourMinutesLegacy('${testDate}') = '${testLegacyResult}'`, () => { @@ -26,7 +26,7 @@ describe('Test DateTime Package', () => { }) }) - describe('Test getDayMonthYear', () => { + describe('getDayMonthYear', () => { const newFormat = 'Di., 19. Januar 2038' it(`getDayMonthYear('${testDate}') = '${newFormat}'`, () => { assert.equal(date.getDayMonthYear(testDate), newFormat) @@ -37,7 +37,7 @@ describe('Test DateTime Package', () => { }) }) - describe('Test getFullRelativeTime', () => { + describe('getFullRelativeTime', () => { const legacyResult = `Di, 19. Januar 2038 - 03:14 Uhr (in ${relativeYears} Jahren)` it(`legacy.getFullRelativeTime('${testDate}') = '${legacyResult}'`, () => { assert.equal(date.legacy.getFullRelativeTime(testDate), legacyResult) @@ -48,35 +48,35 @@ describe('Test DateTime Package', () => { }) }) - describe('Test getHourMinutes', () => { + describe('getHourMinutes', () => { const testResult = '03:14' it(`getHourMinutes('${testDate}') = '${testResult}'`, () => { assert.equal(date.getHourMinutes(testDate), testResult) }) }) - describe('Test getIsoRelativeTime', () => { + describe('getIsoRelativeTime', () => { const testResult = `${testDate} (in ${relativeYears} Jahren)` it(`getIsoRelativeTime('${testDate}') = '${testResult}'`, () => { assert.equal(date.getIsoRelativeTime(testDate), testResult) }) }) - describe('Test getRelativeTime', () => { + describe('getRelativeTime', () => { const testResult = `in ${relativeYears} Jahren` it(`getRelativeTime('${testDate}') = '${testResult}'`, () => { assert.equal(date.getRelativeTime(testDate), testResult) }) }) - describe('Test getYearMonthDay', () => { + describe('getYearMonthDay', () => { const testResult = '20380119' it(`getYearMonthDay('${testDate}') = '${testResult}'`, () => { assert.equal(date.getYearMonthDay(testDate), testResult) }) }) - describe('Test revYearMonthDay', () => { + describe('revYearMonthDay', () => { const test = '20380119' const testResult = '19012038' it(`revYearMonthDay('${test}') = '${testResult}'`, () => { diff --git a/tests/date.utils.test.ts b/tests/date.utils.test.ts index 2de7b34..c2a55e3 100644 --- a/tests/date.utils.test.ts +++ b/tests/date.utils.test.ts @@ -6,79 +6,84 @@ import { formatDateString, formatDateTimeString } from '../src/date/utils.ts' const date = 'Mo., 19. Januar 2038 um 14:08' const formattedDate = 'Mo, 19. Januar 2038 - 14:08 Uhr' -describe('formatDateString(): ', () => { - test('formatDateString(): default values', () => { - assert.strictEqual(formatDateString(''), '') - assert.strictEqual(formatDateString('So., 20'), 'So, 20') - assert.strictEqual(formatDateString(date), date.replace('.,', ',')) +describe('date utils utils', () => { + describe('formatDateString(): ', () => { + test('default values', () => { + assert.strictEqual(formatDateString(''), '') + assert.strictEqual(formatDateString('So., 20'), 'So, 20') + assert.strictEqual(formatDateString(date), date.replace('.,', ',')) + }) + test('weekday with dot', () => { + assert.strictEqual( + formatDateString('.,', { + weekdayWithoutDot: false, + }), + '.,' + ) + assert.strictEqual( + formatDateString('.,', { + weekdayWithoutDot: true, + }), + ',' + ) + assert(formatDateString(date, { weekdayWithoutDot: false }).includes('.,')) + assert(!formatDateString(date, { weekdayWithoutDot: true }).includes('.,')) + }) }) - test('formatDateString(): weekday with dot', () => { - assert.strictEqual( - formatDateString('.,', { - weekdayWithoutDot: false, - }), - '.,' - ) - assert.strictEqual( - formatDateString('.,', { - weekdayWithoutDot: true, - }), - ',' - ) - assert(formatDateString(date, { weekdayWithoutDot: false }).includes('.,')) - assert(!formatDateString(date, { weekdayWithoutDot: true }).includes('.,')) - }) -}) -describe('formatDateTimeString(): ', () => { - test('formatDateTimeString(): default values', () => { - assert.strictEqual(formatDateTimeString(''), ' Uhr') - assert.strictEqual(formatDateTimeString(' um '), ' - Uhr') - assert.strictEqual(formatDateTimeString('So., 20'), 'So, 20 Uhr') - assert.strictEqual(formatDateTimeString(date), formattedDate) - }) - test('formatDateTimeString(): no modifications', () => { - const options = { - addOClockSuffix: false, - timePrefix: false, - weekdayWithoutDot: false, - } - assert.strictEqual(formatDateTimeString('', options), '') - assert.strictEqual(formatDateTimeString(date, options), date) - }) - test('formatDateTimeString(): addOClockSuffix', () => { - assert.strictEqual(formatDateTimeString('', { addOClockSuffix: false }), '') - assert.strictEqual(formatDateTimeString(date, { addOClockSuffix: false }), formattedDate.replace(' Uhr', '')) - assert(!formatDateTimeString(date, { addOClockSuffix: false }).includes('Uhr')) - }) - test('formatDateTimeString(): other timePrefix', () => { - const prefix = 'hello' - assert.strictEqual(formatDateTimeString('', { timePrefix: prefix }), ' Uhr') - assert.strictEqual( - formatDateTimeString(' um ', { - timePrefix: prefix, + describe('formatDateTimeString(): ', () => { + test('default values', () => { + assert.strictEqual(formatDateTimeString(''), ' Uhr') + assert.strictEqual(formatDateTimeString(' um '), ' - Uhr') + assert.strictEqual(formatDateTimeString('So., 20'), 'So, 20 Uhr') + assert.strictEqual(formatDateTimeString(date), formattedDate) + }) + test('no modifications', () => { + const options = { addOClockSuffix: false, - }), - ` ${prefix} ` - ) - assert(formatDateTimeString(date, { timePrefix: prefix }).includes(prefix)) - }) - test('formatDateTimeString(): weekday with dot', () => { - assert.strictEqual( - formatDateTimeString('.,', { + timePrefix: false, weekdayWithoutDot: false, - addOClockSuffix: false, - }), - '.,' - ) - assert.strictEqual( - formatDateTimeString('.,', { - weekdayWithoutDot: true, - addOClockSuffix: false, - }), - ',' - ) - assert(formatDateTimeString(date, { weekdayWithoutDot: false }).includes('.,')) - assert(!formatDateTimeString(date, { weekdayWithoutDot: true }).includes('.,')) + } + assert.strictEqual(formatDateTimeString('', options), '') + assert.strictEqual(formatDateTimeString(date, options), date) + }) + test('addOClockSuffix', () => { + assert.strictEqual(formatDateTimeString('', { addOClockSuffix: false }), '') + assert.strictEqual( + formatDateTimeString(date, { addOClockSuffix: false }), + formattedDate.replace(' Uhr', '') + ) + assert(!formatDateTimeString(date, { addOClockSuffix: false }).includes('Uhr')) + }) + test('other timePrefix', () => { + const prefix = 'hello' + assert.strictEqual(formatDateTimeString('', { timePrefix: prefix }), ' Uhr') + assert.strictEqual( + formatDateTimeString(' um ', { + timePrefix: prefix, + addOClockSuffix: false, + }), + ` ${prefix} ` + ) + assert(formatDateTimeString(date, { timePrefix: prefix }).includes(prefix)) + }) + test('weekday with dot', () => { + assert.strictEqual( + formatDateTimeString('.,', { + weekdayWithoutDot: false, + addOClockSuffix: false, + }), + '.,' + ) + assert.strictEqual( + formatDateTimeString('.,', { + weekdayWithoutDot: true, + addOClockSuffix: false, + }), + ',' + ) + assert(formatDateTimeString(date, { weekdayWithoutDot: false }).includes('.,')) + assert(!formatDateTimeString(date, { weekdayWithoutDot: true }).includes('.,')) + }) }) }) diff --git a/tests/helpers.test.ts b/tests/helpers.test.ts index 97520c8..de58060 100644 --- a/tests/helpers.test.ts +++ b/tests/helpers.test.ts @@ -1,37 +1,13 @@ import assert from 'node:assert' import { describe, it } from 'node:test' -import * as helpers from '../src/helpers/index.ts' +import { sleep } from '../src/helpers/index.ts' -describe('Test Helpers Package', () => { - describe('Test arrayToObjectCount', () => { - it("arrayToObjectCount(['foo', 'bar', 'bar']) = { bar: 2, foo: 1 }", () => { - const test = ['foo', 'bar', 'bar'] - const result = { bar: 2, foo: 1 } - const testResult = helpers.arrayToObjectCount(test) - assert.equal(testResult.bar, result.bar) - assert.equal(testResult.foo, result.foo) - }) - }) - - describe('Test getJsonKeys', () => { - it("getJsonKeys({ hello: 'world', foo: 'bar' }) = ['hello', 'foo']", () => { - const test = { hello: 'world', foo: 'bar' } - const result = ['hello', 'foo'] - const testResult = helpers.getJsonKeys(test) - assert.equal(testResult[0], result[0]) - assert.equal(testResult[1], result[1]) - // just using `Object.keys` - const testResultSimple = Object.keys(test) - assert.equal(testResultSimple[0], result[0]) - assert.equal(testResultSimple[1], result[1]) - }) - }) - - describe('Test sleep', () => { - it('sleep(1e3) will sleep 1s', async () => { +describe('helpers', () => { + describe('sleep', () => { + it('will sleep for one second', async () => { const time = 1e3 const before = Date.now() - await helpers.sleep(time) + await sleep(time) const after = Date.now() assert(after - before >= time) }) diff --git a/tests/number.test.ts b/tests/number.test.ts index c3c3533..3ad454d 100644 --- a/tests/number.test.ts +++ b/tests/number.test.ts @@ -1,19 +1,19 @@ import assert from 'node:assert' -import { describe, it } from 'node:test' +import { describe, it, test } from 'node:test' import * as number from '../src/number/index.ts' -describe('Test Numbers Package', () => { - describe('Test addLeadingZero', () => { - it("addLeadingZero(1) = '01'", () => { +describe('number utils', () => { + describe('addLeadingZero', () => { + it('prepends a zero for one-digit numbers', () => { assert.equal(number.addLeadingZero(1), '01') }) - it("addLeadingZero(10) = '10'", () => { + it('does not change anything for two-digit numbers', () => { assert.equal(number.addLeadingZero(10), '10') }) }) - describe('Test addTrailingZeros', () => { + describe('addTrailingZeros', () => { it("addTrailingZeros(1, 5) = '1.00000'", () => { assert.equal(number.addTrailingZeros(1, 5), '1.00000') }) @@ -39,7 +39,7 @@ describe('Test Numbers Package', () => { }) }) - describe('Test getAverage', () => { + describe('getAverage', () => { it('getAverage([1, 2, 3]) = 2', () => { assert.equal(number.getAverage([1, 2, 3]), 2) }) @@ -49,7 +49,7 @@ describe('Test Numbers Package', () => { }) }) - describe('Test getDiff', () => { + describe('getDiff', () => { it('getDiff(2, 1) = 1', () => { assert.equal(number.getDiff(2, 1), 1) }) @@ -59,7 +59,7 @@ describe('Test Numbers Package', () => { }) }) - describe('Test getRandomInRange', () => { + describe('getRandomInRange', () => { it('getRandomInRange(1, 5) = 1,2,3,4 or 5', () => { assert([1, 2, 3, 4, 5].includes(number.getRandomInRange(1, 5))) }) @@ -69,7 +69,7 @@ describe('Test Numbers Package', () => { }) }) - describe('Test getSum', () => { + describe('getSum', () => { it('getSum([1, 2, 3]) = 6', () => { assert.equal(number.getSum([1, 2, 3]), 6) }) @@ -79,17 +79,19 @@ describe('Test Numbers Package', () => { }) }) - describe('Test isEven', () => { - it('isEven(2) = true', () => { - assert.equal(number.isEven(2), true) + describe('isEven', () => { + test('even numbers', () => { + assert(number.isEven(2)) + assert(number.isEven(4)) }) - it('isEven(1) = false', () => { + test('uneven numbers', () => { assert.equal(number.isEven(1), false) + assert.equal(number.isEven(11), false) }) }) - describe('Test normalize', () => { + describe('normalize', () => { it('normalize(2, 100) = 0.02', () => { assert.equal(number.normalize(2, 100), 0.02) }) @@ -99,7 +101,7 @@ describe('Test Numbers Package', () => { }) }) - describe('Test roundTo', () => { + describe('roundTo', () => { it('roundTo(1.23456) = 1.23', () => { assert.equal(number.roundTo(1.23456), 1.23) }) @@ -123,7 +125,7 @@ describe('Test Numbers Package', () => { }) }) - describe('Test toReadable', () => { + describe('toReadable', () => { it("toReadable(1234567) = '1.234.567'", () => { assert.equal(number.toReadable(1234567), '1.234.567') }) diff --git a/tests/object.test.ts b/tests/object.test.ts new file mode 100644 index 0000000..6516f9e --- /dev/null +++ b/tests/object.test.ts @@ -0,0 +1,74 @@ +import assert from 'node:assert' +import { describe, it, test } from 'node:test' +import { getJsonKeys, getObjectLength, isEmptyObject, notEmptyObject } from '../src/object/index.ts' + +describe('object utils', () => { + describe('getObjectLength', () => { + test('empty object', () => { + assert.strictEqual(getObjectLength({}), 0, 'empty objects should have a length of zero.') + }) + + test('object with one key', () => { + assert.strictEqual(getObjectLength({ hello: 'world' }), 1) + }) + + test('obect with two keys', () => { + assert.equal( + getObjectLength({ + hello: 'world', + foo: 'bar', + }), + 2 + ) + }) + test('obect with nested object', () => { + assert.equal( + getObjectLength({ + hello: 'world', + foo: { bar: 2, baz: 4, boo: 5 }, + }), + 2 + ) + }) + }) + + test('getJsonKeys', () => { + const test = { hello: 'world', foo: 'bar' } + const result = ['hello', 'foo'] + const testResult = getJsonKeys(test) + assert.equal(testResult[0], result[0]) + assert.equal(testResult[1], result[1]) + // just using `Object.keys` + const testResultSimple = Object.keys(test) + assert.equal(testResultSimple[0], result[0]) + assert.equal(testResultSimple[1], result[1]) + }) + + describe('isEmptyObject', () => { + it('is `true` for an empty object', () => { + assert.equal(isEmptyObject({}), true) + }) + + it('is `false` for a non-empty object', () => { + assert.equal(isEmptyObject({ hello: 'world' }), false) + }) + }) + + describe('notEmptyObject', () => { + test('non empty objects return `true`', () => { + assert.equal(notEmptyObject({ hello: 'world' }), true, 'a non-empty object must be true') + }) + + test('empty objects', () => { + assert.equal(notEmptyObject({}), false, 'non empty objects must be false') + }) + + it('is `false` for non-objects', () => { + // @ts-expect-error for testing `false` is alright + assert.equal(notEmptyObject(false), false) + assert.equal(notEmptyObject([]), false) + assert.equal(notEmptyObject(['hello']), false) + assert.equal(notEmptyObject(Object.create(null)), false) + }) + }) +}) diff --git a/tests/predicate.test.ts b/tests/predicate.test.ts new file mode 100644 index 0000000..3c04384 --- /dev/null +++ b/tests/predicate.test.ts @@ -0,0 +1,98 @@ +import assert from 'node:assert' +import { describe, it, test } from 'node:test' +import { isArray, isNull, isObject, isPlainObject, isUndefined, notNullOrUndefined } from '../src/predicate/index.ts' + +describe('predicate utils', () => { + describe('isArray', () => { + it("isArray(['hello world']) = true", () => { + assert.equal(isArray(['hello world']), true) + }) + + it("isArray({ hello: 'world' }) = false", () => { + assert.equal(isArray({ hello: 'world' }), false) + }) + + test('valid arrays', () => { + assert(isArray([])) + assert(isArray([0])) + assert(isArray([false])) + }) + test('non arrays', () => { + assert(!isArray(true)) + assert(!isArray(false)) + assert(!isArray('')) + assert(!isArray('[]')) + assert(!isArray(null)) + assert(!isArray()) + assert(!isArray(undefined)) + }) + }) + + describe('isNull', () => { + test('null returns `true`', () => { + assert(isNull(null)) + }) + + test('non null values all return `false`', () => { + assert.equal(isNull(undefined), false) + assert.equal(isNull(''), false) + assert.equal(isNull(false), false) + assert.equal(isNull(true), false) + assert.equal(isNull([]), false) + assert.equal(isNull('null'), false) + }) + }) + + describe('isObject', () => { + it("isObject({ hello: 'world' }) = true", () => { + assert.equal(isObject({ hello: 'world' }), true) + }) + + it("isObject('hello world') = false", () => { + assert.equal(isObject('hello world'), false) + }) + + it('is true with functions', () => assert(isObject(() => {}))) + }) + + describe('isPlainObject', () => { + it('is true with objects', () => { + assert(isPlainObject({})) + assert(isPlainObject(Object.create(null))) + assert(isPlainObject({ hello: 'world' })) + }) + + it('is false with invalid objects', () => { + assert.equal(isPlainObject([]), false) + assert.equal(isPlainObject('hello world'), false) + }) + }) + + describe('isUndefined', () => { + it('is true for undefined', () => { + assert(isUndefined(undefined)) + }) + + it('is false for null', () => { + assert.equal(isUndefined(null), false) + }) + + it('is false for false', () => { + assert.equal(isUndefined(false), false) + }) + }) + + describe('Test notNullOrUndefined', () => { + it("notNullOrUndefined('hello world') = true", () => { + assert.equal(notNullOrUndefined('hello world'), true) + }) + + it('notNullOrUndefined(null) = false', () => { + assert.equal(notNullOrUndefined(null), false) + }) + + it('notNullOrUndefined(undefined) = false', () => { + assert.equal(notNullOrUndefined(undefined), false) + }) + }) +}) diff --git a/tests/string.test.ts b/tests/string.test.ts index 13bef5c..68b7ef9 100644 --- a/tests/string.test.ts +++ b/tests/string.test.ts @@ -1,220 +1,76 @@ import assert from 'node:assert' import { describe, it, test } from 'node:test' -import * as strings from '../src/string/index.ts' -import { capitalize } from '../src/string/index.ts' +import { capitalize, isEmptyString, isIncluded, pluralize, removeDoubleSpaces, toHex } from '../src/string/index.ts' -describe('Test Strings Package', () => { - describe('Test capitalize', () => { - it("capitalize('a') = 'A'", () => { +describe('string utils', () => { + describe('capitalize', () => { + test("don't capitalize anything on an empty string", () => { + assert.equal(capitalize(''), '') + }) + test('capitalize one letter', () => { assert.equal(capitalize('a'), 'A') }) - it("capitalize('apple') = 'Apple'", () => { + test('capitalize only the first letter', () => { assert.equal(capitalize('apple'), 'Apple') }) - }) - - describe('Test getObjectLength', () => { - it("getObjectLength({ hello: 'world' }) = 1", () => { - assert.equal(strings.getObjectLength({ hello: 'world' }), 1) - }) - - it("getObjectLength({ hello: 'world', foo: 'bar' }) = 2", () => { - assert.equal( - strings.getObjectLength({ - hello: 'world', - foo: 'bar', - }), - 2 - ) - }) - }) - - describe('Test isArray', () => { - it("isArray(['hello world']) = true", () => { - assert.equal(strings.isArray(['hello world']), true) - }) - - it("isArray({ hello: 'world' }) = false", () => { - assert.equal(strings.isArray({ hello: 'world' }), false) - }) - - test('valid arrays', () => { - assert(strings.isArray([])) - assert(strings.isArray([0])) - assert(strings.isArray([false])) - }) - test('non arrays', () => { - assert(!strings.isArray(true)) - assert(!strings.isArray(false)) - assert(!strings.isArray('')) - assert(!strings.isArray('[]')) - assert(!strings.isArray(null)) - assert(!strings.isArray()) - assert(!strings.isArray(undefined)) - }) - }) - - describe('Test isEmptyArray', () => { - it('isEmptyArray([]) = true', () => { - assert.equal(strings.isEmptyArray([]), true) - }) - - it("isEmptyArray(['hello world']) = false", () => { - assert.equal(strings.isEmptyArray(['hello world']), false) - }) - }) - - describe('Test isEmptyObject', () => { - it('isEmptyObject({}) = true', () => { - assert.equal(strings.isEmptyObject({}), true) - }) - - it("isEmptyObject({ hello: 'world' }) = false", () => { - assert.equal(strings.isEmptyObject({ hello: 'world' }), false) - }) - }) - - describe('Test isEmptyString', () => { - it("isEmptyString('') = true", () => { - assert.equal(strings.isEmptyString(''), true) - }) - - it("isEmptyString('hello world') = false", () => { - assert.equal(strings.isEmptyString('hello world'), false) - }) - }) - - describe('Test isIncluded', () => { - it("isIncluded('hello world', 'hello') = true", () => { - assert.equal(strings.isIncluded('hello world', 'hello'), true) - }) - - it("isIncluded('hello world', 'earth') = false", () => { - assert.equal(strings.isIncluded('hello world', 'earth'), false) - }) - }) - - describe('Test isNull', () => { - it('isNull(null) = true', () => { - assert.equal(strings.isNull(null), true) - }) - - it('isNull(undefined) = false', () => { - assert.equal(strings.isNull(undefined), false) + test('capitalize only the first word', () => { + assert.equal(capitalize('happy tree friends'), 'Happy tree friends') }) }) - describe('Test isObject', () => { - it("isObject({ hello: 'world' }) = true", () => { - assert.equal(strings.isObject({ hello: 'world' }), true) - }) - - it("isObject('hello world') = false", () => { - assert.equal(strings.isObject('hello world'), false) - }) + test('isEmptyString', () => { + assert.equal(isEmptyString(''), true, '`true` was expected for an empty string') + assert.equal(isEmptyString('hello world'), false, '`false` was expected for a non empty string') }) - describe('Test isPlainObject', () => { - it('is true with objects', () => { - assert(strings.isPlainObject({})) - assert(strings.isPlainObject(Object.create(null))) - assert(strings.isPlainObject({ hello: 'world' })) + describe('isIncluded', () => { + it('returns true if a sub-string is included', () => { + assert.equal(isIncluded('hello world', 'hello'), true) }) - it('is false with invalid objects', () => { - assert.equal(strings.isPlainObject([]), false) - assert.equal(strings.isPlainObject('hello world'), false) + it('returns false if a sub-string is not included', () => { + assert.equal(isIncluded('hello world', 'earth'), false) }) }) - describe('Test isUndefined', () => { - it('isUndefined(undefined) = true', () => { - assert.equal(strings.isUndefined(undefined), true) - }) - - it('isUndefined(null) = false', () => { - assert.equal(strings.isUndefined(null), false) - }) - - it('isUndefined(false) = false', () => { - assert.equal(strings.isUndefined(false), false) - }) - }) - - describe('Test notEmptyArray', () => { - it("notEmptyArray(['hello world']) = true", () => { - assert.equal(strings.notEmptyArray(['hello world']), true) - }) - - it('notEmptyArray([]) = false', () => { - assert.equal(strings.notEmptyArray([]), false) - }) - }) - - describe('Test notEmptyObject', () => { - it("notEmptyObject({ hello: 'world' }) = true", () => { - assert.equal(strings.notEmptyObject({ hello: 'world' }), true) - }) - - it('notEmptyObject({}) = false', () => { - assert.equal(strings.notEmptyObject({}), false) - }) - }) - - describe('Test notNullOrUndefined', () => { - it("notNullOrUndefined('hello world') = true", () => { - assert.equal(strings.notNullOrUndefined('hello world'), true) - }) - - it('notNullOrUndefined(null) = false', () => { - assert.equal(strings.notNullOrUndefined(null), false) - }) - - it('notNullOrUndefined(undefined) = false', () => { - assert.equal(strings.notNullOrUndefined(undefined), false) - }) - }) - - describe('Test pluralize', () => { + describe('pluralize', () => { it("pluralize(1, 'Apple') = '1 Apple'", () => { - assert.equal(strings.pluralize(1, 'Apple'), '1 Apple') + assert.equal(pluralize(1, 'Apple'), '1 Apple') }) it("pluralize(1000, 'Apple') = '1.000 Apples'", () => { - assert.equal(strings.pluralize(1000, 'Apple'), '1.000 Apples') + assert.equal(pluralize(1000, 'Apple'), '1.000 Apples') }) it("pluralize(1, 'Child', 'Children') = '1 Child'", () => { - assert.equal(strings.pluralize(1, 'Child', 'Children'), '1 Child') + assert.equal(pluralize(1, 'Child', 'Children'), '1 Child') }) it("pluralize(1000, 'Child', 'Children') = '1.000 Children'", () => { - assert.equal(strings.pluralize(1000, 'Child', 'Children'), '1.000 Children') + assert.equal(pluralize(1000, 'Child', 'Children'), '1.000 Children') }) }) - describe('Test removeDoubleSpaces', () => { + describe('removeDoubleSpaces', () => { it("removeDoubleSpaces('hello world')) = 'hello world'", () => { - assert.equal(strings.removeDoubleSpaces('hello world'), 'hello world') + assert.equal(removeDoubleSpaces('hello world'), 'hello world') }) it("removeDoubleSpaces('hello world')) = 'hello world'", () => { - assert.equal(strings.removeDoubleSpaces('hello world'), 'hello world') + assert.equal(removeDoubleSpaces('hello world'), 'hello world') }) it("removeDoubleSpaces('hello world once again')) = 'hello world once again'", () => { - assert.equal(strings.removeDoubleSpaces('hello world once again'), 'hello world once again') + assert.equal(removeDoubleSpaces('hello world once again'), 'hello world once again') }) it('does not remove normal spaces', () => { - assert.equal(strings.removeDoubleSpaces('hello world'), 'hello world') - assert.equal(strings.removeDoubleSpaces(' hello world '), ' hello world ') + assert.equal(removeDoubleSpaces('hello world'), 'hello world') + assert.equal(removeDoubleSpaces(' hello world '), ' hello world ') }) }) - describe('Test toHex', () => { - it("toHex('hello world')) = '68656c6c6f20776f726c64'", () => { - assert.equal(strings.toHex('hello world'), '68656c6c6f20776f726c64') - }) + test('toHex', () => { + assert.equal(toHex('hello world'), '68656c6c6f20776f726c64', 'The hex value did not match the expected value.') }) }) From 9633e6be83a7fe978a5a3e3dd1a375fca68a2210 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Thu, 11 Sep 2025 20:05:08 +0200 Subject: [PATCH 22/42] chore: clean up legacy functions --- bun.lock | 9 +- package.json | 31 ++- src/ard/createHashedId.ts | 5 +- src/date/index.ts | 24 +-- .../{revYearMonthDay.ts => toDayMonthYear.ts} | 0 src/helpers/request.ts | 124 ++++++------ src/legacy.ts | 4 - src/legacy/ard.ts | 1 + src/legacy/date.ts | 24 +++ src/legacy/helpers.ts | 3 + src/legacy/numbers.ts | 23 +++ src/legacy/storage-wrapper.ts | 0 src/legacy/strings.ts | 35 ++++ src/legacy/undici.ts | 173 +++++++++++++++++ src/string/crc64.ts | 126 +++++++++++++ src/string/index.ts | 1 + tests/crc.test.ts | 70 +++++++ tests/date.test.ts | 17 +- tests/legacy/ard.test.mjs | 11 ++ tests/legacy/date.test.mjs | 66 +++++++ tests/legacy/helpers.test.mjs | 35 ++++ tests/legacy/numbers.test.mjs | 117 ++++++++++++ tests/legacy/strings.test.mjs | 177 ++++++++++++++++++ tests/legacy/utils.mjs | 14 ++ tests/storage/utils.test.ts | 7 + tsdown.config.ts | 19 +- 26 files changed, 997 insertions(+), 119 deletions(-) rename src/date/{revYearMonthDay.ts => toDayMonthYear.ts} (100%) delete mode 100644 src/legacy.ts create mode 100644 src/legacy/ard.ts create mode 100644 src/legacy/date.ts create mode 100644 src/legacy/helpers.ts create mode 100644 src/legacy/numbers.ts create mode 100644 src/legacy/storage-wrapper.ts create mode 100644 src/legacy/strings.ts create mode 100644 src/legacy/undici.ts create mode 100644 src/string/crc64.ts create mode 100644 tests/crc.test.ts create mode 100644 tests/legacy/ard.test.mjs create mode 100644 tests/legacy/date.test.mjs create mode 100644 tests/legacy/helpers.test.mjs create mode 100644 tests/legacy/numbers.test.mjs create mode 100644 tests/legacy/strings.test.mjs create mode 100644 tests/legacy/utils.mjs diff --git a/bun.lock b/bun.lock index 16d348c..467943b 100644 --- a/bun.lock +++ b/bun.lock @@ -4,6 +4,7 @@ "": { "dependencies": { "@google-cloud/storage": "^7.17.0", + "@types/node": "^24.3.1", "abort-controller": "^3.0.0", "luxon": "3.7.2", "node-crc": "https://github.com/swrlab/node-crc#v2.1.0", @@ -155,7 +156,7 @@ "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/node": ["@types/node@18.19.64", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ=="], + "@types/node": ["@types/node@24.3.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g=="], "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], @@ -813,7 +814,7 @@ "undici": ["undici@7.15.0", "", {}, "sha512-7oZJCPvvMvTd0OlqWsIxTuItTpJBpU1tcbVl24FMn3xt3+VSunwUasmfPJRE57oNO1KsZ4PgA1xTdAX4hq8NyQ=="], - "undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], + "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], "unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], @@ -931,6 +932,8 @@ "mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + "node-crc/@types/node": ["@types/node@18.19.64", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ=="], + "regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], "rolldown-plugin-dts/get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], @@ -971,6 +974,8 @@ "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + "node-crc/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], + "teeny-request/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], "teeny-request/https-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], diff --git a/package.json b/package.json index a7be610..e47e1fa 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,14 @@ }, "author": "SWR Audio Lab ", "main": "./src/index.ts", + "module": "./src/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": "./src/index.ts", + "./packages/date": "./src/legacy/date.ts", + "./ard": "./src/ard/index.ts", + "./date": "./src/date/index.ts" + }, "publishConfig": { "access": "public", "provenance": true, @@ -17,12 +25,24 @@ "module": "./dist/index.js", "exports": { ".": { - "types": "./dist/index.d.mts", + "types": "./dist/index.d.ts", "default": "./dist/index.js" }, - "/ard.js": { - "types": "./dist/ard/index.d.mts", - "default": "./dist/ard/index.js" + "./ard": { + "types": "./dist/ard.d.ts", + "default": "./dist/ard.js" + }, + "./date": { + "types": "./dist/date.d.ts", + "default": "./dist/date.js" + }, + "./packages/date": { + "types": "./src/legacy/date.d.ts", + "default": "./src/legacy/date.js" + }, + "./packages/*": { + "types": "./src/legacy/*.d.ts", + "default": "./src/legacy/*.js" } } }, @@ -34,11 +54,14 @@ "lint:fix": "eslint --fix", "test": "bun run typecheck && bun run test:bun", "test:bun": "bun test ./tests/**test*.ts", + "test:legacy": "bun test ./tests/legacy/*.test.mjs", + "test:legacy:node": "node --test ./tests/legacy/*.test.mjs", "test:node": "node --test ./tests/**.test.ts", "typecheck": "tsc --noEmit" }, "dependencies": { "@google-cloud/storage": "^7.17.0", + "@types/node": "^24.3.1", "abort-controller": "^3.0.0", "luxon": "3.7.2", "node-crc": "https://github.com/swrlab/node-crc#v2.1.0", diff --git a/src/ard/createHashedId.ts b/src/ard/createHashedId.ts index 3422cae..58544f4 100644 --- a/src/ard/createHashedId.ts +++ b/src/ard/createHashedId.ts @@ -1,5 +1,4 @@ -import { Buffer } from 'node:buffer' -import crc from 'node-crc' +import { crc64String } from '../string/crc64.ts' /** * Create a a CRC64-ECMA182-compliant hash from given input. @@ -16,4 +15,4 @@ import crc from 'node-crc' * ard.createHashedId('my-string-to-encode') * ``` */ -export const createHashedId = (input: string): string => crc.crc64(Buffer.from(input, 'utf-8')).toString('hex') +export const createHashedId = (input: string): string => crc64String(input) diff --git a/src/date/index.ts b/src/date/index.ts index cb208bb..2ee334f 100644 --- a/src/date/index.ts +++ b/src/date/index.ts @@ -6,30 +6,12 @@ import { getDateHourMinutes } from './getDateHourMinutes.ts' import { getDayMonthYear } from './getDayMonthYear.ts' -import { getFullRelativeTime, getFullRelativeTimeLegacy } from './getFullRelativeTime.ts' -import { toDayMonthYear } from './revYearMonthDay.ts' -import { formatDateTimeString, type ISODateString, shortenWeekday } from './utils.ts' - export { getDateHourMinutesLegacy } from './getDateHourMinutes.ts' +export { getFullRelativeTime, getFullRelativeTimeLegacy } from './getFullRelativeTime.ts' export { getHourMinutes } from './getHourMinutes.ts' export { getIsoRelativeTime } from './getIsoRelativeTime.ts' export { getRelativeTime } from './getRelativeTime.ts' - +export { getYearMonthDay } from './getYearMonthDay.ts' export { getDateHourMinutes } export { getDayMonthYear } -export { getFullRelativeTime } -export { getYearMonthDay } from './getYearMonthDay.ts' -// new name -export { toDayMonthYear } -// export old name -/** @deprecated please use `toDayMonthYear` */ -export { toDayMonthYear as revYearMonthDay } - -/** - * Legacy date exports to be compatible with the previous format. - */ -export const legacy = { - getDateHourMinutes: (date: ISODateString): string => formatDateTimeString(getDateHourMinutes(date)), - getDayMonthYear: (date: ISODateString): string => shortenWeekday(getDayMonthYear(date)), - getFullRelativeTime: (date: ISODateString): string => getFullRelativeTimeLegacy(date), -} +export { toDayMonthYear } from './toDayMonthYear.ts' diff --git a/src/date/revYearMonthDay.ts b/src/date/toDayMonthYear.ts similarity index 100% rename from src/date/revYearMonthDay.ts rename to src/date/toDayMonthYear.ts diff --git a/src/helpers/request.ts b/src/helpers/request.ts index b16d68b..91062d4 100644 --- a/src/helpers/request.ts +++ b/src/helpers/request.ts @@ -2,105 +2,91 @@ import { Buffer } from 'node:buffer' import process from 'node:process' import pkg from '../../package.json' with { type: 'json' } -const convertReadableStream = async (readable: any) => { - // create output details - let string = '' - const chunks = [] +const { name, version } = pkg - // handle each chunk - for await (const chunk of readable) { - string += chunk - chunks.push(chunk) - } +const userAgent: string = process.env.USER_AGENT || `${name.replace('@', '')}/${version}` - // reformat buffer - const buffer = Buffer.concat(chunks) +/** 7 seconds (in milliseconds) */ +const DEFAULT_TIMEOUT: number = 7e3 - // return data - return { string, buffer } +type OptionsTimeout = { + /** + * @deprecated Don't use `timeout`. Just use `{ signal: AbortSignal.timeout(timeout) }` in request options instead. Or pass an abortController. + */ + timeout?: number } -const { name, version } = pkg - -const userAgent = `${name.replace('@', '')}/${version}` - -const defaultOptions: RequestInit = { - method: 'GET', - // keepAliveTimeout: 30e3, - // headersTimeout: 0, - // bodyTimeout: 0, - headers: { - 'user-agent': process.env.USER_AGENT || userAgent, - }, +type OptionsReject = { + /** + * @deprecated Don't use `reject`. Just use `Response.ok` instead on a plain fetch. + */ + reject?: boolean } -/** 7 seconds (as milliseconds) */ -const DEFAULT_TIMEOUT = 7e3 - -type OptionsTimeout = { timeout: number } -type OptionsReject = { reject: boolean } - /** - * Create a fetchrequest. + * Create a fetch request. + * Tiny wrapper around the native fetch API. * - * @deprecated Use `fetch` or `ofetch` instead. + * @deprecated If possible, prefer using `fetch` directly or a package like `ofetch` instead. * - * @param {string} url - URL - * @param options - fetch options - * @returns - Custom fetch object. + * @param {string | URL} resource - URL + * @param [options] - (Optional) fetch request options. + * @returns - fetch response object. */ export const request = async ( - url: string, - options: RequestInit & OptionsTimeout & OptionsReject + resource: string | URL, + options: RequestInit & OptionsTimeout & OptionsReject = {} ): Promise> => { + // TODO: Consider using `defu` to merge with defaul parameters safely and easily. const requestOptions = { - ...defaultOptions, - method: options?.method || 'GET', - body: options?.body || undefined, - signal: AbortSignal.timeout(options?.timeout || DEFAULT_TIMEOUT), + ...options, + signal: options.signal ?? AbortSignal.timeout(options?.timeout ?? DEFAULT_TIMEOUT), + headers: { + 'user-agent': userAgent, + ...(options.headers ?? {}), + }, } - if (options?.headers) - requestOptions.headers = { - ...requestOptions.headers, - ...options.headers, - } - - // make actual request - const { status, headers, url: finalUrl, body, ok, redirected } = await fetch(url, requestOptions as RequestInit) - const statusCode = status - - // const ok = statusCode >= 200 && statusCode < 300 - if (!ok && (!options || options?.reject !== false)) return Promise.reject({ statusCode, ok, headers, url }) + // delete non-existing request properties from the Request + delete requestOptions.timeout + delete requestOptions.reject - // turn stream into string - const { string, buffer } = await convertReadableStream(body) + const response = await fetch(resource, requestOptions as RequestInit) + const { status, ok, headers, url, body, redirected } = response - // detect/ set redirect - // const redirect = statusCode >= 300 && statusCode < 400 && headers.location ? new URL(headers.location, url) : null + if (!ok && options?.reject === true) return Promise.reject({ statusCode: status, ok, headers, url }) - // fetch header vars const contentType = headers.get('content-type') - // parse json if set - let json + // TODO: change flow, since there are other types like `blob` and text type should be detecte too. + // TODO: consider using `destr` for more performance, safety and Types. + const text = await response.text() + let json: any try { - json = contentType?.includes('application/json') ? JSON.parse(string) : null + json = contentType?.includes('application/json') ? JSON.parse(text) : null } catch { json = null } - // return data return Promise.resolve({ - statusCode, + /** @deprecated Use `Response.status` instead. */ + statusCode: status, ok, - redirect: redirected ? finalUrl : undefined, + redirectd: redirected, + /** @deprecated Use `Response.redirected` and if true then `Response.url` is the latest one. */ + redirect: redirected ? url : undefined, + url, headers, + /** @deprecated Just use Response.headers.get('content-type') instead. */ contentType, - /** @deprecated */ - trailers: new Error('not supported any longer'), + /** @deprecated Use `Response.headers` instead. */ + trailers: undefined, + /** @deprecated Use a plain fetch if body access is neede. This one hast an already used body. */ body, status, - string, - buffer, + /** @deprecated Use `await Response.text()` instead. This can still be parsed to JSON or a Buffer. */ + string: text, + /** @deprecated Use `Response.arrayBuffer()` instead. A Buffer can be converted to text as well. */ + buffer: Buffer.from(text, 'utf-8'), + /** @deprecated Use `await Response.json()` instead of use `ofetch`. */ json, }) } diff --git a/src/legacy.ts b/src/legacy.ts deleted file mode 100644 index 7ba5eef..0000000 --- a/src/legacy.ts +++ /dev/null @@ -1,4 +0,0 @@ -/** - * @fileoverview Provide all the legacy exports so pre-existing export names and behaviour is still present - * and does not break any code. - */ diff --git a/src/legacy/ard.ts b/src/legacy/ard.ts new file mode 100644 index 0000000..910833f --- /dev/null +++ b/src/legacy/ard.ts @@ -0,0 +1 @@ +export { createHashedId } from '../ard/index.ts' diff --git a/src/legacy/date.ts b/src/legacy/date.ts new file mode 100644 index 0000000..3ea75b1 --- /dev/null +++ b/src/legacy/date.ts @@ -0,0 +1,24 @@ +import { getDateHourMinutes as getDateHourMinutesNew } from '../date/getDateHourMinutes.ts' +import { getDayMonthYear as getDayMonthYearNew } from '../date/getDayMonthYear.ts' +import { getFullRelativeTimeLegacy } from '../date/getFullRelativeTime.ts' +import { getHourMinutes } from '../date/getHourMinutes.ts' +import { getIsoRelativeTime } from '../date/getIsoRelativeTime.ts' +import { getRelativeTime } from '../date/getRelativeTime.ts' +import { getYearMonthDay } from '../date/getYearMonthDay.ts' +import { toDayMonthYear as revYearMonthDay } from '../date/toDayMonthYear.ts' +import { formatDateTimeString, type ISODateString, shortenWeekday } from '../date/utils.ts' + +const getDateHourMinutes = (date: ISODateString): string => formatDateTimeString(getDateHourMinutesNew(date)) +const getDayMonthYear = (date: ISODateString): string => shortenWeekday(getDayMonthYearNew(date)) +const getFullRelativeTime = (date: ISODateString): string => getFullRelativeTimeLegacy(date) + +export { + getDateHourMinutes, + getDayMonthYear, + getFullRelativeTime, + getHourMinutes, + getIsoRelativeTime, + getRelativeTime, + getYearMonthDay, + revYearMonthDay, +} diff --git a/src/legacy/helpers.ts b/src/legacy/helpers.ts new file mode 100644 index 0000000..4d95b22 --- /dev/null +++ b/src/legacy/helpers.ts @@ -0,0 +1,3 @@ +export { arrayToObjectCount } from '../array/arrayToObjectCount.ts' +export { sleep } from '../helpers/sleep.ts' +export { getJsonKeys } from '../object/getJsonKeys.ts' diff --git a/src/legacy/numbers.ts b/src/legacy/numbers.ts new file mode 100644 index 0000000..9631a0a --- /dev/null +++ b/src/legacy/numbers.ts @@ -0,0 +1,23 @@ +import { addLeadingZero } from '../number/addLeadingZero.ts' +import { addTrailingZeros } from '../number/addTrailingZeros.ts' +import { getAverage } from '../number/getAverage.ts' +import { getDiff } from '../number/getDiff.ts' +import { getRandomInRange } from '../number/getRandomInRange.ts' +import { getSum } from '../number/getSum.ts' +import { isEven } from '../number/isEven.ts' +import { normalize } from '../number/normalize.ts' +import { roundTo } from '../number/roundTo.ts' +import { toReadable } from '../number/toReadable.ts' + +export { + addLeadingZero, + addTrailingZeros, + getAverage, + getDiff, + getRandomInRange, + getSum, + isEven, + normalize, + roundTo, + toReadable, +} diff --git a/src/legacy/storage-wrapper.ts b/src/legacy/storage-wrapper.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/legacy/strings.ts b/src/legacy/strings.ts new file mode 100644 index 0000000..4417eb7 --- /dev/null +++ b/src/legacy/strings.ts @@ -0,0 +1,35 @@ +import { isEmptyArray } from '../array/isEmptyArray.ts' +import { notEmptyArray } from '../array/notEmptyArray.ts' +import { getObjectLength } from '../object/getObjectLength.ts' +import { isEmptyObject } from '../object/isEmptyObject.ts' +import { notEmptyObject } from '../object/notEmptyObject.ts' +import { isArray } from '../predicate/isArray.ts' +import { isNull } from '../predicate/isNull.ts' +import { isObject } from '../predicate/isObject.ts' +import { isUndefined } from '../predicate/isUndefined.ts' +import { notNullOrUndefined } from '../predicate/notNullOrUndefined.ts' +import { capitalize } from '../string/capitalize.ts' +import { isEmptyString } from '../string/isEmptyString.ts' +import { isIncluded } from '../string/isIncluded.ts' +import { pluralize } from '../string/pluralize.ts' +import { removeDoubleSpaces } from '../string/removeDoubleSpaces.ts' +import { toHex } from '../string/toHex.ts' + +export { + capitalize, + getObjectLength, + isArray, + isEmptyArray, + isEmptyObject, + isEmptyString, + isIncluded, + isNull, + isObject, + isUndefined, + notEmptyArray, + notEmptyObject, + notNullOrUndefined, + pluralize, + removeDoubleSpaces, + toHex, +} diff --git a/src/legacy/undici.ts b/src/legacy/undici.ts new file mode 100644 index 0000000..0c35106 --- /dev/null +++ b/src/legacy/undici.ts @@ -0,0 +1,173 @@ +import type { Readable } from 'node:stream' +import type { ReadableStream } from 'node:stream/web' +import type { HeaderRecord } from 'undici/types/header.js' +import { Buffer } from 'node:buffer' +import process from 'node:process' +import undici from 'undici' +import pkg from '../../package.json' with { type: 'json' } +const { name, version } = pkg + +const userAgent: string = process.env.USER_AGENT || `${name.replace('@', '')}/${version}` + +const defaultOptions = { + keepAliveTimeout: 30e3, + headersTimeout: 0, + bodyTimeout: 0, + headers: { + 'user-agent': userAgent, + }, +} + +/** + * Convert a readable stream into a final buffer and into a string. + * + * @deprecated Just use fetch `buf = Response.arrayBuffer()` (and perhaps `new Uint8Array(buf)` for bytes) and `Response.text()` instead. + * @param readable - Readable stream. + * @returns - Object with `string` and `buffer` keys. + */ +const convertReadableStream = async ( + readable: ReadableStream | Readable +): Promise<{ string: string; buffer: Buffer }> => { + const chunks = await Array.fromAsync(readable) + const string = chunks.join('') + const buffer = Buffer.concat(chunks) + return { string, buffer } +} + +/** 7_000 milliseconds */ +const DEFAULT_TIMEOUT: number = 7e3 + +type OptionsExtension = { + /** + * (Optional) Request method. + * @type {string} + * @defaultValue `GET` + */ + method?: RequestInit['method'] + + /** + * (Otpional) Request Body. + * @type {BodyInit} + * @defaultValue `null` + */ + body?: any + + /** + * (Optional) Request Headers. + * There is a default header containing the user agent. + * @type {HeaderRecord} + * @defaultValue `{ 'user-agent': 'from ENV or with packageName and packageVersion' }` + */ + headers?: HeaderRecord + + /** + * (Optional) Timeout in milliseconds. Default is 7 seconds. + * @deprecated Use `{ signal: AbortSignal.timeout(options?.timeout ?? 7000) }` as fetch options. + * @type {number} + * @defaultValue `7000` + */ + timeout?: number + + /** + * Usually reserved for the signal of an AbortController. + * Since we have `timeout`, this will always overwrite the `signal` here. + * So don't set it + * @type {never} + * @defaultValue `AbortSignal.timeout(options?.timeout ?? 7000)` + */ + signal?: never + + /** + * Set to `false`, if the request should not return a rejected Promise when the Response is not `ok` + * @deprecated Use modern fetch `Response.ok` and then `throw new Error` or use `Promise.reject` or whatever. + * @type {boolean} + */ + reject?: boolean +} + +/** + * Undici fetch request. + * + * Features + * - Timeout 7 seconds. Can be overriden with `timeout` property in options. + * - Returns rejected promise if Response is not ok. + * - Sets user-agent (with ENV or this utils packgae name and version). + * + * @deprecated Just use native fetch instead or `ofetch` or `axios` if required. But modern fetch solves most problems and works in all Runtimes and Browsers. + * @param url - The URL the request should be made to. + * @param [options] - (Optional) Request options. + * @returns - Object with many deprecated properties. + */ +const request = async ( + url: string | URL, + options: Record & OptionsExtension +): Promise> => { + const requestOptions = { + ...defaultOptions, + method: options?.method ?? 'GET', + body: options?.body ?? null, + signal: AbortSignal.timeout(options?.timeout ?? DEFAULT_TIMEOUT), + } + if (options?.headers) { + requestOptions.headers = { + ...requestOptions.headers, + ...options.headers, + } + } + + const { statusCode, headers, trailers, body } = await undici.request(url, requestOptions) + + // set ok + const ok = statusCode >= 200 && statusCode < 300 + if (!ok && (!options || options?.reject !== false)) return Promise.reject({ statusCode, ok, headers, url }) + + // turn stream into string + const { string, buffer } = await convertReadableStream(body as Readable) + + // detect/ set redirect + const redirect = + statusCode >= 300 && statusCode < 400 && headers.location ? new URL(headers.location as string, url) : null + + // fetch header vars + const contentType = headers['content-type'] + + // parse json if set + let json + try { + json = contentType?.indexOf('application/json') !== -1 ? JSON.parse(string) : null + } catch { + json = null + } + + return Promise.resolve({ + /** @deprecated modern fetch uses `Response.status` instead. */ + statusCode, + /** @deprecated modern fetch has a `Response.ok` value. */ + ok, + /** @deprecated modern fetch has a `Response.redirected` value. And `Response.url` is the final/latest URL. */ + redirect, + headers, + /** @deprecated just use modern fetch's `Response.` */ + contentType, + /** @deprecated Probably just use `Response.headers` instead. Will be removed since unused. */ + trailers, + body, + string, + /** @deprecated Modern fetch has the `Response.arrayBuffer()`. */ + buffer, + /** @deprecated Modern fetch has the `Response.json()`. */ + json, + }) +} + +/** + * Request object, wrapped in a tracer if provided. + * @param [tracer] - (Optional) Tracer object containing a tracer function. + * @param tracer.wrap - (Optional) Object containing `name` and `request`. + * @deprecated Just use native fetch instead or `ofetch` or `axios` if required. But modern fetch solves most problems and works in all Runtimes and Browsers. + * @returns {object} - Request object. + */ +const optionallyWrappedRequest = (tracer?: { wrap: (name: string, request: object) => any }): object => + tracer?.wrap('undici.request', request) || request + +export default optionallyWrappedRequest diff --git a/src/string/crc64.ts b/src/string/crc64.ts new file mode 100644 index 0000000..5c73902 --- /dev/null +++ b/src/string/crc64.ts @@ -0,0 +1,126 @@ +/** + * Performant CRC-64 (ECMA-182) implementation in pure TypeScript without any dependencies. + * @module string + */ + +import { Buffer } from 'node:buffer' + +// ECMA polynomial: 0x42F0E1EBA9EA3693 +const POLY = 0x42f0e1eba9ea3693n + +// 64-bit bit mask: 0xffffffffffffffffn +const MASK64 = (1n << 64n) - 1n + +// cache the table for future usage (in this ESM module). +let _table: bigint[] | null = null + +/** + * Compute value for table. + * @param {bigint} v - The input number as BigInt (accumulator from reduce) + * @returns {bigint} - output as BigInt + */ +const step = (v: bigint): bigint => + // Checks if the MSB of `v` is set. + (v & (1n << 63n)) !== 0n + ? // If the MSB is `1`, then shift v (like multiploy by 2), + // XOR the result with CRC polynomial (modulo polynomial op) and throw overflow away. + ((v << 1n) ^ POLY) & MASK64 + : // Otherwise, shift v and throw overflow away. + (v << 1n) & MASK64 + +/** + * Create a CRC-64 lookup table. + * + * An longer version of this code creating the table: + * ```ts + * const table: bigint[] = Array.from({ length: 256 }) + * for (let i = 0; i < 256; i++) { + * // for non-reflected CRC: start value is byte << 56 + * let v = BigInt(i) << 56n + * for (let j = 0; j < 8; j++) { + * if ((v & (1n << 63n)) !== 0n) { + * v = ((v << 1n) ^ POLY) & MASK64 + * } else { + * v = (v << 1n) & MASK64 + * } + * } + * table[i] = v + * } + * ```` + * + * @returns {bigint[]} - An array of 256 BigInts. + */ +const createTable = (): bigint[] => + _table ?? (_table = Array.from({ length: 256 }, (_, i) => Array.from({ length: 8 }).reduce(step, BigInt(i) << 56n))) + +/** + * Encode a given UTF-8 string to bytes. + * + * @param {string} str - The input string. + * @returns {Uint8Array} - bytes + */ +const encodeUtf8 = (str: string): Uint8Array => + typeof TextEncoder !== 'undefined' ? new TextEncoder().encode(str) : Buffer.from(str, 'utf8') + +/** + * Create a function that updates the CRC-64 state with one byte. + * + * @param {bigint[]} table - The precomputed CRC-64 lookup table with 256 entries. + * @returns - Reducer function + */ +const updateCrc = + (table: bigint[]): ((crc: bigint, b: number) => bigint) => + /** + * Update the CRC value with one byte. + * + * @param {bigint} crc - The current 64-bit CRC value. + * @param {number} b - The next byte (0 - 255) of input data. + * @returns {bigint} - The updated CRC value. + */ + (crc: bigint, b: number): bigint => + // Shift current CRC left by 8 bits (a.k.a multiply by 256). + ((crc << 8n) ^ + // XOR with the precomputed table value. + table[ + Number( + // Take the top 8 bits of the current CRC. + ((crc >> 56n) ^ + // XOR those tops bits with the new data byte. + BigInt(b)) & + // Keep only the lowest 8 bits (mod 256). + 0xffn + ) + ]!) & + // Mask to ensure the result stays within 64 bits. + MASK64 + +/** + * Compute a CRC-64 (ECMA-182) checksum of a given input bytes. + * + * @param {Uint8Array} bytes - The input bytes. + * @returns {bigint} - The CRC-64 checksum of the bytes. + */ +export const crc64 = (bytes: Uint8Array): bigint => bytes.reduce(updateCrc(createTable()), 0n) + +/** + * Convert the given input number into a 16 character long lowercased hex string. + * Fills in leading `0` if the hex string is shorter than 16 chars. + * + * @param {bigint} n - The input number. + * @returns {string} - The 16-character lowercase hex representation of the input. + */ +const toHex = (n: bigint): string => n.toString(16).padStart(16, '0').toLowerCase() + +/** + * Compute a CRC-64 (ECMA-182) checksum of the given UTF-8 string + * + * (so this is not the ISO or Jose implementation.) + * + * @param {string} input - The input string to be checksumed. + * @returns {string} - The 16-char lowercase hex string of the input. + */ +export const crc64String = (input: string): string => { + const bytes: Uint8Array = encodeUtf8(input) + const crc: bigint = crc64(bytes) + return toHex(crc) +} diff --git a/src/string/index.ts b/src/string/index.ts index ef4da1a..8ec18fc 100644 --- a/src/string/index.ts +++ b/src/string/index.ts @@ -5,6 +5,7 @@ */ export { capitalize } from './capitalize.ts' +export { crc64, crc64String } from './crc64.ts' export { isEmptyString } from './isEmptyString.ts' export { isIncluded } from './isIncluded.ts' export { pluralize } from './pluralize.ts' diff --git a/tests/crc.test.ts b/tests/crc.test.ts new file mode 100644 index 0000000..631c9ff --- /dev/null +++ b/tests/crc.test.ts @@ -0,0 +1,70 @@ +import assert from 'node:assert/strict' +import { Buffer } from 'node:buffer' +import { describe, test } from 'node:test' +import { crc64, crc64String } from '../src/string/crc64.ts' + +// Standard check string for CRC algorithms +const stdInput = '123456789' +const stdExpected = '6c40df5f0b497347' // official ECMA-182 check + +describe('CRC-64 string', () => { + test('CRC-64/ECMA known check value', () => { + assert.equal(crc64String(stdInput), stdExpected) + }) + + test('Empty string gives zero CRC', () => { + assert.equal(crc64String(''), '0000000000000000') + }) + + test('Single character', () => { + assert.equal(crc64String('a'), '548f120162451c62') + }) + + test('Different strings produce different CRCs', () => { + const c1 = crc64String('hello') + const c2 = crc64String('world') + assert.notEqual(c1, c2) + }) + + test('Deterministic: same input, same output', () => { + const s = 'functional crc test' + const c1 = crc64String(s) + const c2 = crc64String(s) + assert.equal(c1, c2) + }) + + describe('more tests', () => { + test('test (core-id)', () => { + // NOTE: This is the example from the ARD Core-Id test/example. + assert.equal(crc64String('test'), '0c171b2e54a30c11') + }) + + test('Hello', () => { + assert.equal(crc64String('Hello'), 'ffad3236b47900ab') + }) + + test('hello world', () => { + assert.equal(crc64String('hello world'), '12511f272d9bc22a') + }) + }) +}) + +describe('CRC-64 raw', () => { + test('test (core-id)', () => { + // NOTE: here is no leading `0` filled in (since the CRC checksum is one char shorter.) + assert.equal(crc64(Buffer.from('test', 'utf-8')).toString(16), 'c171b2e54a30c11') + assert.equal(crc64(Buffer.from('test', 'utf-8')), 871194938721897489n) + }) + + test('standard test', () => { + assert.equal(crc64(Buffer.from(stdInput, 'utf-8')), 7800480153909949255n) + assert.equal(crc64(Buffer.from(stdInput, 'utf-8')).toString(16), stdExpected) + }) + + test('empty string', () => { + const checksum = crc64(Buffer.from('', 'utf-8')) + assert.equal(checksum, 0n) + assert.equal(checksum.toString(16), '0') + assert.equal(checksum.toString(), '0') + }) +}) diff --git a/tests/date.test.ts b/tests/date.test.ts index f55aa69..ac046f3 100644 --- a/tests/date.test.ts +++ b/tests/date.test.ts @@ -18,9 +18,6 @@ describe('date utils', () => { it(`getDateHourMinutesLegacy('${testDate}') = '${testLegacyResult}'`, () => { assert.equal(date.getDateHourMinutesLegacy(testDate), testLegacyResult) }) - it(`legacy.getDateHourMinutes('${testDate}') = '${testLegacyResult}'`, () => { - assert.equal(date.legacy.getDateHourMinutes(testDate), testLegacyResult) - }) it(`getDateHourMinutes('${testDate}') = '${newFormat}'`, () => { assert.equal(date.getDateHourMinutes(testDate), newFormat) }) @@ -31,17 +28,9 @@ describe('date utils', () => { it(`getDayMonthYear('${testDate}') = '${newFormat}'`, () => { assert.equal(date.getDayMonthYear(testDate), newFormat) }) - const testLegacyFormat = 'Di, 19. Januar 2038' - it(`legacy.getDayMonthYear('${testDate}') = '${testLegacyFormat}'`, () => { - assert.equal(date.legacy.getDayMonthYear(testDate), testLegacyFormat) - }) }) describe('getFullRelativeTime', () => { - const legacyResult = `Di, 19. Januar 2038 - 03:14 Uhr (in ${relativeYears} Jahren)` - it(`legacy.getFullRelativeTime('${testDate}') = '${legacyResult}'`, () => { - assert.equal(date.legacy.getFullRelativeTime(testDate), legacyResult) - }) const newResult = `Di., 19. Januar 2038 um 03:14 (in ${relativeYears} Jahren)` it(`getFullRelativeTime('${testDate}') = '${newResult}'`, () => { assert.equal(date.getFullRelativeTime(testDate), newResult) @@ -76,11 +65,11 @@ describe('date utils', () => { }) }) - describe('revYearMonthDay', () => { + describe('toDayMonthYear (formerly revYearMonthDay)', () => { const test = '20380119' const testResult = '19012038' - it(`revYearMonthDay('${test}') = '${testResult}'`, () => { - assert.equal(date.revYearMonthDay(test), testResult) + it(`toDayMonthYear('${test}') = '${testResult}'`, () => { + assert.equal(date.toDayMonthYear(test), testResult) }) }) }) diff --git a/tests/legacy/ard.test.mjs b/tests/legacy/ard.test.mjs new file mode 100644 index 0000000..2908f82 --- /dev/null +++ b/tests/legacy/ard.test.mjs @@ -0,0 +1,11 @@ +import { describe, it } from 'node:test' +import { createHashedId } from '../../src/legacy/ard.ts' +import { expect } from './utils.mjs' + +describe('Test ARD Package', () => { + describe('Test ARD-CoreID Hash', () => { + it("createHashedId('test') = 0c171b2e54a30c11", () => { + expect(createHashedId('test')).toEqual('0c171b2e54a30c11') + }) + }) +}) diff --git a/tests/legacy/date.test.mjs b/tests/legacy/date.test.mjs new file mode 100644 index 0000000..f8c4e76 --- /dev/null +++ b/tests/legacy/date.test.mjs @@ -0,0 +1,66 @@ +import { describe, it } from 'node:test' +import * as date from '../../src/legacy/date.ts' +import { expect } from './utils.mjs' + +const testDate = '2038-01-19T03:14:08.000' +const relativeTime = 2147483647000 - Date.now() +const relativeYears = Number.parseInt(relativeTime / (1000 * 60 * 60 * 24 * 365), 10) + +describe('Test DateTime Package', () => { + describe('Test getDateHourMinutes', () => { + const testResult = 'Di, 19. Januar 2038 - 03:14 Uhr' + it(`getDateHourMinutes('${testDate}') = '${testResult}'`, () => { + expect(date.getDateHourMinutes(testDate)).to.equal(testResult) + }) + }) + + describe('Test getDayMonthYear', () => { + const testResult = 'Di, 19. Januar 2038' + it(`getDayMonthYear('${testDate}') = '${testResult}'`, () => { + expect(date.getDayMonthYear(testDate)).to.equal(testResult) + }) + }) + + describe('Test getFullRelativeTime', () => { + const testResult = `Di, 19. Januar 2038 - 03:14 Uhr (in ${relativeYears} Jahren)` + it(`getFullRelativeTime('${testDate}') = '${testResult}'`, () => { + expect(date.getFullRelativeTime(testDate)).to.equal(testResult) + }) + }) + + describe('Test getHourMinutes', () => { + const testResult = '03:14' + it(`getHourMinutes('${testDate}') = '${testResult}'`, () => { + expect(date.getHourMinutes(testDate)).to.equal(testResult) + }) + }) + + describe('Test getIsoRelativeTime', () => { + const testResult = `${testDate} (in ${relativeYears} Jahren)` + it(`getIsoRelativeTime('${testDate}') = '${testResult}'`, () => { + expect(date.getIsoRelativeTime(testDate)).to.equal(testResult) + }) + }) + + describe('Test getRelativeTime', () => { + const testResult = `in ${relativeYears} Jahren` + it(`getRelativeTime('${testDate}') = '${testResult}'`, () => { + expect(date.getRelativeTime(testDate)).to.equal(testResult) + }) + }) + + describe('Test getYearMonthDay', () => { + const testResult = '20380119' + it(`getYearMonthDay('${testDate}') = '${testResult}'`, () => { + expect(date.getYearMonthDay(testDate)).to.equal(testResult) + }) + }) + + describe('Test revYearMonthDay', () => { + const test = '20380119' + const testResult = '19012038' + it(`revYearMonthDay('${test}') = '${testResult}'`, () => { + expect(date.revYearMonthDay(test)).to.equal(testResult) + }) + }) +}) diff --git a/tests/legacy/helpers.test.mjs b/tests/legacy/helpers.test.mjs new file mode 100644 index 0000000..9b7f385 --- /dev/null +++ b/tests/legacy/helpers.test.mjs @@ -0,0 +1,35 @@ +import { describe, it } from 'node:test' +import * as helpers from '../../src/legacy/helpers.ts' +import { expect } from './utils.mjs' + +describe('Test Helpers Package', () => { + describe('Test arrayToObjectCount', () => { + it("arrayToObjectCount(['foo', 'bar', 'bar']) = { bar: 2, foo: 1 }", () => { + const test = ['foo', 'bar', 'bar'] + const result = { bar: 2, foo: 1 } + const testResult = helpers.arrayToObjectCount(test) + expect(testResult.bar).to.equal(result.bar) + expect(testResult.foo).to.equal(result.foo) + }) + }) + + describe('Test getJsonKeys', () => { + it("getJsonKeys({ hello: 'world', foo: 'bar' }) = ['hello', 'foo']", () => { + const test = { hello: 'world', foo: 'bar' } + const result = ['hello', 'foo'] + const testResult = helpers.getJsonKeys(test) + expect(testResult[0]).to.equal(result[0]) + expect(testResult[1]).to.equal(result[1]) + }) + }) + + describe('Test sleep', () => { + it('sleep(1e3) will sleep 1s', async () => { + const time = 1e3 + const before = Date.now() + await helpers.sleep(time) + const after = Date.now() + expect(after - before).to.be.greaterThanOrEqual(time) + }) + }) +}) diff --git a/tests/legacy/numbers.test.mjs b/tests/legacy/numbers.test.mjs new file mode 100644 index 0000000..1b18934 --- /dev/null +++ b/tests/legacy/numbers.test.mjs @@ -0,0 +1,117 @@ +import { describe, it } from 'node:test' +import * as numbers from '../../src/legacy/numbers.ts' +import { expect } from './utils.mjs' + +describe('Test Numbers Package', () => { + describe('Test addLeadingZero', () => { + it("addLeadingZero(1) = '01'", () => { + expect(numbers.addLeadingZero(1)).to.equal('01') + }) + + it("addLeadingZero(10) = '10'", () => { + expect(numbers.addLeadingZero(10)).to.equal('10') + }) + }) + + describe('Test addTrailingZeros', () => { + it("addTrailingZeros(1, 5) = '1.00000'", () => { + expect(numbers.addTrailingZeros(1, 5)).to.equal('1.00000') + }) + + it("addTrailingZeros(1.1, 5) = '1.10000'", () => { + expect(numbers.addTrailingZeros(1.1, 5)).to.equal('1.10000') + }) + + it("addTrailingZeros('1.2', 5) = '1.20000'", () => { + expect(numbers.addTrailingZeros('1.2', 5)).to.equal('1.20000') + }) + + it("addTrailingZeros(2, 2, ',') = '2,00'", () => { + expect(numbers.addTrailingZeros(2, 2, ',')).to.equal('2,00') + }) + + it("addTrailingZeros(2.1, 2, ',') = '2,10'", () => { + expect(numbers.addTrailingZeros(2.1, 2, ',')).to.equal('2,10') + }) + + it("addTrailingZeros('2,2', 2, ','') = '2,20'", () => { + expect(numbers.addTrailingZeros('2,2', 2, ',')).to.equal('2,20') + }) + }) + + describe('Test getAverage', () => { + it('getAverage([1, 2, 3]) = 2', () => { + expect(numbers.getAverage([1, 2, 3])).to.equal(2) + }) + + it('getAverage([1.2, 2.4, 3.6], 1) = 2.4', () => { + expect(numbers.getAverage([1.2, 2.4, 3.6], 1)).to.equal(2.4) + }) + }) + + describe('Test getDiff', () => { + it('getDiff(2, 1) = 1', () => { + expect(numbers.getDiff(2, 1)).to.equal(1) + }) + + it('getDiff(1, 2) = -1', () => { + expect(numbers.getDiff(1, 2)).to.equal(-1) + }) + }) + + describe('Test getRandomInRange', () => { + it('getRandomInRange(1, 5) = 1,2,3,4 or 5', () => { + expect([1, 2, 3, 4, 5]).to.include(numbers.getRandomInRange(1, 5)) + }) + + it('getRandomInRange(5, 9) = 5,6,7,8 or 9', () => { + expect([5, 6, 7, 8, 9]).to.include(numbers.getRandomInRange(5, 9)) + }) + }) + + describe('Test getSum', () => { + it('getSum([1, 2, 3]) = 6', () => { + expect(numbers.getSum([1, 2, 3])).to.equal(6) + }) + + it('getSum([1.2, 2.4, 3.6], 1) = 7.2', () => { + expect(numbers.getSum([1.2, 2.4, 3.6], 1)).to.equal(7.2) + }) + }) + + describe('Test isEven', () => { + it('isEven(2) = true', () => { + expect(numbers.isEven(2)).to.equal(true) + }) + + it('isEven(1) = false', () => { + expect(numbers.isEven(1)).to.equal(false) + }) + }) + + describe('Test normalize', () => { + it('normalize(2, 100) = 0.02', () => { + expect(numbers.normalize(2, 100)).to.equal(0.02) + }) + + it('normalize(80, 100) = 0.8', () => { + expect(numbers.normalize(80, 100)).to.equal(0.8) + }) + }) + + describe('Test roundTo', () => { + it('roundTo(1.23456) = 1.23', () => { + expect(numbers.roundTo(1.23456)).to.equal(1.23) + }) + + it('roundTo(1.23456, 4) = 1.2346', () => { + expect(numbers.roundTo(1.23456, 4)).to.equal(1.2346) + }) + }) + + describe('Test toReadable', () => { + it("toReadable(1234567) = '1.234.567'", () => { + expect(numbers.toReadable(1234567)).to.equal('1.234.567') + }) + }) +}) diff --git a/tests/legacy/strings.test.mjs b/tests/legacy/strings.test.mjs new file mode 100644 index 0000000..63c3ba8 --- /dev/null +++ b/tests/legacy/strings.test.mjs @@ -0,0 +1,177 @@ +import { describe, it } from 'node:test' +import * as strings from '../../src/legacy/strings.ts' +import { expect } from './utils.mjs' + +describe('Test Strings Package', () => { + describe('Test capitalize', () => { + it("capitalize('a') = 'A'", () => { + expect(strings.capitalize('a')).to.equal('A') + }) + it("capitalize('apple') = 'Apple'", () => { + expect(strings.capitalize('apple')).to.equal('Apple') + }) + }) + + describe('Test getObjectLength', () => { + it("getObjectLength({ hello: 'world' }) = 1", () => { + expect(strings.getObjectLength({ hello: 'world' })).to.equal(1) + }) + + it("getObjectLength({ hello: 'world', foo: 'bar' }) = 2", () => { + expect( + strings.getObjectLength({ + hello: 'world', + foo: 'bar', + }) + ).to.equal(2) + }) + }) + + describe('Test isArray', () => { + it("isArray(['hello world']) = true", () => { + expect(strings.isArray(['hello world'])).to.equal(true) + }) + + it("isArray({ hello: 'world' }) = false", () => { + expect(strings.isArray({ hello: 'world' })).to.equal(false) + }) + }) + + describe('Test isEmptyArray', () => { + it('isEmptyArray([]) = true', () => { + expect(strings.isEmptyArray([])).to.equal(true) + }) + + it("isEmptyArray(['hello world']) = false", () => { + expect(strings.isEmptyArray(['hello world'])).to.equal(false) + }) + }) + + describe('Test isEmptyObject', () => { + it('isEmptyObject({}) = true', () => { + expect(strings.isEmptyObject({})).to.equal(true) + }) + + it("isEmptyObject({ hello: 'world' }) = false", () => { + expect(strings.isEmptyObject({ hello: 'world' })).to.equal(false) + }) + }) + + describe('Test isEmptyString', () => { + it("isEmptyString('') = true", () => { + expect(strings.isEmptyString('')).to.equal(true) + }) + + it("isEmptyString('hello world') = false", () => { + expect(strings.isEmptyString('hello world')).to.equal(false) + }) + }) + + describe('Test isIncluded', () => { + it("isIncluded('hello world', 'hello') = true", () => { + expect(strings.isIncluded('hello world', 'hello')).to.equal(true) + }) + + it("isIncluded('hello world', 'earth') = false", () => { + expect(strings.isIncluded('hello world', 'earth')).to.equal(false) + }) + }) + + describe('Test isNull', () => { + it('isNull(null) = true', () => { + expect(strings.isNull(null)).to.equal(true) + }) + + it('isNull(undefined) = false', () => { + expect(strings.isNull(undefined)).to.equal(false) + }) + }) + + describe('Test isObject', () => { + it("isObject({ hello: 'world' }) = true", () => { + expect(strings.isObject({ hello: 'world' })).to.equal(true) + }) + + it("isObject('hello world') = false", () => { + expect(strings.isObject('hello world')).to.equal(false) + }) + }) + + describe('Test isUndefined', () => { + it('isUndefined(undefined) = true', () => { + expect(strings.isUndefined(undefined)).to.equal(true) + }) + + it('isUndefined(null) = false', () => { + expect(strings.isUndefined(null)).to.equal(false) + }) + }) + + describe('Test notEmptyArray', () => { + it("notEmptyArray(['hello world']) = true", () => { + expect(strings.notEmptyArray(['hello world'])).to.equal(true) + }) + + it('notEmptyArray([]) = false', () => { + expect(strings.notEmptyArray([])).to.equal(false) + }) + }) + + describe('Test notEmptyObject', () => { + it("notEmptyObject({ hello: 'world' }) = true", () => { + expect(strings.notEmptyObject({ hello: 'world' })).to.equal(true) + }) + + it('notEmptyObject({}) = false', () => { + expect(strings.notEmptyObject({})).to.equal(false) + }) + }) + + describe('Test notNullOrUndefined', () => { + it("notNullOrUndefined('hello world') = true", () => { + expect(strings.notNullOrUndefined('hello world')).to.equal(true) + }) + + it('notNullOrUndefined(null) = false', () => { + expect(strings.notNullOrUndefined(null)).to.equal(false) + }) + + it('notNullOrUndefined(undefined) = false', () => { + expect(strings.notNullOrUndefined(undefined)).to.equal(false) + }) + }) + + describe('Test pluralize', () => { + it("pluralize(1, 'Apple') = '1 Apple'", () => { + expect(strings.pluralize(1, 'Apple')).to.equal('1 Apple') + }) + + it("pluralize(1000, 'Apple') = '1.000 Apples'", () => { + expect(strings.pluralize(1000, 'Apple')).to.equal('1.000 Apples') + }) + + it("pluralize(1, 'Child', 'Children') = '1 Child'", () => { + expect(strings.pluralize(1, 'Child', 'Children')).to.equal('1 Child') + }) + + it("pluralize(1000, 'Child', 'Children') = '1.000 Children'", () => { + expect(strings.pluralize(1000, 'Child', 'Children')).to.equal('1.000 Children') + }) + }) + + describe('Test removeDoubleSpaces', () => { + it("removeDoubleSpaces('hello world')) = 'hello world'", () => { + expect(strings.removeDoubleSpaces('hello world')).to.equal('hello world') + }) + + it("removeDoubleSpaces('hello world once again')) = 'hello world once again'", () => { + expect(strings.removeDoubleSpaces('hello world once again')).to.equal('hello world once again') + }) + }) + + describe('Test toHex', () => { + it("toHex('hello world')) = '68656c6c6f20776f726c64'", () => { + expect(strings.toHex('hello world')).to.equal('68656c6c6f20776f726c64') + }) + }) +}) diff --git a/tests/legacy/utils.mjs b/tests/legacy/utils.mjs new file mode 100644 index 0000000..d684405 --- /dev/null +++ b/tests/legacy/utils.mjs @@ -0,0 +1,14 @@ +import assert, { equal } from 'node:assert' + +export const expect = (a) => ({ + // chai + to: { + equal: (b) => equal(a, b), + include: (needle) => assert(a.includes(needle)), + be: { + greaterThanOrEqual: (b) => a >= b, + }, + }, + // jest / bun + toEqual: (b) => equal(a, b), +}) diff --git a/tests/storage/utils.test.ts b/tests/storage/utils.test.ts index 814f5e1..7e58dd9 100644 --- a/tests/storage/utils.test.ts +++ b/tests/storage/utils.test.ts @@ -9,10 +9,15 @@ describe('storage utils', () => { assert(isHttp('https:')) }) test('invalid http protocols', () => { + // @ts-expect-error - error is ok assert.equal(isHttp(''), false) + // @ts-expect-error - error is ok assert(!isHttp('http')) + // @ts-expect-error - error is ok assert(!isHttp('https')) + // @ts-expect-error - error is ok assert(!isHttp('http://')) + // @ts-expect-error - error is ok assert(!isHttp('https://')) }) }) @@ -22,7 +27,9 @@ describe('storage utils', () => { assert(isCloudStorage('gs:')) }) test('invalid Cloud Storage protocols', () => { + // @ts-expect-error - error is ok assert(!isCloudStorage('gs')) + // @ts-expect-error - error is ok assert(!isCloudStorage('gs:/')) assert(!isCloudStorage('http:')) assert(!isCloudStorage('https:')) diff --git a/tsdown.config.ts b/tsdown.config.ts index 43c624b..d414fe2 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -3,9 +3,24 @@ import { defineConfig } from 'tsdown' export default defineConfig({ entry: { index: 'src/index.ts', + ard: 'src/ard/index.ts', - dates: 'src/date/index.ts', - string: 'src/string/index.ts', + array: 'src/array/index.ts', + date: 'src/date/index.ts', + helpers: 'src/helpers/index.ts', number: 'src/number/index.ts', + object: 'src/object/index.ts', + predicate: 'src/predicate/index.ts', + storage: 'src/storage/index.ts', + string: 'src/string/index.ts', + + // legacy + 'packages/ard': './src/legacy/ard.ts', + 'packages/date': './src/legacy/date.ts', + 'packages/helpers': './src/legacy/helpers.ts', + 'packages/numbers': './src/legacy/numbers.ts', + 'packages/storage-wrapper': './src/legacy/storage-wrapper.ts', + 'packages/strings': './src/legacy/strings.ts', + 'packages/undici': './src/legacy/undici.ts', }, }) From 7e23e129deb28c9d010f671af9898fb09ec514b8 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Thu, 11 Sep 2025 21:05:04 +0200 Subject: [PATCH 23/42] feat(helper): create minimal fetch wrapper --- package.json | 14 +++++++-- src/helpers/request.ts | 64 ++++++++++++------------------------------ 2 files changed, 29 insertions(+), 49 deletions(-) diff --git a/package.json b/package.json index e47e1fa..11c1508 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "types": "./dist/index.d.ts", "exports": { ".": "./src/index.ts", - "./packages/date": "./src/legacy/date.ts", + "./packages/*": "./src/legacy/*.ts", "./ard": "./src/ard/index.ts", "./date": "./src/date/index.ts" }, @@ -37,8 +37,16 @@ "default": "./dist/date.js" }, "./packages/date": { - "types": "./src/legacy/date.d.ts", - "default": "./src/legacy/date.js" + "types": "./dist/packages/date.d.ts", + "default": "./dist/packages/date.js" + }, + "./packages/strings": { + "types": "./dist/packages/strings.d.ts", + "default": "./dist/packages/strings.js" + }, + "./packages/numbers": { + "types": "./dist/packages/strings.d.ts", + "default": "./dist/packages/strings.js" }, "./packages/*": { "types": "./src/legacy/*.d.ts", diff --git a/src/helpers/request.ts b/src/helpers/request.ts index 91062d4..06de3b1 100644 --- a/src/helpers/request.ts +++ b/src/helpers/request.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'node:buffer' import process from 'node:process' import pkg from '../../package.json' with { type: 'json' } @@ -20,23 +19,28 @@ type OptionsReject = { * @deprecated Don't use `reject`. Just use `Response.ok` instead on a plain fetch. */ reject?: boolean + + /** + * Set to `true`, to bypass status error catching. + * For compat with `ofetch`. + */ + ignoreResponseError?: boolean } /** * Create a fetch request. * Tiny wrapper around the native fetch API. * - * @deprecated If possible, prefer using `fetch` directly or a package like `ofetch` instead. + * NOTE: If possible, prefer using `fetch` directly or a package like `ofetch` instead. * - * @param {string | URL} resource - URL + * @param resource - URL * @param [options] - (Optional) fetch request options. * @returns - fetch response object. */ export const request = async ( - resource: string | URL, + resource: string | URL | Request, options: RequestInit & OptionsTimeout & OptionsReject = {} -): Promise> => { - // TODO: Consider using `defu` to merge with defaul parameters safely and easily. +): Promise => { const requestOptions = { ...options, signal: options.signal ?? AbortSignal.timeout(options?.timeout ?? DEFAULT_TIMEOUT), @@ -45,48 +49,16 @@ export const request = async ( ...(options.headers ?? {}), }, } - // delete non-existing request properties from the Request delete requestOptions.timeout delete requestOptions.reject - const response = await fetch(resource, requestOptions as RequestInit) - const { status, ok, headers, url, body, redirected } = response - - if (!ok && options?.reject === true) return Promise.reject({ statusCode: status, ok, headers, url }) - - const contentType = headers.get('content-type') - - // TODO: change flow, since there are other types like `blob` and text type should be detecte too. - // TODO: consider using `destr` for more performance, safety and Types. - const text = await response.text() - let json: any - try { - json = contentType?.includes('application/json') ? JSON.parse(text) : null - } catch { - json = null + if (!response.ok && options?.reject === true) { + return Promise.reject({ + status: response.status, + ok: response.ok, + headers: response.headers, + url: response.url, + }) } - - return Promise.resolve({ - /** @deprecated Use `Response.status` instead. */ - statusCode: status, - ok, - redirectd: redirected, - /** @deprecated Use `Response.redirected` and if true then `Response.url` is the latest one. */ - redirect: redirected ? url : undefined, - url, - headers, - /** @deprecated Just use Response.headers.get('content-type') instead. */ - contentType, - /** @deprecated Use `Response.headers` instead. */ - trailers: undefined, - /** @deprecated Use a plain fetch if body access is neede. This one hast an already used body. */ - body, - status, - /** @deprecated Use `await Response.text()` instead. This can still be parsed to JSON or a Buffer. */ - string: text, - /** @deprecated Use `Response.arrayBuffer()` instead. A Buffer can be converted to text as well. */ - buffer: Buffer.from(text, 'utf-8'), - /** @deprecated Use `await Response.json()` instead of use `ofetch`. */ - json, - }) + return response } From 7e4062381dba123b2c4b445f0bf037c6aabb0227 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 16:17:31 +0200 Subject: [PATCH 24/42] chore: clean up unused files and adjust READMEs --- .env.example | 3 - .gitignore | 72 +- README.md | 133 +- bin/ard-coreId.mjs | 4 + bun.lock | 91 +- data/.gitkeep | 0 data/ard/.gitkeep | 0 data/ard/categories.json | 6649 -------------------- docs/LINTING.md | 42 - docs/NPM.md | 36 - eslint.config.js | 45 +- index.js | 7 - keys/.gitignore | 1 - package.json | 137 +- packages/ard/README.md | 33 - packages/helpers/README.md | 68 - packages/storage-wrapper/README.md | 172 - packages/strings/README.md | 354 -- packages/undici/README.md | 57 - packages/undici/_options.js | 13 - packages/undici/convertReadableStream.js | 18 - packages/undici/index.js | 5 - packages/undici/request.js | 71 - scripts/ard/coreId.js | 10 - src/ard/coreId.ts | 17 + src/array/README.md | 74 + {packages => src}/date/README.md | 16 +- src/env.ts | 160 + src/helpers/README.md | 32 + src/index.ts | 3 + src/legacy/storage-wrapper.ts | 33 + src/legacy/undici.ts | 4 +- {packages/numbers => src/number}/README.md | 28 +- src/object/README.md | 95 + src/predicate/README.md | 102 + src/storage/index.ts | 46 +- src/storage/utils.ts | 33 +- src/string/README.md | 167 + src/string/base64.ts | 15 + src/string/index.ts | 1 + tests/base64.test.ts | 36 + tests/env.test.ts | 85 + tests/helpers.test.ts | 5 +- tmp/.gitkeep | 0 tsdown.config.ts | 4 +- utils/undici/index.js | 13 - 46 files changed, 1165 insertions(+), 7825 deletions(-) delete mode 100644 .env.example create mode 100644 bin/ard-coreId.mjs delete mode 100644 data/.gitkeep delete mode 100644 data/ard/.gitkeep delete mode 100644 data/ard/categories.json delete mode 100644 docs/LINTING.md delete mode 100644 docs/NPM.md delete mode 100644 index.js delete mode 100644 keys/.gitignore delete mode 100644 packages/ard/README.md delete mode 100644 packages/helpers/README.md delete mode 100644 packages/storage-wrapper/README.md delete mode 100644 packages/strings/README.md delete mode 100644 packages/undici/README.md delete mode 100644 packages/undici/_options.js delete mode 100644 packages/undici/convertReadableStream.js delete mode 100644 packages/undici/index.js delete mode 100644 packages/undici/request.js delete mode 100644 scripts/ard/coreId.js create mode 100644 src/ard/coreId.ts create mode 100644 src/array/README.md rename {packages => src}/date/README.md (84%) create mode 100644 src/env.ts create mode 100644 src/helpers/README.md rename {packages/numbers => src/number}/README.md (84%) create mode 100644 src/object/README.md create mode 100644 src/predicate/README.md create mode 100644 src/string/README.md create mode 100644 src/string/base64.ts create mode 100644 tests/base64.test.ts create mode 100644 tests/env.test.ts delete mode 100644 tmp/.gitkeep delete mode 100644 utils/undici/index.js diff --git a/.env.example b/.env.example deleted file mode 100644 index b1dc0bf..0000000 --- a/.env.example +++ /dev/null @@ -1,3 +0,0 @@ -# set google login -GCP_PROJECT_ID=my-project -GOOGLE_APPLICATION_CREDENTIALS=./keys/gcp.json diff --git a/.gitignore b/.gitignore index 1dda601..bc83d31 100644 --- a/.gitignore +++ b/.gitignore @@ -1,72 +1,8 @@ -dist/ +node_modules +dist -# Logs -logs -*.log -npm-debug.log* -.DS_Store -.env - -# config -config.js - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# Typescript v1 declaration files -typings/ - -# Optional npm cache directory -.npm - -# Optional eslint cache .eslintcache -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# https://yarnpkg.com/getting-started/qa#which-files-should-be-gitignored -.yarn/ -!**/.yarn/cache -!**/.yarn/patches -!**/.yarn/plugins -!**/.yarn/releases -!**/.yarn/sdks -!**/.yarn/versions - -# next.js build output -.next +.env -tmp/* -!tmp/.gitkeep +.DS_Store diff --git a/README.md b/README.md index 9356aab..cdcf393 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,112 @@ -# SWR Audio Lab / Node.js Utils +# `@swrlab/utils` - Node.js utils This repository contains several frequently used packages and scripts for easier access and maintenance. ## Install -Packages are meant to be imported into other projects: +```sh +npm install @swrlab/utils -```js -const undici = require('@swrlab/utils/packages/undici') +# or with pnpm +pnpm add @swrlab/utils + +# or with bun: +bun add @swrlab/utils ``` -Scripts are meant to be run locally, therefore clone the repository and first install dependencies. We prefer `yarn` for this: +## Features -```sh -yarn add @swrlab/utils -``` +- ESM-only (-> requires Node.js v20 at least, preferred ^v22.10 or 24.6 and newer) +- TypeScript support +- tree-shakable (thanks to ESM and separte exports) -Then run the desired script. +## Usage + +Each utility category (`string`, `date`, etc.) has their own export and thus can be imported individually. + +```js +// examples +import { toRelativeTime } from '@swrlab/utils/date' +import { roundTo, getRandomInRange } from '@swrlab/utils/number' +import * as numberUtilities from '@swrlab/utils/number' +``` ## Packages -- [ARD](./packages/ard) - Common internal ARD tools like ID creation -- [Date](./packages/date) - Common date functions and time helpers -- [Helpers](./packages/helpers) - Common functions and helpers -- [Numbers](./packages/numbers) - Common number and math helpers -- [Storage Wrapper](./packages/storage-wrapper) - A utility to wrap file access to local, Google Cloud Storage and AWS S3 file storage -- [Strings](./packages/strings) - Common string, array, object encoding and getter helpers -- [Undici](./packages/undici) - Provides the latest install of [`undici-wrapper`](https://github.com/frytg/undici-wrapper), a wrapper around the [`undici`](https://undici.nodejs.org/) HTTP library +- [ARD](./src/ard) - ARD utilities. +- [Array](./src/array) - Common array utilities. +- [Date](./src/date) - Common date functions and time utilities. +- [Env](./src/env.ts) - Utility to safely work with environment variables (around `process.env`). +- [Helpers](./src/helpers) - Common helper utilities. +- [Number](./src/number) - Common number and math utilities. +- [Object](./src/object) - Common JavaScript object utilities. +- [Predicate](./src/predicate) - Collection of predicate functions, especially useful for TypeScript. +- [Storage Wrapper](./src/storage) - A utility to wrap file access to local, Google Cloud Storage and AWS S3 file storage. +- [String](./src/string) - Common string, array, object encoding and getter utilities. + +### ARD Core ID -### ARD +Import the utility function: ```js -import { createHashedId } from '@swrlab/utils/ard.js' +import { createHashedId } from '@swrlab/utils/ard' +``` + +Then use it to convert a string: + +```js +const myString = 'my-string-to-encode' +const hashedString = createHashedId(myString) +// prints: 6a80b80f748c9b50 +``` -// or globally -import { ard } from '@swrlab/utils' +### Array + +Import the utility function: + +```js +import { arrayToObjectCount, isEmptyArray, notEmptyArray } from '@swrlab/utils/array' +// or (but the approach above is preferred): +import * as array from '@swrlab/utils/array' ``` -## Scripts +### Date + +Date functions and time helpers. + +- [SWR Audio Lab / Date](#swr-audio-lab--date) + - [Install](#install) + - [`getDateHourMinutes` - get date with hours and minutes](#getdatehourminutes---get-date-with-hours-and-minutes) + - [`getDayMonthYear` - get date with month and year](#getdaymonthyear---get-date-with-month-and-year) + - [`getFullRelativeTime` - get full date with relative years](#getfullrelativetime---get-full-date-with-relative-years) + - [`getHourMinutes` - get hours and minutes from iso date](#gethourminutes---get-hours-and-minutes-from-iso-date) + - [`getIsoRelativeTime` - get iso date with relative years](#getisorelativetime---get-iso-date-with-relative-years) + - [`getRelativeTime` - get relative years from iso date](#getrelativetime---get-relative-years-from-iso-date) + - [`getYearMonthDay` - get YYYYMMDD from iso date](#getyearmonthday---get-yyyymmdd-from-iso-date) + - [`revYearMonthDay` - get DDMMYYYY from YYYYMMDD](#revyearmonthday---get-ddmmyyyy-from-yyyymmdd) -### ARD Core ID generator +### Helpers -A CLI to encode strings into the ARD Core ID standard: +### bin / scripts + +#### ARD Core ID Generator + +After installing this package, the command/bin `ard-coreId` is available. + +Run ARD CoreId script, to generate a new coreId from an input string: ```sh -yarn ard:coreId "my-string-to-encode" +# npm's npx +npx --package=@swrlab/utils -c 'ard-coreId hello' + +# pnpm +pnpm --package=@swrlab/utils dlx ard-coreId hello + +# bun +bunx -p @swrlab/utils ard-coreId hello + +# bun (without nodejs-runtime) -> use the `--bun` flag to overwrite runtime. +bunx --bun -p @swrlab/utils ard-coreId hello ``` This will print: @@ -57,20 +119,6 @@ OUTPUT (CRC64-ECMA182): 6a80b80f748c9b50 ``` -## Publish to npm - -Sign in to npm and provide username, password, and email-address: - -```sh -npm login -``` - -Publish updates of this package with: - -```sh -npm publish -``` - ## Changelog A separate Changelog is available in [CHANGELOG.md](CHANGELOG.md) @@ -78,3 +126,12 @@ A separate Changelog is available in [CHANGELOG.md](CHANGELOG.md) ## License See [LICENSE.txt](LICENSE.txt) + +## Development + +### Requirements + +This repo is using _bun_ as package-manager and TypeScript runtime, however all functionality works in plain Node.js with ESM support as well. + +- bun and/or +- node: `>= v24.6` or `^22.18` diff --git a/bin/ard-coreId.mjs b/bin/ard-coreId.mjs new file mode 100644 index 0000000..9722e30 --- /dev/null +++ b/bin/ard-coreId.mjs @@ -0,0 +1,4 @@ +#!/usr/bin/env node +import { coreId } from '../dist/ard-coreId.js' + +coreId() diff --git a/bun.lock b/bun.lock index 467943b..ec332d3 100644 --- a/bun.lock +++ b/bun.lock @@ -3,18 +3,17 @@ "workspaces": { "": { "dependencies": { - "@google-cloud/storage": "^7.17.0", - "@types/node": "^24.3.1", - "abort-controller": "^3.0.0", "luxon": "3.7.2", - "node-crc": "https://github.com/swrlab/node-crc#v2.1.0", "undici": "7.15.0", }, "devDependencies": { + "@google-cloud/storage": "^7.17.0", "@swrlab/style-guide": "^2.0.7", "@types/bun": "^1.2.21", "@types/luxon": "^3.7.1", + "@types/node": "^24.3.1", "eslint": "^9.35.0", + "knip": "^5.63.1", "prettier": "^3.6.2", "tsdown": "^0.14.2", "typescript": "^5.9.2", @@ -88,7 +87,7 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="], - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.3", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@tybys/wasm-util": "^0.10.0" } }, "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.5", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" } }, "sha512-TBr9Cf9onSAS2LQ2+QHx6XcC6h9+RIzJgbqG3++9TUZSH204AwEy5jg3BTQ0VATsyoGj4ee49tN/y6rvaOOtcg=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -100,6 +99,44 @@ "@oxc-project/types": ["@oxc-project/types@0.82.3", "", {}, "sha512-6nCUxBnGX0c6qfZW5MaF6/fmu5dHJDMiMPaioKHKs5mi5+8/FHQ7WGjgQIz1zxpmceMYfdIXkOaLYE+ejbuOtA=="], + "@oxc-resolver/binding-android-arm-eabi": ["@oxc-resolver/binding-android-arm-eabi@11.8.0", "", { "os": "android", "cpu": "arm" }, "sha512-St1Muhuw4EVprhV3/D7M9KmKZZiOUTrRu1UTRKFjJAzuec9eCq4OAEk3bPRXCJlKtdmS2ijvywTN++bjJUmYvg=="], + + "@oxc-resolver/binding-android-arm64": ["@oxc-resolver/binding-android-arm64@11.8.0", "", { "os": "android", "cpu": "arm64" }, "sha512-aNq7fIcJN1+hdWL2vTLd8E/MNIaYa8hL6L2TFwIEo0VuIuaaYxk4/GiZK8w50z7QLDbD5GUMlXwb2ccI5RqL7A=="], + + "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@11.8.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-/mX3v6M9gyyAyV1VZSCbo5A5cJE32zrST5Qs3QxK+S9gc/8d1uNTmPgkoki8E6s561OA9S3KAepeTz+AtxD62w=="], + + "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@11.8.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-OWwbNzDS0adva5xS5H/Lx5t/duek555cgP2j0cF+EdfAhQOEEm5ObSEBJmwipzyq/wAA+pjk5m5XEpFVrXDm5A=="], + + "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@11.8.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-G6NDJ1WbndODtMAvTOeW5PnF0GkGWUjBR5WdkR+MLn54mSwhCu/y+TqXs9QPoTBUlvU9qxCAfA2i9DFfQQFxlQ=="], + + "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@11.8.0", "", { "os": "linux", "cpu": "arm" }, "sha512-/ZazyRR+K0DsJDdzEg8LfgQ8L93oG2nqw388VoAuMW9pP6c8eZpvuqw3z7gwFur7QUb6ZMS6lrUneiPFERbAew=="], + + "@oxc-resolver/binding-linux-arm-musleabihf": ["@oxc-resolver/binding-linux-arm-musleabihf@11.8.0", "", { "os": "linux", "cpu": "arm" }, "sha512-qWreuwBb7+d8oxcqkgyq1lRT3YPsL9Z69LFC6zIrE/evTcYHAbOa6reSQzpVNsivbVZUYwMY12rAl/lWBP3FpA=="], + + "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@11.8.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-m3p8ujvcjf7UOqI1AmOqMRmwhDQBXB/Z99FSCW5U4PY8f0CHBBX+o7uqirOsb7+iIwW7jyDQ7EoqSw79dQMvkA=="], + + "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@11.8.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-YuZQpvoRxUU+6pbqAZmvvKvhYtfOlCc6wunBrIau62xW0oD2xA67KVdq6E9FpvHFjnpgVZW7gcu5PrucgkiEXQ=="], + + "@oxc-resolver/binding-linux-ppc64-gnu": ["@oxc-resolver/binding-linux-ppc64-gnu@11.8.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-O9JETvqjywxeM0VZZaRz8HLSQcC94JBTFT668xaeKIyFDG1QCos8RZC5jJ6u2RJIM2h28pf3LkinINBfayZYOg=="], + + "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@11.8.0", "", { "os": "linux", "cpu": "none" }, "sha512-aaaqf/lbiQBquj/OO56Z0eFnlLHtmwaJ6gCJs9a4koobv2KII8XOb+0f/cn04Ix2elWFmRetKpOoDofhCoYvug=="], + + "@oxc-resolver/binding-linux-riscv64-musl": ["@oxc-resolver/binding-linux-riscv64-musl@11.8.0", "", { "os": "linux", "cpu": "none" }, "sha512-xFYcrvf6J+PWwmqNyA7ktnVTGid0SNkd8Ru+Uv7CxVMK9TF9nIEqTMM+66f8XxcWxWsczwqV7YYnRonIU+Wpyg=="], + + "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@11.8.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-wvZQyx4FjCBf4IvFnR5k3H0BW7aiBAkqxYlHV+C6n4zaEHhhaVSCrXgLsvtVt7ma4Cgay1NQGEA0fXx5W2YiWA=="], + + "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@11.8.0", "", { "os": "linux", "cpu": "x64" }, "sha512-Ihvel1igcoP9BFiVmiwy/CSqCIQzF9ROpdxRLWn1DbZKXNC5TjfiQJjlWrjECc8cPGZwv9yGDZR80oAOgHTE3Q=="], + + "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@11.8.0", "", { "os": "linux", "cpu": "x64" }, "sha512-GSa6/PSd5JTq/h1IIagWiKEMkWOtFJn5mpbbGsoOYEBml4FPIZ6WTZPzKOzOWnVfYDzM+8+xba6QTyIBP4bifg=="], + + "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@11.8.0", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.5" }, "cpu": "none" }, "sha512-z4S+KT5Yfyv+nhimBHKYEi/4ZgkkxRlXkk839g+p9r347RavGUo9hzm3qHkzTxacrDFcGhXLBLN+kSt5B1AWeQ=="], + + "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@11.8.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-BnoBbPHuin8n0fqi1y+Psvur3Y1q6WrJUxKmmBJ2QxQFFq3aaegph5uYINP+i91bokHgwetV9lZMqBmYpu+Itg=="], + + "@oxc-resolver/binding-win32-ia32-msvc": ["@oxc-resolver/binding-win32-ia32-msvc@11.8.0", "", { "os": "win32", "cpu": "ia32" }, "sha512-SUfay8dZz10OJFOtD7GCkr3/7cKvC6vC00+NI5iVSGOTtzyo6vfXXU9SXyX7D/V/9gX8IkbeEOcN+JuYtwVETA=="], + + "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.8.0", "", { "os": "win32", "cpu": "x64" }, "sha512-FA6zw1RV8SsEP4oYJvK6RhTMDpf0Inw5w9/+8ihT0dzOZCIb1hzWcCe5EzDyRvV/Wyqqu43LqVydAYAK3l+rLw=="], + "@pkgr/core": ["@pkgr/core@0.2.9", "", {}, "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA=="], "@quansync/fs": ["@quansync/fs@0.1.5", "", { "dependencies": { "quansync": "^0.2.11" } }, "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA=="], @@ -138,7 +175,7 @@ "@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="], - "@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], @@ -328,8 +365,6 @@ "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], - "detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="], - "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], @@ -428,7 +463,7 @@ "fast-diff": ["fast-diff@1.3.0", "", {}, "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="], - "fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="], + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], @@ -440,6 +475,8 @@ "fault": ["fault@2.0.1", "", { "dependencies": { "format": "^0.2.0" } }, "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ=="], + "fd-package-json": ["fd-package-json@2.0.0", "", { "dependencies": { "walk-up-path": "^4.0.0" } }, "sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ=="], + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], @@ -458,6 +495,8 @@ "format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="], + "formatly": ["formatly@0.3.0", "", { "dependencies": { "fd-package-json": "^2.0.0" }, "bin": { "formatly": "bin/index.mjs" } }, "sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w=="], + "functional-red-black-tree": ["functional-red-black-tree@1.0.1", "", {}, "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g=="], "gaxios": ["gaxios@6.7.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", "node-fetch": "^2.6.9", "uuid": "^9.0.1" } }, "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ=="], @@ -540,6 +579,8 @@ "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + "knip": ["knip@5.63.1", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "jiti": "^2.5.1", "js-yaml": "^4.1.0", "minimist": "^1.2.8", "oxc-resolver": "^11.6.2", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.4.1", "strip-json-comments": "5.0.2", "zod": "^3.25.0", "zod-validation-error": "^3.0.3" }, "peerDependencies": { "@types/node": ">=18", "typescript": ">=5.0.4" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-wSznedUAzcU4o9e0O2WPqDnP7Jttu8cesq/R23eregRY8QYQ9NLJ3aGt9fadJfRzPBoU4tRyutwVQu6chhGDlA=="], + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], "local-pkg": ["local-pkg@1.1.2", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.3.0", "quansync": "^0.2.11" } }, "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A=="], @@ -652,6 +693,8 @@ "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + "mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], @@ -662,8 +705,6 @@ "natural-orderby": ["natural-orderby@5.0.0", "", {}, "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg=="], - "node-crc": ["node-crc@github:swrlab/node-crc#92864dc", { "dependencies": { "@types/node": "^18.11.17", "detect-libc": "^2.0.1" } }, "swrlab-node-crc-92864dc"], - "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], @@ -674,6 +715,8 @@ "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + "oxc-resolver": ["oxc-resolver@11.8.0", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.8.0", "@oxc-resolver/binding-android-arm64": "11.8.0", "@oxc-resolver/binding-darwin-arm64": "11.8.0", "@oxc-resolver/binding-darwin-x64": "11.8.0", "@oxc-resolver/binding-freebsd-x64": "11.8.0", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.8.0", "@oxc-resolver/binding-linux-arm-musleabihf": "11.8.0", "@oxc-resolver/binding-linux-arm64-gnu": "11.8.0", "@oxc-resolver/binding-linux-arm64-musl": "11.8.0", "@oxc-resolver/binding-linux-ppc64-gnu": "11.8.0", "@oxc-resolver/binding-linux-riscv64-gnu": "11.8.0", "@oxc-resolver/binding-linux-riscv64-musl": "11.8.0", "@oxc-resolver/binding-linux-s390x-gnu": "11.8.0", "@oxc-resolver/binding-linux-x64-gnu": "11.8.0", "@oxc-resolver/binding-linux-x64-musl": "11.8.0", "@oxc-resolver/binding-wasm32-wasi": "11.8.0", "@oxc-resolver/binding-win32-arm64-msvc": "11.8.0", "@oxc-resolver/binding-win32-ia32-msvc": "11.8.0", "@oxc-resolver/binding-win32-x64-msvc": "11.8.0" } }, "sha512-iTBXOucxbG40DGURl0cXChZn1WbvXteW4F/U3SZNbhlixFhd3+ZoHU8cmavOSS+Ob9GUPEUoZhGpj1empxwAiQ=="], + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], @@ -754,6 +797,8 @@ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + "smol-toml": ["smol-toml@1.4.2", "", {}, "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g=="], + "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], "spdx-expression-parse": ["spdx-expression-parse@4.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ=="], @@ -770,7 +815,7 @@ "strip-indent": ["strip-indent@4.0.0", "", { "dependencies": { "min-indent": "^1.0.1" } }, "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA=="], - "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + "strip-json-comments": ["strip-json-comments@5.0.2", "", {}, "sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g=="], "strnum": ["strnum@1.0.5", "", {}, "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="], @@ -836,6 +881,8 @@ "vue-eslint-parser": ["vue-eslint-parser@10.2.0", "", { "dependencies": { "debug": "^4.4.0", "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.6.0", "semver": "^7.6.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw=="], + "walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="], + "webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], "whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], @@ -854,6 +901,10 @@ "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + + "zod-validation-error": ["zod-validation-error@3.5.3", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-OT5Y8lbUadqVZCsnyFaTQ4/O2mys4tj7PqhdbBCp7McPwvIEKfPtdA6QfPeFQK2/Rz5LgwmAXRJTugBNBi0btw=="], + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -864,12 +915,18 @@ "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + "@eslint/eslintrc/strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], + "@rolldown/binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.3", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@tybys/wasm-util": "^0.10.0" } }, "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q=="], + "@types/request/@types/node": ["@types/node@22.9.0", "", { "dependencies": { "undici-types": "~6.19.8" } }, "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ=="], "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + "@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="], + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "@unrs/resolver-binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], @@ -932,8 +989,6 @@ "mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], - "node-crc/@types/node": ["@types/node@18.19.64", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ=="], - "regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], "rolldown-plugin-dts/get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], @@ -946,10 +1001,16 @@ "yaml-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@rolldown/binding-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], + "@types/request/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], + "@typescript-eslint/typescript-estree/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + "@unrs/resolver-binding-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], + "bun-types/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], "eslint-plugin-es-x/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -974,8 +1035,6 @@ "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], - "node-crc/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], - "teeny-request/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], "teeny-request/https-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], diff --git a/data/.gitkeep b/data/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/data/ard/.gitkeep b/data/ard/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/data/ard/categories.json b/data/ard/categories.json deleted file mode 100644 index 609c812..0000000 --- a/data/ard/categories.json +++ /dev/null @@ -1,6649 +0,0 @@ -{ - "tree": [ - { - "id": "urn:ard:category-genre:877523a636bebe4a", - "externalId": "vokabel-251973", - "title": "Genre", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-genre:dbb7bf3926b2277a", - "externalId": "vokabel-242033", - "title": "Dokumentation/Reportage", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:39ac8d318f50317b", - "externalId": "vokabel-272072", - "title": "Docutainmentserie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:98f913ef413cd576", - "externalId": "vokabel-272249", - "title": "Erklärfilm", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1dc4559b3ab4ff50", - "externalId": "vokabel-250945", - "title": "Essay", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e06dc83c6b9de023", - "externalId": "vokabel-280992", - "title": "Filminterview", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e816bdfbdecb1a39", - "externalId": "vokabel-271929", - "title": "Geschichtliche und zeitgeschichtliche Doku", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9785baf1382a2a1d", - "externalId": "vokabel-271930", - "title": "Geschichtliche und zeitgeschichtliche Dokuserie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:cd1962bccdd383ba", - "externalId": "vokabel-271949", - "title": "Gesellschafts-, Sozial- und Kulturdoku", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:759b478ad10ce82b", - "externalId": "vokabel-271953", - "title": "Inside-Access- und gesellschaftliche Dokuserie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:fcca0b4e0e45fc3f", - "externalId": "vokabel-272149", - "title": "Interview-Serie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ae70d08b25c53b1f", - "externalId": "vokabel-271970", - "title": "Kulinarische Doku", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ec8031608c2f0d8c", - "externalId": "vokabel-271971", - "title": "Kulinarische Dokuserie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a29d29d7c277d6b0", - "externalId": "vokabel-280993", - "title": "Lyrik-Show", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8706dc32ebe2b0bc", - "externalId": "vokabel-271989", - "title": "Mockumentary", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:658c0beb38498d05", - "externalId": "vokabel-280990", - "title": "Musikdoku", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:0059e74b92bf2079", - "externalId": "vokabel-272032", - "title": "Natur - und Tierdoku", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ba653ad3a4e9b60b", - "externalId": "vokabel-271991", - "title": "Natur- und Tierdokuserie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:277cea0091a3bb96", - "externalId": "vokabel-280991", - "title": "Radiofeature", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a10c79955cd3c474", - "externalId": "vokabel-272209", - "title": "Reisedoku", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:83590c44e8a4cc1b", - "externalId": "vokabel-272150", - "title": "Reportage", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:bdf6cca852244cf5", - "externalId": "vokabel-272229", - "title": "Sportdoku", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e030be7300b274be", - "externalId": "vokabel-272169", - "title": "True-Crime-Doku", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9fa3b979e653449a", - "externalId": "vokabel-272170", - "title": "True-Crime-Serie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:df24fcd13492e4f8", - "externalId": "vokabel-272049", - "title": "Wissenschafts- und Technikdoku", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c3de49ec3a656c79", - "externalId": "vokabel-272069", - "title": "Wissenschafts- und Technikdokuserie", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:9284d97c28f0cba5", - "externalId": "vokabel-242037", - "title": "Film", - "isAudio": false, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:63359a0f3a6d4ceb", - "externalId": "vokabel-242029", - "title": "Action- und Abenteuerfilm", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:696a48d7c22196e6", - "externalId": "vokabel-272409", - "title": "Animationsfilm", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:17651aab7b24a683", - "externalId": "vokabel-242035", - "title": "Beziehungsdrama", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:db7b2ca737d4985f", - "externalId": "vokabel-271890", - "title": "Biopic", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1c6a0e9bcdeac3ea", - "externalId": "vokabel-271893", - "title": "Coming-of-Age-Film", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f4ec08c6d03c92b8", - "externalId": "vokabel-271909", - "title": "Europäischer Filmklassiker", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b28a65b62b32b39e", - "externalId": "vokabel-271950", - "title": "Heimatfilm", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f07a845d82d8850d", - "externalId": "vokabel-271951", - "title": "High-Concept-Komödie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5409ae368d2a9051", - "externalId": "vokabel-272411", - "title": "Horrorfilm", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:376ba66178e6deb8", - "externalId": "vokabel-271952", - "title": "Indie-Komödie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:51bd4a15662461f0", - "externalId": "vokabel-242043", - "title": "Krimi", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:df9f0e6c9258d69a", - "externalId": "vokabel-242044", - "title": "Kultfilm", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9d6fef873bb2e009", - "externalId": "vokabel-242045", - "title": "Kurzfilm/Videokunst", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8706dc32ebe2b0bc", - "externalId": "vokabel-271989", - "title": "Mockumentary", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:04caa4a3809fe3fb", - "externalId": "vokabel-242048", - "title": "Märchen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7d7418ef5ed7edbe", - "externalId": "vokabel-271992", - "title": "Politthriller", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:3f84f904f73ddb2d", - "externalId": "vokabel-271993", - "title": "Programmkino-Film", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b1a6bd7d03416c47", - "externalId": "vokabel-271994", - "title": "Psychothriller", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:39a94242cf94e54c", - "externalId": "vokabel-242050", - "title": "Roadmovie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e6d196ab297df5fa", - "externalId": "vokabel-272009", - "title": "Romantische Komödie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:0b7a9e23e8efa3b5", - "externalId": "vokabel-272392", - "title": "Sci-Fi- & Fantasy-Film", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f1085afe5ddafeb7", - "externalId": "vokabel-272389", - "title": "Sportfilm", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:42a906a03b5516ea", - "externalId": "vokabel-272033", - "title": "TV-Komödie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:fa2b2396278a7d7b", - "externalId": "vokabel-272029", - "title": "Tatort", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8e9b5df4bb3bce93", - "externalId": "vokabel-272390", - "title": "Westernfilm", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ad75aa6b81ecd654", - "externalId": "vokabel-272290", - "title": "Zeichentrickfilm", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:bc4d4ee6dc845c5d", - "externalId": "vokabel-272070", - "title": "Zeitgeschichtliches und historisches Drama", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:93e611e2cec8483a", - "externalId": "vokabel-250942", - "title": "Hörspiel", - "isAudio": true, - "isVideo": false, - "children": [ - { - "id": "urn:ard:category-subgenre:a95eae7965df0cfc", - "externalId": "vokabel-280996", - "title": "Action- und Abenteuer-Hörspiel", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b51a268a8d266228", - "externalId": "vokabel-280999", - "title": "Audio Roadmovie", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ee44b69244ef8ef6", - "externalId": "vokabel-281006", - "title": "Audio-Soap", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:17651aab7b24a683", - "externalId": "vokabel-242035", - "title": "Beziehungsdrama", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b0f0df8a05fcd6b1", - "externalId": "vokabel-281008", - "title": "Bioaud", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:2296130019790f0f", - "externalId": "vokabel-281000", - "title": "Coming-of-Age-Hörspiel", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f2003e61ac16e022", - "externalId": "vokabel-281009", - "title": "Doku-Hörspiel", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ebae4f92cc353a6f", - "externalId": "vokabel-280997", - "title": "Heimat-Hörspiel", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f07a845d82d8850d", - "externalId": "vokabel-271951", - "title": "High-Concept-Komödie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e587313ce34754ba", - "externalId": "vokabel-281003", - "title": "Horror-Hörspiel", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:376ba66178e6deb8", - "externalId": "vokabel-271952", - "title": "Indie-Komödie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:134dabfecfce5763", - "externalId": "vokabel-242042", - "title": "Komödie", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:51bd4a15662461f0", - "externalId": "vokabel-242043", - "title": "Krimi", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f7eac76124cc54bb", - "externalId": "vokabel-280998", - "title": "Kult-Hörspiel", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:295594aebed1d543", - "externalId": "vokabel-281005", - "title": "Kurzgeschichte", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8706dc32ebe2b0bc", - "externalId": "vokabel-271989", - "title": "Mockumentary", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:acb45779ed05b865", - "externalId": "vokabel-281007", - "title": "Mystery-Hörspiel", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:04caa4a3809fe3fb", - "externalId": "vokabel-242048", - "title": "Märchen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7d7418ef5ed7edbe", - "externalId": "vokabel-271992", - "title": "Politthriller", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b1a6bd7d03416c47", - "externalId": "vokabel-271994", - "title": "Psychothriller", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e6d196ab297df5fa", - "externalId": "vokabel-272009", - "title": "Romantische Komödie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:6066f2ebb093399c", - "externalId": "vokabel-281001", - "title": "Sci-Fi- & Fantasy-Hörspiel", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a777d0d74aad6229", - "externalId": "vokabel-281002", - "title": "Sport-Hörspiel", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:fa2b2396278a7d7b", - "externalId": "vokabel-272029", - "title": "Tatort", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:6ba57545173be3d0", - "externalId": "vokabel-281004", - "title": "Western-Hörspiel", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:bc4d4ee6dc845c5d", - "externalId": "vokabel-272070", - "title": "Zeitgeschichtliches und historisches Drama", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:d116f00967227ea9", - "externalId": "vokabel-250943", - "title": "Lesung", - "isAudio": true, - "isVideo": false, - "children": [ - { - "id": "urn:ard:category-subgenre:8d93396b4af7d006", - "externalId": "vokabel-281010", - "title": "Action- und Abenteuer-Lesung", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b51a268a8d266228", - "externalId": "vokabel-280999", - "title": "Audio Roadmovie", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ee44b69244ef8ef6", - "externalId": "vokabel-281006", - "title": "Audio-Soap", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:17651aab7b24a683", - "externalId": "vokabel-242035", - "title": "Beziehungsdrama", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b0f0df8a05fcd6b1", - "externalId": "vokabel-281008", - "title": "Bioaud", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:4a821b57b0c98bb3", - "externalId": "vokabel-281013", - "title": "Coming-of-Age-Lesung", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5d05140aff983f2b", - "externalId": "vokabel-281019", - "title": "Gedicht", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:cf63d880e31de695", - "externalId": "vokabel-281011", - "title": "Heimat-Lesung", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f07a845d82d8850d", - "externalId": "vokabel-271951", - "title": "High-Concept-Komödie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:41419cf9176151ff", - "externalId": "vokabel-281016", - "title": "Horror-Lesung", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:376ba66178e6deb8", - "externalId": "vokabel-271952", - "title": "Indie-Komödie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:134dabfecfce5763", - "externalId": "vokabel-242042", - "title": "Komödie", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:51bd4a15662461f0", - "externalId": "vokabel-242043", - "title": "Krimi", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:0872fabc1923bd20", - "externalId": "vokabel-281012", - "title": "Kult-Lesung", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:295594aebed1d543", - "externalId": "vokabel-281005", - "title": "Kurzgeschichte", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8706dc32ebe2b0bc", - "externalId": "vokabel-271989", - "title": "Mockumentary", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1ff5f5e1567209b8", - "externalId": "vokabel-281018", - "title": "Mystery-Lesung", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:04caa4a3809fe3fb", - "externalId": "vokabel-242048", - "title": "Märchen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7d7418ef5ed7edbe", - "externalId": "vokabel-271992", - "title": "Politthriller", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b1a6bd7d03416c47", - "externalId": "vokabel-271994", - "title": "Psychothriller", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e6d196ab297df5fa", - "externalId": "vokabel-272009", - "title": "Romantische Komödie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:3e6ca63d178e878e", - "externalId": "vokabel-281020", - "title": "Sachbuch-Lesung", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c4a05f2e44b53cd9", - "externalId": "vokabel-281014", - "title": "Sci-Fi- & Fantasy-Lesung", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8650bec5ed5f0a4a", - "externalId": "vokabel-281015", - "title": "Sport-Lesung", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:fa2b2396278a7d7b", - "externalId": "vokabel-272029", - "title": "Tatort", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:03b17d12be8b676c", - "externalId": "vokabel-281017", - "title": "Western-Lesung", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:bc4d4ee6dc845c5d", - "externalId": "vokabel-272070", - "title": "Zeitgeschichtliches und historisches Drama", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-subgenre:a2041d0aad1fdae1", - "externalId": "vokabel-281189", - "title": "Live-Ereignis", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-genre:0fb71ec3c139dfe2", - "externalId": "vokabel-242062", - "title": "Nachrichten/Information", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:d4d8354408c34b46", - "externalId": "vokabel-276030", - "title": "Bericht-Format", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ab4b324eee227b62", - "externalId": "vokabel-276029", - "title": "Interview-Format", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5139f6935b172660", - "externalId": "vokabel-276032", - "title": "Nachrichten", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9628d4afa1297dd5", - "externalId": "vokabel-276031", - "title": "Nachrichten-Magazin", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:feb8607e35aabef9", - "externalId": "vokabel-242053", - "title": "Serie", - "isAudio": false, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:1ca69d05dc8c7ccf", - "externalId": "vokabel-242030", - "title": "Action- und Abenteuerserie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:16f94fdd24c0a6c2", - "externalId": "vokabel-272410", - "title": "Animationsserie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a4e82badd135a87b", - "externalId": "vokabel-271889", - "title": "Beziehungsdramaserie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:998bcd4c9e3eaecc", - "externalId": "vokabel-271891", - "title": "Comedyserie & Dramedy", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8b7f0fcc36dda29c", - "externalId": "vokabel-271910", - "title": "Familienserie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:93188c0a7714cbe4", - "externalId": "vokabel-272412", - "title": "Horrorserie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d1e3d781c3240b3b", - "externalId": "vokabel-271969", - "title": "Krimiserie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f895db380d038098", - "externalId": "vokabel-271990", - "title": "Mystery-Serie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:04caa4a3809fe3fb", - "externalId": "vokabel-242048", - "title": "Märchen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:498a7fc841059526", - "externalId": "vokabel-272393", - "title": "Sci-Fi- & Fantasy-Serie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:709a2407c1d60993", - "externalId": "vokabel-242054", - "title": "Soap/Telenovela", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:85b8249cc16b4d5f", - "externalId": "vokabel-272030", - "title": "Teenserie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c748c57768817bcc", - "externalId": "vokabel-272031", - "title": "Thriller-Serie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:cc6bbc1f12d1f800", - "externalId": "vokabel-272391", - "title": "Westernserie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d2e6ad61670de670", - "externalId": "vokabel-272289", - "title": "Zeichentrickserie", - "isAudio": false, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:febdaf0d756e6ace", - "externalId": "vokabel-272071", - "title": "Zeitgeschichtliche & historische Dramaserie", - "isAudio": false, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:efde47fb53348b25", - "externalId": "vokabel-242139", - "title": "Show/Magazin", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:5e9aef706400f579", - "externalId": "vokabel-271892", - "title": "Comedy-Show", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c3e107d7a19c198b", - "externalId": "vokabel-276015", - "title": "Gottesdienst", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c82280790634c3c7", - "externalId": "vokabel-276010", - "title": "Kochshow", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:6e4f8c459fe15749", - "externalId": "vokabel-280995", - "title": "Kommentar", - "isAudio": true, - "isVideo": false, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9580b0e2b469e59c", - "externalId": "vokabel-242084", - "title": "Konzert", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8111e63c08762f18", - "externalId": "vokabel-276014", - "title": "Kultur-Magazin", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:2b91135c76115639", - "externalId": "vokabel-271972", - "title": "Late-Night-Show", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:04f025eb5ba2423e", - "externalId": "vokabel-276016", - "title": "Literaturshow", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a7ed514d751c4530", - "externalId": "vokabel-272369", - "title": "Musik-Show", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8ad26192afdef554", - "externalId": "vokabel-276011", - "title": "Polit-Magazin", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:646affeaddc60930", - "externalId": "vokabel-272332", - "title": "Polit-Talkshow", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:2cbf6dae360b61da", - "externalId": "vokabel-280994", - "title": "Reality-Show", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d87e564793fd7514", - "externalId": "vokabel-272370", - "title": "Samstagabend-Show", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7b5c6cda26ba07e8", - "externalId": "vokabel-272073", - "title": "Satire-Show", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:994291a1cf9cc5de", - "externalId": "vokabel-272010", - "title": "Sketch-Show", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:82e28e0a6604dcb3", - "externalId": "vokabel-272309", - "title": "Stand-up-Show", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:abcf8ec8d3113cf2", - "externalId": "vokabel-242058", - "title": "Talkshow", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:4dc343ae55e0aee1", - "externalId": "vokabel-276012", - "title": "Verbraucher-Magazin", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9825964c69609276", - "externalId": "vokabel-250947", - "title": "Vortrag", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a37bddd627f85285", - "externalId": "vokabel-272331", - "title": "Wissens-Show", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - } - ] - }, - { - "id": "urn:ard:category-genre:095767dfc2c20920", - "externalId": "vokabel-251974", - "title": "Inhaltskategorien", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-genre:e93f6f237afb0a61", - "externalId": "vokabel-242059", - "title": "Aktuelles", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:8a56dd1492edb2c4", - "externalId": "vokabel-242060", - "title": "Katastrophen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c8a63cff3b078457", - "externalId": "vokabel-242061", - "title": "Krisengebiete", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7c9c47d6be64b11d", - "externalId": "vokabel-281021", - "title": "Regionales", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:4d47ff2868d3e971", - "externalId": "vokabel-242063", - "title": "Terrorismus", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f4192f4e743ae72a", - "externalId": "vokabel-250923", - "title": "Verkehrsservice", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c365bb519caf5e1b", - "externalId": "vokabel-242064", - "title": "Wahl", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:81955aba35456888", - "externalId": "vokabel-242065", - "title": "Wetter", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:2724533cba48fb3c", - "externalId": "vokabel-242148", - "title": "Geschichte", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:fbf219b56778cc86", - "externalId": "vokabel-250951", - "title": "ARD Retro", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:65d4b2d713a2cdaf", - "externalId": "vokabel-242149", - "title": "DDR", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1a47b5ddf543fd8b", - "externalId": "vokabel-242150", - "title": "Nationalsozialismus", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:58b754365ca9cb18", - "externalId": "vokabel-242151", - "title": "Weltkrieg I", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9fa6760aa69790ad", - "externalId": "vokabel-242152", - "title": "Weltkrieg II", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:4ba6d7f0411c6835", - "externalId": "vokabel-242103", - "title": "Gesellschaft", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:bf64595eb43357b3", - "externalId": "vokabel-242096", - "title": "Arbeit", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:fd94b8b51dd96120", - "externalId": "vokabel-242097", - "title": "Ausbildung", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e1d03046f5200ff4", - "externalId": "vokabel-242098", - "title": "Bildung", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1830119e8e686b7a", - "externalId": "vokabel-242068", - "title": "Digitale Welt/Internet", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e39e20133b6b53b2", - "externalId": "vokabel-250929", - "title": "Divers/Inter", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a320d1ad5cca3967", - "externalId": "vokabel-242099", - "title": "Erziehung", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8cb7f5ccbb223380", - "externalId": "vokabel-242100", - "title": "Familie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ce47142712c80513", - "externalId": "vokabel-242101", - "title": "Frauen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:0956361be8f65ea6", - "externalId": "vokabel-242102", - "title": "Freizeit", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:52501f3f0ad4f2d2", - "externalId": "vokabel-281044", - "title": "Gemeinnützigkeit", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a16ec1f892816521", - "externalId": "vokabel-250928", - "title": "Hobby", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d2bda11a1c3f8d92", - "externalId": "vokabel-242121", - "title": "Inklusion", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c5849389b560df5f", - "externalId": "vokabel-242104", - "title": "Integration", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:877472621c8ae9cc", - "externalId": "vokabel-242105", - "title": "Islam", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:4065505ee6b4b279", - "externalId": "vokabel-242106", - "title": "Jugend", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:0295b1b54f5e84ea", - "externalId": "vokabel-242107", - "title": "Kinder", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d45c89c235f00cd6", - "externalId": "vokabel-242041", - "title": "Kinderprogramm", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1ed13946a7a7ea3e", - "externalId": "vokabel-242108", - "title": "Kriminalität", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5c21d8ad0e4ddcad", - "externalId": "vokabel-242109", - "title": "Liebe", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:23b2dfa7e8acec89", - "externalId": "vokabel-242110", - "title": "Lifestyle", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a6531c70bb7881af", - "externalId": "vokabel-242112", - "title": "Medien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e4a3fd9b1292b73c", - "externalId": "vokabel-242113", - "title": "Migration", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:6a81b9e2e6ee0056", - "externalId": "vokabel-242114", - "title": "Mode", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:61423e4c4146da1a", - "externalId": "vokabel-242111", - "title": "Männer", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:bd2a490b7a780bf5", - "externalId": "vokabel-250927", - "title": "Prominente", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:287158094f0436c5", - "externalId": "vokabel-242115", - "title": "Religion", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ef607a35b53a6d70", - "externalId": "vokabel-242116", - "title": "Religionen der Welt", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ad909bde1cd05be3", - "externalId": "vokabel-242117", - "title": "Schicksale", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b1d4132df4293537", - "externalId": "vokabel-242118", - "title": "Senioren", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f324f2c65dc303a4", - "externalId": "vokabel-242119", - "title": "Sexualität", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:904d40f1b5d5bb01", - "externalId": "vokabel-242120", - "title": "Weihnachten", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:f5c5da1e740c82e0", - "externalId": "vokabel-242079", - "title": "Kultur", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:f97d8401edb0dc3b", - "externalId": "vokabel-281023", - "title": "Alte Musik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:dcb3d6a7ba2b0943", - "externalId": "vokabel-242080", - "title": "Architektur", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1b63797a04961e0d", - "externalId": "vokabel-281040", - "title": "Bildende Kunst", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:78757b624e0d0c06", - "externalId": "vokabel-242095", - "title": "Brauchtum", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:775fc07819cc6b51", - "externalId": "vokabel-281024", - "title": "Country", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:35af2193b0265dc2", - "externalId": "vokabel-281025", - "title": "CrossOver", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f2be03af4a180677", - "externalId": "vokabel-281026", - "title": "Dance", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:41ffa137f16fb7aa", - "externalId": "vokabel-281039", - "title": "Darstellende Kunst", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:030f40dc58858139", - "externalId": "vokabel-281038", - "title": "Design", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1f4bc82fb07cefed", - "externalId": "vokabel-281037", - "title": "Elektronische Musik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b04ee244e3f230e4", - "externalId": "vokabel-281027", - "title": "Ernste Musik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ac0a6ab70b0b5e30", - "externalId": "vokabel-281028", - "title": "Ethno/Weltmusik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:59939891ad7c289e", - "externalId": "vokabel-281041", - "title": "Film & Serien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:38cb8adc29ac66d3", - "externalId": "vokabel-250925", - "title": "Fotografie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:eefa8b5ca2e168a3", - "externalId": "vokabel-281029", - "title": "Geistliche Musik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:91698c5644005887", - "externalId": "vokabel-281030", - "title": "Hip-Hop", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d3996dbdedea6e14", - "externalId": "vokabel-281031", - "title": "Hitparade", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9e43374c13c13fd0", - "externalId": "vokabel-242081", - "title": "Jazz", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:14884f8117d435a1", - "externalId": "vokabel-281032", - "title": "Kammermusik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:59521570e9ff6465", - "externalId": "vokabel-242082", - "title": "Kino", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1ba2f49b401552f6", - "externalId": "vokabel-242083", - "title": "Klassik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d77051091d83d30f", - "externalId": "vokabel-242085", - "title": "Kunst", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ffdaa8e0d3923d66", - "externalId": "vokabel-250926", - "title": "Künstler", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:10617335e7bd88ba", - "externalId": "vokabel-242086", - "title": "Literatur", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b902f85ece92fa15", - "externalId": "vokabel-250950", - "title": "Mundart", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:529192de4e57be29", - "externalId": "vokabel-242087", - "title": "Musical", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:4ed51a2da6aed0fd", - "externalId": "vokabel-242088", - "title": "Musik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:0c25fbc60f44e66e", - "externalId": "vokabel-242089", - "title": "Musik-Festival", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5678ae6abe3e0332", - "externalId": "vokabel-281033", - "title": "Neue Musik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d85aea134a42b458", - "externalId": "vokabel-281034", - "title": "Oldies", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:73b6fccce9a5d64a", - "externalId": "vokabel-242090", - "title": "Oper", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:463a45482975d568", - "externalId": "vokabel-242049", - "title": "Porträt/Biografie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9aaa0bf8e3a882cb", - "externalId": "vokabel-281035", - "title": "R&B", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:31461d27404fe0d9", - "externalId": "vokabel-242091", - "title": "Rock/Pop", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7a3b6b3780465040", - "externalId": "vokabel-250924", - "title": "Schlager", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:88a5c5d1d4f563a5", - "externalId": "vokabel-276129", - "title": "Show", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5dbb29c41996d97e", - "externalId": "vokabel-281036", - "title": "Sinfonische Musik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:84611ebf8199fca2", - "externalId": "vokabel-250948", - "title": "Soundart", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9e82baad5742732b", - "externalId": "vokabel-281042", - "title": "Spiele", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5f34b470935ec9c3", - "externalId": "vokabel-250944", - "title": "Sport", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f6573f1bba71bb6c", - "externalId": "vokabel-242092", - "title": "Theater", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:dc725b46fea845b8", - "externalId": "vokabel-281043", - "title": "Videogames/Games", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b4a7def0139b8dff", - "externalId": "vokabel-242093", - "title": "Volksmusik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:3a859a89e7e73a95", - "externalId": "vokabel-242094", - "title": "Weltmusik", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:dd5697e10f7da63e", - "externalId": "vokabel-242153", - "title": "Politik", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:5374d398fb011154", - "externalId": "vokabel-242154", - "title": "EU", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1184327352eb27c7", - "externalId": "vokabel-242155", - "title": "Extremismus", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d695104fa8d57c72", - "externalId": "vokabel-242156", - "title": "Krieg", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:15ac8326e601d627", - "externalId": "vokabel-242122", - "title": "Ratgeber", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:0474996d669105ae", - "externalId": "vokabel-242067", - "title": "Auto/Verkehr", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:575c62cd4febe0b4", - "externalId": "vokabel-242123", - "title": "Ernährung", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9c0d2719dd8a6396", - "externalId": "vokabel-250930", - "title": "Fitness", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:10a0fed4a33ec441", - "externalId": "vokabel-281045", - "title": "Fremdsprachen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d97e26b4bb9757de", - "externalId": "vokabel-242124", - "title": "Geld", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9b8ec75f127d614d", - "externalId": "vokabel-242125", - "title": "Gesundheit", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d7b1dce859009ff4", - "externalId": "vokabel-281046", - "title": "Handarbeit", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5c9fe563e8433af8", - "externalId": "vokabel-242126", - "title": "Haus/Garten", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:defdc6f274605505", - "externalId": "vokabel-250931", - "title": "Haushalt", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1e6f048841a90c6b", - "externalId": "vokabel-242127", - "title": "Kochen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:022b8c7ba95062bf", - "externalId": "vokabel-242128", - "title": "Recht", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:6c60913acf218112", - "externalId": "vokabel-242074", - "title": "Reise", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:b5429fb6a6cd2282", - "externalId": "vokabel-242140", - "title": "Umwelt", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:f7b27e5d0f271411", - "externalId": "vokabel-242141", - "title": "Berge", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:19ece4ce8e5e0eb0", - "externalId": "vokabel-250932", - "title": "Klima", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:30a35c61f5194fa4", - "externalId": "vokabel-242142", - "title": "Meer", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7253bd8a5cf37937", - "externalId": "vokabel-242143", - "title": "Natur", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:fc71f9f3a88fce5d", - "externalId": "vokabel-242144", - "title": "Tiere", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:be8118180165f8ce", - "externalId": "vokabel-242145", - "title": "Zoogeschichten", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5b1c052527b43823", - "externalId": "vokabel-250933", - "title": "Ökologie", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:baa9a94db58f092e", - "externalId": "vokabel-242132", - "title": "Unterhaltung", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:f85948a61c653fbd", - "externalId": "vokabel-242133", - "title": "Boulevard", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:767b0cdfe81988d7", - "externalId": "vokabel-242134", - "title": "Comedy/Satire", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:348bed3441f3be44", - "externalId": "vokabel-242135", - "title": "Fasching/Karneval", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f39acf08bbcde5f1", - "externalId": "vokabel-242136", - "title": "Quiz", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b16a2ee31227d362", - "externalId": "vokabel-242137", - "title": "Royalty", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ad2ea610fadebdb6", - "externalId": "vokabel-242138", - "title": "Rückblicke", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:79903a24fb5ba37b", - "externalId": "vokabel-242146", - "title": "Wirtschaft", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:3b60dbcf52b195e8", - "externalId": "vokabel-242147", - "title": "Börse", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:97cea0b77a22b9da", - "externalId": "vokabel-250935", - "title": "Dienstleistungen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:122f636029f6d4fc", - "externalId": "vokabel-250937", - "title": "Globalisierung", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:50df828b801ce26f", - "externalId": "vokabel-250936", - "title": "Handel", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d53e415cd3c88f49", - "externalId": "vokabel-250934", - "title": "Industrie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5ac0f07527825de9", - "externalId": "vokabel-242069", - "title": "Landwirtschaft", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:46847886cf7b333d", - "externalId": "vokabel-242066", - "title": "Wissen", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:bb8d65ea445aeaa8", - "externalId": "vokabel-281022", - "title": "Beziehung", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:78766394ef9ea4e9", - "externalId": "vokabel-258458", - "title": "Luftfahrt/Raumfahrt", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:2553f77fc1636dcd", - "externalId": "vokabel-242070", - "title": "Medizin", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:67a3169468895b5e", - "externalId": "vokabel-242071", - "title": "Naturwissenschaft", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a0b234a892b700eb", - "externalId": "vokabel-242072", - "title": "Philosophie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e242d5433b5d3678", - "externalId": "vokabel-242073", - "title": "Psychologie", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:2e9070d166cbb781", - "externalId": "vokabel-242075", - "title": "Technik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e98152ed9cf5ec34", - "externalId": "vokabel-242076", - "title": "Weltraum", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ab71b306351fdaa7", - "externalId": "vokabel-242077", - "title": "Wissenschaft", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b7353bf5dde6b473", - "externalId": "vokabel-242078", - "title": "Zukunft", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - } - ] - }, - { - "id": "urn:ard:category-genre:4ba786346b283fb3", - "externalId": "vokabel-251975", - "title": "Ortsangaben", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:9465f1a4013f4ae1", - "externalId": "vokabel-242157", - "title": "Afghanistan", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:0eb2a143a997291f", - "externalId": "vokabel-242214", - "title": "Afrika", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:057126ed0e3ff353", - "externalId": "vokabel-242211", - "title": "Alpen und Berge", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:4c4240a8007d1f8c", - "externalId": "vokabel-242215", - "title": "Asien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8b536294fa434439", - "externalId": "vokabel-242216", - "title": "Australien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:50580b53d372ce8d", - "externalId": "vokabel-242190", - "title": "Baden-Württemberg", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:4c9b0a7868e58cbb", - "externalId": "vokabel-250939", - "title": "Balkan", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:2be2ecc8ab4d58cf", - "externalId": "vokabel-251988", - "title": "Baltikum", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:12a8eab87a98f81e", - "externalId": "vokabel-242191", - "title": "Bayern", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:cad198bc402c12a6", - "externalId": "vokabel-242159", - "title": "Belgien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:69120d2302a76e5c", - "externalId": "vokabel-251989", - "title": "Benelux", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d5b9c88480a6a3ab", - "externalId": "vokabel-242192", - "title": "Berlin", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9749296f294c9538", - "externalId": "vokabel-242193", - "title": "Brandenburg", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:196b6d16dd302252", - "externalId": "vokabel-242194", - "title": "Bremen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a9b82a8ba83aaa03", - "externalId": "vokabel-242160", - "title": "Deutschland", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c9a3837f53a972aa", - "externalId": "vokabel-242217", - "title": "Europa", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7e95027e4df6dac4", - "externalId": "vokabel-251983", - "title": "Frankfurt am Main", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:eb48cb6001d09c90", - "externalId": "vokabel-242161", - "title": "Frankreich", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:2c59e95cfbeec725", - "externalId": "vokabel-242162", - "title": "Griechenland", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:6ea908b75204f1b6", - "externalId": "vokabel-242163", - "title": "Großbritannien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5b9b8cfd74da14c1", - "externalId": "vokabel-242195", - "title": "Hamburg", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:3f486a9ae65b6408", - "externalId": "vokabel-242130", - "title": "Heimat", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9c8aaec18ee44f74", - "externalId": "vokabel-242196", - "title": "Hessen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e08b4ccea67846dc", - "externalId": "vokabel-242164", - "title": "Indien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a27bad250f92704f", - "externalId": "vokabel-242165", - "title": "Irak", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:656a8f19f5ac2bfa", - "externalId": "vokabel-242166", - "title": "Iran", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:279a6ef25c461d69", - "externalId": "vokabel-242167", - "title": "Israel", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:3bdee601b4bf73bd", - "externalId": "vokabel-242168", - "title": "Italien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:792e07ea1d55452e", - "externalId": "vokabel-242169", - "title": "Japan", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:06bd00e0fbb4750a", - "externalId": "vokabel-242170", - "title": "Jemen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:444de10b525e4399", - "externalId": "vokabel-242171", - "title": "Kuba", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7db88b714fb1529b", - "externalId": "vokabel-242131", - "title": "Land/Leute", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f0b74607b98a6dae", - "externalId": "vokabel-251984", - "title": "Leipzig", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:835cc337a860182c", - "externalId": "vokabel-242172", - "title": "Libyen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b247a7ec10605b3d", - "externalId": "vokabel-251985", - "title": "Mainz", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:de7a4f2a270e79e7", - "externalId": "vokabel-242197", - "title": "Mecklenburg-Vorpommern", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c1ac22dc018a2ebf", - "externalId": "vokabel-242173", - "title": "Mexiko", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1607d2359d1c251c", - "externalId": "vokabel-250940", - "title": "Mittelmeer", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:755685d0ea5e0088", - "externalId": "vokabel-251986", - "title": "München", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1a809c23f9ffb4e2", - "externalId": "vokabel-272489", - "title": "Nahost", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:4f8e66a5f5f699d5", - "externalId": "vokabel-242174", - "title": "Niederlande", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c23ec7d9cff71733", - "externalId": "vokabel-242198", - "title": "Niedersachsen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:0d7e874e5c1caf46", - "externalId": "vokabel-242175", - "title": "Nigeria", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d5e70b8cbb501c7e", - "externalId": "vokabel-242218", - "title": "Nordamerika", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:66a6a9140027ada3", - "externalId": "vokabel-242207", - "title": "Norddeutschland", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ca6fa572a622f4f3", - "externalId": "vokabel-242176", - "title": "Nordkorea", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:80ce2632661d21a0", - "externalId": "vokabel-242199", - "title": "Nordrhein-Westfalen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c26004d1f401a8e6", - "externalId": "vokabel-242212", - "title": "Nordsee", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:16810a29e4465e78", - "externalId": "vokabel-251990", - "title": "Orient", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5471ebc24dac68eb", - "externalId": "vokabel-251991", - "title": "Ostasien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7ae221e7e8dec377", - "externalId": "vokabel-242208", - "title": "Ostdeutschland", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8090e53a5deb9e75", - "externalId": "vokabel-242213", - "title": "Ostsee", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:94dbcc6ae731acb4", - "externalId": "vokabel-242178", - "title": "Pakistan", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9360c9feb792335e", - "externalId": "vokabel-251992", - "title": "Polarkreis", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d62b2d814edb9a27", - "externalId": "vokabel-242179", - "title": "Polen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ff5d213880fc1184", - "externalId": "vokabel-242180", - "title": "Portugal", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e884ed6df45b1ac9", - "externalId": "vokabel-242200", - "title": "Rheinland-Pfalz", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:bdadc0d329162717", - "externalId": "vokabel-242181", - "title": "Russland", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:aa740c865db12c5a", - "externalId": "vokabel-242201", - "title": "Saarland", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:6d652ebaa78f77ef", - "externalId": "vokabel-242202", - "title": "Sachsen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:2f95cf510e65417c", - "externalId": "vokabel-242203", - "title": "Sachsen-Anhalt", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a1b78b28fa19f616", - "externalId": "vokabel-242204", - "title": "Schleswig-Holstein", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7abce2efd3287ca2", - "externalId": "vokabel-242182", - "title": "Schweden", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:384c03047ac24a31", - "externalId": "vokabel-242183", - "title": "Schweiz", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:0e6beb93c10fba28", - "externalId": "vokabel-250938", - "title": "Skandinavien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b66e477d8ebefd5b", - "externalId": "vokabel-242184", - "title": "Somalia", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f49ea6962754cbc8", - "externalId": "vokabel-242185", - "title": "Spanien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:37a6643b43b4361b", - "externalId": "vokabel-251987", - "title": "Stuttgart", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:338f84aadd6a907d", - "externalId": "vokabel-242186", - "title": "Syrien", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9717ea6712ba2aed", - "externalId": "vokabel-242219", - "title": "Südamerika", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:3812c00c4134f5e4", - "externalId": "vokabel-242209", - "title": "Süddeutschland", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e3476ac353f3c085", - "externalId": "vokabel-242205", - "title": "Thüringen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:717f65417480a6ee", - "externalId": "vokabel-242187", - "title": "Türkei", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:2fcb0c593593fea9", - "externalId": "vokabel-242189", - "title": "USA", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:6d3bedb29c79c83a", - "externalId": "vokabel-242188", - "title": "Ukraine", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:4781c706a7d5c5c0", - "externalId": "vokabel-242210", - "title": "Westdeutschland", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:88217957e9c62435", - "externalId": "vokabel-242158", - "title": "Ägypten", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:889f44990fc8c260", - "externalId": "vokabel-242177", - "title": "Österreich", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - }, - { - "id": "urn:ard:category-genre:8cb6a40891166406", - "externalId": "vokabel-251976", - "title": "Sportarten", - "isAudio": true, - "isVideo": true, - "children": [ - { - "id": "urn:ard:category-subgenre:f47e5850faac9248", - "externalId": "vokabel-242220", - "title": "American Football", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b68eb9bb5346a4db", - "externalId": "vokabel-242221", - "title": "Badminton", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:719f9b87a978ff6e", - "externalId": "vokabel-242222", - "title": "Baseball", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:336f7a6c0092c9fd", - "externalId": "vokabel-242223", - "title": "Basketball", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:bd4d3e15f4ee7e97", - "externalId": "vokabel-242224", - "title": "Beach Volleyball", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ffbddffe5d044804", - "externalId": "vokabel-242225", - "title": "Biathlon", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:38acfdc2a73a13b1", - "externalId": "vokabel-242226", - "title": "Bob", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7a5c1c290ed02522", - "externalId": "vokabel-242227", - "title": "Bogenschießen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:661894dae6294bf6", - "externalId": "vokabel-242228", - "title": "Boxen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:95413d03f0eaa967", - "externalId": "vokabel-281047", - "title": "Cricket", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:24e875314fc37d65", - "externalId": "vokabel-242229", - "title": "Curling", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:6ff16cc9a0cf1071", - "externalId": "vokabel-258452", - "title": "Darts", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5b7b723ba9224d41", - "externalId": "vokabel-242230", - "title": "Doping allgemein", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:198b93d000c87bd2", - "externalId": "vokabel-242231", - "title": "Eishockey", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:de9ab1ecfaf62067", - "externalId": "vokabel-242232", - "title": "Eiskunstlauf", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9c6a5007531c16f4", - "externalId": "vokabel-242233", - "title": "Eisschnellauf", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1248147ea760a19e", - "externalId": "vokabel-242234", - "title": "Fechten", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:50b8f5950e8a970d", - "externalId": "vokabel-242235", - "title": "Flugsport", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:97a9d7a9f4b4ccb8", - "externalId": "vokabel-242236", - "title": "Fußball Bundesliga", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d55936425d5efa2b", - "externalId": "vokabel-242237", - "title": "Fußball Damen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c91dbeb1b5a794ff", - "externalId": "vokabel-242238", - "title": "Fußball Herren", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8bed5f5a1c4da26c", - "externalId": "vokabel-242239", - "title": "Gewichtheben", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d1718717e9b40bcb", - "externalId": "vokabel-242240", - "title": "Golf", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:938166fc405e3d58", - "externalId": "vokabel-242241", - "title": "Gymnastik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:549044c0ba6066ed", - "externalId": "vokabel-242242", - "title": "Handball", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1660a52b138a507e", - "externalId": "vokabel-242243", - "title": "Hockey", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ea10af1ef31b7d57", - "externalId": "vokabel-258450", - "title": "Icecross", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:3747cb39b478381d", - "externalId": "vokabel-242254", - "title": "Inklusionssport", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9842e152e7f6e714", - "externalId": "vokabel-242244", - "title": "Judo", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:75b72ad21d920e8e", - "externalId": "vokabel-242255", - "title": "Jugend Olympische Winterspiele", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:dab200b94e1cd187", - "externalId": "vokabel-242245", - "title": "Kanu/Kajak", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:26c20a8cae8dfcae", - "externalId": "vokabel-258456", - "title": "Karate", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b617534d640c5267", - "externalId": "vokabel-272472", - "title": "Kitesurfing", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a323c95bfd599188", - "externalId": "vokabel-258454", - "title": "Klettern", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1da32285b4228a32", - "externalId": "vokabel-242246", - "title": "Leichtathletik", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5f53c36e1dc8bca1", - "externalId": "vokabel-242247", - "title": "Moderner Fünfkampf", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:43174b9df531d275", - "externalId": "vokabel-242248", - "title": "Motorrad", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:01e7aa765cdbe4e6", - "externalId": "vokabel-242249", - "title": "Motorsport", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:7e74ad7cba3ad4c2", - "externalId": "vokabel-242250", - "title": "Olympische Sommerspiele", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:3c844c9713d0e251", - "externalId": "vokabel-242251", - "title": "Olympische Winterspiele", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d7d0d1c2c78b15e9", - "externalId": "vokabel-251016", - "title": "Paralympics Special", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8964b8da86984dae", - "externalId": "vokabel-251018", - "title": "Paralympische Sportarten", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b2a608eee7ac553b", - "externalId": "vokabel-242256", - "title": "Radsport", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f056e9054e4663a8", - "externalId": "vokabel-242257", - "title": "Reiten", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ec1261f6a6bf0d7c", - "externalId": "vokabel-242258", - "title": "Ringen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:aee2801d0f553bef", - "externalId": "vokabel-242259", - "title": "Rodeln", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:cd8b322ae743834a", - "externalId": "vokabel-242260", - "title": "Rudern", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:8f7bd3c14ea9b5d9", - "externalId": "vokabel-242261", - "title": "Rugby", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a8e04ef55af14bc4", - "externalId": "vokabel-258451", - "title": "Schach", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:bfd97c66f3ae1909", - "externalId": "vokabel-258474", - "title": "Schießsport", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:486af1fdb497ee6c", - "externalId": "vokabel-242262", - "title": "Schwimmen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:0a9a10161d7dd8ff", - "externalId": "vokabel-242263", - "title": "Segeln", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:84b8546fe9016f95", - "externalId": "vokabel-242264", - "title": "Short Track", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:2d018d22092526e2", - "externalId": "vokabel-258453", - "title": "Skateboard", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:c648b58440eb5906", - "externalId": "vokabel-242265", - "title": "Skeleton", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:015997b8bad502b3", - "externalId": "vokabel-242266", - "title": "Ski Alpin", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e76fdb96e7193165", - "externalId": "vokabel-242272", - "title": "Ski Cross", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:43a97653133f3420", - "externalId": "vokabel-242267", - "title": "Ski Freestyle", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:5fedfea0fbc65af4", - "externalId": "vokabel-242268", - "title": "Ski Langlauf", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:628e1841b4cd5c43", - "externalId": "vokabel-242270", - "title": "Ski Mounteneering", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1d1d1f4b522c6c67", - "externalId": "vokabel-242269", - "title": "Ski Nordisch/NoKo", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:207ef9aa1d276ad0", - "externalId": "vokabel-242271", - "title": "Skisprung/Skiflug", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:a59f3a7d4ef307f6", - "externalId": "vokabel-242273", - "title": "Snowboard", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:fb956eabe9eeb9e4", - "externalId": "vokabel-242252", - "title": "Sommer/Winter Paralympics", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b9658f4040048f77", - "externalId": "vokabel-242253", - "title": "Special Olympics", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:e1d328b054b3a71b", - "externalId": "vokabel-258455", - "title": "Surfen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:6432eb670767ca3d", - "externalId": "vokabel-258457", - "title": "Taekwondo", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:2bbd7e04ba8fb09c", - "externalId": "vokabel-242274", - "title": "Tanzen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:694d9fef1365860f", - "externalId": "vokabel-242275", - "title": "Tennis", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ae5cbdd3e95bddba", - "externalId": "vokabel-242276", - "title": "Tischtennis", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:ecac5c3840b1eb29", - "externalId": "vokabel-242277", - "title": "Trampolin", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:f0e8d4cba84885fd", - "externalId": "vokabel-242278", - "title": "Triathlon", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:b218352001a2b36e", - "externalId": "vokabel-242279", - "title": "Turnen", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9b6e3999cf8538cd", - "externalId": "vokabel-242280", - "title": "Volleyball", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:4c659790d1390f65", - "externalId": "vokabel-272469", - "title": "Wakeboard", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:d99ed872666f0e5e", - "externalId": "vokabel-242281", - "title": "Wasserball", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:33f6909a37d83f41", - "externalId": "vokabel-272470", - "title": "Wasserski", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:710671719e3209d2", - "externalId": "vokabel-272471", - "title": "Wassersport", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:1e8ffa4e9c5155eb", - "externalId": "vokabel-242282", - "title": "Wintersport", - "isAudio": true, - "isVideo": true, - "children": null - }, - { - "id": "urn:ard:category-subgenre:9583a81415fa4d73", - "externalId": "vokabel-258449", - "title": "eSport", - "isAudio": true, - "isVideo": true, - "children": null - } - ] - } - ], - "list": [ - { - "id": "urn:ard:category-subgenre:39ac8d318f50317b", - "externalId": "vokabel-272072", - "title": "Docutainmentserie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:98f913ef413cd576", - "externalId": "vokabel-272249", - "title": "Erklärfilm", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1dc4559b3ab4ff50", - "externalId": "vokabel-250945", - "title": "Essay", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:e06dc83c6b9de023", - "externalId": "vokabel-280992", - "title": "Filminterview", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:e816bdfbdecb1a39", - "externalId": "vokabel-271929", - "title": "Geschichtliche und zeitgeschichtliche Doku", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9785baf1382a2a1d", - "externalId": "vokabel-271930", - "title": "Geschichtliche und zeitgeschichtliche Dokuserie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:cd1962bccdd383ba", - "externalId": "vokabel-271949", - "title": "Gesellschafts-, Sozial- und Kulturdoku", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:759b478ad10ce82b", - "externalId": "vokabel-271953", - "title": "Inside-Access- und gesellschaftliche Dokuserie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:fcca0b4e0e45fc3f", - "externalId": "vokabel-272149", - "title": "Interview-Serie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ae70d08b25c53b1f", - "externalId": "vokabel-271970", - "title": "Kulinarische Doku", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ec8031608c2f0d8c", - "externalId": "vokabel-271971", - "title": "Kulinarische Dokuserie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a29d29d7c277d6b0", - "externalId": "vokabel-280993", - "title": "Lyrik-Show", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:8706dc32ebe2b0bc", - "externalId": "vokabel-271989", - "title": "Mockumentary", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:658c0beb38498d05", - "externalId": "vokabel-280990", - "title": "Musikdoku", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:0059e74b92bf2079", - "externalId": "vokabel-272032", - "title": "Natur - und Tierdoku", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ba653ad3a4e9b60b", - "externalId": "vokabel-271991", - "title": "Natur- und Tierdokuserie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:277cea0091a3bb96", - "externalId": "vokabel-280991", - "title": "Radiofeature", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:a10c79955cd3c474", - "externalId": "vokabel-272209", - "title": "Reisedoku", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:83590c44e8a4cc1b", - "externalId": "vokabel-272150", - "title": "Reportage", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:bdf6cca852244cf5", - "externalId": "vokabel-272229", - "title": "Sportdoku", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e030be7300b274be", - "externalId": "vokabel-272169", - "title": "True-Crime-Doku", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9fa3b979e653449a", - "externalId": "vokabel-272170", - "title": "True-Crime-Serie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:df24fcd13492e4f8", - "externalId": "vokabel-272049", - "title": "Wissenschafts- und Technikdoku", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c3de49ec3a656c79", - "externalId": "vokabel-272069", - "title": "Wissenschafts- und Technikdokuserie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:dbb7bf3926b2277a", - "externalId": "vokabel-242033", - "title": "Dokumentation/Reportage", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:63359a0f3a6d4ceb", - "externalId": "vokabel-242029", - "title": "Action- und Abenteuerfilm", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:696a48d7c22196e6", - "externalId": "vokabel-272409", - "title": "Animationsfilm", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:17651aab7b24a683", - "externalId": "vokabel-242035", - "title": "Beziehungsdrama", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:db7b2ca737d4985f", - "externalId": "vokabel-271890", - "title": "Biopic", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1c6a0e9bcdeac3ea", - "externalId": "vokabel-271893", - "title": "Coming-of-Age-Film", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f4ec08c6d03c92b8", - "externalId": "vokabel-271909", - "title": "Europäischer Filmklassiker", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b28a65b62b32b39e", - "externalId": "vokabel-271950", - "title": "Heimatfilm", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f07a845d82d8850d", - "externalId": "vokabel-271951", - "title": "High-Concept-Komödie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5409ae368d2a9051", - "externalId": "vokabel-272411", - "title": "Horrorfilm", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:376ba66178e6deb8", - "externalId": "vokabel-271952", - "title": "Indie-Komödie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:51bd4a15662461f0", - "externalId": "vokabel-242043", - "title": "Krimi", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:df9f0e6c9258d69a", - "externalId": "vokabel-242044", - "title": "Kultfilm", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9d6fef873bb2e009", - "externalId": "vokabel-242045", - "title": "Kurzfilm/Videokunst", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:04caa4a3809fe3fb", - "externalId": "vokabel-242048", - "title": "Märchen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:7d7418ef5ed7edbe", - "externalId": "vokabel-271992", - "title": "Politthriller", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:3f84f904f73ddb2d", - "externalId": "vokabel-271993", - "title": "Programmkino-Film", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b1a6bd7d03416c47", - "externalId": "vokabel-271994", - "title": "Psychothriller", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:39a94242cf94e54c", - "externalId": "vokabel-242050", - "title": "Roadmovie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e6d196ab297df5fa", - "externalId": "vokabel-272009", - "title": "Romantische Komödie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:0b7a9e23e8efa3b5", - "externalId": "vokabel-272392", - "title": "Sci-Fi- & Fantasy-Film", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f1085afe5ddafeb7", - "externalId": "vokabel-272389", - "title": "Sportfilm", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:42a906a03b5516ea", - "externalId": "vokabel-272033", - "title": "TV-Komödie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:fa2b2396278a7d7b", - "externalId": "vokabel-272029", - "title": "Tatort", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:8e9b5df4bb3bce93", - "externalId": "vokabel-272390", - "title": "Westernfilm", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ad75aa6b81ecd654", - "externalId": "vokabel-272290", - "title": "Zeichentrickfilm", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:bc4d4ee6dc845c5d", - "externalId": "vokabel-272070", - "title": "Zeitgeschichtliches und historisches Drama", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:9284d97c28f0cba5", - "externalId": "vokabel-242037", - "title": "Film", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a95eae7965df0cfc", - "externalId": "vokabel-280996", - "title": "Action- und Abenteuer-Hörspiel", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:b51a268a8d266228", - "externalId": "vokabel-280999", - "title": "Audio Roadmovie", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:ee44b69244ef8ef6", - "externalId": "vokabel-281006", - "title": "Audio-Soap", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:b0f0df8a05fcd6b1", - "externalId": "vokabel-281008", - "title": "Bioaud", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:2296130019790f0f", - "externalId": "vokabel-281000", - "title": "Coming-of-Age-Hörspiel", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:f2003e61ac16e022", - "externalId": "vokabel-281009", - "title": "Doku-Hörspiel", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:ebae4f92cc353a6f", - "externalId": "vokabel-280997", - "title": "Heimat-Hörspiel", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:e587313ce34754ba", - "externalId": "vokabel-281003", - "title": "Horror-Hörspiel", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:134dabfecfce5763", - "externalId": "vokabel-242042", - "title": "Komödie", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:f7eac76124cc54bb", - "externalId": "vokabel-280998", - "title": "Kult-Hörspiel", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:295594aebed1d543", - "externalId": "vokabel-281005", - "title": "Kurzgeschichte", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:acb45779ed05b865", - "externalId": "vokabel-281007", - "title": "Mystery-Hörspiel", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:6066f2ebb093399c", - "externalId": "vokabel-281001", - "title": "Sci-Fi- & Fantasy-Hörspiel", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:a777d0d74aad6229", - "externalId": "vokabel-281002", - "title": "Sport-Hörspiel", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:6ba57545173be3d0", - "externalId": "vokabel-281004", - "title": "Western-Hörspiel", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-genre:93e611e2cec8483a", - "externalId": "vokabel-250942", - "title": "Hörspiel", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:8d93396b4af7d006", - "externalId": "vokabel-281010", - "title": "Action- und Abenteuer-Lesung", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:4a821b57b0c98bb3", - "externalId": "vokabel-281013", - "title": "Coming-of-Age-Lesung", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:5d05140aff983f2b", - "externalId": "vokabel-281019", - "title": "Gedicht", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:cf63d880e31de695", - "externalId": "vokabel-281011", - "title": "Heimat-Lesung", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:41419cf9176151ff", - "externalId": "vokabel-281016", - "title": "Horror-Lesung", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:0872fabc1923bd20", - "externalId": "vokabel-281012", - "title": "Kult-Lesung", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:1ff5f5e1567209b8", - "externalId": "vokabel-281018", - "title": "Mystery-Lesung", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:3e6ca63d178e878e", - "externalId": "vokabel-281020", - "title": "Sachbuch-Lesung", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:c4a05f2e44b53cd9", - "externalId": "vokabel-281014", - "title": "Sci-Fi- & Fantasy-Lesung", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:8650bec5ed5f0a4a", - "externalId": "vokabel-281015", - "title": "Sport-Lesung", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:03b17d12be8b676c", - "externalId": "vokabel-281017", - "title": "Western-Lesung", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-genre:d116f00967227ea9", - "externalId": "vokabel-250943", - "title": "Lesung", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:a2041d0aad1fdae1", - "externalId": "vokabel-281189", - "title": "Live-Ereignis", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d4d8354408c34b46", - "externalId": "vokabel-276030", - "title": "Bericht-Format", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ab4b324eee227b62", - "externalId": "vokabel-276029", - "title": "Interview-Format", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5139f6935b172660", - "externalId": "vokabel-276032", - "title": "Nachrichten", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9628d4afa1297dd5", - "externalId": "vokabel-276031", - "title": "Nachrichten-Magazin", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:0fb71ec3c139dfe2", - "externalId": "vokabel-242062", - "title": "Nachrichten/Information", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1ca69d05dc8c7ccf", - "externalId": "vokabel-242030", - "title": "Action- und Abenteuerserie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:16f94fdd24c0a6c2", - "externalId": "vokabel-272410", - "title": "Animationsserie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a4e82badd135a87b", - "externalId": "vokabel-271889", - "title": "Beziehungsdramaserie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:998bcd4c9e3eaecc", - "externalId": "vokabel-271891", - "title": "Comedyserie & Dramedy", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:8b7f0fcc36dda29c", - "externalId": "vokabel-271910", - "title": "Familienserie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:93188c0a7714cbe4", - "externalId": "vokabel-272412", - "title": "Horrorserie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d1e3d781c3240b3b", - "externalId": "vokabel-271969", - "title": "Krimiserie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f895db380d038098", - "externalId": "vokabel-271990", - "title": "Mystery-Serie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:498a7fc841059526", - "externalId": "vokabel-272393", - "title": "Sci-Fi- & Fantasy-Serie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:709a2407c1d60993", - "externalId": "vokabel-242054", - "title": "Soap/Telenovela", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:85b8249cc16b4d5f", - "externalId": "vokabel-272030", - "title": "Teenserie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c748c57768817bcc", - "externalId": "vokabel-272031", - "title": "Thriller-Serie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:cc6bbc1f12d1f800", - "externalId": "vokabel-272391", - "title": "Westernserie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d2e6ad61670de670", - "externalId": "vokabel-272289", - "title": "Zeichentrickserie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:febdaf0d756e6ace", - "externalId": "vokabel-272071", - "title": "Zeitgeschichtliche & historische Dramaserie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:feb8607e35aabef9", - "externalId": "vokabel-242053", - "title": "Serie", - "isAudio": false, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5e9aef706400f579", - "externalId": "vokabel-271892", - "title": "Comedy-Show", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c3e107d7a19c198b", - "externalId": "vokabel-276015", - "title": "Gottesdienst", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c82280790634c3c7", - "externalId": "vokabel-276010", - "title": "Kochshow", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:6e4f8c459fe15749", - "externalId": "vokabel-280995", - "title": "Kommentar", - "isAudio": true, - "isVideo": false - }, - { - "id": "urn:ard:category-subgenre:9580b0e2b469e59c", - "externalId": "vokabel-242084", - "title": "Konzert", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:8111e63c08762f18", - "externalId": "vokabel-276014", - "title": "Kultur-Magazin", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:2b91135c76115639", - "externalId": "vokabel-271972", - "title": "Late-Night-Show", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:04f025eb5ba2423e", - "externalId": "vokabel-276016", - "title": "Literaturshow", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a7ed514d751c4530", - "externalId": "vokabel-272369", - "title": "Musik-Show", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:8ad26192afdef554", - "externalId": "vokabel-276011", - "title": "Polit-Magazin", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:646affeaddc60930", - "externalId": "vokabel-272332", - "title": "Polit-Talkshow", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:2cbf6dae360b61da", - "externalId": "vokabel-280994", - "title": "Reality-Show", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d87e564793fd7514", - "externalId": "vokabel-272370", - "title": "Samstagabend-Show", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:7b5c6cda26ba07e8", - "externalId": "vokabel-272073", - "title": "Satire-Show", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:994291a1cf9cc5de", - "externalId": "vokabel-272010", - "title": "Sketch-Show", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:82e28e0a6604dcb3", - "externalId": "vokabel-272309", - "title": "Stand-up-Show", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:abcf8ec8d3113cf2", - "externalId": "vokabel-242058", - "title": "Talkshow", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:4dc343ae55e0aee1", - "externalId": "vokabel-276012", - "title": "Verbraucher-Magazin", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9825964c69609276", - "externalId": "vokabel-250947", - "title": "Vortrag", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a37bddd627f85285", - "externalId": "vokabel-272331", - "title": "Wissens-Show", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:efde47fb53348b25", - "externalId": "vokabel-242139", - "title": "Show/Magazin", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:877523a636bebe4a", - "externalId": "vokabel-251973", - "title": "Genre", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:8a56dd1492edb2c4", - "externalId": "vokabel-242060", - "title": "Katastrophen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c8a63cff3b078457", - "externalId": "vokabel-242061", - "title": "Krisengebiete", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:7c9c47d6be64b11d", - "externalId": "vokabel-281021", - "title": "Regionales", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:4d47ff2868d3e971", - "externalId": "vokabel-242063", - "title": "Terrorismus", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f4192f4e743ae72a", - "externalId": "vokabel-250923", - "title": "Verkehrsservice", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c365bb519caf5e1b", - "externalId": "vokabel-242064", - "title": "Wahl", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:81955aba35456888", - "externalId": "vokabel-242065", - "title": "Wetter", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:e93f6f237afb0a61", - "externalId": "vokabel-242059", - "title": "Aktuelles", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:fbf219b56778cc86", - "externalId": "vokabel-250951", - "title": "ARD Retro", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:65d4b2d713a2cdaf", - "externalId": "vokabel-242149", - "title": "DDR", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1a47b5ddf543fd8b", - "externalId": "vokabel-242150", - "title": "Nationalsozialismus", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:58b754365ca9cb18", - "externalId": "vokabel-242151", - "title": "Weltkrieg I", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9fa6760aa69790ad", - "externalId": "vokabel-242152", - "title": "Weltkrieg II", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:2724533cba48fb3c", - "externalId": "vokabel-242148", - "title": "Geschichte", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:bf64595eb43357b3", - "externalId": "vokabel-242096", - "title": "Arbeit", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:fd94b8b51dd96120", - "externalId": "vokabel-242097", - "title": "Ausbildung", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e1d03046f5200ff4", - "externalId": "vokabel-242098", - "title": "Bildung", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1830119e8e686b7a", - "externalId": "vokabel-242068", - "title": "Digitale Welt/Internet", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e39e20133b6b53b2", - "externalId": "vokabel-250929", - "title": "Divers/Inter", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a320d1ad5cca3967", - "externalId": "vokabel-242099", - "title": "Erziehung", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:8cb7f5ccbb223380", - "externalId": "vokabel-242100", - "title": "Familie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ce47142712c80513", - "externalId": "vokabel-242101", - "title": "Frauen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:0956361be8f65ea6", - "externalId": "vokabel-242102", - "title": "Freizeit", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:52501f3f0ad4f2d2", - "externalId": "vokabel-281044", - "title": "Gemeinnützigkeit", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a16ec1f892816521", - "externalId": "vokabel-250928", - "title": "Hobby", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d2bda11a1c3f8d92", - "externalId": "vokabel-242121", - "title": "Inklusion", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c5849389b560df5f", - "externalId": "vokabel-242104", - "title": "Integration", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:877472621c8ae9cc", - "externalId": "vokabel-242105", - "title": "Islam", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:4065505ee6b4b279", - "externalId": "vokabel-242106", - "title": "Jugend", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:0295b1b54f5e84ea", - "externalId": "vokabel-242107", - "title": "Kinder", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d45c89c235f00cd6", - "externalId": "vokabel-242041", - "title": "Kinderprogramm", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1ed13946a7a7ea3e", - "externalId": "vokabel-242108", - "title": "Kriminalität", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5c21d8ad0e4ddcad", - "externalId": "vokabel-242109", - "title": "Liebe", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:23b2dfa7e8acec89", - "externalId": "vokabel-242110", - "title": "Lifestyle", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a6531c70bb7881af", - "externalId": "vokabel-242112", - "title": "Medien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e4a3fd9b1292b73c", - "externalId": "vokabel-242113", - "title": "Migration", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:6a81b9e2e6ee0056", - "externalId": "vokabel-242114", - "title": "Mode", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:61423e4c4146da1a", - "externalId": "vokabel-242111", - "title": "Männer", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:bd2a490b7a780bf5", - "externalId": "vokabel-250927", - "title": "Prominente", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:287158094f0436c5", - "externalId": "vokabel-242115", - "title": "Religion", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ef607a35b53a6d70", - "externalId": "vokabel-242116", - "title": "Religionen der Welt", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ad909bde1cd05be3", - "externalId": "vokabel-242117", - "title": "Schicksale", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b1d4132df4293537", - "externalId": "vokabel-242118", - "title": "Senioren", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f324f2c65dc303a4", - "externalId": "vokabel-242119", - "title": "Sexualität", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:904d40f1b5d5bb01", - "externalId": "vokabel-242120", - "title": "Weihnachten", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:4ba6d7f0411c6835", - "externalId": "vokabel-242103", - "title": "Gesellschaft", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f97d8401edb0dc3b", - "externalId": "vokabel-281023", - "title": "Alte Musik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:dcb3d6a7ba2b0943", - "externalId": "vokabel-242080", - "title": "Architektur", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1b63797a04961e0d", - "externalId": "vokabel-281040", - "title": "Bildende Kunst", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:78757b624e0d0c06", - "externalId": "vokabel-242095", - "title": "Brauchtum", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:775fc07819cc6b51", - "externalId": "vokabel-281024", - "title": "Country", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:35af2193b0265dc2", - "externalId": "vokabel-281025", - "title": "CrossOver", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f2be03af4a180677", - "externalId": "vokabel-281026", - "title": "Dance", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:41ffa137f16fb7aa", - "externalId": "vokabel-281039", - "title": "Darstellende Kunst", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:030f40dc58858139", - "externalId": "vokabel-281038", - "title": "Design", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1f4bc82fb07cefed", - "externalId": "vokabel-281037", - "title": "Elektronische Musik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b04ee244e3f230e4", - "externalId": "vokabel-281027", - "title": "Ernste Musik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ac0a6ab70b0b5e30", - "externalId": "vokabel-281028", - "title": "Ethno/Weltmusik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:59939891ad7c289e", - "externalId": "vokabel-281041", - "title": "Film & Serien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:38cb8adc29ac66d3", - "externalId": "vokabel-250925", - "title": "Fotografie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:eefa8b5ca2e168a3", - "externalId": "vokabel-281029", - "title": "Geistliche Musik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:91698c5644005887", - "externalId": "vokabel-281030", - "title": "Hip-Hop", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d3996dbdedea6e14", - "externalId": "vokabel-281031", - "title": "Hitparade", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9e43374c13c13fd0", - "externalId": "vokabel-242081", - "title": "Jazz", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:14884f8117d435a1", - "externalId": "vokabel-281032", - "title": "Kammermusik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:59521570e9ff6465", - "externalId": "vokabel-242082", - "title": "Kino", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1ba2f49b401552f6", - "externalId": "vokabel-242083", - "title": "Klassik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d77051091d83d30f", - "externalId": "vokabel-242085", - "title": "Kunst", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ffdaa8e0d3923d66", - "externalId": "vokabel-250926", - "title": "Künstler", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:10617335e7bd88ba", - "externalId": "vokabel-242086", - "title": "Literatur", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b902f85ece92fa15", - "externalId": "vokabel-250950", - "title": "Mundart", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:529192de4e57be29", - "externalId": "vokabel-242087", - "title": "Musical", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:4ed51a2da6aed0fd", - "externalId": "vokabel-242088", - "title": "Musik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:0c25fbc60f44e66e", - "externalId": "vokabel-242089", - "title": "Musik-Festival", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5678ae6abe3e0332", - "externalId": "vokabel-281033", - "title": "Neue Musik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d85aea134a42b458", - "externalId": "vokabel-281034", - "title": "Oldies", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:73b6fccce9a5d64a", - "externalId": "vokabel-242090", - "title": "Oper", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:463a45482975d568", - "externalId": "vokabel-242049", - "title": "Porträt/Biografie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9aaa0bf8e3a882cb", - "externalId": "vokabel-281035", - "title": "R&B", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:31461d27404fe0d9", - "externalId": "vokabel-242091", - "title": "Rock/Pop", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:7a3b6b3780465040", - "externalId": "vokabel-250924", - "title": "Schlager", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:88a5c5d1d4f563a5", - "externalId": "vokabel-276129", - "title": "Show", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5dbb29c41996d97e", - "externalId": "vokabel-281036", - "title": "Sinfonische Musik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:84611ebf8199fca2", - "externalId": "vokabel-250948", - "title": "Soundart", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9e82baad5742732b", - "externalId": "vokabel-281042", - "title": "Spiele", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5f34b470935ec9c3", - "externalId": "vokabel-250944", - "title": "Sport", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f6573f1bba71bb6c", - "externalId": "vokabel-242092", - "title": "Theater", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:dc725b46fea845b8", - "externalId": "vokabel-281043", - "title": "Videogames/Games", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b4a7def0139b8dff", - "externalId": "vokabel-242093", - "title": "Volksmusik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:3a859a89e7e73a95", - "externalId": "vokabel-242094", - "title": "Weltmusik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:f5c5da1e740c82e0", - "externalId": "vokabel-242079", - "title": "Kultur", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5374d398fb011154", - "externalId": "vokabel-242154", - "title": "EU", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1184327352eb27c7", - "externalId": "vokabel-242155", - "title": "Extremismus", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d695104fa8d57c72", - "externalId": "vokabel-242156", - "title": "Krieg", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:dd5697e10f7da63e", - "externalId": "vokabel-242153", - "title": "Politik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:0474996d669105ae", - "externalId": "vokabel-242067", - "title": "Auto/Verkehr", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:575c62cd4febe0b4", - "externalId": "vokabel-242123", - "title": "Ernährung", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9c0d2719dd8a6396", - "externalId": "vokabel-250930", - "title": "Fitness", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:10a0fed4a33ec441", - "externalId": "vokabel-281045", - "title": "Fremdsprachen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d97e26b4bb9757de", - "externalId": "vokabel-242124", - "title": "Geld", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9b8ec75f127d614d", - "externalId": "vokabel-242125", - "title": "Gesundheit", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d7b1dce859009ff4", - "externalId": "vokabel-281046", - "title": "Handarbeit", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5c9fe563e8433af8", - "externalId": "vokabel-242126", - "title": "Haus/Garten", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:defdc6f274605505", - "externalId": "vokabel-250931", - "title": "Haushalt", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1e6f048841a90c6b", - "externalId": "vokabel-242127", - "title": "Kochen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:022b8c7ba95062bf", - "externalId": "vokabel-242128", - "title": "Recht", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:6c60913acf218112", - "externalId": "vokabel-242074", - "title": "Reise", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:15ac8326e601d627", - "externalId": "vokabel-242122", - "title": "Ratgeber", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f7b27e5d0f271411", - "externalId": "vokabel-242141", - "title": "Berge", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:19ece4ce8e5e0eb0", - "externalId": "vokabel-250932", - "title": "Klima", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:30a35c61f5194fa4", - "externalId": "vokabel-242142", - "title": "Meer", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:7253bd8a5cf37937", - "externalId": "vokabel-242143", - "title": "Natur", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:fc71f9f3a88fce5d", - "externalId": "vokabel-242144", - "title": "Tiere", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:be8118180165f8ce", - "externalId": "vokabel-242145", - "title": "Zoogeschichten", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5b1c052527b43823", - "externalId": "vokabel-250933", - "title": "Ökologie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:b5429fb6a6cd2282", - "externalId": "vokabel-242140", - "title": "Umwelt", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f85948a61c653fbd", - "externalId": "vokabel-242133", - "title": "Boulevard", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:767b0cdfe81988d7", - "externalId": "vokabel-242134", - "title": "Comedy/Satire", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:348bed3441f3be44", - "externalId": "vokabel-242135", - "title": "Fasching/Karneval", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f39acf08bbcde5f1", - "externalId": "vokabel-242136", - "title": "Quiz", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b16a2ee31227d362", - "externalId": "vokabel-242137", - "title": "Royalty", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ad2ea610fadebdb6", - "externalId": "vokabel-242138", - "title": "Rückblicke", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:baa9a94db58f092e", - "externalId": "vokabel-242132", - "title": "Unterhaltung", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:3b60dbcf52b195e8", - "externalId": "vokabel-242147", - "title": "Börse", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:97cea0b77a22b9da", - "externalId": "vokabel-250935", - "title": "Dienstleistungen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:122f636029f6d4fc", - "externalId": "vokabel-250937", - "title": "Globalisierung", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:50df828b801ce26f", - "externalId": "vokabel-250936", - "title": "Handel", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d53e415cd3c88f49", - "externalId": "vokabel-250934", - "title": "Industrie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5ac0f07527825de9", - "externalId": "vokabel-242069", - "title": "Landwirtschaft", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:79903a24fb5ba37b", - "externalId": "vokabel-242146", - "title": "Wirtschaft", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:bb8d65ea445aeaa8", - "externalId": "vokabel-281022", - "title": "Beziehung", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:78766394ef9ea4e9", - "externalId": "vokabel-258458", - "title": "Luftfahrt/Raumfahrt", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:2553f77fc1636dcd", - "externalId": "vokabel-242070", - "title": "Medizin", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:67a3169468895b5e", - "externalId": "vokabel-242071", - "title": "Naturwissenschaft", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a0b234a892b700eb", - "externalId": "vokabel-242072", - "title": "Philosophie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e242d5433b5d3678", - "externalId": "vokabel-242073", - "title": "Psychologie", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:2e9070d166cbb781", - "externalId": "vokabel-242075", - "title": "Technik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e98152ed9cf5ec34", - "externalId": "vokabel-242076", - "title": "Weltraum", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ab71b306351fdaa7", - "externalId": "vokabel-242077", - "title": "Wissenschaft", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b7353bf5dde6b473", - "externalId": "vokabel-242078", - "title": "Zukunft", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:46847886cf7b333d", - "externalId": "vokabel-242066", - "title": "Wissen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:095767dfc2c20920", - "externalId": "vokabel-251974", - "title": "Inhaltskategorien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9465f1a4013f4ae1", - "externalId": "vokabel-242157", - "title": "Afghanistan", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:0eb2a143a997291f", - "externalId": "vokabel-242214", - "title": "Afrika", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:057126ed0e3ff353", - "externalId": "vokabel-242211", - "title": "Alpen und Berge", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:4c4240a8007d1f8c", - "externalId": "vokabel-242215", - "title": "Asien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:8b536294fa434439", - "externalId": "vokabel-242216", - "title": "Australien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:50580b53d372ce8d", - "externalId": "vokabel-242190", - "title": "Baden-Württemberg", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:4c9b0a7868e58cbb", - "externalId": "vokabel-250939", - "title": "Balkan", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:2be2ecc8ab4d58cf", - "externalId": "vokabel-251988", - "title": "Baltikum", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:12a8eab87a98f81e", - "externalId": "vokabel-242191", - "title": "Bayern", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:cad198bc402c12a6", - "externalId": "vokabel-242159", - "title": "Belgien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:69120d2302a76e5c", - "externalId": "vokabel-251989", - "title": "Benelux", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d5b9c88480a6a3ab", - "externalId": "vokabel-242192", - "title": "Berlin", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9749296f294c9538", - "externalId": "vokabel-242193", - "title": "Brandenburg", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:196b6d16dd302252", - "externalId": "vokabel-242194", - "title": "Bremen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a9b82a8ba83aaa03", - "externalId": "vokabel-242160", - "title": "Deutschland", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c9a3837f53a972aa", - "externalId": "vokabel-242217", - "title": "Europa", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:7e95027e4df6dac4", - "externalId": "vokabel-251983", - "title": "Frankfurt am Main", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:eb48cb6001d09c90", - "externalId": "vokabel-242161", - "title": "Frankreich", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:2c59e95cfbeec725", - "externalId": "vokabel-242162", - "title": "Griechenland", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:6ea908b75204f1b6", - "externalId": "vokabel-242163", - "title": "Großbritannien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5b9b8cfd74da14c1", - "externalId": "vokabel-242195", - "title": "Hamburg", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:3f486a9ae65b6408", - "externalId": "vokabel-242130", - "title": "Heimat", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9c8aaec18ee44f74", - "externalId": "vokabel-242196", - "title": "Hessen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e08b4ccea67846dc", - "externalId": "vokabel-242164", - "title": "Indien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a27bad250f92704f", - "externalId": "vokabel-242165", - "title": "Irak", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:656a8f19f5ac2bfa", - "externalId": "vokabel-242166", - "title": "Iran", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:279a6ef25c461d69", - "externalId": "vokabel-242167", - "title": "Israel", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:3bdee601b4bf73bd", - "externalId": "vokabel-242168", - "title": "Italien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:792e07ea1d55452e", - "externalId": "vokabel-242169", - "title": "Japan", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:06bd00e0fbb4750a", - "externalId": "vokabel-242170", - "title": "Jemen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:444de10b525e4399", - "externalId": "vokabel-242171", - "title": "Kuba", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:7db88b714fb1529b", - "externalId": "vokabel-242131", - "title": "Land/Leute", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f0b74607b98a6dae", - "externalId": "vokabel-251984", - "title": "Leipzig", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:835cc337a860182c", - "externalId": "vokabel-242172", - "title": "Libyen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b247a7ec10605b3d", - "externalId": "vokabel-251985", - "title": "Mainz", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:de7a4f2a270e79e7", - "externalId": "vokabel-242197", - "title": "Mecklenburg-Vorpommern", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c1ac22dc018a2ebf", - "externalId": "vokabel-242173", - "title": "Mexiko", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1607d2359d1c251c", - "externalId": "vokabel-250940", - "title": "Mittelmeer", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:755685d0ea5e0088", - "externalId": "vokabel-251986", - "title": "München", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1a809c23f9ffb4e2", - "externalId": "vokabel-272489", - "title": "Nahost", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:4f8e66a5f5f699d5", - "externalId": "vokabel-242174", - "title": "Niederlande", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c23ec7d9cff71733", - "externalId": "vokabel-242198", - "title": "Niedersachsen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:0d7e874e5c1caf46", - "externalId": "vokabel-242175", - "title": "Nigeria", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d5e70b8cbb501c7e", - "externalId": "vokabel-242218", - "title": "Nordamerika", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:66a6a9140027ada3", - "externalId": "vokabel-242207", - "title": "Norddeutschland", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ca6fa572a622f4f3", - "externalId": "vokabel-242176", - "title": "Nordkorea", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:80ce2632661d21a0", - "externalId": "vokabel-242199", - "title": "Nordrhein-Westfalen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c26004d1f401a8e6", - "externalId": "vokabel-242212", - "title": "Nordsee", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:16810a29e4465e78", - "externalId": "vokabel-251990", - "title": "Orient", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5471ebc24dac68eb", - "externalId": "vokabel-251991", - "title": "Ostasien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:7ae221e7e8dec377", - "externalId": "vokabel-242208", - "title": "Ostdeutschland", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:8090e53a5deb9e75", - "externalId": "vokabel-242213", - "title": "Ostsee", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:94dbcc6ae731acb4", - "externalId": "vokabel-242178", - "title": "Pakistan", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9360c9feb792335e", - "externalId": "vokabel-251992", - "title": "Polarkreis", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d62b2d814edb9a27", - "externalId": "vokabel-242179", - "title": "Polen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ff5d213880fc1184", - "externalId": "vokabel-242180", - "title": "Portugal", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e884ed6df45b1ac9", - "externalId": "vokabel-242200", - "title": "Rheinland-Pfalz", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:bdadc0d329162717", - "externalId": "vokabel-242181", - "title": "Russland", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:aa740c865db12c5a", - "externalId": "vokabel-242201", - "title": "Saarland", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:6d652ebaa78f77ef", - "externalId": "vokabel-242202", - "title": "Sachsen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:2f95cf510e65417c", - "externalId": "vokabel-242203", - "title": "Sachsen-Anhalt", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a1b78b28fa19f616", - "externalId": "vokabel-242204", - "title": "Schleswig-Holstein", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:7abce2efd3287ca2", - "externalId": "vokabel-242182", - "title": "Schweden", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:384c03047ac24a31", - "externalId": "vokabel-242183", - "title": "Schweiz", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:0e6beb93c10fba28", - "externalId": "vokabel-250938", - "title": "Skandinavien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b66e477d8ebefd5b", - "externalId": "vokabel-242184", - "title": "Somalia", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f49ea6962754cbc8", - "externalId": "vokabel-242185", - "title": "Spanien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:37a6643b43b4361b", - "externalId": "vokabel-251987", - "title": "Stuttgart", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:338f84aadd6a907d", - "externalId": "vokabel-242186", - "title": "Syrien", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9717ea6712ba2aed", - "externalId": "vokabel-242219", - "title": "Südamerika", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:3812c00c4134f5e4", - "externalId": "vokabel-242209", - "title": "Süddeutschland", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e3476ac353f3c085", - "externalId": "vokabel-242205", - "title": "Thüringen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:717f65417480a6ee", - "externalId": "vokabel-242187", - "title": "Türkei", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:2fcb0c593593fea9", - "externalId": "vokabel-242189", - "title": "USA", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:6d3bedb29c79c83a", - "externalId": "vokabel-242188", - "title": "Ukraine", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:4781c706a7d5c5c0", - "externalId": "vokabel-242210", - "title": "Westdeutschland", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:88217957e9c62435", - "externalId": "vokabel-242158", - "title": "Ägypten", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:889f44990fc8c260", - "externalId": "vokabel-242177", - "title": "Österreich", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:4ba786346b283fb3", - "externalId": "vokabel-251975", - "title": "Ortsangaben", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f47e5850faac9248", - "externalId": "vokabel-242220", - "title": "American Football", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b68eb9bb5346a4db", - "externalId": "vokabel-242221", - "title": "Badminton", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:719f9b87a978ff6e", - "externalId": "vokabel-242222", - "title": "Baseball", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:336f7a6c0092c9fd", - "externalId": "vokabel-242223", - "title": "Basketball", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:bd4d3e15f4ee7e97", - "externalId": "vokabel-242224", - "title": "Beach Volleyball", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ffbddffe5d044804", - "externalId": "vokabel-242225", - "title": "Biathlon", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:38acfdc2a73a13b1", - "externalId": "vokabel-242226", - "title": "Bob", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:7a5c1c290ed02522", - "externalId": "vokabel-242227", - "title": "Bogenschießen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:661894dae6294bf6", - "externalId": "vokabel-242228", - "title": "Boxen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:95413d03f0eaa967", - "externalId": "vokabel-281047", - "title": "Cricket", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:24e875314fc37d65", - "externalId": "vokabel-242229", - "title": "Curling", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:6ff16cc9a0cf1071", - "externalId": "vokabel-258452", - "title": "Darts", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5b7b723ba9224d41", - "externalId": "vokabel-242230", - "title": "Doping allgemein", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:198b93d000c87bd2", - "externalId": "vokabel-242231", - "title": "Eishockey", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:de9ab1ecfaf62067", - "externalId": "vokabel-242232", - "title": "Eiskunstlauf", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9c6a5007531c16f4", - "externalId": "vokabel-242233", - "title": "Eisschnellauf", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1248147ea760a19e", - "externalId": "vokabel-242234", - "title": "Fechten", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:50b8f5950e8a970d", - "externalId": "vokabel-242235", - "title": "Flugsport", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:97a9d7a9f4b4ccb8", - "externalId": "vokabel-242236", - "title": "Fußball Bundesliga", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d55936425d5efa2b", - "externalId": "vokabel-242237", - "title": "Fußball Damen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c91dbeb1b5a794ff", - "externalId": "vokabel-242238", - "title": "Fußball Herren", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:8bed5f5a1c4da26c", - "externalId": "vokabel-242239", - "title": "Gewichtheben", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d1718717e9b40bcb", - "externalId": "vokabel-242240", - "title": "Golf", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:938166fc405e3d58", - "externalId": "vokabel-242241", - "title": "Gymnastik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:549044c0ba6066ed", - "externalId": "vokabel-242242", - "title": "Handball", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1660a52b138a507e", - "externalId": "vokabel-242243", - "title": "Hockey", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ea10af1ef31b7d57", - "externalId": "vokabel-258450", - "title": "Icecross", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:3747cb39b478381d", - "externalId": "vokabel-242254", - "title": "Inklusionssport", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9842e152e7f6e714", - "externalId": "vokabel-242244", - "title": "Judo", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:75b72ad21d920e8e", - "externalId": "vokabel-242255", - "title": "Jugend Olympische Winterspiele", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:dab200b94e1cd187", - "externalId": "vokabel-242245", - "title": "Kanu/Kajak", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:26c20a8cae8dfcae", - "externalId": "vokabel-258456", - "title": "Karate", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b617534d640c5267", - "externalId": "vokabel-272472", - "title": "Kitesurfing", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a323c95bfd599188", - "externalId": "vokabel-258454", - "title": "Klettern", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1da32285b4228a32", - "externalId": "vokabel-242246", - "title": "Leichtathletik", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5f53c36e1dc8bca1", - "externalId": "vokabel-242247", - "title": "Moderner Fünfkampf", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:43174b9df531d275", - "externalId": "vokabel-242248", - "title": "Motorrad", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:01e7aa765cdbe4e6", - "externalId": "vokabel-242249", - "title": "Motorsport", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:7e74ad7cba3ad4c2", - "externalId": "vokabel-242250", - "title": "Olympische Sommerspiele", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:3c844c9713d0e251", - "externalId": "vokabel-242251", - "title": "Olympische Winterspiele", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d7d0d1c2c78b15e9", - "externalId": "vokabel-251016", - "title": "Paralympics Special", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:8964b8da86984dae", - "externalId": "vokabel-251018", - "title": "Paralympische Sportarten", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b2a608eee7ac553b", - "externalId": "vokabel-242256", - "title": "Radsport", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f056e9054e4663a8", - "externalId": "vokabel-242257", - "title": "Reiten", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ec1261f6a6bf0d7c", - "externalId": "vokabel-242258", - "title": "Ringen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:aee2801d0f553bef", - "externalId": "vokabel-242259", - "title": "Rodeln", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:cd8b322ae743834a", - "externalId": "vokabel-242260", - "title": "Rudern", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:8f7bd3c14ea9b5d9", - "externalId": "vokabel-242261", - "title": "Rugby", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a8e04ef55af14bc4", - "externalId": "vokabel-258451", - "title": "Schach", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:bfd97c66f3ae1909", - "externalId": "vokabel-258474", - "title": "Schießsport", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:486af1fdb497ee6c", - "externalId": "vokabel-242262", - "title": "Schwimmen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:0a9a10161d7dd8ff", - "externalId": "vokabel-242263", - "title": "Segeln", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:84b8546fe9016f95", - "externalId": "vokabel-242264", - "title": "Short Track", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:2d018d22092526e2", - "externalId": "vokabel-258453", - "title": "Skateboard", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:c648b58440eb5906", - "externalId": "vokabel-242265", - "title": "Skeleton", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:015997b8bad502b3", - "externalId": "vokabel-242266", - "title": "Ski Alpin", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e76fdb96e7193165", - "externalId": "vokabel-242272", - "title": "Ski Cross", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:43a97653133f3420", - "externalId": "vokabel-242267", - "title": "Ski Freestyle", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:5fedfea0fbc65af4", - "externalId": "vokabel-242268", - "title": "Ski Langlauf", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:628e1841b4cd5c43", - "externalId": "vokabel-242270", - "title": "Ski Mounteneering", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1d1d1f4b522c6c67", - "externalId": "vokabel-242269", - "title": "Ski Nordisch/NoKo", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:207ef9aa1d276ad0", - "externalId": "vokabel-242271", - "title": "Skisprung/Skiflug", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:a59f3a7d4ef307f6", - "externalId": "vokabel-242273", - "title": "Snowboard", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:fb956eabe9eeb9e4", - "externalId": "vokabel-242252", - "title": "Sommer/Winter Paralympics", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b9658f4040048f77", - "externalId": "vokabel-242253", - "title": "Special Olympics", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:e1d328b054b3a71b", - "externalId": "vokabel-258455", - "title": "Surfen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:6432eb670767ca3d", - "externalId": "vokabel-258457", - "title": "Taekwondo", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:2bbd7e04ba8fb09c", - "externalId": "vokabel-242274", - "title": "Tanzen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:694d9fef1365860f", - "externalId": "vokabel-242275", - "title": "Tennis", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ae5cbdd3e95bddba", - "externalId": "vokabel-242276", - "title": "Tischtennis", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:ecac5c3840b1eb29", - "externalId": "vokabel-242277", - "title": "Trampolin", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:f0e8d4cba84885fd", - "externalId": "vokabel-242278", - "title": "Triathlon", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:b218352001a2b36e", - "externalId": "vokabel-242279", - "title": "Turnen", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9b6e3999cf8538cd", - "externalId": "vokabel-242280", - "title": "Volleyball", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:4c659790d1390f65", - "externalId": "vokabel-272469", - "title": "Wakeboard", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:d99ed872666f0e5e", - "externalId": "vokabel-242281", - "title": "Wasserball", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:33f6909a37d83f41", - "externalId": "vokabel-272470", - "title": "Wasserski", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:710671719e3209d2", - "externalId": "vokabel-272471", - "title": "Wassersport", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:1e8ffa4e9c5155eb", - "externalId": "vokabel-242282", - "title": "Wintersport", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-subgenre:9583a81415fa4d73", - "externalId": "vokabel-258449", - "title": "eSport", - "isAudio": true, - "isVideo": true - }, - { - "id": "urn:ard:category-genre:8cb6a40891166406", - "externalId": "vokabel-251976", - "title": "Sportarten", - "isAudio": true, - "isVideo": true - } - ] -} diff --git a/docs/LINTING.md b/docs/LINTING.md deleted file mode 100644 index abd8748..0000000 --- a/docs/LINTING.md +++ /dev/null @@ -1,42 +0,0 @@ -# Super Linter for SWR Audio Lab - -To simplify linting, this repository contains a template, that can be used by all SWR Audio Lab projects. - -## Super Linter - -The used linter of choice here is `super-linter`, which bundles a lot of different projects. Some that are really not needed are disabled in the config. - -Super Linter: [github.com/github/super-linter](https://github.com/github/super-linter) - -## Usage - -Simply create a file `.github/workflows/linter.yml`: - -```yaml -name: Linter - -on: - workflow_dispatch: - pull_request: - -jobs: - lint: - uses: swrlab/node-utils/.github/workflows/linter.yml - with: - install-all: true - generate-keys: true - validate-all-codebase: true -``` - -This uses the re-usable GitHub Actions workflow and calls the template from `node-utils` using the provided input variables: - -- `install-all` - If `true` it will use `yarn install:all` instead of `yarn install` to trigger a custom script. - This is useful, if the repository has multiple sub-folders that all need to be installed -- `generate-keys` - If `true` will call `yarn keys:generate` to run a custom script for dummy key creation. -- `log-level` - One of the follorwing: `ERROR`, `WARN`, `NOTICE`, `VERBOSE`, `DEBUG` or `TRACE`; defaults to `VERBOSE`. -- `validate-all-codebase` - Corresponds to `VALIDATE_ALL_CODEBASE` for `super-linter`: - _When set to `false`, only new or edited files will be parsed for validation._ - -## Configuration - -To prevent copying configuration files to every repository, all `super-linter` options are included in this one ([`.github/linters`](./../.github/linters/)) and get cloned into every run. diff --git a/docs/NPM.md b/docs/NPM.md deleted file mode 100644 index a3f9741..0000000 --- a/docs/NPM.md +++ /dev/null @@ -1,36 +0,0 @@ -# SWR Audio Lab on npm - -This is a quick guide and some notes about SWR Audio Lab packages on [npmjs.com](https://www.npmjs.com/). - -## Security - -Two-factor authentication (2FA) is enabled for all of SWR Audio Lab's packages (published as `@swrlab`). -To set up 2FA for your account, visit this guide: [docs.npmjs.com/configuring-two-factor-authentication](https://docs.npmjs.com/configuring-two-factor-authentication). - -## Publishing - -First, make sure you are logged into the `npm` CLI locally (`npm config list`). If not, use the web authentication workflow: - -```sh -npm login --auth-type web -``` - -Now go to the folder locally: - -```sh -cd /path/to/my/repo -``` - -Make sure it is up-to-date and the version you plan on publishing. You can also check the config with: - -```sh -npm publish --dry-run -``` - -Once everything is ready, hit publish: - -```sh -npm publish --access public -``` - -It will ask for a one-time password (OTP), enter it into the CLI and hit Enter. diff --git a/eslint.config.js b/eslint.config.js index 533adc4..bf95ae1 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,43 +1,6 @@ import { audiolab } from '@swrlab/style-guide/eslint.js' -export default audiolab( - { - prettier: true, - comments: true, - }, - [ - { - name: 'node-utils/disabled-rules', - files: ['packages/**', 'utils/**'], - // because we disable some rules, there might be complaints about unused disable directives - linterOptions: { - reportUnusedDisableDirectives: false, - }, - rules: { - 'unicorn/prefer-string-slice': 'off', - 'perfectionist/sort-imports': 'off', - 'unicorn/prefer-string-replace-all': 'off', - 'node/prefer-global/buffer': 'off', - '@eslint-community/eslint-comments/require-description': 'off', - 'jsonc/sort-keys': 'off', - 'no-console': 'off', - 'node/prefer-global/process': 'off', - 'prefer-template': 'off', - 'require-await': 'off', - 'security/detect-non-literal-fs-filename': 'off', - 'security/detect-non-literal-regexp': 'off', - 'security/detect-object-injection': 'off', - 'sonarjs/no-ignored-exceptions': 'off', - 'sonarjs/os-command': 'off', - 'sonarjs/pseudo-random': 'off', - 'sonarjs/slow-regex': 'off', - 'unicorn/no-instanceof-builtins': 'off', - 'unicorn/prefer-date-now': 'off', - 'unicorn/prefer-includes': 'off', - 'unicorn/prefer-optional-catch-binding': 'off', - 'unicorn/prefer-prototype-methods': 'off', - 'unused-imports/no-unused-vars': 'off', - }, - }, - ] -) +export default audiolab({ + prettier: true, + comments: true, +}) diff --git a/index.js b/index.js deleted file mode 100644 index 3d8d6da..0000000 --- a/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const storage = require('./packages/storage-wrapper') -const undici = require('./packages/undici') - -module.exports = { - storage, - undici, -} diff --git a/keys/.gitignore b/keys/.gitignore deleted file mode 100644 index a6c57f5..0000000 --- a/keys/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.json diff --git a/package.json b/package.json index 11c1508..e992abb 100644 --- a/package.json +++ b/package.json @@ -6,61 +6,107 @@ "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/swrlab/node-utils" + "url": "git+https://github.com/swrlab/node-utils.git" }, "author": "SWR Audio Lab ", - "main": "./src/index.ts", - "module": "./src/index.js", + "files": [ + "bin", + "dist" + ], + "main": "./dist/index.js", + "module": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { - ".": "./src/index.ts", - "./packages/*": "./src/legacy/*.ts", - "./ard": "./src/ard/index.ts", - "./date": "./src/date/index.ts" + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./ard": { + "types": "./dist/ard.d.ts", + "default": "./dist/ard.js" + }, + "./array": { + "types": "./dist/array.d.ts", + "default": "./dist/array.js" + }, + "./date": { + "types": "./dist/date.d.ts", + "default": "./dist/date.js" + }, + "./env": { + "types": "./dist/env.d.ts", + "default": "./dist/env.js" + }, + "./helper": { + "types": "./dist/helper.d.ts", + "default": "./dist/helper.js" + }, + "./number": { + "types": "./dist/number.d.ts", + "default": "./dist/number.js" + }, + "./object": { + "types": "./dist/object.d.ts", + "default": "./dist/object.js" + }, + "./predicate": { + "types": "./dist/predicate.d.ts", + "default": "./dist/predicate.js" + }, + "./storage": { + "types": "./dist/storage.d.ts", + "default": "./dist/storage.js" + }, + "./string": { + "types": "./dist/string.d.ts", + "default": "./dist/string.js" + }, + "./packages/ard": { + "types": "./dist/packages/ard.d.ts", + "default": "./dist/packages/ard.js" + }, + "./packages/date": { + "types": "./dist/packages/date.d.ts", + "default": "./dist/packages/date.js" + }, + "./packages/helpers": { + "types": "./dist/packages/helpers.d.ts", + "default": "./dist/packages/helpers.js" + }, + "./packages/numbers": { + "types": "./dist/packages/numbers.d.ts", + "default": "./dist/packages/numbers.js" + }, + "./packages/storage-wrapper": { + "types": "./dist/packages/storage-wrapper.d.ts", + "default": "./dist/packages/storage-wrapper.js" + }, + "./packages/strings": { + "types": "./dist/packages/strings.d.ts", + "default": "./dist/packages/strings.js" + }, + "./packages/undici": { + "types": "./dist/packages/undici.d.ts", + "default": "./dist/packages/undici.js" + } + }, + "bin": { + "ard-coreId": "./bin/ard-coreId.js" }, "publishConfig": { "access": "public", - "provenance": true, - "main": "./dist/index.js", - "module": "./dist/index.js", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "./ard": { - "types": "./dist/ard.d.ts", - "default": "./dist/ard.js" - }, - "./date": { - "types": "./dist/date.d.ts", - "default": "./dist/date.js" - }, - "./packages/date": { - "types": "./dist/packages/date.d.ts", - "default": "./dist/packages/date.js" - }, - "./packages/strings": { - "types": "./dist/packages/strings.d.ts", - "default": "./dist/packages/strings.js" - }, - "./packages/numbers": { - "types": "./dist/packages/strings.d.ts", - "default": "./dist/packages/strings.js" - }, - "./packages/*": { - "types": "./src/legacy/*.d.ts", - "default": "./src/legacy/*.js" - } - } + "provenance": true }, "scripts": { - "ard:coreId": "node ./scripts/ard/coreId.js", + "ard:coreId": "bun ./bin/ard-coreId.mjs", + "attw": "bunx @arethetypeswrong/cli --pack . --profile esm-only", "build": "tsdown", "format": "prettier --write .", + "knip": "knip", "lint": "eslint", "lint:fix": "eslint --fix", - "test": "bun run typecheck && bun run test:bun", + "release": "bunx bumpp", + "test": "bun run typecheck && bun run test:bun && bun run test:legacy", "test:bun": "bun test ./tests/**test*.ts", "test:legacy": "bun test ./tests/legacy/*.test.mjs", "test:legacy:node": "node --test ./tests/legacy/*.test.mjs", @@ -68,18 +114,17 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@google-cloud/storage": "^7.17.0", - "@types/node": "^24.3.1", - "abort-controller": "^3.0.0", "luxon": "3.7.2", - "node-crc": "https://github.com/swrlab/node-crc#v2.1.0", "undici": "7.15.0" }, "devDependencies": { + "@google-cloud/storage": "^7.17.0", "@swrlab/style-guide": "^2.0.7", "@types/bun": "^1.2.21", "@types/luxon": "^3.7.1", + "@types/node": "^24.3.1", "eslint": "^9.35.0", + "knip": "^5.63.1", "prettier": "^3.6.2", "tsdown": "^0.14.2", "typescript": "^5.9.2" diff --git a/packages/ard/README.md b/packages/ard/README.md deleted file mode 100644 index 1cd05ab..0000000 --- a/packages/ard/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# SWR Audio Lab / ARD helpers - -Common internal ARD tools like ID creation. - -- [SWR Audio Lab / ARD helpers](#swr-audio-lab--ard-helpers) - - [Install](#install) - - [`createHashedId` - Convert a string to ARD's hash style](#createhashedid---convert-a-string-to-ards-hash-style) - -## Install - -Add the parent package to your dependencies: - -```sh -yarn add @swrlab/utils -``` - -## `createHashedId` - Convert a string to ARD's hash style - -- `string` (required) - value to encode - -Import the library: - -```js -const ardTools = require('@swrlab/utils/packages/ard') -``` - -Then use the toolkit to convert a string: - -```js -const myString = 'my-string-to-encode' -const hashedString = ard.createHashedId(myString) -// 6a80b80f748c9b50 -``` diff --git a/packages/helpers/README.md b/packages/helpers/README.md deleted file mode 100644 index 586e6b6..0000000 --- a/packages/helpers/README.md +++ /dev/null @@ -1,68 +0,0 @@ -# SWR Audio Lab / Helpers - -Common functions and helpers. - -- [SWR Audio Lab / Helpers](#swr-audio-lab--helpers) - - [Install](#install) - - [`arrayToObjectCount` - reduce array elements to object with count](#arraytoobjectcount---reduce-array-elements-to-object-with-count) - - [`getJsonKeys` - get all keys of json input](#getjsonkeys---get-all-keys-of-json-input) - - [`sleep` - sleep a given time (async)](#sleep---sleep-a-given-time-async) - -## Install - -Add the parent package to your dependencies: - -```sh -yarn add @swrlab/utils -``` - -## `arrayToObjectCount` - reduce array elements to object with count - -- `value` (required) - Array to get entries from - -Import the library: - -```js -const { arrayToObjectCount } = require('@swrlab/utils/packages/helpers') -``` - -Then use the toolkit: - -```js -arrayToObjectCount(['foo', 'bar', 'bar']) -// { bar: 2, foo: 1 } -``` - -## `getJsonKeys` - get all keys of json input - -- `value` (required) - Json to get keys from - -Import the library: - -```js -const { getJsonKeys } = require('@swrlab/utils/packages/helpers') -``` - -Then use the toolkit: - -```js -getJsonKeys({ hello: 'world', foo: 'bar' }) -// ['hello', 'foo'] -``` - -## `sleep` - sleep a given time (async) - -- `value` (required) - Value to sleep (in ms) - -Import the library: - -```js -const { sleep } = require('@swrlab/utils/packages/helpers') -``` - -Then use the toolkit: - -```js -await sleep(1e3) -// will sleep 1s -``` diff --git a/packages/storage-wrapper/README.md b/packages/storage-wrapper/README.md deleted file mode 100644 index 083b320..0000000 --- a/packages/storage-wrapper/README.md +++ /dev/null @@ -1,172 +0,0 @@ -# SWR Audio Lab / Storage Wrapper - -A utility to wrap file access to local, Google Cloud Storage and AWS S3 file storage. - -- [SWR Audio Lab / Storage Wrapper](#swr-audio-lab--storage-wrapper) - - [Install](#install) - - [Initialization](#initialization) - - [`createUri` - Convert to URI](#createuri---convert-to-uri) - - [`createUrl` - Sign a URI for public URL](#createurl---sign-a-uri-for-public-url) - - [`delete` - Delete a file](#delete---delete-a-file) - - [`list` - List files by prefix](#list---list-files-by-prefix) - - [`load` - Download a file](#load---download-a-file) - - [`move` - Copy or Move a file](#move---copy-or-move-a-file) - - [`save` - Save a file](#save---save-a-file) - -## Install - -Add the parent package to your dependencies: - -```sh -yarn add @swrlab/utils -``` - -## Initialization - -We like to create one local file in a project that provides this initialized utility: - -```js -// load node util -const Storage = require('@swrlab/utils/packages/storage-wrapper') - -// load custom keys and storage -const storage = new Storage({ - gs: { - projectId: 'my-project-id', - }, - s3: { region: 'eu-west-1' }, - logging: true, -}) - -// export everything -module.exports = storage -``` - -The `gs` object is the same, as one can provide to the [Google Cloud Storage utility](https://googleapis.dev/nodejs/storage/latest/index.html). We usually only set the `projectId` explicitly. If needed you can provide more details like `keyFilename` or [set credentials using `GOOGLE_APPLICATION_CREDENTIALS`](https://cloud.google.com/docs/authentication/production#auth-cloud-implicit-nodejs) env. - -For AWS the `s3` also provides access to configure the `aws-sdk` library. It has multiple options to load credentials, all documented in [AWS: Configuring the SDK for JavaScript](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/configuring-the-jssdk.html). We sometimes also set the credentials asynchronously using Google Cloud Secret Manager: - -```js -const storage = new Storage({ - gs: { - projectId: 'my-project-id', - }, - s3: { region: 'eu-west-1' }, - logging: true, -}) - -secrets.get('radiohub-ingest-aws').then(({ json }) => { - storage.sdk.s3.config.update(json) -}) -``` - -The `logging` flag controls whether all file actions by this utility should be logged. - -## `createUri` - Convert to URI - -- `bucket` (required) -- `path` (required) - -Create a URI (e.g. `gs://my-bucket/my-file.txt`) from bucket and path names. - -Works with Google Cloud Storage (`gs`): - -```js -const fileUri = storage.createUri.gs(bucket, name) -// gs://bucket/name -``` - -And `s3`: - -```js -const fileUri = storage.createUri.s3(bucket, name) -// s3://bucket/name -``` - -## `createUrl` - Sign a URI for public URL - -- `uri` (required) - Source URI to use for signing -- `ttl` (required) - Time to live in milliseconds for public link, provide as integer or shortform (e.g. `60e3` for `60000`) -- `logPrefix` (optional) - Prefix for log lines - -Use this to sign a URI into a (publicly) accessible URL. Currently only implemented for Google Cloud Storage: - -```js -const sourceUrl = await storage.createUrl(fileUri, 60e3) -``` - -## `delete` - Delete a file - -- `uri` (required) - Source URI to delete -- `logPrefix` (optional) - Prefix for log lines - -Delete an existing file: - -```js -await storage.delete(fileUri) -``` - -The proper connector is detected using the prefixes (`s3://`, `gs://`, `http[s]://` or local file). Actions against `http[s]://` are rejected. - -## `list` - List files by prefix - -- `uri` (required) - Source URI prefix to list -- `max` (required) - Rough maximum of elements expected -- `next` (optional) - Next token if available (AWS only) -- `logPrefix` (optional) - Prefix for log lines - -List all elements matching a prefix, which can be a folder name or folder + fileprefix. -Google Cloud provides a full list of elements: - -```js -const list = await storage.list(fileUriPrefix, 300) -``` - -AWS also returns a next token if available - -```js -const { list, next } = await storage.list(fileUriPrefix, 300) -``` - -The utility keeps listing more elements until either max is reached or no more items are available. Please note that AWS and GCP provide lists in batches, the maximum of elements might be exceeded. - -## `load` - Download a file - -- `uri` (required) - Source URI to load -- `logPrefix` (optional) - Prefix for log lines -- `options` (optional) - Prefix for log lines - - `timeout` (optional) - Timeout for http[s] requests - -Download a single file and returns the contents buffer. - -```js -const fileBuffer = await storage.list(fileUri) -``` - -## `move` - Copy or Move a file - -- `sourceUri` (required) - Source file URI to copy -- `destinationUri` (required) - Destination URI where to copy the file to -- `keepOriginal` (required) - Boolean whether to keep the source -- `logPrefix` (optional) - Prefix for log lines - -Moving provides easy access to copy and move actions between multiple storage types and providers. Switching between copying (non-destructive) and moving (deletes the source) is handled via the `keepOriginal` flag. - -There are essentially three ways to move files: - -1. `gs` to `gs` - Use the Google Cloud's native Storage option to move or copy a file -2. `s3` to `s3` - Use the AWS method for copying and deleting an object -3. `any` to `any` - This uses the internal methods to `load`, `save` and `delete` the files. Please note that this actually downloads the file (incurring bandwidth), rather than using the cloud provider's native methods for moving data. - -## `save` - Save a file - -- `uri` (required) - Destination URI to use for saving -- `buffer` (required) - File buffer to save -- `logPrefix` (optional) - Prefix for log lines -- `resumable` (optional) - Set Google Cloud transfer as `resumable` - -Provide a URI and file buffer to save a file. - -```js -await storage.save(fileUri, myBuffer) -``` diff --git a/packages/strings/README.md b/packages/strings/README.md deleted file mode 100644 index 303fd4c..0000000 --- a/packages/strings/README.md +++ /dev/null @@ -1,354 +0,0 @@ -# SWR Audio Lab / Strings, Arrays, Objects - -Common string, array, object encoding and getter helpers. - -- [SWR Audio Lab / Strings, Arrays, Objects](#swr-audio-lab--strings-arrays-objects) - - [Install](#install) - - [`capitalize` - get capitalized string](#capitalize---get-capitalized-string) - - [`getObjectLength` - get the length of an object](#getobjectlength---get-the-length-of-an-object) - - [`isArray` - check if a value is a proper array](#isarray---check-if-a-value-is-a-proper-array) - - [`isEmptyArray` - check if a value is an empty array](#isemptyarray---check-if-a-value-is-an-empty-array) - - [`isEmptyObject` - check if a value is an empty object](#isemptyobject---check-if-a-value-is-an-empty-object) - - [`isEmptyString` - check if a value is an empty string](#isemptystring---check-if-a-value-is-an-empty-string) - - [`isIncluded` - check if a value (haystack) includes another value (needle)](#isincluded---check-if-a-value-haystack-includes-another-value-needle) - - [`isNull` - check if a value is null](#isnull---check-if-a-value-is-null) - - [`isObject` - check if a value is a proper object](#isobject---check-if-a-value-is-a-proper-object) - - [`isUndefined` - check if a value is undefined](#isundefined---check-if-a-value-is-undefined) - - [`notEmptyArray` - check if a value is not an empty array](#notemptyarray---check-if-a-value-is-not-an-empty-array) - - [`notEmptyObject` - check if a value is not an empty object](#notemptyobject---check-if-a-value-is-not-an-empty-object) - - [`notNullOrUndefined` - check if a value is neither null nor undefined](#notnullorundefined---check-if-a-value-is-neither-null-nor-undefined) - - [`pluralize` - get pluralized string](#pluralize---get-pluralized-string) - - [`removeDoubleSpaces` - take a string and remove its duplicate spaces](#removedoublespaces---take-a-string-and-remove-its-duplicate-spaces) - - [`toHex` - take a string convert it to a hex string](#tohex---take-a-string-convert-it-to-a-hex-string) - -## Install - -Add the parent package to your dependencies: - -```sh -yarn add @swrlab/utils -``` - -## `capitalize` - get capitalized string - -- `value` (required) - String to capitalize - -Import the library: - -```js -const { capitalize } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -capitalize('apple') -// Apple -``` - -## `getObjectLength` - get the length of an object - -- `value` (required) - Value to check - -Import the library: - -```js -const { getObjectLength } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -getObjectLength({ hello: 'world' }) -// 1 - -getObjectLength({ hello: 'world', foo: 'bar' }) -// 2 -``` - -## `isArray` - check if a value is a proper array - -- `value` (required) - Value to check - -Import the library: - -```js -const { isArray } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -isArray(['hello world']) -// true - -isArray('hello world') -// false -``` - -## `isEmptyArray` - check if a value is an empty array - -- `value` (required) - Value to check - -Import the library: - -```js -const { isEmptyArray } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -isEmptyArray([]) -// true - -isEmptyArray(['hello world']) -// false -``` - -## `isEmptyObject` - check if a value is an empty object - -- `value` (required) - Value to check - -Import the library: - -```js -const { isEmptyObject } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -isEmptyObject({}) -// true - -isEmptyObject({ hello: 'world' }) -// false -``` - -## `isEmptyString` - check if a value is an empty string - -- `value` (required) - Value to check - -Import the library: - -```js -const { isEmptyString } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -isEmptyString('') -// true - -isEmptyString('hello world') -// false -``` - -## `isIncluded` - check if a value (haystack) includes another value (needle) - -- `haystack` (required) - Array or value to check -- `needle` (required) - Array or value to check - -Import the library: - -```js -const { isIncluded } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -isIncluded('hello world', 'hello') -// true - -isIncluded('hello world', 'earth') -// false -``` - -## `isNull` - check if a value is null - -- `value` (required) - Value to check - -Import the library: - -```js -const { isNull } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -isNull(null) -// true - -isNull(undefined) -// false -``` - -## `isObject` - check if a value is a proper object - -- `value` (required) - Value to check - -Import the library: - -```js -const { isObject } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -isObject({ hello: 'world' }) -// true - -isObject('hello world') -// false -``` - -## `isUndefined` - check if a value is undefined - -- `value` (required) - Value to check - -Import the library: - -```js -const { isUndefined } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -isUndefined(undefined) -// true - -isUndefined(null) -// false -``` - -## `notEmptyArray` - check if a value is not an empty array - -- `value` (required) - Value to check - -Import the library: - -```js -const { notEmptyArray } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -notEmptyArray(['hello world']) -// true - -notEmptyArray([]) -// false -``` - -## `notEmptyObject` - check if a value is not an empty object - -- `value` (required) - Value to check - -Import the library: - -```js -const { notEmptyObject } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -notEmptyObject({ hello: 'world' }) -// true - -notEmptyObject({}) -// false -``` - -## `notNullOrUndefined` - check if a value is neither null nor undefined - -- `value` (required) - Value to check - -Import the library: - -```js -const { notNullOrUndefined } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -notNullOrUndefined('hello world') -// true - -notNullOrUndefined(null) -// false - -notNullOrUndefined(undefined) -// false -``` - -## `pluralize` - get pluralized string - -- `value` (required) - String to pluralize - -Import the library: - -```js -const { pluralize } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -pluralize(1, 'Apple') -// 1 Apple - -pluralize(1000, 'Apple') -// 1.000 Apples - -pluralize(1, 'Child', 'Children') -// 1 Child - -pluralize(1000, 'Child', 'Children') -// 1.000 Children -``` - -## `removeDoubleSpaces` - take a string and remove its duplicate spaces - -- `value` (required) - String to convert - -Import the library: - -```js -const { removeDoubleSpaces } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -removeDoubleSpaces('hello world') -// hello world - -removeDoubleSpaces('hello world once again') -// hello world once again -``` - -## `toHex` - take a string convert it to a hex string - -- `value` (required) - String to convert - -Import the library: - -```js -const { toHex } = require('@swrlab/utils/packages/strings') -``` - -Then use the toolkit: - -```js -toHex('hello world') -// 68656c6c6f20776f726c64 -``` diff --git a/packages/undici/README.md b/packages/undici/README.md deleted file mode 100644 index e54ae30..0000000 --- a/packages/undici/README.md +++ /dev/null @@ -1,57 +0,0 @@ -# SWR Audio Lab / Undici - -See [undici.nodejs.org](https://undici.nodejs.org) for the full Undici configuration and usage. - -- [SWR Audio Lab / Undici](#swr-audio-lab--undici) - - [Import](#import) - - [Request](#request) - -## Import - -Basic import: - -```js -// load request handler -const undici = require('@swrlab/utils/packages/undici') - -// export handler -module.exports = undici() -``` - -Import with Datadog tracer enabled: - -```js -// add tracing -const tracer = process.env.DD_TRACE_ENABLED === 'true' ? require('../tracer') : null - -// load request handler -const undici = require('@swrlab/utils/packages/undici') - -// export handler -module.exports = undici(tracer) -``` - -## Request - -Simple request: - -```js -const data = await undici(someApiUrl) -``` - -Advanced usage: - -```js -const data = await undici(someApiUrl, { - method: 'GET', - timeout: 6e3, - reject: false, - maxRedirections: 5, -}) -``` - -You can also use object desctructuring for easy access to the output: - -```js -const { headers, statusCode, json } = await undici(someApiUrl) -``` diff --git a/packages/undici/_options.js b/packages/undici/_options.js deleted file mode 100644 index 3672e72..0000000 --- a/packages/undici/_options.js +++ /dev/null @@ -1,13 +0,0 @@ -// load config -const { name, version } = require('../../package.json') - -const userAgent = `${name.replace('@', '')}/${version}` - -module.exports = { - keepAliveTimeout: 30e3, - headersTimeout: 0, - bodyTimeout: 0, - headers: { - 'user-agent': process.env.USER_AGENT || userAgent, - }, -} diff --git a/packages/undici/convertReadableStream.js b/packages/undici/convertReadableStream.js deleted file mode 100644 index ddb5ca5..0000000 --- a/packages/undici/convertReadableStream.js +++ /dev/null @@ -1,18 +0,0 @@ -// provide util to confert readable stream to buffer -module.exports = async (readable) => { - // create output details - let string = '' - const chunks = [] - - // handle each chunk - for await (const chunk of readable) { - string += chunk - chunks.push(chunk) - } - - // reformat buffer - const buffer = Buffer.concat(chunks) - - // return data - return { string, buffer } -} diff --git a/packages/undici/index.js b/packages/undici/index.js deleted file mode 100644 index c6daa22..0000000 --- a/packages/undici/index.js +++ /dev/null @@ -1,5 +0,0 @@ -// load utils -const request = require('./request') - -// export handler with tracing, if enabled -module.exports = (tracer) => tracer?.wrap('undici.request', request) || request diff --git a/packages/undici/request.js b/packages/undici/request.js deleted file mode 100644 index fa890e0..0000000 --- a/packages/undici/request.js +++ /dev/null @@ -1,71 +0,0 @@ -// load node utils -const undici = require('undici') -const AbortController = require('abort-controller') - -// fetch options and utils -const _options = require('./_options') -const convertReadableStream = require('./convertReadableStream') - -const DEFAULT_TIMEOUT = 7e3 - -module.exports = async (url, options) => { - // use controller for timeouts - const abortController = new AbortController() - const abortTimeout = setTimeout(() => { - abortController.abort() - }, options?.timeout || DEFAULT_TIMEOUT) - - // prepare options - const requestOptions = { - ..._options, - method: options?.method || 'GET', - body: options?.body || undefined, - signal: abortController.signal, - } - if (options?.headers) - requestOptions.headers = { - ...requestOptions.headers, - ...options.headers, - } - - // make actual request - const { statusCode, headers, trailers, body } = await undici.request(url, requestOptions) - - // remove timeout since request finished beforehand - clearTimeout(abortTimeout) - - // set ok - const ok = statusCode >= 200 && statusCode < 300 - if (!ok && (!options || options?.reject !== false)) return Promise.reject({ statusCode, ok, headers, url }) - - // turn stream into string - const { string, buffer } = await convertReadableStream(body) - - // detect/ set redirect - const redirect = statusCode >= 300 && statusCode < 400 && headers.location ? new URL(headers.location, url) : null - - // fetch header vars - const contentType = headers['content-type'] - - // parse json if set - let json - try { - json = contentType?.indexOf('application/json') !== -1 ? JSON.parse(string) : null - } catch (error) { - json = null - } - - // return data - return Promise.resolve({ - statusCode, - ok, - redirect, - headers, - contentType, - trailers, - body, - string, - buffer, - json, - }) -} diff --git a/scripts/ard/coreId.js b/scripts/ard/coreId.js deleted file mode 100644 index 689d4a8..0000000 --- a/scripts/ard/coreId.js +++ /dev/null @@ -1,10 +0,0 @@ -import process from 'node:process' -import { createHashedId } from '../../src/ard/index.ts' - -const input = process.argv.slice(2) - -console.info('INPUT:') -console.info(input) -console.info(' ') -console.info('OUTPUT (CRC64-ECMA182):') -console.info(createHashedId(input)) diff --git a/src/ard/coreId.ts b/src/ard/coreId.ts new file mode 100644 index 0000000..3878be6 --- /dev/null +++ b/src/ard/coreId.ts @@ -0,0 +1,17 @@ +import process from 'node:process' +import { createHashedId } from './createHashedId.ts' + +export const coreId = (): void => { + const [input] = process.argv.slice(2) + + if (!input) { + console.error('Please provide an input') + return + } + + console.info('INPUT:') + console.info(input) + console.info(' ') + console.info('OUTPUT (CRC64-ECMA182):') + console.info(createHashedId(input)) +} diff --git a/src/array/README.md b/src/array/README.md new file mode 100644 index 0000000..e606636 --- /dev/null +++ b/src/array/README.md @@ -0,0 +1,74 @@ +# SWR Audio Lab / Array + +Common array utilities. + +- [SWR Audio Lab / Array](#swr-audio-lab--array) + - [Install](#install) + - [`arrayToObjectCount` - reduce array elements to object with count](#arraytoobjectcount---reduce-array-elements-to-object-with-count) + - [`isEmptyArray` - check if a value is an empty array](#isemptyarray---check-if-a-value-is-an-empty-array) + - [`notEmptyArray` - check if a value is not an empty array](#notemptyarray---check-if-a-value-is-not-an-empty-array) + +## Install + +Add the parent package to your dependencies: + +```sh +npm add @swrlab/utils +``` + +## `arrayToObjectCount` - reduce array elements to object with count + +- `value` (required) - Array to get entries from + +Import the library: + +```js +import { arrayToObjectCount } from '@swrlab/utils/array' +``` + +Then use the toolkit: + +```js +arrayToObjectCount(['foo', 'bar', 'bar']) +// { bar: 2, foo: 1 } +``` + +## `isEmptyArray` - check if a value is an empty array + +- `value` (required) - Value to check + +Import the library: + +```js +import { isEmptyArray } from '@swrlab/utils/array' +``` + +Then use the toolkit: + +```js +isEmptyArray([]) +// true + +isEmptyArray(['hello world']) +// false +``` + +## `notEmptyArray` - check if a value is not an empty array + +- `value` (required) - Value to check + +Import the library: + +```js +import { notEmptyArray } from '@swrlab/utils/array' +``` + +Then use the toolkit: + +```js +notEmptyArray(['hello world']) +// true + +notEmptyArray([]) +// false +``` diff --git a/packages/date/README.md b/src/date/README.md similarity index 84% rename from packages/date/README.md rename to src/date/README.md index f85a0b6..b58870e 100644 --- a/packages/date/README.md +++ b/src/date/README.md @@ -28,7 +28,7 @@ yarn add @swrlab/utils Import the library: ```js -const { getDateHourMinutes } = require('@swrlab/utils/packages/date') +import { getDateHourMinutes } from '@swrlab/utils/date' ``` Then use the toolkit: @@ -45,7 +45,7 @@ getDateHourMinutes('2038-01-19T03:14:08.000') Import the library: ```js -const { getDayMonthYear } = require('@swrlab/utils/packages/date') +import { getDayMonthYear } from '@swrlab/utils/date' ``` Then use the toolkit: @@ -62,7 +62,7 @@ getDayMonthYear('2038-01-19T03:14:08.000') Import the library: ```js -const { getFullRelativeTime } = require('@swrlab/utils/packages/date') +import { getFullRelativeTime } from '@swrlab/utils/date' ``` Then use the toolkit: @@ -79,7 +79,7 @@ getFullRelativeTime('2038-01-19T03:14:08.000') Import the library: ```js -const { getHourMinutes } = require('@swrlab/utils/packages/date') +import { getHourMinutes } from '@swrlab/utils/date' ``` Then use the toolkit: @@ -96,7 +96,7 @@ getHourMinutes('2038-01-19T03:14:08.000') Import the library: ```js -const { getIsoRelativeTime } = require('@swrlab/utils/packages/date') +import { getIsoRelativeTime } from '@swrlab/utils/date' ``` Then use the toolkit: @@ -113,7 +113,7 @@ getIsoRelativeTime('2038-01-19T03:14:08.000') Import the library: ```js -const { getRelativeTime } = require('@swrlab/utils/packages/date') +import { getRelativeTime } from '@swrlab/utils/date' ``` Then use the toolkit: @@ -130,7 +130,7 @@ getRelativeTime('2038-01-19T03:14:08.000') Import the library: ```js -const { getYearMonthDay } = require('@swrlab/utils/packages/date') +import { getYearMonthDay } from '@swrlab/utils/date' ``` Then use the toolkit: @@ -147,7 +147,7 @@ getYearMonthDay('2038-01-19T03:14:08.000') Import the library: ```js -const { revYearMonthDay } = require('@swrlab/utils/packages/date') +import { revYearMonthDay } from '@swrlab/utils/date' ``` Then use the toolkit: diff --git a/src/env.ts b/src/env.ts new file mode 100644 index 0000000..6a652ac --- /dev/null +++ b/src/env.ts @@ -0,0 +1,160 @@ +/** + * Environment variable utilities with TypeScript support + * @fileoverview + */ + +import process from 'node:process' +import { parseBase64 } from './string/base64.ts' + +/** + * Type definitions for environment variable value types. + * boolean accepts `true` and `1`. + * base64 is parsed as JSON after decoding. + */ +type EnvVarType = 'string' | 'number' | 'boolean' | 'json' | 'base64' + +/** + * Configuration for environment variable retrieval + */ +interface EnvConfig { + /** Default value if environment variable is not set */ + defaultValue?: T | undefined + /** Whether the environment variable is required */ + required?: boolean + /** Type of the environment variable */ + type?: EnvVarType +} + +/** + * Error thrown when a required environment variable is missing + */ +export class MissingEnvVarError extends Error { + constructor(key: string) { + super(`Missing required environment variable: ${key}`) + this.name = 'MissingEnvVarError' + } +} + +/** + * Get an environment variable with proper typing + * + * @param key - The name of the environment variable + * @param config - Configuration options + * @returns The value of the environment variable with proper typing + * @throws {MissingEnvVarError} When a required environment variable is missing + * @throws {Error} When JSON parsing fails + */ +export function getEnv(key: string, config: EnvConfig = {}): T { + const { defaultValue, required = false, type = 'string' } = config + + // @ts-expect-error - Insert mocked values from vitest test. + const env = globalThis.__VitestMockEnv ?? process.env + // eslint-disable-next-line security/detect-object-injection -- There is no unsafe user-input. + const value = env[key] + + if (value === undefined) { + if (required) { + throw new MissingEnvVarError(key) + } + if (!required && defaultValue === undefined) { + console.info('There is no defaultValue for optional env key', key) + } + return defaultValue as T + } + + switch (type) { + case 'string': + return value as unknown as T + + case 'number': { + const num = Number.parseFloat(value) + return Number.isNaN(num) ? (defaultValue as T) : (num as unknown as T) + } + + case 'boolean': + return (value.toLowerCase() === 'true' || value === '1') as unknown as T + + case 'base64': + try { + const decoded = parseBase64(value) + return JSON.parse(decoded) as T + } catch (error) { + throw new Error(`Failed to parse environment variable ${key} as from base64 JSON: ${error}`, { + cause: error, + }) + } + + case 'json': + try { + return JSON.parse(value) as T + } catch (error) { + throw new Error(`Failed to parse environment variable ${key} as JSON: ${error}`) + } + + default: + return value as unknown as T + } +} + +/** + * Get a string environment variable + * + * @param key - The name of the environment variable + * @param defaultValue - Default value if the environment variable is not set + * @param required - Whether the environment variable is required + * @returns The string value of the environment variable + */ +export function getEnvString(key: string, defaultValue?: string, required = true): string { + if (required === false && defaultValue === undefined) + console.warn('When the env value is optional, a default value should be passed.') + return getEnv(key, { defaultValue, required, type: 'string' }) +} + +/** + * Get a JSON object from a base64 environment variable string. + * + * @param key - The name of the environment variable + * @param defaultValue - Default value if the environment variable is not set + * @param required - Whether the environment variable is required + * @throws {MissingEnvVarError} When a required environment variable is missing + * @returns The string value of the environment variable + */ +export function getEnvBase64(key: string, defaultValue?: T, required = true): T { + return getEnv(key, { defaultValue, required, type: 'base64' }) +} + +/** + * Get a number environment variable + * + * @param key - The name of the environment variable + * @param defaultValue - Default value if the environment variable is not set + * @param required - Whether the environment variable is required + * @returns The number value of the environment variable + */ +export function getEnvNumber(key: string, defaultValue?: number, required = false): number { + return getEnv(key, { defaultValue, required, type: 'number' }) +} + +/** + * Get a boolean environment variable + * + * @param key - The name of the environment variable + * @param defaultValue - Default value if the environment variable is not set + * @param required - Whether the environment variable is required + * @returns The boolean value of the environment variable + */ +export function getEnvBoolean(key: string, defaultValue?: boolean, required = false): boolean { + return getEnv(key, { defaultValue, required, type: 'boolean' }) +} + +/** + * Get a JSON environment variable + * + * @param key - The name of the environment variable + * @param defaultValue - Default value if the environment variable is not set + * @param required - Whether the environment variable is required + * @returns The parsed JSON value of the environment variable + */ +export function getEnvJson(key: string, defaultValue?: T, required = false): T { + return getEnv(key, { defaultValue, required, type: 'json' }) +} diff --git a/src/helpers/README.md b/src/helpers/README.md new file mode 100644 index 0000000..89eeba9 --- /dev/null +++ b/src/helpers/README.md @@ -0,0 +1,32 @@ +# SWR Audio Lab / Helpers + +Common functions and helpers. + +- [SWR Audio Lab / Helpers](#swr-audio-lab--helpers) + - [Install](#install) + - [`sleep` - sleep a given time (async)](#sleep---sleep-a-given-time-async) + +## Install + +Add the parent package to your dependencies: + +```sh +npm install @swrlab/utils +``` + +## `sleep` - sleep a given time (async) + +- `value` (required) - Value to sleep (in ms) + +Import the library: + +```js +import { sleep } from '@swrlab/utils/helpers' +``` + +Then use the toolkit: + +```js +await sleep(1e3) +// will sleep 1s +``` diff --git a/src/index.ts b/src/index.ts index 102244b..1b47e6e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,8 @@ export * from './ard/index.ts' export * from './date/index.ts' +export * from './env.ts' export * from './helpers/index.ts' export * from './number/index.ts' +export * from './object/index.ts' +export * from './predicate/index.ts' export * from './string/index.ts' diff --git a/src/legacy/storage-wrapper.ts b/src/legacy/storage-wrapper.ts index e69de29..26cafc5 100644 --- a/src/legacy/storage-wrapper.ts +++ b/src/legacy/storage-wrapper.ts @@ -0,0 +1,33 @@ +import type { StorageConfig, StorageWrapperInstance } from '../storage/utils.ts' +import * as google from '../storage/google.ts' + +import { createUri, createUrl, deleteFile, list, load, move, save } from '../storage/index.ts' + +/** + * Create a Google Cloud Storage Wrapper. + * @deprecated Use `@swrlab/utils/storage` instead. + * + * @param config - Storage Config. + * @returns A StorageWrapper + */ +export function StorageWrapper(config: StorageConfig): Promise | StorageWrapperInstance { + if (!config || !config.gs) { + throw new Error('storage config invalid') + } + + google.initialize(config.gs) + + const api: StorageWrapperInstance = { + createUri, + createUrl, + /** @deprecated Use `deleteFile` instead. */ + delete: deleteFile, + deleteFile, + list, + load, + save, + move, + } + + return api +} diff --git a/src/legacy/undici.ts b/src/legacy/undici.ts index 0c35106..52f54d6 100644 --- a/src/legacy/undici.ts +++ b/src/legacy/undici.ts @@ -161,8 +161,8 @@ const request = async ( } /** - * Request object, wrapped in a tracer if provided. - * @param [tracer] - (Optional) Tracer object containing a tracer function. + * Request object, wrapped in a Datadog tracer if provided. + * @param [tracer] - (Optional) Datadog APM Tracer object containing a tracer function. * @param tracer.wrap - (Optional) Object containing `name` and `request`. * @deprecated Just use native fetch instead or `ofetch` or `axios` if required. But modern fetch solves most problems and works in all Runtimes and Browsers. * @returns {object} - Request object. diff --git a/packages/numbers/README.md b/src/number/README.md similarity index 84% rename from packages/numbers/README.md rename to src/number/README.md index b3c2999..0d555ca 100644 --- a/packages/numbers/README.md +++ b/src/number/README.md @@ -1,6 +1,6 @@ -# SWR Audio Lab / Numbers +# SWR Audio Lab / Number -Common number and math helpers. +Common number and math utilities. - [SWR Audio Lab / Numbers](#swr-audio-lab--numbers) - [Install](#install) @@ -20,7 +20,9 @@ Common number and math helpers. Add the parent package to your dependencies: ```sh -yarn add @swrlab/utils +bun install @swrlab/utils +# or +bun install @swrlab/utils ``` ## `addLeadingZero` - add leading zero to number @@ -30,7 +32,7 @@ yarn add @swrlab/utils Import the library: ```js -const { addLeadingZero } = require('@swrlab/utils/packages/numbers') +import { addLeadingZero } from '@swrlab/utils/number' ``` Then use the toolkit: @@ -52,7 +54,7 @@ addLeadingZero(10) Import the library: ```js -const { addTrailingZeros } = require('@swrlab/utils/packages/numbers') +import { addTrailingZeros } from '@swrlab/utils/number' ``` Then use the toolkit: @@ -85,7 +87,7 @@ addTrailingZeros('2,2', 2, ',') Import the library: ```js -const { getAverage } = require('@swrlab/utils/packages/numbers') +import { getAverage } from '@swrlab/utils/number' ``` Then use the toolkit: @@ -106,7 +108,7 @@ getAverage([1.2, 2.4, 3.6], 1) Import the library: ```js -const { getDiff } = require('@swrlab/utils/packages/numbers') +import { getDiff } from '@swrlab/utils/number' ``` Then use the toolkit: @@ -127,7 +129,7 @@ getDiff(1, 2) Import the library: ```js -const { getRandomInRange } = require('@swrlab/utils/packages/numbers') +import { getRandomInRange } from '@swrlab/utils/number' ``` Then use the toolkit: @@ -148,7 +150,7 @@ getRandomInRange(5, 9) Import the library: ```js -const { getSum } = require('@swrlab/utils/packages/numbers') +import { getSum } from '@swrlab/utils/number' ``` Then use the toolkit: @@ -168,7 +170,7 @@ getSum([1.2, 2.4, 3.6], 1) Import the library: ```js -const { isEven } = require('@swrlab/utils/packages/numbers') +import { isEven } from '@swrlab/utils/number' ``` Then use the toolkit: @@ -189,7 +191,7 @@ isEven(1) Import the library: ```js -const { normalize } = require('@swrlab/utils/packages/numbers') +import { normalize } from '@swrlab/utils/number' ``` Then use the toolkit: @@ -210,7 +212,7 @@ normalize(80, 100) Import the library: ```js -const { roundTo } = require('@swrlab/utils/packages/numbers') +import { roundTo } from '@swrlab/utils/number' ``` Then use the toolkit: @@ -230,7 +232,7 @@ roundTo(1.23456, 4) Import the library: ```js -const { toReadable } = require('@swrlab/utils/packages/numbers') +import { toReadable } from '@swrlab/utils/number' ``` Then use the toolkit: diff --git a/src/object/README.md b/src/object/README.md new file mode 100644 index 0000000..1b8f251 --- /dev/null +++ b/src/object/README.md @@ -0,0 +1,95 @@ +# SWR Audio Lab / Object + +Common string, array, object encoding and getter helpers. + +- [SWR Audio Lab / Object](#swr-audio-lab--object) + - [Install](#install) + - [`getJsonKeys` - get all keys of json input](#getjsonkeys---get-all-keys-of-json-input) + - [`getObjectLength` - get the length of an object](#getobjectlength---get-the-length-of-an-object) + - [`isEmptyObject` - check if a value is an empty object](#isemptyobject---check-if-a-value-is-an-empty-object) + - [`notEmptyObject` - check if a value is not an empty object](#notemptyobject---check-if-a-value-is-not-an-empty-object) + +## Install + +Add the parent package to your dependencies: + +```sh +npm install @swrlab/utils +``` + +## `getJsonKeys` - get all keys of json input + +- `value` (required) - Json to get keys from + +Import the library: + +```js +import { getJsonKeys } from '@swrlab/utils/object' +``` + +Then use the toolkit: + +```js +getJsonKeys({ hello: 'world', foo: 'bar' }) +// ['hello', 'foo'] +``` + +## `getObjectLength` - get the length of an object + +- `value` (required) - Value to check + +Import the library: + +```js +import { getObjectLength } from '@swrlab/utils/object' +``` + +Then use the toolkit: + +```js +getObjectLength({ hello: 'world' }) +// 1 + +getObjectLength({ hello: 'world', foo: 'bar' }) +// 2 +``` + +## `isEmptyObject` - check if a value is an empty object + +- `value` (required) - Value to check + +Import the library: + +```js +import { isEmptyObject } from '@swrlab/utils/object' +``` + +Then use the toolkit: + +```js +isEmptyObject({}) +// true + +isEmptyObject({ hello: 'world' }) +// false +``` + +## `notEmptyObject` - check if a value is not an empty object + +- `value` (required) - Value to check + +Import the library: + +```js +import { notEmptyObject } from '@swrlab/utils/object' +``` + +Then use the toolkit: + +```js +notEmptyObject({ hello: 'world' }) +// true + +notEmptyObject({}) +// false +``` diff --git a/src/predicate/README.md b/src/predicate/README.md new file mode 100644 index 0000000..9d6d2d9 --- /dev/null +++ b/src/predicate/README.md @@ -0,0 +1,102 @@ +# SWR Audio Lab / Predicate + +Common predicate utilities. + +- [SWR Audio Lab / Predicate](#swr-audio-lab--predicate) + - [Install](#install) + - [`isArray` - check if a value is a proper array](#isarray---check-if-a-value-is-a-proper-array) + - [`isNull` - check if a value is null](#isnull---check-if-a-value-is-null) + - [`isObject` - check if a value is a proper object](#isobject---check-if-a-value-is-a-proper-object) + - [`isUndefined` - check if a value is undefined](#isundefined---check-if-a-value-is-undefined) + - [`notNullOrUndefined` - check if a value is neither null nor undefined](#notnullorundefined---check-if-a-value-is-neither-null-nor-undefined) + +## Install + +Add the parent package to your dependencies: + +```sh +npm install @swrlab/utils +``` + +## `isNull` - check if a value is null + +- `value` (required) - Value to check + +Import the library: + +```js +import { isNull } from '@swrlab/utils/predicate' +``` + +Then use the toolkit: + +```js +isNull(null) +// true + +isNull(undefined) +// false +``` + +## `isObject` - check if a value is a proper object + +- `value` (required) - Value to check + +Import the library: + +```js +import { isObject } from '@swrlab/utils/predicate' +``` + +Then use the toolkit: + +```js +isObject({ hello: 'world' }) +// true + +isObject('hello world') +// false +``` + +## `isUndefined` - check if a value is undefined + +- `value` (required) - Value to check + +Import the library: + +```js +import { isUndefined } from '@swrlab/utils/predicate' +``` + +Then use the toolkit: + +```js +isUndefined(undefined) +// true + +isUndefined(null) +// false +``` + +## `notNullOrUndefined` - check if a value is neither null nor undefined + +- `value` (required) - Value to check + +Import the library: + +```js +import { notNullOrUndefined } from '@swrlab/utils/predicate' +``` + +Then use the toolkit: + +```js +notNullOrUndefined('hello world') +// true + +notNullOrUndefined(null) +// false + +notNullOrUndefined(undefined) +// false +``` diff --git a/src/storage/index.ts b/src/storage/index.ts index 7f78ae9..1ea8f1a 100644 --- a/src/storage/index.ts +++ b/src/storage/index.ts @@ -1,23 +1,24 @@ -import type { File } from '@google-cloud/storage' /** * @fileoverview API for Storage. */ + +import type { File } from '@google-cloud/storage' import type { Buffer } from 'node:buffer' -import type { StorageConfig, StorageWrapperInstance } from './utils.ts' import { randomUUID } from 'node:crypto' import os from 'node:os' import path from 'node:path' -import * as createUri from './createUri.ts' import * as google from './google.ts' import * as localFs from './local.ts' import { isCloudStorageUrl, isHttpUrl, validateUrl } from './utils.ts' -const createUrl = async (url: string, ttl: number): Promise => { +export * as createUri from './createUri.ts' + +export const createUrl = async (url: string, ttl: number): Promise => { validateUrl(url) return isCloudStorageUrl(url) ? await google.createSignedUrl(url, ttl) : Promise.resolve(url) } -const deleteFile = async (url: string): Promise => { +export const deleteFile = async (url: string): Promise => { if (isCloudStorageUrl(url)) { await google.deleteFile(url) } @@ -29,7 +30,7 @@ const deleteFile = async (url: string): Promise => { await localFs.deleteFile(url) } -const list = async (url: string): Promise<(File | string)[]> => { +export const list = async (url: string): Promise<(File | string)[]> => { if (isCloudStorageUrl(url)) { return await google.listFiles(url) } @@ -58,7 +59,7 @@ const fetchContents = async (url: string, timeout?: number): Promise ${response.status}`) } -const load = async (uri: string): Promise | ArrayBufferLike | string> => { +export const load = async (uri: string): Promise | ArrayBufferLike | string> => { if (isCloudStorageUrl(uri)) { return await google.download(uri) } @@ -75,7 +76,7 @@ const createTempFile = async (contents: any): Promise => { return filePath } -const save = async ( +export const save = async ( uri: string, contents: Buffer | ArrayBufferLike | string, _logPrefix?: string, @@ -92,7 +93,7 @@ const save = async ( localFs.writeFile(uri, contents.toString()) } -const move = async (sourceUri: string, destinationUri: string, keepOriginal: boolean = false): Promise => { +export const move = async (sourceUri: string, destinationUri: string, keepOriginal: boolean = false): Promise => { if (isCloudStorageUrl(sourceUri) && isCloudStorageUrl(destinationUri)) { return await google.move(sourceUri, destinationUri, keepOriginal) } @@ -108,30 +109,3 @@ const move = async (sourceUri: string, destinationUri: string, keepOriginal: boo await deleteFile(sourceUri) } } - -// legacy export -/** - * Create a Google Cloud Storage Wrapper. - * @deprecated - * - * @param config - Storage Config. - * @returns A StorageWrapper - */ -export function StorageWrapper(config: StorageConfig): Promise | StorageWrapperInstance { - // TODO: just throw the Error and make an async function - if (!config || !config.gs) return Promise.reject(new Error('storage config invalid')) - - google.initialize(config.gs) - - const api: StorageWrapperInstance = { - createUri, - createUrl, - delete: deleteFile, - list, - load, - save, - move, - } - - return api -} diff --git a/src/storage/utils.ts b/src/storage/utils.ts index 43e2c02..ccd815c 100644 --- a/src/storage/utils.ts +++ b/src/storage/utils.ts @@ -3,7 +3,8 @@ import type { Buffer } from 'node:buffer' import type { CloudStorageURI } from './createUri.ts' import assert from 'node:assert' -// Types +// Types: + export type StorageConfig = { gs: StorageOptions } @@ -11,9 +12,17 @@ export type StorageConfig = { type CreateUrlFn = (inputUrl: string, ttl: number) => Promise export type StorageWrapperInstance = { + /** Create a storage URI to either `s3` or `gs` (Google Storage) with bucket and path. */ createUri: Record<'s3' | 'gs', (bucket: string, path: string) => CloudStorageURI> + /** + * @param inputURL - Input URL. + * @param ttl - Cache time to live in milliseconds. + * @returns - URL + */ createUrl: CreateUrlFn + /** @deprecated Use `deleteFile` instead. */ delete: (url: string) => Promise + deleteFile: (url: string) => Promise list: (url: string) => Promise<(File | string)[]> load: (uri: string) => Promise | ArrayBufferLike | string> save: ( @@ -25,17 +34,25 @@ export type StorageWrapperInstance = { move: (sourceUri: string, destinationUri: string, keepOriginal: boolean) => Promise } -// URL Helpers +// URL Helpers: export type StartsWith = `${Prefix}{string}` +/** Protocol or scheme of an URL. Must end with a `:`. */ export type Protocol = `${string}:` export type CloudStorageUrl = StartsWith<'gs://'> export type HttpUrl = StartsWith<'https://' | 'http://'> export type KnownURL = CloudStorageUrl & HttpUrl +/** @returns `true` if the given protocol string is either `https:` or `http:`. */ export const isHttp = (protocol: Protocol): boolean => protocol === 'https:' || protocol === 'http:' +/** @returns `true` if the given protocol string is either `gs:` (Google Storage). */ export const isCloudStorage = (protocol: Protocol): boolean => protocol === 'gs:' +/** + * Checks whether the given url string is a http(s) or Cloud Storage URL. + * @param urlString - The URL to validate. Must start with `http(s)://` or `gs://`. + * @returns `true` if the URL is valid, `false` otherwise. + */ export const isValidUrl = (urlString: string): urlString is KnownURL => { const url = new URL(urlString) const protocol = url.protocol as Protocol @@ -43,6 +60,13 @@ export const isValidUrl = (urlString: string): urlString is KnownURL => { return isHttp(protocol) || isCloudStorage(protocol) } +/** + * Throws an Error if the given url is invalid. + * Valid urls start with either `http(s)://` or `gs://`. + * @param {string} url - The URL string to validate. + * @throws {Error} - If the given url is invalid. + * @returns {void | never} - Never returns anything. + */ export const validateUrl = (url: string): void | never => { if (!isValidUrl(url)) { throw new Error('not implemented') @@ -59,4 +83,9 @@ export const isCloudStorageUrl = (url: string): url is CloudStorageUrl => { return isCloudStorage(new URL(url).protocol as Protocol) } +/** + * Checks if the given url is a valid http(s):// url. + * @param url - The url string to check. + * @returns - `true` if the url starts with `http(s)://`, `false` otherwise. + */ export const isHttpUrl = (url: string): url is HttpUrl => url.startsWith('http://') || url.startsWith('https://') diff --git a/src/string/README.md b/src/string/README.md new file mode 100644 index 0000000..3d873ef --- /dev/null +++ b/src/string/README.md @@ -0,0 +1,167 @@ +# SWR Audio Lab / Strings, Arrays, Objects + +Common string, array, object encoding and getter helpers. + +- [SWR Audio Lab / String](#swr-audio-lab--string) + - [Install](#install) + - [`base64` - get capitalized string](#base64) + - [`capitalize` - get capitalized string](#capitalize---get-capitalized-string) + - [`crc64` - get capitalized string](#crc64) + - [`isEmptyString` - check if a value is an empty string](#isemptystring---check-if-a-value-is-an-empty-string) + - [`isIncluded` - Deprecated: check if a value (haystack) includes another value (needle)](#isincluded---check-if-a-value-haystack-includes-another-value-needle) + - [`pluralize` - get pluralized string](#pluralize---get-pluralized-string) + - [`removeDoubleSpaces` - take a string and remove its duplicate spaces](#removedoublespaces---take-a-string-and-remove-its-duplicate-spaces) + - [`toHex` - take a string convert it to a hex string](#tohex---take-a-string-convert-it-to-a-hex-string) + +## Install + +Add the parent package to your dependencies: + +```sh +npm add @swrlab/utils +``` + +## `toBase64`, `parseBase64` - decode and encode base64 + +- `value` (required) - String to capitalize + +Import the library: + +```js +import { toBase64, parseBase64 } from ('@swrlab/utils/string') +``` + +Then use the toolkit: + +```js +toBase64('123456789') +// prints: MTIzNDU2Nzg5 + +parseBase64('MTIzNDU2Nzg5') +// prints: 123456789 +``` + +## `capitalize` - get capitalized string + +- `value` (required) - String to capitalize + +Import the library: + +```js +import { capitalize } from ('@swrlab/utils/string') +``` + +Then use the toolkit: + +```js +capitalize('apple') +// Apple +``` + +## `crc64` - get the crc64 ECMA-182 checksum of a string + +- `value` (required) - Value to convert + +Import the library: + +```js +import { crc64 } from '@swrlab/utils/string' +``` + +Then use the toolkit: + +```js +crc64('123456789') +// 6c40df5f0b497347 +``` + +## `isEmptyString` - check if a value is an empty string + +- `value` (required) - Value to check + +Import the library: + +```js +import { isEmptyString } from '@swrlab/utils/string' +``` + +Then use the toolkit: + +```js +isEmptyString('') +// true + +isEmptyString('hello world') +// false +``` + +## Deprecated: `isIncluded` - check if a value (haystack) includes another value (needle) + +> ![NOTE] +> Use the native `stringOrArray.includes(needle)` instead. + +- `haystack` (required) - Array or value to check +- `needle` (required) - Array or value to check + +## `pluralize` - get pluralized string + +- `value` (required) - String to pluralize + +Import the library: + +```js +import { pluralize } from '@swrlab/utils/string' +``` + +Then use the toolkit: + +```js +pluralize(1, 'Apple') +// 1 Apple + +pluralize(1000, 'Apple') +// 1.000 Apples + +pluralize(1, 'Child', 'Children') +// 1 Child + +pluralize(1000, 'Child', 'Children') +// 1.000 Children +``` + +## `removeDoubleSpaces` - take a string and remove its duplicate spaces + +- `value` (required) - String to convert + +Import the library: + +```js +import { removeDoubleSpaces } from '@swrlab/utils/string' +``` + +Then use the toolkit: + +```js +removeDoubleSpaces('hello world') +// hello world + +removeDoubleSpaces('hello world once again') +// hello world once again +``` + +## `toHex` - take a string convert it to a hex string + +- `value` (required) - String to convert + +Import the library: + +```js +import { toHex } from '@swrlab/utils/string' +``` + +Then use the toolkit: + +```js +toHex('hello world') +// 68656c6c6f20776f726c64 +``` diff --git a/src/string/base64.ts b/src/string/base64.ts new file mode 100644 index 0000000..edb1129 --- /dev/null +++ b/src/string/base64.ts @@ -0,0 +1,15 @@ +import { Buffer } from 'node:buffer' + +/** + * Encode the given string into it's base64 representation. + * @param str - The input string encoded in utf-8. + * @returns - The base64 encoded string. + */ +export const toBase64 = (str: string): string => Buffer.from(str, 'utf-8').toString('base64') + +/** + * Decode the given base64 string. + * @param str - The base64 encoded string. + * @returns - The decoded contents of the string in utf-8. + */ +export const parseBase64 = (str: string): string => Buffer.from(str, 'base64').toString('utf-8') diff --git a/src/string/index.ts b/src/string/index.ts index 8ec18fc..811db0f 100644 --- a/src/string/index.ts +++ b/src/string/index.ts @@ -4,6 +4,7 @@ * @module string */ +export { parseBase64, toBase64 } from './base64.ts' export { capitalize } from './capitalize.ts' export { crc64, crc64String } from './crc64.ts' export { isEmptyString } from './isEmptyString.ts' diff --git a/tests/base64.test.ts b/tests/base64.test.ts new file mode 100644 index 0000000..a6827f9 --- /dev/null +++ b/tests/base64.test.ts @@ -0,0 +1,36 @@ +import assert from 'node:assert/strict' +import { describe, it } from 'node:test' +import { parseBase64, toBase64 } from '../src/string/base64.ts' + +describe('toBase64', () => { + it('should encode an empty string', () => { + assert.equal(toBase64(''), '') + }) + it('should encode a string to base64', () => { + assert.equal(toBase64('123456789'), 'MTIzNDU2Nzg5') + assert.equal(toBase64('hello'), 'aGVsbG8=') + }) + it('should throw a TypeError if a number is passed', () => { + // @ts-expect-error - undefined won't work, but is fine for testing. + assert.throws(() => toBase64(undefined), { name: 'TypeError', message: /The first argument/ }) + // @ts-expect-error - A number won't work, but is fine for testing. + assert.throws(() => toBase64(123456789), { name: 'TypeError', code: 'ERR_INVALID_ARG_TYPE' }) + }) +}) + +describe('parseBase64', () => { + it('should throw a TypeError on undefined', () => { + // @ts-expect-error - A number won't work, but is fine for testing. + assert.throws(() => parseBase64(undefined), { + name: 'TypeError', + message: /The first argument must be of type/, + }) + }) + it('should decode an empty base64 to an empty string', () => { + assert.equal(parseBase64(''), '') + }) + it('should decode base64', () => { + assert.equal(parseBase64('MTIzNDU2Nzg5'), '123456789') + assert.equal(parseBase64('SGVsbG8gV29ybGQ='), 'Hello World') + }) +}) diff --git a/tests/env.test.ts b/tests/env.test.ts new file mode 100644 index 0000000..7de871f --- /dev/null +++ b/tests/env.test.ts @@ -0,0 +1,85 @@ +import assert from 'node:assert/strict' +import { after, before, describe, it } from 'node:test' +import { getEnv, getEnvBase64, getEnvBoolean, getEnvString } from './../src/env.ts' + +describe('no env values available', () => { + it('should throw an error for missing required values', () => { + assert.throws(() => getEnv('MISSING', { type: 'string', required: true }), { + name: 'MissingEnvVarError', + }) + }) + it('should throw an error for missing required values (even with defaultValue)', () => { + assert.throws(() => getEnv('MISSING', { type: 'string', required: true, defaultValue: 'hi' }), { + name: 'MissingEnvVarError', + }) + }) + it('should return the defaultValue for optional values', () => { + assert.equal(getEnv('MISSING', { type: 'string', required: false, defaultValue: 'def' }), 'def') + }) + describe('functions with `required` set to `true` by default', () => { + it('should throw an error for getEnvString when the value is missing', () => { + assert.throws(() => getEnvString('MISSING'), { name: 'MissingEnvVarError' }) + }) + it('should throw an error for getEnvBase64 when the value is missing', () => { + assert.throws(() => getEnvBase64('MISSING'), { name: 'MissingEnvVarError' }) + }) + }) + describe('functions with `required` set to `false` by default', () => { + it('should return `undefined` for a missing boolean value', () => { + assert.equal(getEnvBoolean('MISSING'), undefined) + }) + it('should return `undefined` for a missing general/string value', () => { + assert.equal(getEnv('MISSING'), undefined) + }) + }) +}) + +describe('mocked env values', () => { + const mocked: Record = { + FOO: 'BAR', + BASE64: 'eyJkdHMiOnRydWV9', + BASE64_BROKEN: 'asdf', + EMPTY_JSON: '', + BROKEN_JSON: '{ "asdf"', + } as const + + before(() => { + // set mocked env values for env.ts + globalThis.__VitestMockEnv = mocked + }) + after(() => { + // clean up + globalThis.__VitestMockEnv = undefined + }) + it('should throw an error for missing required values', () => { + assert.throws(() => getEnv('MISSING', { type: 'string', required: true }), { + name: 'MissingEnvVarError', + }) + }) + it('should return the mocked exsiting value', () => { + assert.deepEqual(getEnv('FOO', { type: 'string', required: true }), mocked.FOO) + }) + describe('getEnvBase64', () => { + it('should have the value', () => { + const value = getEnvBase64('BASE64') + assert.deepEqual(value, { dts: true }) + }) + it('should throw a SyntaxError for invalid json data', () => { + assert.throws(() => getEnvBase64('BASE64_BROKEN'), { + message: /BASE64_BROKEN.*SyntaxError: JSON Parse error: Unexpected identifier/, + }) + assert.throws(() => getEnvBase64('BASE64_BROKEN'), { message: /variable BASE64_BROKEN as/ }) + }) + }) + describe('getEnvJSON', () => { + it('should throw a SyntaxError for an empty value', () => { + assert.throws(() => getEnvBase64('EMPTY_JSON'), { + name: 'Error', + message: /EMPTY_JSON.*SyntaxError: /, + }) + }) + it('should throw a SyntaxError for mal-formed json', () => { + assert.throws(() => getEnvBase64('BROKEN_JSON'), { message: /SyntaxError: JSON Parse error: Unexpected/ }) + }) + }) +}) diff --git a/tests/helpers.test.ts b/tests/helpers.test.ts index de58060..46a4581 100644 --- a/tests/helpers.test.ts +++ b/tests/helpers.test.ts @@ -1,9 +1,10 @@ import assert from 'node:assert' -import { describe, it } from 'node:test' +import { describe, it, skip } from 'node:test' import { sleep } from '../src/helpers/index.ts' describe('helpers', () => { - describe('sleep', () => { + // skip sleep test, since it works and takes "too long" + skip('sleep', () => { it('will sleep for one second', async () => { const time = 1e3 const before = Date.now() diff --git a/tmp/.gitkeep b/tmp/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/tsdown.config.ts b/tsdown.config.ts index d414fe2..7be7200 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -5,9 +5,11 @@ export default defineConfig({ index: 'src/index.ts', ard: 'src/ard/index.ts', + 'ard-coreId': 'src/ard/coreId.ts', array: 'src/array/index.ts', date: 'src/date/index.ts', - helpers: 'src/helpers/index.ts', + env: 'src/env.ts', + helper: 'src/helpers/index.ts', number: 'src/number/index.ts', object: 'src/object/index.ts', predicate: 'src/predicate/index.ts', diff --git a/utils/undici/index.js b/utils/undici/index.js deleted file mode 100644 index e424968..0000000 --- a/utils/undici/index.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - - by SWR Audio Lab - - this file runs the undici-wrapper util - -*/ - -// load request handler -const undici = require('../../packages/undici/index') - -// export handler -module.exports = undici() From 43a8eb26fcdc957fd20d90f3f9ba4ca5aa32a94d Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 16:25:15 +0200 Subject: [PATCH 25/42] ci: remove pr test label It is safe to run the tests now at any time. --- .github/workflows/pull.yml | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index a318348..4e910d7 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -1,18 +1,10 @@ -name: Test on Pull +name: Run tests for pull requests on: - pull_request_target: - types: [labeled] + workflow_dispatch: + pull_request: jobs: - security: - name: Check permissions for pull request runs - runs-on: ubuntu-latest - if: contains(github.event.pull_request.labels.*.name, 'safe to test') - steps: - - run: | - echo "Security checks passed!" - test: needs: security name: Run Tests From c1710c7b08203f44ec78979ee1e093266a81ada4 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 16:28:53 +0200 Subject: [PATCH 26/42] fix(ci): remove dependency --- .github/workflows/pull.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index 4e910d7..f915a4c 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -6,7 +6,6 @@ on: jobs: test: - needs: security name: Run Tests runs-on: ubuntu-latest strategy: From aa7b54c4bbf03362d82c4ca14bd2b1bf34193d4a Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 16:36:56 +0200 Subject: [PATCH 27/42] ci: separate node 20 test from other node tests --- .github/workflows/pull.yml | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index f915a4c..03fed66 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - version: [20, 22, 24] + version: [22, 24] steps: - name: 👀 Checkout Code uses: actions/checkout@v4 @@ -42,3 +42,35 @@ jobs: - name: 🧪 Run Tests (in via npm in Node) run: npm run test:node + + test-node-20: + name: Run Tests + runs-on: ubuntu-latest + steps: + - name: 👀 Checkout Code + uses: actions/checkout@v4 + + - name: 🏗 Install Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: 🛠 Setup Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: 📦 Install Dependencies (via Bun) + run: bun install + + - name: 🧪 Run Lint (in Bun) + run: bun run lint + + - name: 🧪 Run Tests (in Bun) + run: bun run test + + - name: 🧪 Run Node Tests (in via npm in Bun) + run: npm run test:node + + - name: 🧪 Run Tests (in via npm in Node) + run: npm run test From fc800ac9cc67e055d600e4aed1f6aea8e72282a8 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 16:45:15 +0200 Subject: [PATCH 28/42] fix(test): adjust regex to work in bun and node --- tests/env.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/env.test.ts b/tests/env.test.ts index 7de871f..37c3cfa 100644 --- a/tests/env.test.ts +++ b/tests/env.test.ts @@ -66,7 +66,7 @@ describe('mocked env values', () => { }) it('should throw a SyntaxError for invalid json data', () => { assert.throws(() => getEnvBase64('BASE64_BROKEN'), { - message: /BASE64_BROKEN.*SyntaxError: JSON Parse error: Unexpected identifier/, + message: /SyntaxError:.*Unexpected/, }) assert.throws(() => getEnvBase64('BASE64_BROKEN'), { message: /variable BASE64_BROKEN as/ }) }) @@ -79,7 +79,7 @@ describe('mocked env values', () => { }) }) it('should throw a SyntaxError for mal-formed json', () => { - assert.throws(() => getEnvBase64('BROKEN_JSON'), { message: /SyntaxError: JSON Parse error: Unexpected/ }) + assert.throws(() => getEnvBase64('BROKEN_JSON'), { message: /SyntaxError:.*Unexpected/ }) }) }) }) From 473896c83865f715d7c68124572ae283982c57e5 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 17:14:30 +0200 Subject: [PATCH 29/42] ci: use npm to run tests on older node --- .github/workflows/pull.yml | 20 ++++++++++---------- package.json | 2 ++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index 03fed66..99bdf36 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -31,6 +31,9 @@ jobs: - name: 🧪 Run Lint run: bun run lint + - name: 🧪 Run build + run: bun run build + - name: 🧪 Run Tests (in Bun) run: bun run test @@ -60,17 +63,14 @@ jobs: with: bun-version: latest - - name: 📦 Install Dependencies (via Bun) - run: bun install + - name: 📦 Install Dependencies (via npm) + run: npm install - - name: 🧪 Run Lint (in Bun) - run: bun run lint + - name: 📦 Install Dependencies (via Bun) + run: npm run build - name: 🧪 Run Tests (in Bun) - run: bun run test - - - name: 🧪 Run Node Tests (in via npm in Bun) - run: npm run test:node - - - name: 🧪 Run Tests (in via npm in Node) run: npm run test + + - name: 🧪 Run Dist Tests (in Node via npm) + run: npm run test:dist:node diff --git a/package.json b/package.json index e992abb..f4c95df 100644 --- a/package.json +++ b/package.json @@ -108,6 +108,8 @@ "release": "bunx bumpp", "test": "bun run typecheck && bun run test:bun && bun run test:legacy", "test:bun": "bun test ./tests/**test*.ts", + "test:dist": "bun test ./tests/dist-legacy/*test*.mjs", + "test:dist:node": "node --test ./tests/dist-legacy/*test*.mjs", "test:legacy": "bun test ./tests/legacy/*.test.mjs", "test:legacy:node": "node --test ./tests/legacy/*.test.mjs", "test:node": "node --test ./tests/**.test.ts", From 361f997d762960da789c922a247e66682eff4da6 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:05:49 +0200 Subject: [PATCH 30/42] ci: adjust test files --- .github/workflows/pull.yml | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index 99bdf36..c3069be 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -66,10 +66,10 @@ jobs: - name: 📦 Install Dependencies (via npm) run: npm install - - name: 📦 Install Dependencies (via Bun) + - name: 📦 Run build run: npm run build - - name: 🧪 Run Tests (in Bun) + - name: 🧪 Run Tests run: npm run test - name: 🧪 Run Dist Tests (in Node via npm) diff --git a/package.json b/package.json index f4c95df..2368dbd 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "test": "bun run typecheck && bun run test:bun && bun run test:legacy", "test:bun": "bun test ./tests/**test*.ts", "test:dist": "bun test ./tests/dist-legacy/*test*.mjs", - "test:dist:node": "node --test ./tests/dist-legacy/*test*.mjs", + "test:dist:node": "node --test ./tests/dist-legacy/*test.mjs", "test:legacy": "bun test ./tests/legacy/*.test.mjs", "test:legacy:node": "node --test ./tests/legacy/*.test.mjs", "test:node": "node --test ./tests/**.test.ts", From 9cc4f1c6e9f31e6fcd462793ce5754274839d52e Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:12:42 +0200 Subject: [PATCH 31/42] fix(ci): remove glob star --- .github/workflows/pull.yml | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index c3069be..fa6ea8c 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -72,5 +72,11 @@ jobs: - name: 🧪 Run Tests run: npm run test + - name: Test dist Strings + run: node --test ./tests/legacy/strings.test.mjs + + - name: Test dist ARD + run: node --test ./tests/legacy/ard.test.mjs + - name: 🧪 Run Dist Tests (in Node via npm) run: npm run test:dist:node diff --git a/package.json b/package.json index 2368dbd..d38d09d 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "test:dist": "bun test ./tests/dist-legacy/*test*.mjs", "test:dist:node": "node --test ./tests/dist-legacy/*test.mjs", "test:legacy": "bun test ./tests/legacy/*.test.mjs", - "test:legacy:node": "node --test ./tests/legacy/*.test.mjs", + "test:legacy:node": "node --test ./tests/legacy/", "test:node": "node --test ./tests/**.test.ts", "typecheck": "tsc --noEmit" }, From 4850ea0c697576b4870966ef4f474ca0b569bf66 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:15:52 +0200 Subject: [PATCH 32/42] fix(ci): remove glob star --- .github/workflows/pull.yml | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index fa6ea8c..abb30a2 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -73,10 +73,10 @@ jobs: run: npm run test - name: Test dist Strings - run: node --test ./tests/legacy/strings.test.mjs + run: node --test ./tests/dist-legacy/strings.test.mjs - name: Test dist ARD - run: node --test ./tests/legacy/ard.test.mjs + run: node --test ./tests/dist-legacy/ard.test.mjs - name: 🧪 Run Dist Tests (in Node via npm) run: npm run test:dist:node diff --git a/package.json b/package.json index d38d09d..05ad358 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "test": "bun run typecheck && bun run test:bun && bun run test:legacy", "test:bun": "bun test ./tests/**test*.ts", "test:dist": "bun test ./tests/dist-legacy/*test*.mjs", - "test:dist:node": "node --test ./tests/dist-legacy/*test.mjs", + "test:dist:node": "node --test ./tests/dist-legacy/", "test:legacy": "bun test ./tests/legacy/*.test.mjs", "test:legacy:node": "node --test ./tests/legacy/", "test:node": "node --test ./tests/**.test.ts", From 1ae37d5da074b7f93c9797066bcad14bdaea5dbc Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:19:35 +0200 Subject: [PATCH 33/42] chore(test): rename tests to test and add dist-legacy tests --- package.json | 12 +- {tests => test}/ard.test.bun.ts | 0 {tests => test}/ard.test.ts | 0 {tests => test}/array.test.ts | 0 {tests => test}/base64.test.ts | 0 {tests => test}/crc.test.ts | 0 {tests => test}/date.test.ts | 0 {tests => test}/date.utils.test.ts | 0 test/dist-legacy/ard.test.mjs | 11 ++ test/dist-legacy/date.test.mjs | 66 +++++++ test/dist-legacy/helpers.test.mjs | 35 ++++ test/dist-legacy/numbers.test.mjs | 117 ++++++++++++ test/dist-legacy/strings.test.mjs | 177 +++++++++++++++++++ {tests/legacy => test/dist-legacy}/utils.mjs | 0 {tests => test}/env.test.ts | 0 {tests => test}/helpers.test.ts | 0 {tests => test}/legacy/ard.test.mjs | 0 {tests => test}/legacy/date.test.mjs | 0 {tests => test}/legacy/helpers.test.mjs | 0 {tests => test}/legacy/numbers.test.mjs | 0 {tests => test}/legacy/strings.test.mjs | 0 test/legacy/utils.mjs | 14 ++ {tests => test}/number.test.ts | 0 {tests => test}/object.test.ts | 0 {tests => test}/predicate.test.ts | 0 {tests => test}/storage/utils.test.ts | 0 {tests => test}/string.test.ts | 0 27 files changed, 426 insertions(+), 6 deletions(-) rename {tests => test}/ard.test.bun.ts (100%) rename {tests => test}/ard.test.ts (100%) rename {tests => test}/array.test.ts (100%) rename {tests => test}/base64.test.ts (100%) rename {tests => test}/crc.test.ts (100%) rename {tests => test}/date.test.ts (100%) rename {tests => test}/date.utils.test.ts (100%) create mode 100644 test/dist-legacy/ard.test.mjs create mode 100644 test/dist-legacy/date.test.mjs create mode 100644 test/dist-legacy/helpers.test.mjs create mode 100644 test/dist-legacy/numbers.test.mjs create mode 100644 test/dist-legacy/strings.test.mjs rename {tests/legacy => test/dist-legacy}/utils.mjs (100%) rename {tests => test}/env.test.ts (100%) rename {tests => test}/helpers.test.ts (100%) rename {tests => test}/legacy/ard.test.mjs (100%) rename {tests => test}/legacy/date.test.mjs (100%) rename {tests => test}/legacy/helpers.test.mjs (100%) rename {tests => test}/legacy/numbers.test.mjs (100%) rename {tests => test}/legacy/strings.test.mjs (100%) create mode 100644 test/legacy/utils.mjs rename {tests => test}/number.test.ts (100%) rename {tests => test}/object.test.ts (100%) rename {tests => test}/predicate.test.ts (100%) rename {tests => test}/storage/utils.test.ts (100%) rename {tests => test}/string.test.ts (100%) diff --git a/package.json b/package.json index 05ad358..b70c7a7 100644 --- a/package.json +++ b/package.json @@ -107,12 +107,12 @@ "lint:fix": "eslint --fix", "release": "bunx bumpp", "test": "bun run typecheck && bun run test:bun && bun run test:legacy", - "test:bun": "bun test ./tests/**test*.ts", - "test:dist": "bun test ./tests/dist-legacy/*test*.mjs", - "test:dist:node": "node --test ./tests/dist-legacy/", - "test:legacy": "bun test ./tests/legacy/*.test.mjs", - "test:legacy:node": "node --test ./tests/legacy/", - "test:node": "node --test ./tests/**.test.ts", + "test:bun": "bun test ./test/**test*.ts", + "test:dist": "bun test ./test/dist-legacy/*test*.mjs", + "test:dist:node": "node --test ./test/dist-legacy/", + "test:legacy": "bun test ./test/legacy/*.test.mjs", + "test:legacy:node": "node --test ./test/legacy/", + "test:node": "node --test ./test/**.test.ts", "typecheck": "tsc --noEmit" }, "dependencies": { diff --git a/tests/ard.test.bun.ts b/test/ard.test.bun.ts similarity index 100% rename from tests/ard.test.bun.ts rename to test/ard.test.bun.ts diff --git a/tests/ard.test.ts b/test/ard.test.ts similarity index 100% rename from tests/ard.test.ts rename to test/ard.test.ts diff --git a/tests/array.test.ts b/test/array.test.ts similarity index 100% rename from tests/array.test.ts rename to test/array.test.ts diff --git a/tests/base64.test.ts b/test/base64.test.ts similarity index 100% rename from tests/base64.test.ts rename to test/base64.test.ts diff --git a/tests/crc.test.ts b/test/crc.test.ts similarity index 100% rename from tests/crc.test.ts rename to test/crc.test.ts diff --git a/tests/date.test.ts b/test/date.test.ts similarity index 100% rename from tests/date.test.ts rename to test/date.test.ts diff --git a/tests/date.utils.test.ts b/test/date.utils.test.ts similarity index 100% rename from tests/date.utils.test.ts rename to test/date.utils.test.ts diff --git a/test/dist-legacy/ard.test.mjs b/test/dist-legacy/ard.test.mjs new file mode 100644 index 0000000..6b45f98 --- /dev/null +++ b/test/dist-legacy/ard.test.mjs @@ -0,0 +1,11 @@ +import { describe, it } from 'node:test' +import { createHashedId } from '../../dist/packages/ard.js' +import { expect } from './utils.mjs' + +describe('Test ARD Package', () => { + describe('Test ARD-CoreID Hash', () => { + it("createHashedId('test') = 0c171b2e54a30c11", () => { + expect(createHashedId('test')).toEqual('0c171b2e54a30c11') + }) + }) +}) diff --git a/test/dist-legacy/date.test.mjs b/test/dist-legacy/date.test.mjs new file mode 100644 index 0000000..9c9fb0d --- /dev/null +++ b/test/dist-legacy/date.test.mjs @@ -0,0 +1,66 @@ +import { describe, it } from 'node:test' +import * as date from '../../dist/packages/date.js' +import { expect } from './utils.mjs' + +const testDate = '2038-01-19T03:14:08.000' +const relativeTime = 2147483647000 - Date.now() +const relativeYears = Number.parseInt(relativeTime / (1000 * 60 * 60 * 24 * 365), 10) + +describe('Test DateTime Package', () => { + describe('Test getDateHourMinutes', () => { + const testResult = 'Di, 19. Januar 2038 - 03:14 Uhr' + it(`getDateHourMinutes('${testDate}') = '${testResult}'`, () => { + expect(date.getDateHourMinutes(testDate)).to.equal(testResult) + }) + }) + + describe('Test getDayMonthYear', () => { + const testResult = 'Di, 19. Januar 2038' + it(`getDayMonthYear('${testDate}') = '${testResult}'`, () => { + expect(date.getDayMonthYear(testDate)).to.equal(testResult) + }) + }) + + describe('Test getFullRelativeTime', () => { + const testResult = `Di, 19. Januar 2038 - 03:14 Uhr (in ${relativeYears} Jahren)` + it(`getFullRelativeTime('${testDate}') = '${testResult}'`, () => { + expect(date.getFullRelativeTime(testDate)).to.equal(testResult) + }) + }) + + describe('Test getHourMinutes', () => { + const testResult = '03:14' + it(`getHourMinutes('${testDate}') = '${testResult}'`, () => { + expect(date.getHourMinutes(testDate)).to.equal(testResult) + }) + }) + + describe('Test getIsoRelativeTime', () => { + const testResult = `${testDate} (in ${relativeYears} Jahren)` + it(`getIsoRelativeTime('${testDate}') = '${testResult}'`, () => { + expect(date.getIsoRelativeTime(testDate)).to.equal(testResult) + }) + }) + + describe('Test getRelativeTime', () => { + const testResult = `in ${relativeYears} Jahren` + it(`getRelativeTime('${testDate}') = '${testResult}'`, () => { + expect(date.getRelativeTime(testDate)).to.equal(testResult) + }) + }) + + describe('Test getYearMonthDay', () => { + const testResult = '20380119' + it(`getYearMonthDay('${testDate}') = '${testResult}'`, () => { + expect(date.getYearMonthDay(testDate)).to.equal(testResult) + }) + }) + + describe('Test revYearMonthDay', () => { + const test = '20380119' + const testResult = '19012038' + it(`revYearMonthDay('${test}') = '${testResult}'`, () => { + expect(date.revYearMonthDay(test)).to.equal(testResult) + }) + }) +}) diff --git a/test/dist-legacy/helpers.test.mjs b/test/dist-legacy/helpers.test.mjs new file mode 100644 index 0000000..3e1acf7 --- /dev/null +++ b/test/dist-legacy/helpers.test.mjs @@ -0,0 +1,35 @@ +import { describe, it } from 'node:test' +import * as helpers from '../../dist/packages/helpers.js' +import { expect } from './utils.mjs' + +describe('Test Helpers Package', () => { + describe('Test arrayToObjectCount', () => { + it("arrayToObjectCount(['foo', 'bar', 'bar']) = { bar: 2, foo: 1 }", () => { + const test = ['foo', 'bar', 'bar'] + const result = { bar: 2, foo: 1 } + const testResult = helpers.arrayToObjectCount(test) + expect(testResult.bar).to.equal(result.bar) + expect(testResult.foo).to.equal(result.foo) + }) + }) + + describe('Test getJsonKeys', () => { + it("getJsonKeys({ hello: 'world', foo: 'bar' }) = ['hello', 'foo']", () => { + const test = { hello: 'world', foo: 'bar' } + const result = ['hello', 'foo'] + const testResult = helpers.getJsonKeys(test) + expect(testResult[0]).to.equal(result[0]) + expect(testResult[1]).to.equal(result[1]) + }) + }) + + describe('Test sleep', () => { + it('sleep(1e3) will sleep 1s', async () => { + const time = 1e3 + const before = Date.now() + await helpers.sleep(time) + const after = Date.now() + expect(after - before).to.be.greaterThanOrEqual(time) + }) + }) +}) diff --git a/test/dist-legacy/numbers.test.mjs b/test/dist-legacy/numbers.test.mjs new file mode 100644 index 0000000..3636576 --- /dev/null +++ b/test/dist-legacy/numbers.test.mjs @@ -0,0 +1,117 @@ +import { describe, it } from 'node:test' +import * as numbers from '../../dist/packages/numbers.js' +import { expect } from './utils.mjs' + +describe('Test Numbers Package', () => { + describe('Test addLeadingZero', () => { + it("addLeadingZero(1) = '01'", () => { + expect(numbers.addLeadingZero(1)).to.equal('01') + }) + + it("addLeadingZero(10) = '10'", () => { + expect(numbers.addLeadingZero(10)).to.equal('10') + }) + }) + + describe('Test addTrailingZeros', () => { + it("addTrailingZeros(1, 5) = '1.00000'", () => { + expect(numbers.addTrailingZeros(1, 5)).to.equal('1.00000') + }) + + it("addTrailingZeros(1.1, 5) = '1.10000'", () => { + expect(numbers.addTrailingZeros(1.1, 5)).to.equal('1.10000') + }) + + it("addTrailingZeros('1.2', 5) = '1.20000'", () => { + expect(numbers.addTrailingZeros('1.2', 5)).to.equal('1.20000') + }) + + it("addTrailingZeros(2, 2, ',') = '2,00'", () => { + expect(numbers.addTrailingZeros(2, 2, ',')).to.equal('2,00') + }) + + it("addTrailingZeros(2.1, 2, ',') = '2,10'", () => { + expect(numbers.addTrailingZeros(2.1, 2, ',')).to.equal('2,10') + }) + + it("addTrailingZeros('2,2', 2, ','') = '2,20'", () => { + expect(numbers.addTrailingZeros('2,2', 2, ',')).to.equal('2,20') + }) + }) + + describe('Test getAverage', () => { + it('getAverage([1, 2, 3]) = 2', () => { + expect(numbers.getAverage([1, 2, 3])).to.equal(2) + }) + + it('getAverage([1.2, 2.4, 3.6], 1) = 2.4', () => { + expect(numbers.getAverage([1.2, 2.4, 3.6], 1)).to.equal(2.4) + }) + }) + + describe('Test getDiff', () => { + it('getDiff(2, 1) = 1', () => { + expect(numbers.getDiff(2, 1)).to.equal(1) + }) + + it('getDiff(1, 2) = -1', () => { + expect(numbers.getDiff(1, 2)).to.equal(-1) + }) + }) + + describe('Test getRandomInRange', () => { + it('getRandomInRange(1, 5) = 1,2,3,4 or 5', () => { + expect([1, 2, 3, 4, 5]).to.include(numbers.getRandomInRange(1, 5)) + }) + + it('getRandomInRange(5, 9) = 5,6,7,8 or 9', () => { + expect([5, 6, 7, 8, 9]).to.include(numbers.getRandomInRange(5, 9)) + }) + }) + + describe('Test getSum', () => { + it('getSum([1, 2, 3]) = 6', () => { + expect(numbers.getSum([1, 2, 3])).to.equal(6) + }) + + it('getSum([1.2, 2.4, 3.6], 1) = 7.2', () => { + expect(numbers.getSum([1.2, 2.4, 3.6], 1)).to.equal(7.2) + }) + }) + + describe('Test isEven', () => { + it('isEven(2) = true', () => { + expect(numbers.isEven(2)).to.equal(true) + }) + + it('isEven(1) = false', () => { + expect(numbers.isEven(1)).to.equal(false) + }) + }) + + describe('Test normalize', () => { + it('normalize(2, 100) = 0.02', () => { + expect(numbers.normalize(2, 100)).to.equal(0.02) + }) + + it('normalize(80, 100) = 0.8', () => { + expect(numbers.normalize(80, 100)).to.equal(0.8) + }) + }) + + describe('Test roundTo', () => { + it('roundTo(1.23456) = 1.23', () => { + expect(numbers.roundTo(1.23456)).to.equal(1.23) + }) + + it('roundTo(1.23456, 4) = 1.2346', () => { + expect(numbers.roundTo(1.23456, 4)).to.equal(1.2346) + }) + }) + + describe('Test toReadable', () => { + it("toReadable(1234567) = '1.234.567'", () => { + expect(numbers.toReadable(1234567)).to.equal('1.234.567') + }) + }) +}) diff --git a/test/dist-legacy/strings.test.mjs b/test/dist-legacy/strings.test.mjs new file mode 100644 index 0000000..074a01e --- /dev/null +++ b/test/dist-legacy/strings.test.mjs @@ -0,0 +1,177 @@ +import { describe, it } from 'node:test' +import * as strings from '../../dist/packages/strings.js' +import { expect } from './utils.mjs' + +describe('Test Strings Package', () => { + describe('Test capitalize', () => { + it("capitalize('a') = 'A'", () => { + expect(strings.capitalize('a')).to.equal('A') + }) + it("capitalize('apple') = 'Apple'", () => { + expect(strings.capitalize('apple')).to.equal('Apple') + }) + }) + + describe('Test getObjectLength', () => { + it("getObjectLength({ hello: 'world' }) = 1", () => { + expect(strings.getObjectLength({ hello: 'world' })).to.equal(1) + }) + + it("getObjectLength({ hello: 'world', foo: 'bar' }) = 2", () => { + expect( + strings.getObjectLength({ + hello: 'world', + foo: 'bar', + }) + ).to.equal(2) + }) + }) + + describe('Test isArray', () => { + it("isArray(['hello world']) = true", () => { + expect(strings.isArray(['hello world'])).to.equal(true) + }) + + it("isArray({ hello: 'world' }) = false", () => { + expect(strings.isArray({ hello: 'world' })).to.equal(false) + }) + }) + + describe('Test isEmptyArray', () => { + it('isEmptyArray([]) = true', () => { + expect(strings.isEmptyArray([])).to.equal(true) + }) + + it("isEmptyArray(['hello world']) = false", () => { + expect(strings.isEmptyArray(['hello world'])).to.equal(false) + }) + }) + + describe('Test isEmptyObject', () => { + it('isEmptyObject({}) = true', () => { + expect(strings.isEmptyObject({})).to.equal(true) + }) + + it("isEmptyObject({ hello: 'world' }) = false", () => { + expect(strings.isEmptyObject({ hello: 'world' })).to.equal(false) + }) + }) + + describe('Test isEmptyString', () => { + it("isEmptyString('') = true", () => { + expect(strings.isEmptyString('')).to.equal(true) + }) + + it("isEmptyString('hello world') = false", () => { + expect(strings.isEmptyString('hello world')).to.equal(false) + }) + }) + + describe('Test isIncluded', () => { + it("isIncluded('hello world', 'hello') = true", () => { + expect(strings.isIncluded('hello world', 'hello')).to.equal(true) + }) + + it("isIncluded('hello world', 'earth') = false", () => { + expect(strings.isIncluded('hello world', 'earth')).to.equal(false) + }) + }) + + describe('Test isNull', () => { + it('isNull(null) = true', () => { + expect(strings.isNull(null)).to.equal(true) + }) + + it('isNull(undefined) = false', () => { + expect(strings.isNull(undefined)).to.equal(false) + }) + }) + + describe('Test isObject', () => { + it("isObject({ hello: 'world' }) = true", () => { + expect(strings.isObject({ hello: 'world' })).to.equal(true) + }) + + it("isObject('hello world') = false", () => { + expect(strings.isObject('hello world')).to.equal(false) + }) + }) + + describe('Test isUndefined', () => { + it('isUndefined(undefined) = true', () => { + expect(strings.isUndefined(undefined)).to.equal(true) + }) + + it('isUndefined(null) = false', () => { + expect(strings.isUndefined(null)).to.equal(false) + }) + }) + + describe('Test notEmptyArray', () => { + it("notEmptyArray(['hello world']) = true", () => { + expect(strings.notEmptyArray(['hello world'])).to.equal(true) + }) + + it('notEmptyArray([]) = false', () => { + expect(strings.notEmptyArray([])).to.equal(false) + }) + }) + + describe('Test notEmptyObject', () => { + it("notEmptyObject({ hello: 'world' }) = true", () => { + expect(strings.notEmptyObject({ hello: 'world' })).to.equal(true) + }) + + it('notEmptyObject({}) = false', () => { + expect(strings.notEmptyObject({})).to.equal(false) + }) + }) + + describe('Test notNullOrUndefined', () => { + it("notNullOrUndefined('hello world') = true", () => { + expect(strings.notNullOrUndefined('hello world')).to.equal(true) + }) + + it('notNullOrUndefined(null) = false', () => { + expect(strings.notNullOrUndefined(null)).to.equal(false) + }) + + it('notNullOrUndefined(undefined) = false', () => { + expect(strings.notNullOrUndefined(undefined)).to.equal(false) + }) + }) + + describe('Test pluralize', () => { + it("pluralize(1, 'Apple') = '1 Apple'", () => { + expect(strings.pluralize(1, 'Apple')).to.equal('1 Apple') + }) + + it("pluralize(1000, 'Apple') = '1.000 Apples'", () => { + expect(strings.pluralize(1000, 'Apple')).to.equal('1.000 Apples') + }) + + it("pluralize(1, 'Child', 'Children') = '1 Child'", () => { + expect(strings.pluralize(1, 'Child', 'Children')).to.equal('1 Child') + }) + + it("pluralize(1000, 'Child', 'Children') = '1.000 Children'", () => { + expect(strings.pluralize(1000, 'Child', 'Children')).to.equal('1.000 Children') + }) + }) + + describe('Test removeDoubleSpaces', () => { + it("removeDoubleSpaces('hello world')) = 'hello world'", () => { + expect(strings.removeDoubleSpaces('hello world')).to.equal('hello world') + }) + + it("removeDoubleSpaces('hello world once again')) = 'hello world once again'", () => { + expect(strings.removeDoubleSpaces('hello world once again')).to.equal('hello world once again') + }) + }) + + describe('Test toHex', () => { + it("toHex('hello world')) = '68656c6c6f20776f726c64'", () => { + expect(strings.toHex('hello world')).to.equal('68656c6c6f20776f726c64') + }) + }) +}) diff --git a/tests/legacy/utils.mjs b/test/dist-legacy/utils.mjs similarity index 100% rename from tests/legacy/utils.mjs rename to test/dist-legacy/utils.mjs diff --git a/tests/env.test.ts b/test/env.test.ts similarity index 100% rename from tests/env.test.ts rename to test/env.test.ts diff --git a/tests/helpers.test.ts b/test/helpers.test.ts similarity index 100% rename from tests/helpers.test.ts rename to test/helpers.test.ts diff --git a/tests/legacy/ard.test.mjs b/test/legacy/ard.test.mjs similarity index 100% rename from tests/legacy/ard.test.mjs rename to test/legacy/ard.test.mjs diff --git a/tests/legacy/date.test.mjs b/test/legacy/date.test.mjs similarity index 100% rename from tests/legacy/date.test.mjs rename to test/legacy/date.test.mjs diff --git a/tests/legacy/helpers.test.mjs b/test/legacy/helpers.test.mjs similarity index 100% rename from tests/legacy/helpers.test.mjs rename to test/legacy/helpers.test.mjs diff --git a/tests/legacy/numbers.test.mjs b/test/legacy/numbers.test.mjs similarity index 100% rename from tests/legacy/numbers.test.mjs rename to test/legacy/numbers.test.mjs diff --git a/tests/legacy/strings.test.mjs b/test/legacy/strings.test.mjs similarity index 100% rename from tests/legacy/strings.test.mjs rename to test/legacy/strings.test.mjs diff --git a/test/legacy/utils.mjs b/test/legacy/utils.mjs new file mode 100644 index 0000000..d684405 --- /dev/null +++ b/test/legacy/utils.mjs @@ -0,0 +1,14 @@ +import assert, { equal } from 'node:assert' + +export const expect = (a) => ({ + // chai + to: { + equal: (b) => equal(a, b), + include: (needle) => assert(a.includes(needle)), + be: { + greaterThanOrEqual: (b) => a >= b, + }, + }, + // jest / bun + toEqual: (b) => equal(a, b), +}) diff --git a/tests/number.test.ts b/test/number.test.ts similarity index 100% rename from tests/number.test.ts rename to test/number.test.ts diff --git a/tests/object.test.ts b/test/object.test.ts similarity index 100% rename from tests/object.test.ts rename to test/object.test.ts diff --git a/tests/predicate.test.ts b/test/predicate.test.ts similarity index 100% rename from tests/predicate.test.ts rename to test/predicate.test.ts diff --git a/tests/storage/utils.test.ts b/test/storage/utils.test.ts similarity index 100% rename from tests/storage/utils.test.ts rename to test/storage/utils.test.ts diff --git a/tests/string.test.ts b/test/string.test.ts similarity index 100% rename from tests/string.test.ts rename to test/string.test.ts From 1b8e4b321d871e5739c00ddd421de31d6222faac Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:24:15 +0200 Subject: [PATCH 34/42] fix(ci): add mjs-suffix --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b70c7a7..17c86c1 100644 --- a/package.json +++ b/package.json @@ -109,9 +109,9 @@ "test": "bun run typecheck && bun run test:bun && bun run test:legacy", "test:bun": "bun test ./test/**test*.ts", "test:dist": "bun test ./test/dist-legacy/*test*.mjs", - "test:dist:node": "node --test ./test/dist-legacy/", + "test:dist:node": "node --test ./test/dist-legacy/*.mjs", "test:legacy": "bun test ./test/legacy/*.test.mjs", - "test:legacy:node": "node --test ./test/legacy/", + "test:legacy:node": "node --test ./test/legacy/*.mjs", "test:node": "node --test ./test/**.test.ts", "typecheck": "tsc --noEmit" }, From 6ff983fa26e62b98e2942ae7ccb29428c4633db9 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:27:15 +0200 Subject: [PATCH 35/42] fix(ci): fix tests path --- .github/workflows/pull.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index abb30a2..47d44a5 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -73,10 +73,10 @@ jobs: run: npm run test - name: Test dist Strings - run: node --test ./tests/dist-legacy/strings.test.mjs + run: node --test ./test/dist-legacy/strings.test.mjs - name: Test dist ARD - run: node --test ./tests/dist-legacy/ard.test.mjs + run: node --test ./test/dist-legacy/ard.test.mjs - name: 🧪 Run Dist Tests (in Node via npm) run: npm run test:dist:node From 8f1f94d04e6976abb24ab2ad92c0b4cd44742ae5 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:31:43 +0200 Subject: [PATCH 36/42] chore(ci): clean up test job --- .github/workflows/pull.yml | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index 47d44a5..b856499 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -6,7 +6,7 @@ on: jobs: test: - name: Run Tests + name: Run Node.js Tests runs-on: ubuntu-latest strategy: matrix: @@ -31,7 +31,7 @@ jobs: - name: 🧪 Run Lint run: bun run lint - - name: 🧪 Run build + - name: 🔨 Run build run: bun run build - name: 🧪 Run Tests (in Bun) @@ -46,8 +46,11 @@ jobs: - name: 🧪 Run Tests (in via npm in Node) run: npm run test:node + - name: 🧪 Run Dist Tests (in via npm in Node) + run: npm run test:dist:node + test-node-20: - name: Run Tests + name: Run Tests in Node.js v20 runs-on: ubuntu-latest steps: - name: 👀 Checkout Code @@ -72,11 +75,5 @@ jobs: - name: 🧪 Run Tests run: npm run test - - name: Test dist Strings - run: node --test ./test/dist-legacy/strings.test.mjs - - - name: Test dist ARD - run: node --test ./test/dist-legacy/ard.test.mjs - - name: 🧪 Run Dist Tests (in Node via npm) run: npm run test:dist:node From 0f6994803330571c94e2bec6c4efcb757c2899b3 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:43:03 +0200 Subject: [PATCH 37/42] chore: release v3.0.0-beta.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 17c86c1..73437a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@swrlab/utils", - "version": "3.0.0", + "version": "3.0.0-beta.1", "description": "Wrapping common SWR Audio Lab utils", "type": "module", "license": "MIT", From 488a6cbbc706420192712fc9307b397f35dd9150 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:49:07 +0200 Subject: [PATCH 38/42] fix: use correct extension for bin --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 73437a6..aab1a0f 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ } }, "bin": { - "ard-coreId": "./bin/ard-coreId.js" + "ard-coreId": "./bin/ard-coreId.mjs" }, "publishConfig": { "access": "public", From 88afa84f7418aa49bf94b44c458b39dd8be03018 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:49:54 +0200 Subject: [PATCH 39/42] chore: release v3.0.0-beta.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index aab1a0f..886b63b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@swrlab/utils", - "version": "3.0.0-beta.1", + "version": "3.0.0-beta.2", "description": "Wrapping common SWR Audio Lab utils", "type": "module", "license": "MIT", From f50be34c6aa6fa5c1254bed00122d7562824abd9 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:50:36 +0200 Subject: [PATCH 40/42] fix(npm): use bin path suggested from npm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 886b63b..e4e329d 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,7 @@ } }, "bin": { - "ard-coreId": "./bin/ard-coreId.mjs" + "ard-coreId": "bin/ard-coreId.mjs" }, "publishConfig": { "access": "public", From 5a1d9ae012bc5312fe366af6c3465af58eb35371 Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Wed, 17 Sep 2025 20:51:03 +0200 Subject: [PATCH 41/42] chore: release v3.0.0-beta.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e4e329d..10202d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@swrlab/utils", - "version": "3.0.0-beta.2", + "version": "3.0.0-beta.3", "description": "Wrapping common SWR Audio Lab utils", "type": "module", "license": "MIT", From fc071e1daf6a811ac57fd56165bfaa2fc4e00dfd Mon Sep 17 00:00:00 2001 From: Pascal Weiland Date: Fri, 19 Sep 2025 10:07:15 +0200 Subject: [PATCH 42/42] refact: migrate to workspaces --- .github/dependabot.yml | 16 +- .gitignore | 2 + README.md | 2 +- biome.json | 69 ++ bun.lock | 691 +++++++++++++++++- eslint.config.js | 27 +- knip.json | 9 + package.json | 144 +--- packages/date/package.json | 67 ++ packages/date/src/index.ts | 281 +++++++ packages/date/test/compare.test.ts | 67 ++ packages/date/test/index.test.ts | 181 +++++ packages/date/tsconfig.json | 10 + packages/legacy/README.md | 20 + packages/legacy/package.json | 69 ++ packages/legacy/src/ard.ts | 1 + packages/legacy/src/date.ts | 24 + {src => packages/legacy/src}/date/README.md | 0 .../legacy/src}/date/getDateHourMinutes.ts | 0 .../legacy/src}/date/getDayMonthYear.ts | 0 .../legacy/src}/date/getFullRelativeTime.ts | 0 .../legacy/src}/date/getHourMinutes.ts | 0 .../legacy/src}/date/getIsoRelativeTime.ts | 0 .../legacy/src}/date/getRelativeTime.ts | 0 .../legacy/src}/date/getYearMonthDay.ts | 0 {src => packages/legacy/src}/date/index.ts | 8 +- .../legacy/src}/date/toDayMonthYear.ts | 0 {src => packages/legacy/src}/date/utils.ts | 0 packages/legacy/src/helpers.ts | 3 + packages/legacy/src/index.ts | 19 + packages/legacy/src/numbers.ts | 13 + .../legacy/src}/storage-wrapper.ts | 7 +- packages/legacy/src/strings.ts | 4 + {src/legacy => packages/legacy/src}/undici.ts | 11 +- .../legacy/test}/ard.test.mjs | 2 +- .../legacy/test}/date.test.mjs | 2 +- {test => packages/legacy/test}/date.test.ts | 0 .../legacy/test}/date.utils.test.ts | 0 .../legacy/test/dist}/ard.test.mjs | 0 .../legacy/test/dist}/date.test.mjs | 0 .../legacy/test/dist}/helpers.test.mjs | 0 .../legacy/test/dist}/numbers.test.mjs | 0 .../legacy/test/dist}/strings.test.mjs | 0 .../legacy/test/dist}/utils.mjs | 0 .../legacy/test}/helpers.test.mjs | 2 +- .../legacy/test}/numbers.test.mjs | 2 +- .../legacy/test}/strings.test.mjs | 2 +- .../legacy => packages/legacy/test}/utils.mjs | 0 packages/legacy/tsconfig.json | 9 + packages/logger/package.json | 64 ++ packages/storage/package.json | 60 ++ .../storage/src}/createUri.ts | 0 .../storage/src}/google.ts | 5 +- .../storage => packages/storage/src}/index.ts | 2 + .../storage => packages/storage/src}/local.ts | 3 - .../storage => packages/storage/src}/utils.ts | 2 +- .../storage/test/storage.utils.test.ts | 2 +- packages/storage/tsconfig.json | 10 + {bin => packages/utils/bin}/ard-coreId.mjs | 0 packages/utils/package.json | 97 +++ {src => packages/utils/src}/ard/coreId.ts | 4 + .../utils/src}/ard/createHashedId.ts | 0 {src => packages/utils/src}/ard/index.ts | 0 {src => packages/utils/src}/array/README.md | 0 .../utils/src}/array/arrayToObjectCount.ts | 1 - {src => packages/utils/src}/array/index.ts | 0 .../utils/src}/array/isEmptyArray.ts | 0 .../utils/src}/array/notEmptyArray.ts | 0 {src => packages/utils/src}/env.ts | 2 +- {src => packages/utils/src}/helpers/README.md | 0 {src => packages/utils/src}/helpers/index.ts | 0 .../utils/src}/helpers/request.ts | 5 +- {src => packages/utils/src}/helpers/sleep.ts | 0 {src => packages/utils/src}/index.ts | 2 +- {src => packages/utils/src}/number/README.md | 0 .../utils/src}/number/addLeadingZero.ts | 1 + .../utils/src}/number/addTrailingZeros.ts | 1 + .../utils/src}/number/getAverage.ts | 2 +- {src => packages/utils/src}/number/getDiff.ts | 0 .../utils/src}/number/getRandomInRange.ts | 0 {src => packages/utils/src}/number/getSum.ts | 2 +- {src => packages/utils/src}/number/index.ts | 6 +- {src => packages/utils/src}/number/isEven.ts | 0 .../utils/src}/number/normalize.ts | 0 {src => packages/utils/src}/number/roundTo.ts | 0 .../utils/src}/number/toReadable.ts | 4 +- {src => packages/utils/src}/object/README.md | 0 .../utils/src}/object/getJsonKeys.ts | 2 +- .../utils/src}/object/getObjectLength.ts | 0 {src => packages/utils/src}/object/index.ts | 0 .../utils/src}/object/isEmptyObject.ts | 0 .../utils/src}/object/notEmptyObject.ts | 0 .../utils/src}/predicate/README.md | 0 .../utils/src}/predicate/index.ts | 0 .../utils/src}/predicate/isArray.ts | 0 .../utils/src}/predicate/isNull.ts | 0 .../utils/src}/predicate/isObject.ts | 0 .../utils/src}/predicate/isUndefined.ts | 0 .../src}/predicate/notNullOrUndefined.ts | 0 {src => packages/utils/src}/string/README.md | 4 +- {src => packages/utils/src}/string/base64.ts | 0 .../utils/src}/string/capitalize.ts | 0 {src => packages/utils/src}/string/crc64.ts | 2 + {src => packages/utils/src}/string/index.ts | 0 .../utils/src}/string/isEmptyString.ts | 0 .../utils/src}/string/isIncluded.ts | 0 .../utils/src}/string/pluralize.ts | 0 .../utils/src}/string/removeDoubleSpaces.ts | 0 {src => packages/utils/src}/string/toHex.ts | 0 packages/utils/test/ard.test.ts | 40 + {test => packages/utils/test}/array.test.ts | 5 +- {test => packages/utils/test}/base64.test.ts | 14 +- {test => packages/utils/test}/crc.test.ts | 3 +- {test => packages/utils/test}/env.test.ts | 39 +- packages/utils/test/helpers.test.ts | 75 ++ packages/utils/test/number.test.ts | 211 ++++++ {test => packages/utils/test}/object.test.ts | 39 +- .../utils/test}/predicate.test.ts | 37 +- {test => packages/utils/test}/string.test.ts | 43 +- packages/utils/tsconfig.json | 9 + packages/utils/tsdown.config.ts | 18 + packages/utils/vitest.config.ts | 9 + prettier.config.js | 12 + src/legacy/ard.ts | 1 - src/legacy/date.ts | 24 - src/legacy/helpers.ts | 3 - src/legacy/numbers.ts | 23 - src/legacy/strings.ts | 35 - src/storage/createUrl.ts | 0 src/storage/delete.ts | 0 src/storage/list.ts | 0 src/storage/load.ts | 0 src/storage/move.ts | 0 src/storage/save.ts | 0 test/ard.test.bun.ts | 14 - test/ard.test.ts | 9 - test/helpers.test.ts | 16 - test/number.test.ts | 133 ---- tsconfig.base.json | 37 + tsconfig.json | 52 +- tsdown.config.ts | 28 - 141 files changed, 2365 insertions(+), 611 deletions(-) create mode 100644 biome.json create mode 100644 knip.json create mode 100644 packages/date/package.json create mode 100644 packages/date/src/index.ts create mode 100644 packages/date/test/compare.test.ts create mode 100644 packages/date/test/index.test.ts create mode 100644 packages/date/tsconfig.json create mode 100644 packages/legacy/README.md create mode 100644 packages/legacy/package.json create mode 100644 packages/legacy/src/ard.ts create mode 100644 packages/legacy/src/date.ts rename {src => packages/legacy/src}/date/README.md (100%) rename {src => packages/legacy/src}/date/getDateHourMinutes.ts (100%) rename {src => packages/legacy/src}/date/getDayMonthYear.ts (100%) rename {src => packages/legacy/src}/date/getFullRelativeTime.ts (100%) rename {src => packages/legacy/src}/date/getHourMinutes.ts (100%) rename {src => packages/legacy/src}/date/getIsoRelativeTime.ts (100%) rename {src => packages/legacy/src}/date/getRelativeTime.ts (100%) rename {src => packages/legacy/src}/date/getYearMonthDay.ts (100%) rename {src => packages/legacy/src}/date/index.ts (62%) rename {src => packages/legacy/src}/date/toDayMonthYear.ts (100%) rename {src => packages/legacy/src}/date/utils.ts (100%) create mode 100644 packages/legacy/src/helpers.ts create mode 100644 packages/legacy/src/index.ts create mode 100644 packages/legacy/src/numbers.ts rename {src/legacy => packages/legacy/src}/storage-wrapper.ts (68%) create mode 100644 packages/legacy/src/strings.ts rename {src/legacy => packages/legacy/src}/undici.ts (97%) rename {test/legacy => packages/legacy/test}/ard.test.mjs (83%) rename {test/legacy => packages/legacy/test}/date.test.mjs (97%) rename {test => packages/legacy/test}/date.test.ts (100%) rename {test => packages/legacy/test}/date.utils.test.ts (100%) rename {test/dist-legacy => packages/legacy/test/dist}/ard.test.mjs (100%) rename {test/dist-legacy => packages/legacy/test/dist}/date.test.mjs (100%) rename {test/dist-legacy => packages/legacy/test/dist}/helpers.test.mjs (100%) rename {test/dist-legacy => packages/legacy/test/dist}/numbers.test.mjs (100%) rename {test/dist-legacy => packages/legacy/test/dist}/strings.test.mjs (100%) rename {test/dist-legacy => packages/legacy/test/dist}/utils.mjs (100%) rename {test/legacy => packages/legacy/test}/helpers.test.mjs (95%) rename {test/legacy => packages/legacy/test}/numbers.test.mjs (98%) rename {test/legacy => packages/legacy/test}/strings.test.mjs (98%) rename {test/legacy => packages/legacy/test}/utils.mjs (100%) create mode 100644 packages/legacy/tsconfig.json create mode 100644 packages/logger/package.json create mode 100644 packages/storage/package.json rename {src/storage => packages/storage/src}/createUri.ts (100%) rename {src/storage => packages/storage/src}/google.ts (96%) rename {src/storage => packages/storage/src}/index.ts (95%) rename {src/storage => packages/storage/src}/local.ts (72%) rename {src/storage => packages/storage/src}/utils.ts (98%) rename test/storage/utils.test.ts => packages/storage/test/storage.utils.test.ts (95%) create mode 100644 packages/storage/tsconfig.json rename {bin => packages/utils/bin}/ard-coreId.mjs (100%) mode change 100644 => 100755 create mode 100644 packages/utils/package.json rename {src => packages/utils/src}/ard/coreId.ts (91%) rename {src => packages/utils/src}/ard/createHashedId.ts (100%) rename {src => packages/utils/src}/ard/index.ts (100%) rename {src => packages/utils/src}/array/README.md (100%) rename {src => packages/utils/src}/array/arrayToObjectCount.ts (80%) rename {src => packages/utils/src}/array/index.ts (100%) rename {src => packages/utils/src}/array/isEmptyArray.ts (100%) rename {src => packages/utils/src}/array/notEmptyArray.ts (100%) rename {src => packages/utils/src}/env.ts (98%) rename {src => packages/utils/src}/helpers/README.md (100%) rename {src => packages/utils/src}/helpers/index.ts (100%) rename {src => packages/utils/src}/helpers/request.ts (94%) rename {src => packages/utils/src}/helpers/sleep.ts (100%) rename {src => packages/utils/src}/index.ts (87%) rename {src => packages/utils/src}/number/README.md (100%) rename {src => packages/utils/src}/number/addLeadingZero.ts (80%) rename {src => packages/utils/src}/number/addTrailingZeros.ts (82%) rename {src => packages/utils/src}/number/getAverage.ts (87%) rename {src => packages/utils/src}/number/getDiff.ts (100%) rename {src => packages/utils/src}/number/getRandomInRange.ts (100%) rename {src => packages/utils/src}/number/getSum.ts (86%) rename {src => packages/utils/src}/number/index.ts (69%) rename {src => packages/utils/src}/number/isEven.ts (100%) rename {src => packages/utils/src}/number/normalize.ts (100%) rename {src => packages/utils/src}/number/roundTo.ts (100%) rename {src => packages/utils/src}/number/toReadable.ts (68%) rename {src => packages/utils/src}/object/README.md (100%) rename {src => packages/utils/src}/object/getJsonKeys.ts (82%) rename {src => packages/utils/src}/object/getObjectLength.ts (100%) rename {src => packages/utils/src}/object/index.ts (100%) rename {src => packages/utils/src}/object/isEmptyObject.ts (100%) rename {src => packages/utils/src}/object/notEmptyObject.ts (100%) rename {src => packages/utils/src}/predicate/README.md (100%) rename {src => packages/utils/src}/predicate/index.ts (100%) rename {src => packages/utils/src}/predicate/isArray.ts (100%) rename {src => packages/utils/src}/predicate/isNull.ts (100%) rename {src => packages/utils/src}/predicate/isObject.ts (100%) rename {src => packages/utils/src}/predicate/isUndefined.ts (100%) rename {src => packages/utils/src}/predicate/notNullOrUndefined.ts (100%) rename {src => packages/utils/src}/string/README.md (96%) rename {src => packages/utils/src}/string/base64.ts (100%) rename {src => packages/utils/src}/string/capitalize.ts (100%) rename {src => packages/utils/src}/string/crc64.ts (96%) rename {src => packages/utils/src}/string/index.ts (100%) rename {src => packages/utils/src}/string/isEmptyString.ts (100%) rename {src => packages/utils/src}/string/isIncluded.ts (100%) rename {src => packages/utils/src}/string/pluralize.ts (100%) rename {src => packages/utils/src}/string/removeDoubleSpaces.ts (100%) rename {src => packages/utils/src}/string/toHex.ts (100%) create mode 100644 packages/utils/test/ard.test.ts rename {test => packages/utils/test}/array.test.ts (87%) rename {test => packages/utils/test}/base64.test.ts (67%) rename {test => packages/utils/test}/crc.test.ts (96%) rename {test => packages/utils/test}/env.test.ts (67%) create mode 100644 packages/utils/test/helpers.test.ts create mode 100644 packages/utils/test/number.test.ts rename {test => packages/utils/test}/object.test.ts (58%) rename {test => packages/utils/test}/predicate.test.ts (62%) rename {test => packages/utils/test}/string.test.ts (57%) create mode 100644 packages/utils/tsconfig.json create mode 100644 packages/utils/tsdown.config.ts create mode 100644 packages/utils/vitest.config.ts create mode 100644 prettier.config.js delete mode 100644 src/legacy/ard.ts delete mode 100644 src/legacy/date.ts delete mode 100644 src/legacy/helpers.ts delete mode 100644 src/legacy/numbers.ts delete mode 100644 src/legacy/strings.ts delete mode 100644 src/storage/createUrl.ts delete mode 100644 src/storage/delete.ts delete mode 100644 src/storage/list.ts delete mode 100644 src/storage/load.ts delete mode 100644 src/storage/move.ts delete mode 100644 src/storage/save.ts delete mode 100644 test/ard.test.bun.ts delete mode 100644 test/ard.test.ts delete mode 100644 test/helpers.test.ts delete mode 100644 test/number.test.ts create mode 100644 tsconfig.base.json delete mode 100644 tsdown.config.ts diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8d658f7..2ba5646 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,14 +1,14 @@ version: 2 updates: - - package-ecosystem: 'npm' - directory: '/' + - package-ecosystem: npm + directory: / open-pull-requests-limit: 10 schedule: - interval: 'weekly' - day: 'sunday' - - package-ecosystem: 'github-actions' - directory: '/' + interval: weekly + day: sunday + - package-ecosystem: github-actions + directory: / open-pull-requests-limit: 10 schedule: - interval: 'weekly' - day: 'sunday' + interval: weekly + day: sunday diff --git a/.gitignore b/.gitignore index bc83d31..f07f9a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ node_modules dist +coverage/ + .eslintcache .env diff --git a/README.md b/README.md index cdcf393..35da53e 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Each utility category (`string`, `date`, etc.) has their own export and thus can ```js // examples import { toRelativeTime } from '@swrlab/utils/date' -import { roundTo, getRandomInRange } from '@swrlab/utils/number' +import { getRandomInRange, roundTo } from '@swrlab/utils/number' import * as numberUtilities from '@swrlab/utils/number' ``` diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..710327b --- /dev/null +++ b/biome.json @@ -0,0 +1,69 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.2.4/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": false, + "includes": ["packages/**/*.{js,mjs,ts}", "!**/dist/*", "!**/coverage/*"] + }, + "formatter": { + "enabled": true, + "indentStyle": "tab", + "useEditorconfig": true, + "bracketSpacing": true, + "expand": "auto" + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "suspicious": { + "noExplicitAny": "off" + }, + "style": { + "useImportType": "on", + "useExportType": "on", + "useNodejsImportProtocol": "on" + } + } + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "lineEnding": "lf", + "semicolons": "asNeeded", + "lineWidth": 120, + "trailingCommas": "es5", + "arrowParentheses": "always", + "attributePosition": "auto", + "bracketSameLine": true, + "bracketSpacing": true + } + }, + "assist": { + "enabled": true, + "actions": { + "source": { + "organizeImports": { + "level": "off", + "options": { + "identifierOrder": "natural", + "groups": [ + { "type": true }, + ":URL:", + ":PACKAGE_WITH_PROTOCOL:", + ":PACKAGE:", + ":NODE:", + ":BUN:", + ":ALIAS:", + ":PATH:" + ] + } + } + } + } + } +} diff --git a/bun.lock b/bun.lock index ec332d3..369ebfa 100644 --- a/bun.lock +++ b/bun.lock @@ -2,25 +2,100 @@ "lockfileVersion": 1, "workspaces": { "": { - "dependencies": { + "devDependencies": { + "@arethetypeswrong/cli": "^0.18.2", + "@biomejs/biome": "2.2.4", + "@swrlab/style-guide": "^2.0.8", + "@types/node": "^24.5.2", + "bumpp": "^10.2.3", + "eslint": "^9.35.0", + "knip": "^5.63.1", + "prettier": "^3.6.2", + "typescript": "^5.9.2", + "vitest": "^3.2.4", + }, + }, + "packages/date": { + "name": "@swrlab/date", + "version": "3.0.0-beta.3", + "devDependencies": { + "@types/luxon": "^3.7.1", + "@types/node": "^24.3.1", "luxon": "3.7.2", - "undici": "7.15.0", + "tsdown": "^0.14.2", + "typescript": "^5.9.2", + }, + }, + "packages/legacy": { + "name": "@swrlab/utils-legacy", + "version": "3.0.0-beta.3", + "dependencies": { + "@google-cloud/storage": "^7.16.0", + "@swrlab/storage": "workspace:*", + "@swrlab/utils": "workspace:*", + "abort-controller": "^3.0.0", + "luxon": "3.7.1", + "node-crc": "https://github.com/swrlab/node-crc#v2.1.0", + "undici": "7.13.0", + }, + "devDependencies": { + "@types/node": "^24.3.1", + "tsdown": "^0.14.2", + "typescript": "^5.9.2", + }, + }, + "packages/logger": { + "name": "@swrlab/logger", + "version": "3.0.0-beta.3", + "dependencies": { + "winston": "^3.17.0", }, "devDependencies": { - "@google-cloud/storage": "^7.17.0", - "@swrlab/style-guide": "^2.0.7", - "@types/bun": "^1.2.21", "@types/luxon": "^3.7.1", "@types/node": "^24.3.1", - "eslint": "^9.35.0", + "consola": "^3.4.2", + "luxon": "3.7.2", + "tsdown": "^0.14.2", + "typescript": "^5.9.2", + }, + }, + "packages/storage": { + "name": "@swrlab/storage", + "version": "3.0.0-beta.3", + "dependencies": { + "@google-cloud/storage": "^7.17.0", + }, + "devDependencies": { + "@types/node": "^24.3.1", + "tsdown": "^0.14.2", + "typescript": "^5.9.2", + }, + }, + "packages/utils": { + "name": "@swrlab/utils", + "version": "3.0.0-beta.3", + "bin": { + "ard-coreId": "bin/ard-coreId.mjs", + }, + "devDependencies": { + "@types/node": "^24.3.1", + "@vitest/coverage-v8": "3.2.4", "knip": "^5.63.1", - "prettier": "^3.6.2", "tsdown": "^0.14.2", "typescript": "^5.9.2", + "vitest": "^3.2.4", }, }, }, "packages": { + "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + + "@andrewbranch/untar.js": ["@andrewbranch/untar.js@1.0.3", "", {}, "sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw=="], + + "@arethetypeswrong/cli": ["@arethetypeswrong/cli@0.18.2", "", { "dependencies": { "@arethetypeswrong/core": "0.18.2", "chalk": "^4.1.2", "cli-table3": "^0.6.3", "commander": "^10.0.1", "marked": "^9.1.2", "marked-terminal": "^7.1.0", "semver": "^7.5.4" }, "bin": { "attw": "dist/index.js" } }, "sha512-PcFM20JNlevEDKBg4Re29Rtv2xvjvQZzg7ENnrWFSS0PHgdP2njibVFw+dRUhNkPgNfac9iUqO0ohAXqQL4hbw=="], + + "@arethetypeswrong/core": ["@arethetypeswrong/core@0.18.2", "", { "dependencies": { "@andrewbranch/untar.js": "^1.0.3", "@loaderkit/resolve": "^1.0.2", "cjs-module-lexer": "^1.2.3", "fflate": "^0.8.2", "lru-cache": "^11.0.1", "semver": "^7.5.4", "typescript": "5.6.1-rc", "validate-npm-package-name": "^5.0.0" } }, "sha512-GiwTmBFOU1/+UVNqqCGzFJYfBXEytUkiI+iRZ6Qx7KmUVtLm00sYySkfe203C9QtPG11yOz1ZaMek8dT/xnlgg=="], + "@babel/generator": ["@babel/generator@7.28.3", "", { "dependencies": { "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw=="], "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], @@ -31,13 +106,91 @@ "@babel/types": ["@babel/types@7.28.2", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ=="], + "@bcoe/v8-coverage": ["@bcoe/v8-coverage@1.0.2", "", {}, "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA=="], + + "@biomejs/biome": ["@biomejs/biome@2.2.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.2.4", "@biomejs/cli-darwin-x64": "2.2.4", "@biomejs/cli-linux-arm64": "2.2.4", "@biomejs/cli-linux-arm64-musl": "2.2.4", "@biomejs/cli-linux-x64": "2.2.4", "@biomejs/cli-linux-x64-musl": "2.2.4", "@biomejs/cli-win32-arm64": "2.2.4", "@biomejs/cli-win32-x64": "2.2.4" }, "bin": { "biome": "bin/biome" } }, "sha512-TBHU5bUy/Ok6m8c0y3pZiuO/BZoY/OcGxoLlrfQof5s8ISVwbVBdFINPQZyFfKwil8XibYWb7JMwnT8wT4WVPg=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RJe2uiyaloN4hne4d2+qVj3d3gFJFbmrr5PYtkkjei1O9c+BjGXgpUPVbi8Pl8syumhzJjFsSIYkcLt2VlVLMA=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-cFsdB4ePanVWfTnPVaUX+yr8qV8ifxjBKMkZwN7gKb20qXPxd/PmwqUH8mY5wnM9+U0QwM76CxFyBRJhC9tQwg=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-M/Iz48p4NAzMXOuH+tsn5BvG/Jb07KOMTdSVwJpicmhN309BeEyRyQX+n1XDF0JVSlu28+hiTQ2L4rZPvu7nMw=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-7TNPkMQEWfjvJDaZRSkDCPT/2r5ESFPKx+TEev+I2BXDGIjfCZk2+b88FOhnJNHtksbOZv8ZWnxrA5gyTYhSsQ=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-orr3nnf2Dpb2ssl6aihQtvcKtLySLta4E2UcXdp7+RTa7mfJjBgIsbS0B9GC8gVu0hjOu021aU8b3/I1tn+pVQ=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-m41nFDS0ksXK2gwXL6W6yZTYPMH0LughqbsxInSKetoH6morVj43szqKx79Iudkp8WRT5SxSh7qVb8KCUiewGg=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.2.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-NXnfTeKHDFUWfxAefa57DiGmu9VyKi0cDqFpdI+1hJWQjGJhJutHPX0b5m+eXvTKOaf+brU+P0JrQAZMb5yYaQ=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.2.4", "", { "os": "win32", "cpu": "x64" }, "sha512-3Y4V4zVRarVh/B/eSHczR4LYoSVyv3Dfuvm3cWs5w/HScccS0+Wt/lHOcDTRYeHjQmMYVC3rIRWqyN2EI52+zg=="], + + "@braidai/lang": ["@braidai/lang@1.1.2", "", {}, "sha512-qBcknbBufNHlui137Hft8xauQMTZDKdophmLFv05r2eNmdIv/MlPuP4TdUknHG68UdWLgVZwgxVe735HzJNIwA=="], + + "@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="], + + "@dabh/diagnostics": ["@dabh/diagnostics@2.0.3", "", { "dependencies": { "colorspace": "1.1.x", "enabled": "2.0.x", "kuler": "^2.0.0" } }, "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA=="], + "@emnapi/core": ["@emnapi/core@1.5.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg=="], "@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="], "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], - "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.53.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.39.1", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~4.8.0" } }, "sha512-Wyed8Wfn3vMNVwrZrgLMxmqwmlcCE1/RfUAOHFzMJb3QLH03mi9Yv1iOCZjif0yx5EZUeJ+17VD1MHPka9IQjQ=="], + "@es-joy/jsdoccomment": ["@es-joy/jsdoccomment@0.58.0", "", { "dependencies": { "@types/estree": "^1.0.8", "@typescript-eslint/types": "^8.43.0", "comment-parser": "1.4.1", "esquery": "^1.6.0", "jsdoc-type-pratt-parser": "~5.4.0" } }, "sha512-smMc5pDht/UVsCD3hhw/a/e/p8m0RdRYiluXToVfd+d4yaQQh7nn9bACjkk6nXJvat7EWPAxuFkMEFfrxeGa3Q=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.10", "", { "os": "aix", "cpu": "ppc64" }, "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.10", "", { "os": "android", "cpu": "arm" }, "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.10", "", { "os": "android", "cpu": "arm64" }, "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.10", "", { "os": "android", "cpu": "x64" }, "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.10", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.10", "", { "os": "darwin", "cpu": "x64" }, "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.10", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.10", "", { "os": "freebsd", "cpu": "x64" }, "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.10", "", { "os": "linux", "cpu": "arm" }, "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.10", "", { "os": "linux", "cpu": "arm64" }, "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.10", "", { "os": "linux", "cpu": "ia32" }, "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.10", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.10", "", { "os": "linux", "cpu": "none" }, "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.10", "", { "os": "linux", "cpu": "s390x" }, "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.10", "", { "os": "linux", "cpu": "x64" }, "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.10", "", { "os": "none", "cpu": "x64" }, "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.10", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.10", "", { "os": "openbsd", "cpu": "x64" }, "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.10", "", { "os": "none", "cpu": "arm64" }, "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.10", "", { "os": "sunos", "cpu": "x64" }, "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.10", "", { "os": "win32", "cpu": "arm64" }, "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.10", "", { "os": "win32", "cpu": "ia32" }, "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.10", "", { "os": "win32", "cpu": "x64" }, "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw=="], "@eslint-community/eslint-plugin-eslint-comments": ["@eslint-community/eslint-plugin-eslint-comments@4.5.0", "", { "dependencies": { "escape-string-regexp": "^4.0.0", "ignore": "^5.2.4" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-MAhuTKlr4y/CE3WYX26raZjy+I/kS2PLKSzvfmDCGrBLTFHOYwqROZdr4XwPgXwX3K9rjzMr4pSmUWGnzsUyMg=="], @@ -55,7 +208,7 @@ "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], - "@eslint/js": ["@eslint/js@9.34.0", "", {}, "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw=="], + "@eslint/js": ["@eslint/js@9.35.0", "", {}, "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw=="], "@eslint/markdown": ["@eslint/markdown@7.2.0", "", { "dependencies": { "@eslint/core": "^0.15.2", "@eslint/plugin-kit": "^0.3.5", "github-slugger": "^2.0.0", "mdast-util-from-markdown": "^2.0.2", "mdast-util-frontmatter": "^2.0.1", "mdast-util-gfm": "^3.1.0", "micromark-extension-frontmatter": "^2.0.0", "micromark-extension-gfm": "^3.0.0", "micromark-util-normalize-identifier": "^2.0.1" } }, "sha512-cmDloByulvKzofM0tIkSGWwxMcrKOLsXZC+EM0FLkRIrxKzW+2RkZAt9TAh37EtQRmx1M4vjBEmlC6R0wiGkog=="], @@ -79,6 +232,10 @@ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="], + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], @@ -87,6 +244,8 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.30", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q=="], + "@loaderkit/resolve": ["@loaderkit/resolve@1.0.4", "", { "dependencies": { "@braidai/lang": "^1.0.0" } }, "sha512-rJzYKVcV4dxJv+vW6jlvagF8zvGxHJ2+HTr1e2qOejfmGhAApgJHl8Aog4mMszxceTRiKTTbnpgmTO1bEZHV/A=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.5", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" } }, "sha512-TBr9Cf9onSAS2LQ2+QHx6XcC6h9+RIzJgbqG3++9TUZSH204AwEy5jg3BTQ0VATsyoGj4ee49tN/y6rvaOOtcg=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -137,6 +296,8 @@ "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.8.0", "", { "os": "win32", "cpu": "x64" }, "sha512-FA6zw1RV8SsEP4oYJvK6RhTMDpf0Inw5w9/+8ihT0dzOZCIb1hzWcCe5EzDyRvV/Wyqqu43LqVydAYAK3l+rLw=="], + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + "@pkgr/core": ["@pkgr/core@0.2.9", "", {}, "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA=="], "@quansync/fs": ["@quansync/fs@0.1.5", "", { "dependencies": { "quansync": "^0.2.11" } }, "sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA=="], @@ -171,18 +332,74 @@ "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.35", "", {}, "sha512-slYrCpoxJUqzFDDNlvrOYRazQUNRvWPjXA17dAOISY3rDMxX6k8K4cj2H+hEYMHF81HO3uNd5rHVigAWRM5dSg=="], - "@swrlab/style-guide": ["@swrlab/style-guide@2.0.7", "", { "dependencies": { "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0", "@eslint/js": "^9.34.0", "@eslint/markdown": "^7.2.0", "eslint-config-flat-gitignore": "^2.1.0", "eslint-config-prettier": "^10.1.8", "eslint-flat-config-utils": "^2.1.1", "eslint-plugin-de-morgan": "^1.3.1", "eslint-plugin-import-x": "^4.16.1", "eslint-plugin-jsdoc": "^54.2.1", "eslint-plugin-jsonc": "^2.20.1", "eslint-plugin-n": "^17.21.3", "eslint-plugin-perfectionist": "^4.15.0", "eslint-plugin-pnpm": "^1.1.1", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-regexp": "^2.10.0", "eslint-plugin-security": "^3.0.1", "eslint-plugin-sonarjs": "^3.0.5", "eslint-plugin-testing-library": "^7.6.8", "eslint-plugin-unicorn": "^60.0.0", "eslint-plugin-unused-imports": "^4.2.0", "eslint-plugin-vue": "^10.4.0", "eslint-plugin-vuejs-accessibility": "^2.4.1", "eslint-plugin-yml": "^1.18.0", "globals": "^16.3.0", "jsonc-eslint-parser": "^2.4.0", "local-pkg": "^1.1.2", "prettier": "^3.6.2", "typescript-eslint": "^8.42.0", "vue-eslint-parser": "^10.2.0", "yaml-eslint-parser": "^1.3.0" }, "peerDependencies": { "eslint": "^9.34.0" } }, "sha512-4GHnx/7iiXrT146tIiql8O5cSDvr0IZ17JA7307O+vazeURrJQlVsrW/OITCsooD/gWa9rcnxj2uWSe8OioBdA=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.50.2", "", { "os": "android", "cpu": "arm" }, "sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.50.2", "", { "os": "android", "cpu": "arm64" }, "sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.50.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.50.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.50.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.50.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.50.2", "", { "os": "linux", "cpu": "arm" }, "sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.50.2", "", { "os": "linux", "cpu": "arm" }, "sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.50.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.50.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ=="], + + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.50.2", "", { "os": "linux", "cpu": "none" }, "sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.50.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.50.2", "", { "os": "linux", "cpu": "none" }, "sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.50.2", "", { "os": "linux", "cpu": "none" }, "sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.50.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.50.2", "", { "os": "linux", "cpu": "x64" }, "sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.50.2", "", { "os": "linux", "cpu": "x64" }, "sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.50.2", "", { "os": "none", "cpu": "arm64" }, "sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.50.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.50.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.50.2", "", { "os": "win32", "cpu": "x64" }, "sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA=="], + + "@sindresorhus/is": ["@sindresorhus/is@4.6.0", "", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="], + + "@swrlab/date": ["@swrlab/date@workspace:packages/date"], + + "@swrlab/logger": ["@swrlab/logger@workspace:packages/logger"], + + "@swrlab/storage": ["@swrlab/storage@workspace:packages/storage"], + + "@swrlab/style-guide": ["@swrlab/style-guide@2.0.8", "", { "dependencies": { "@eslint-community/eslint-plugin-eslint-comments": "^4.5.0", "@eslint/js": "^9.35.0", "@eslint/markdown": "^7.2.0", "eslint-config-flat-gitignore": "^2.1.0", "eslint-config-prettier": "^10.1.8", "eslint-flat-config-utils": "^2.1.1", "eslint-plugin-de-morgan": "^1.3.1", "eslint-plugin-import-x": "^4.16.1", "eslint-plugin-jsdoc": "^59.0.0", "eslint-plugin-jsonc": "^2.20.1", "eslint-plugin-n": "^17.23.0", "eslint-plugin-perfectionist": "^4.15.0", "eslint-plugin-pnpm": "^1.1.1", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-regexp": "^2.10.0", "eslint-plugin-security": "^3.0.1", "eslint-plugin-sonarjs": "^3.0.5", "eslint-plugin-testing-library": "^7.8.0", "eslint-plugin-unicorn": "^61.0.2", "eslint-plugin-unused-imports": "^4.2.0", "eslint-plugin-vue": "^10.4.0", "eslint-plugin-vuejs-accessibility": "^2.4.1", "eslint-plugin-yml": "^1.18.0", "globals": "^16.4.0", "jsonc-eslint-parser": "^2.4.0", "local-pkg": "^1.1.2", "prettier": "^3.6.2", "typescript-eslint": "^8.44.0", "vue-eslint-parser": "^10.2.0", "yaml-eslint-parser": "^1.3.0" }, "peerDependencies": { "eslint": "^9.34.0" }, "optionalPeers": ["eslint"] }, "sha512-Xd2LKPt50cptuMZwqNGBeUpOOefvjrpGqOmWNsnRSVQ9DHkR/LVOX7Pz2gda6An8JErLN27XBPejnZg19SLPKg=="], + + "@swrlab/utils": ["@swrlab/utils@workspace:packages/utils"], + + "@swrlab/utils-legacy": ["@swrlab/utils-legacy@workspace:packages/legacy"], "@tootallnate/once": ["@tootallnate/once@2.0.0", "", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="], "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], - "@types/bun": ["@types/bun@1.2.21", "", { "dependencies": { "bun-types": "1.2.21" } }, "sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A=="], - "@types/caseless": ["@types/caseless@0.12.5", "", {}, "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg=="], + "@types/chai": ["@types/chai@5.2.2", "", { "dependencies": { "@types/deep-eql": "*" } }, "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg=="], + "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], + "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], @@ -193,31 +410,31 @@ "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="], - "@types/node": ["@types/node@24.3.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g=="], - - "@types/react": ["@types/react@19.1.12", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w=="], + "@types/node": ["@types/node@24.5.2", "", { "dependencies": { "undici-types": "~7.12.0" } }, "sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ=="], "@types/request": ["@types/request@2.48.12", "", { "dependencies": { "@types/caseless": "*", "@types/node": "*", "@types/tough-cookie": "*", "form-data": "^2.5.0" } }, "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw=="], "@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="], + "@types/triple-beam": ["@types/triple-beam@1.3.5", "", {}, "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw=="], + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.42.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/type-utils": "8.42.0", "@typescript-eslint/utils": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.42.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Aq2dPqsQkxHOLfb2OPv43RnIvfj05nw8v/6n3B2NABIPpHnjQnaLo9QGMTvml+tv4korl/Cjfrb/BYhoL8UUTQ=="], "@typescript-eslint/parser": ["@typescript-eslint/parser@8.42.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-r1XG74QgShUgXph1BYseJ+KZd17bKQib/yF3SR+demvytiRXrwd12Blnz5eYGm8tXaeRdd4x88MlfwldHoudGg=="], - "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.42.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.42.0", "@typescript-eslint/types": "^8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg=="], + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.44.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.44.0", "@typescript-eslint/types": "^8.44.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ZeaGNraRsq10GuEohKTo4295Z/SuGcSq2LzfGlqiuEvfArzo/VRrT0ZaJsVPuKZ55lVbNk8U6FcL+ZMH8CoyVA=="], "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0" } }, "sha512-51+x9o78NBAVgQzOPd17DkNTnIzJ8T/O2dmMBLoK9qbY0Gm52XJcdJcCl18ExBMiHo6jPMErUQWUv5RLE51zJw=="], - "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.42.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ=="], + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.44.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-x5Y0+AuEPqAInc6yd0n5DAcvtoQ/vyaGwuX5HE9n6qAefk1GaedqrLQF8kQGylLUb9pnZyLf+iEiL9fr8APDtQ=="], "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.42.0", "", { "dependencies": { "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/utils": "8.42.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-9KChw92sbPTYVFw3JLRH1ockhyR3zqqn9lQXol3/YbI6jVxzWoGcT3AsAW0mu1MY0gYtsXnUGV/AKpkAj5tVlQ=="], "@typescript-eslint/types": ["@typescript-eslint/types@8.42.0", "", {}, "sha512-LdtAWMiFmbRLNP7JNeY0SqEtJvGMYSzfiWBSmx+VSZ1CH+1zyl8Mmw1TT39OrtsRvIYShjJWzTDMPWZJCpwBlw=="], - "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.42.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.42.0", "@typescript-eslint/tsconfig-utils": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ=="], + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.44.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.44.0", "@typescript-eslint/tsconfig-utils": "8.44.0", "@typescript-eslint/types": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-lqNj6SgnGcQZwL4/SBJ3xdPEfcBuhCG8zdcwCPgYcmiPLgokiNDKlbPzCwEwu7m279J/lBYWtDYL+87OEfn8Jw=="], "@typescript-eslint/utils": ["@typescript-eslint/utils@8.42.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-JnIzu7H3RH5BrKC4NoZqRfmjqCIS1u3hGZltDYJgkVdqAezl4L9d1ZLw+36huCujtSBSAirGINF/S4UxOcR+/g=="], @@ -261,6 +478,22 @@ "@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g=="], + "@vitest/coverage-v8": ["@vitest/coverage-v8@3.2.4", "", { "dependencies": { "@ampproject/remapping": "^2.3.0", "@bcoe/v8-coverage": "^1.0.2", "ast-v8-to-istanbul": "^0.3.3", "debug": "^4.4.1", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-lib-source-maps": "^5.0.6", "istanbul-reports": "^3.1.7", "magic-string": "^0.30.17", "magicast": "^0.3.5", "std-env": "^3.9.0", "test-exclude": "^7.0.1", "tinyrainbow": "^2.0.0" }, "peerDependencies": { "@vitest/browser": "3.2.4", "vitest": "3.2.4" }, "optionalPeers": ["@vitest/browser"] }, "sha512-EyF9SXU6kS5Ku/U82E259WSnvg6c8KTjppUncuNdm5QHpe17mwREHnjDzozC8x9MZ0xfBUFSaLkRv4TMA75ALQ=="], + + "@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="], + + "@vitest/mocker": ["@vitest/mocker@3.2.4", "", { "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ=="], + + "@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], + + "@vitest/runner": ["@vitest/runner@3.2.4", "", { "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" } }, "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ=="], + + "@vitest/snapshot": ["@vitest/snapshot@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ=="], + + "@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="], + + "@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="], + "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], "acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], @@ -271,20 +504,34 @@ "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], + "ansi-escapes": ["ansi-escapes@7.1.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-YdhtCd19sKRKfAAUsrcC1wzm4JuzJoiX4pOJqIoW2qmKj5WzG/dL8uUJ0361zaXtHqK7gEhOwtAtz7t3Yq3X5g=="], + + "ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "ansis": ["ansis@4.1.0", "", {}, "sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w=="], + "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], + "are-docs-informative": ["are-docs-informative@0.0.2", "", {}, "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig=="], "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "args-tokenizer": ["args-tokenizer@0.3.0", "", {}, "sha512-xXAd7G2Mll5W8uo37GETpQ2VrE84M181Z7ugHFGQnJZ50M2mbOv0osSZ9VsSgPfJQ+LVG0prSi0th+ELMsno7Q=="], + "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], "arrify": ["arrify@2.0.1", "", {}, "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug=="], + "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + "ast-kit": ["ast-kit@2.1.2", "", { "dependencies": { "@babel/parser": "^7.28.0", "pathe": "^2.0.3" } }, "sha512-cl76xfBQM6pztbrFWRnxbrDm9EOqDr1BF6+qQnnDZG2Co2LjyUktkN9GTJfBAfdae+DbT2nJf2nCGAdDDN7W2g=="], + "ast-v8-to-istanbul": ["ast-v8-to-istanbul@0.3.5", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.30", "estree-walker": "^3.0.3", "js-tokens": "^9.0.1" } }, "sha512-9SdXjNheSiE8bALAQCQQuT6fgQaoxJh7IRYrRGZ8/9nv8WhJeC1aXAwN8TbaOssGOukUvyvnkgD9+Yuykvl1aA=="], + + "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], + "async-retry": ["async-retry@1.3.3", "", { "dependencies": { "retry": "0.13.1" } }, "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw=="], "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], @@ -309,10 +556,12 @@ "builtin-modules": ["builtin-modules@3.3.0", "", {}, "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw=="], - "bun-types": ["bun-types@1.2.21", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw=="], + "bumpp": ["bumpp@10.2.3", "", { "dependencies": { "ansis": "^4.1.0", "args-tokenizer": "^0.3.0", "c12": "^3.2.0", "cac": "^6.7.14", "escalade": "^3.2.0", "jsonc-parser": "^3.3.1", "package-manager-detector": "^1.3.0", "semver": "^7.7.2", "tinyexec": "^1.0.1", "tinyglobby": "^0.2.14", "yaml": "^2.8.1" }, "bin": { "bumpp": "bin/bumpp.mjs" } }, "sha512-nsFBZACxuBVu6yzDSaZZaWpX5hTQ+++9WtYkmO+0Bd3cpSq0Mzvqw5V83n+fOyRj3dYuZRFCQf5Z9NNfZj+Rnw=="], "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], + "c12": ["c12@3.3.0", "", { "dependencies": { "chokidar": "^4.0.3", "confbox": "^0.2.2", "defu": "^6.1.4", "dotenv": "^17.2.2", "exsolve": "^1.0.7", "giget": "^2.0.0", "jiti": "^2.5.1", "ohash": "^2.0.11", "pathe": "^2.0.3", "perfect-debounce": "^2.0.0", "pkg-types": "^2.3.0", "rc9": "^2.1.2" }, "peerDependencies": { "magicast": "^0.3.5" }, "optionalPeers": ["magicast"] }, "sha512-K9ZkuyeJQeqLEyqldbYLG3wjqwpw4BVaAqvmxq3GYKK0b1A/yYQdIcJxkzAOWcNVWhJpRXAPfZFueekiY/L8Dw=="], + "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="], "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], @@ -321,42 +570,68 @@ "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], + "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="], + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "change-case": ["change-case@5.4.4", "", {}, "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w=="], + "char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="], + "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="], + "check-error": ["check-error@2.1.1", "", {}, "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw=="], + "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], "ci-info": ["ci-info@4.3.0", "", {}, "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ=="], + "citty": ["citty@0.1.6", "", { "dependencies": { "consola": "^3.2.3" } }, "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ=="], + + "cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="], + "clean-regexp": ["clean-regexp@1.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw=="], + "cli-highlight": ["cli-highlight@2.1.11", "", { "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", "mz": "^2.4.0", "parse5": "^5.1.1", "parse5-htmlparser2-tree-adapter": "^6.0.0", "yargs": "^16.0.0" }, "bin": { "highlight": "bin/highlight" } }, "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg=="], + + "cli-table3": ["cli-table3@0.6.5", "", { "dependencies": { "string-width": "^4.2.0" }, "optionalDependencies": { "@colors/colors": "1.5.0" } }, "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ=="], + + "cliui": ["cliui@7.0.4", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], + + "color": ["color@3.2.1", "", { "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="], + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], + + "colorspace": ["colorspace@1.1.4", "", { "dependencies": { "color": "^3.1.3", "text-hex": "1.0.x" } }, "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w=="], + "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + "commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="], + "comment-parser": ["comment-parser@1.4.1", "", {}, "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg=="], "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], "confbox": ["confbox@0.2.2", "", {}, "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ=="], + "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], + "core-js-compat": ["core-js-compat@3.45.1", "", { "dependencies": { "browserslist": "^4.25.3" } }, "sha512-tqTt5T4PzsMIZ430XGviK4vzYSoeNJ6CXODi6c/voxOT6IZqBht5/EKaSNnYiEjjRYxjVz7DQIsOsY0XNi8PIA=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], - "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], - "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], "decode-named-character-reference": ["decode-named-character-reference@1.2.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q=="], + "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="], + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], @@ -365,26 +640,44 @@ "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], + "destr": ["destr@2.0.5", "", {}, "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="], + + "detect-libc": ["detect-libc@2.1.0", "", {}, "sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg=="], + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], + "dotenv": ["dotenv@17.2.2", "", {}, "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q=="], + "dts-resolver": ["dts-resolver@2.1.2", "", { "peerDependencies": { "oxc-resolver": ">=11.0.0" }, "optionalPeers": ["oxc-resolver"] }, "sha512-xeXHBQkn2ISSXxbJWD828PFjtyg+/UrMDo7W4Ffcs7+YWCquxU8YjV1KoxuiL+eJ5pg3ll+bC6flVv61L3LKZg=="], "duplexify": ["duplexify@4.1.3", "", { "dependencies": { "end-of-stream": "^1.4.1", "inherits": "^2.0.3", "readable-stream": "^3.1.1", "stream-shift": "^1.0.2" } }, "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA=="], + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], "electron-to-chromium": ["electron-to-chromium@1.5.214", "", {}, "sha512-TpvUNdha+X3ybfU78NoQatKvQEm1oq3lf2QbnmCEdw+Bd9RuIAY+hJTvq1avzHM0f7EJfnH3vbCnbzKzisc/9Q=="], "emoji-regex": ["emoji-regex@10.5.0", "", {}, "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg=="], + "emojilib": ["emojilib@2.4.0", "", {}, "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw=="], + "empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="], + "enabled": ["enabled@2.0.0", "", {}, "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ=="], + "end-of-stream": ["end-of-stream@1.4.4", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q=="], "enhanced-resolve": ["enhanced-resolve@5.17.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg=="], + "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], + + "es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="], + + "esbuild": ["esbuild@0.25.10", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.10", "@esbuild/android-arm": "0.25.10", "@esbuild/android-arm64": "0.25.10", "@esbuild/android-x64": "0.25.10", "@esbuild/darwin-arm64": "0.25.10", "@esbuild/darwin-x64": "0.25.10", "@esbuild/freebsd-arm64": "0.25.10", "@esbuild/freebsd-x64": "0.25.10", "@esbuild/linux-arm": "0.25.10", "@esbuild/linux-arm64": "0.25.10", "@esbuild/linux-ia32": "0.25.10", "@esbuild/linux-loong64": "0.25.10", "@esbuild/linux-mips64el": "0.25.10", "@esbuild/linux-ppc64": "0.25.10", "@esbuild/linux-riscv64": "0.25.10", "@esbuild/linux-s390x": "0.25.10", "@esbuild/linux-x64": "0.25.10", "@esbuild/netbsd-arm64": "0.25.10", "@esbuild/netbsd-x64": "0.25.10", "@esbuild/openbsd-arm64": "0.25.10", "@esbuild/openbsd-x64": "0.25.10", "@esbuild/openharmony-arm64": "0.25.10", "@esbuild/sunos-x64": "0.25.10", "@esbuild/win32-arm64": "0.25.10", "@esbuild/win32-ia32": "0.25.10", "@esbuild/win32-x64": "0.25.10" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ=="], + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], @@ -409,11 +702,11 @@ "eslint-plugin-import-x": ["eslint-plugin-import-x@4.16.1", "", { "dependencies": { "@typescript-eslint/types": "^8.35.0", "comment-parser": "^1.4.1", "debug": "^4.4.1", "eslint-import-context": "^0.1.9", "is-glob": "^4.0.3", "minimatch": "^9.0.3 || ^10.0.1", "semver": "^7.7.2", "stable-hash-x": "^0.2.0", "unrs-resolver": "^1.9.2" }, "peerDependencies": { "@typescript-eslint/utils": "^8.0.0", "eslint": "^8.57.0 || ^9.0.0", "eslint-import-resolver-node": "*" }, "optionalPeers": ["@typescript-eslint/utils", "eslint-import-resolver-node"] }, "sha512-vPZZsiOKaBAIATpFE2uMI4w5IRwdv/FpQ+qZZMR4E+PeOcM4OeoEbqxRMnywdxP19TyB/3h6QBB0EWon7letSQ=="], - "eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@54.3.1", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.53.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.4.1", "escape-string-regexp": "^4.0.0", "espree": "^10.4.0", "esquery": "^1.6.0", "parse-imports-exports": "^0.2.4", "semver": "^7.7.2", "spdx-expression-parse": "^4.0.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-6KlEwRCaQfSi1Wsis4cxsqDfOuQDPG56ozSPCkG+N9aISTQpahbo2n0YZs6c7CIVXQzVdYSxuvQ6w31rfeiMhw=="], + "eslint-plugin-jsdoc": ["eslint-plugin-jsdoc@59.0.0", "", { "dependencies": { "@es-joy/jsdoccomment": "~0.58.0", "are-docs-informative": "^0.0.2", "comment-parser": "1.4.1", "debug": "^4.4.3", "escape-string-regexp": "^4.0.0", "espree": "^10.4.0", "esquery": "^1.6.0", "object-deep-merge": "^1.0.5", "parse-imports-exports": "^0.2.4", "semver": "^7.7.2", "spdx-expression-parse": "^4.0.0" }, "peerDependencies": { "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "sha512-WYm9a2OcnoM2MzdTaklRdsmzQ5iigO9KT3pFS9DwN+CkJWdBfMI0EmAJo5hhkTYREFsZrZtNe3QbmFrKDuzmhw=="], "eslint-plugin-jsonc": ["eslint-plugin-jsonc@2.20.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.5.1", "eslint-compat-utils": "^0.6.4", "eslint-json-compat-utils": "^0.2.1", "espree": "^9.6.1 || ^10.3.0", "graphemer": "^1.4.0", "jsonc-eslint-parser": "^2.4.0", "natural-compare": "^1.4.0", "synckit": "^0.6.2 || ^0.7.3 || ^0.11.5" }, "peerDependencies": { "eslint": ">=6.0.0" } }, "sha512-gUzIwQHXx7ZPypUoadcyRi4WbHW2TPixDr0kqQ4miuJBU0emJmyGTlnaT3Og9X2a8R1CDayN9BFSq5weGWbTng=="], - "eslint-plugin-n": ["eslint-plugin-n@17.21.3", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.5.0", "enhanced-resolve": "^5.17.1", "eslint-plugin-es-x": "^7.8.0", "get-tsconfig": "^4.8.1", "globals": "^15.11.0", "globrex": "^0.1.2", "ignore": "^5.3.2", "semver": "^7.6.3", "ts-declaration-location": "^1.0.6" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-MtxYjDZhMQgsWRm/4xYLL0i2EhusWT7itDxlJ80l1NND2AL2Vi5Mvneqv/ikG9+zpran0VsVRXTEHrpLmUZRNw=="], + "eslint-plugin-n": ["eslint-plugin-n@17.23.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.5.0", "enhanced-resolve": "^5.17.1", "eslint-plugin-es-x": "^7.8.0", "get-tsconfig": "^4.8.1", "globals": "^15.11.0", "globrex": "^0.1.2", "ignore": "^5.3.2", "semver": "^7.6.3", "ts-declaration-location": "^1.0.6" }, "peerDependencies": { "eslint": ">=8.23.0" } }, "sha512-aPePGxUr5LezcXmMRBF83eK1MmqUYY1NdLdHC+jdpfc5b98eL7yDXY20gXJ6DcTxrHBhrLsfYYqo7J+m0h9YXQ=="], "eslint-plugin-perfectionist": ["eslint-plugin-perfectionist@4.15.0", "", { "dependencies": { "@typescript-eslint/types": "^8.34.1", "@typescript-eslint/utils": "^8.34.1", "natural-orderby": "^5.0.0" }, "peerDependencies": { "eslint": ">=8.45.0" } }, "sha512-pC7PgoXyDnEXe14xvRUhBII8A3zRgggKqJFx2a82fjrItDs1BSI7zdZnQtM2yQvcyod6/ujmzb7ejKPx8lZTnw=="], @@ -427,9 +720,9 @@ "eslint-plugin-sonarjs": ["eslint-plugin-sonarjs@3.0.5", "", { "dependencies": { "@eslint-community/regexpp": "4.12.1", "builtin-modules": "3.3.0", "bytes": "3.1.2", "functional-red-black-tree": "1.0.1", "jsx-ast-utils-x": "0.1.0", "lodash.merge": "4.6.2", "minimatch": "9.0.5", "scslre": "0.3.0", "semver": "7.7.2", "typescript": ">=5" }, "peerDependencies": { "eslint": "^8.0.0 || ^9.0.0" } }, "sha512-dI62Ff3zMezUToi161hs2i1HX1ie8Ia2hO0jtNBfdgRBicAG4ydy2WPt0rMTrAe3ZrlqhpAO3w1jcQEdneYoFA=="], - "eslint-plugin-testing-library": ["eslint-plugin-testing-library@7.6.8", "", { "dependencies": { "@typescript-eslint/scope-manager": "^8.15.0", "@typescript-eslint/utils": "^8.15.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-8qvVtc9gzYsBWJd2bMJByAlOdr/GBBH2RZygvp70OTivsJkLkYRxSZFtHq1XQK8k+zNi8DcV7aiSx3avE0rf2w=="], + "eslint-plugin-testing-library": ["eslint-plugin-testing-library@7.8.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "^8.15.0", "@typescript-eslint/utils": "^8.15.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-zmu9xtpULN5KCtJBABBmXK3jfKZej2ZJ6QzCX4MtywP3UTJ7yn/Zful8Kn5mUiOCxX6KBt0to3OZf7Usuhtvfg=="], - "eslint-plugin-unicorn": ["eslint-plugin-unicorn@60.0.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "@eslint-community/eslint-utils": "^4.7.0", "@eslint/plugin-kit": "^0.3.3", "change-case": "^5.4.4", "ci-info": "^4.3.0", "clean-regexp": "^1.0.0", "core-js-compat": "^3.44.0", "esquery": "^1.6.0", "find-up-simple": "^1.0.1", "globals": "^16.3.0", "indent-string": "^5.0.0", "is-builtin-module": "^5.0.0", "jsesc": "^3.1.0", "pluralize": "^8.0.0", "regexp-tree": "^0.1.27", "regjsparser": "^0.12.0", "semver": "^7.7.2", "strip-indent": "^4.0.0" }, "peerDependencies": { "eslint": ">=9.29.0" } }, "sha512-QUzTefvP8stfSXsqKQ+vBQSEsXIlAiCduS/V1Em+FKgL9c21U/IIm20/e3MFy1jyCf14tHAhqC1sX8OTy6VUCg=="], + "eslint-plugin-unicorn": ["eslint-plugin-unicorn@61.0.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.27.1", "@eslint-community/eslint-utils": "^4.7.0", "@eslint/plugin-kit": "^0.3.3", "change-case": "^5.4.4", "ci-info": "^4.3.0", "clean-regexp": "^1.0.0", "core-js-compat": "^3.44.0", "esquery": "^1.6.0", "find-up-simple": "^1.0.1", "globals": "^16.3.0", "indent-string": "^5.0.0", "is-builtin-module": "^5.0.0", "jsesc": "^3.1.0", "pluralize": "^8.0.0", "regexp-tree": "^0.1.27", "regjsparser": "^0.12.0", "semver": "^7.7.2", "strip-indent": "^4.0.0" }, "peerDependencies": { "eslint": ">=9.29.0" } }, "sha512-zLihukvneYT7f74GNbVJXfWIiNQmkc/a9vYBTE4qPkQZswolWNdu+Wsp9sIXno1JOzdn6OUwLPd19ekXVkahRA=="], "eslint-plugin-unused-imports": ["eslint-plugin-unused-imports@4.2.0", "", { "peerDependencies": { "@typescript-eslint/eslint-plugin": "^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0", "eslint": "^9.0.0 || ^8.0.0" }, "optionalPeers": ["@typescript-eslint/eslint-plugin"] }, "sha512-hLbJ2/wnjKq4kGA9AUaExVFIbNzyxYdVo49QZmKCnhk5pc9wcYRbfgLHvWJ8tnsdcseGhoUAddm9gn/lt+d74w=="], @@ -451,10 +744,14 @@ "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], + "expect-type": ["expect-type@1.2.2", "", {}, "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA=="], + "exsolve": ["exsolve@1.0.7", "", {}, "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw=="], "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], @@ -479,6 +776,10 @@ "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + "fecha": ["fecha@4.2.3", "", {}, "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw=="], + + "fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], @@ -491,25 +792,37 @@ "flatted": ["flatted@3.3.1", "", {}, "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw=="], + "fn.name": ["fn.name@1.1.0", "", {}, "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="], + + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + "form-data": ["form-data@2.5.2", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", "mime-types": "^2.1.12", "safe-buffer": "^5.2.1" } }, "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q=="], "format": ["format@0.2.2", "", {}, "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww=="], "formatly": ["formatly@0.3.0", "", { "dependencies": { "fd-package-json": "^2.0.0" }, "bin": { "formatly": "bin/index.mjs" } }, "sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w=="], + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "functional-red-black-tree": ["functional-red-black-tree@1.0.1", "", {}, "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g=="], "gaxios": ["gaxios@6.7.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "is-stream": "^2.0.0", "node-fetch": "^2.6.9", "uuid": "^9.0.1" } }, "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ=="], "gcp-metadata": ["gcp-metadata@6.1.0", "", { "dependencies": { "gaxios": "^6.0.0", "json-bigint": "^1.0.0" } }, "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg=="], - "get-tsconfig": ["get-tsconfig@4.8.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg=="], + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + + "get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], + + "giget": ["giget@2.0.0", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.0", "defu": "^6.1.4", "node-fetch-native": "^1.6.6", "nypm": "^0.6.0", "pathe": "^2.0.3" }, "bin": { "giget": "dist/cli.mjs" } }, "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA=="], "github-slugger": ["github-slugger@2.0.0", "", {}, "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw=="], + "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], - "globals": ["globals@16.3.0", "", {}, "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ=="], + "globals": ["globals@16.4.0", "", {}, "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw=="], "globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="], @@ -523,10 +836,14 @@ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + "highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], + "hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="], "html-entities": ["html-entities@2.5.2", "", {}, "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA=="], + "html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="], + "http-proxy-agent": ["http-proxy-agent@5.0.0", "", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="], "https-proxy-agent": ["https-proxy-agent@7.0.5", "", { "dependencies": { "agent-base": "^7.0.2", "debug": "4" } }, "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw=="], @@ -541,10 +858,14 @@ "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + "is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="], + "is-builtin-module": ["is-builtin-module@5.0.0", "", { "dependencies": { "builtin-modules": "^5.0.0" } }, "sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA=="], "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], @@ -553,8 +874,20 @@ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + "istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="], + + "istanbul-lib-report": ["istanbul-lib-report@3.0.1", "", { "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", "supports-color": "^7.1.0" } }, "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw=="], + + "istanbul-lib-source-maps": ["istanbul-lib-source-maps@5.0.6", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.23", "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0" } }, "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A=="], + + "istanbul-reports": ["istanbul-reports@3.2.0", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA=="], + + "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + "jiti": ["jiti@2.5.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w=="], + "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="], + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], "jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@4.8.0", "", {}, "sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw=="], @@ -571,6 +904,8 @@ "jsonc-eslint-parser": ["jsonc-eslint-parser@2.4.0", "", { "dependencies": { "acorn": "^8.5.0", "eslint-visitor-keys": "^3.0.0", "espree": "^9.0.0", "semver": "^7.3.5" } }, "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg=="], + "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], + "jsx-ast-utils-x": ["jsx-ast-utils-x@0.1.0", "", {}, "sha512-eQQBjBnsVtGacsG9uJNB8qOr3yA8rga4wAaGG1qRcBzSIvfhERLrWxMAM1hp5fcS6Abo8M4+bUBTekYR0qTPQw=="], "jwa": ["jwa@2.0.0", "", { "dependencies": { "buffer-equal-constant-time": "1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA=="], @@ -581,6 +916,8 @@ "knip": ["knip@5.63.1", "", { "dependencies": { "@nodelib/fs.walk": "^1.2.3", "fast-glob": "^3.3.3", "formatly": "^0.3.0", "jiti": "^2.5.1", "js-yaml": "^4.1.0", "minimist": "^1.2.8", "oxc-resolver": "^11.6.2", "picocolors": "^1.1.1", "picomatch": "^4.0.1", "smol-toml": "^1.4.1", "strip-json-comments": "5.0.2", "zod": "^3.25.0", "zod-validation-error": "^3.0.3" }, "peerDependencies": { "@types/node": ">=18", "typescript": ">=5.0.4" }, "bin": { "knip": "bin/knip.js", "knip-bun": "bin/knip-bun.js" } }, "sha512-wSznedUAzcU4o9e0O2WPqDnP7Jttu8cesq/R23eregRY8QYQ9NLJ3aGt9fadJfRzPBoU4tRyutwVQu6chhGDlA=="], + "kuler": ["kuler@2.0.0", "", {}, "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A=="], + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], "local-pkg": ["local-pkg@1.1.2", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.3.0", "quansync": "^0.2.11" } }, "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A=="], @@ -591,12 +928,28 @@ "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + "logform": ["logform@2.7.0", "", { "dependencies": { "@colors/colors": "1.6.0", "@types/triple-beam": "^1.3.2", "fecha": "^4.2.0", "ms": "^2.1.1", "safe-stable-stringify": "^2.3.1", "triple-beam": "^1.3.0" } }, "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ=="], + "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], + "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="], + + "lru-cache": ["lru-cache@11.2.1", "", {}, "sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ=="], + "luxon": ["luxon@3.7.2", "", {}, "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew=="], + "magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="], + + "magicast": ["magicast@0.3.5", "", { "dependencies": { "@babel/parser": "^7.25.4", "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ=="], + + "make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="], + "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="], + "marked": ["marked@9.1.6", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q=="], + + "marked-terminal": ["marked-terminal@7.3.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "ansi-regex": "^6.1.0", "chalk": "^5.4.1", "cli-highlight": "^2.1.11", "cli-table3": "^0.6.5", "node-emoji": "^2.2.0", "supports-hyperlinks": "^3.1.0" }, "peerDependencies": { "marked": ">=1 <16" } }, "sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw=="], + "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA=="], @@ -695,24 +1048,46 @@ "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + "mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="], "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + "napi-postinstall": ["napi-postinstall@0.3.3", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-uTp172LLXSxuSYHv/kou+f6KW3SMppU9ivthaVTXian9sOt3XM/zHYHpRZiLgQoxeWfYUnslNWQHF1+G71xcow=="], "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], "natural-orderby": ["natural-orderby@5.0.0", "", {}, "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg=="], + "node-crc": ["node-crc@github:swrlab/node-crc#92864dc", { "dependencies": { "@types/node": "^18.11.17", "detect-libc": "^2.0.1" } }, "swrlab-node-crc-92864dc"], + + "node-emoji": ["node-emoji@2.2.0", "", { "dependencies": { "@sindresorhus/is": "^4.6.0", "char-regex": "^1.0.2", "emojilib": "^2.4.0", "skin-tone": "^2.0.0" } }, "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw=="], + "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], + "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + "nypm": ["nypm@0.6.2", "", { "dependencies": { "citty": "^0.1.6", "consola": "^3.4.2", "pathe": "^2.0.3", "pkg-types": "^2.3.0", "tinyexec": "^1.0.1" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "object-deep-merge": ["object-deep-merge@1.0.5", "", { "dependencies": { "type-fest": "4.2.0" } }, "sha512-3DioFgOzetbxbeUq8pB2NunXo8V0n4EvqsWM/cJoI6IA9zghd7cl/2pBOuWRf4dlvA+fcg5ugFMZaN2/RuoaGg=="], + + "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + "one-time": ["one-time@1.0.0", "", { "dependencies": { "fn.name": "1.x.x" } }, "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g=="], + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], "oxc-resolver": ["oxc-resolver@11.8.0", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.8.0", "@oxc-resolver/binding-android-arm64": "11.8.0", "@oxc-resolver/binding-darwin-arm64": "11.8.0", "@oxc-resolver/binding-darwin-x64": "11.8.0", "@oxc-resolver/binding-freebsd-x64": "11.8.0", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.8.0", "@oxc-resolver/binding-linux-arm-musleabihf": "11.8.0", "@oxc-resolver/binding-linux-arm64-gnu": "11.8.0", "@oxc-resolver/binding-linux-arm64-musl": "11.8.0", "@oxc-resolver/binding-linux-ppc64-gnu": "11.8.0", "@oxc-resolver/binding-linux-riscv64-gnu": "11.8.0", "@oxc-resolver/binding-linux-riscv64-musl": "11.8.0", "@oxc-resolver/binding-linux-s390x-gnu": "11.8.0", "@oxc-resolver/binding-linux-x64-gnu": "11.8.0", "@oxc-resolver/binding-linux-x64-musl": "11.8.0", "@oxc-resolver/binding-wasm32-wasi": "11.8.0", "@oxc-resolver/binding-win32-arm64-msvc": "11.8.0", "@oxc-resolver/binding-win32-ia32-msvc": "11.8.0", "@oxc-resolver/binding-win32-x64-msvc": "11.8.0" } }, "sha512-iTBXOucxbG40DGURl0cXChZn1WbvXteW4F/U3SZNbhlixFhd3+ZoHU8cmavOSS+Ob9GUPEUoZhGpj1empxwAiQ=="], @@ -721,18 +1096,32 @@ "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + + "package-manager-detector": ["package-manager-detector@1.3.0", "", {}, "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ=="], + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], "parse-imports-exports": ["parse-imports-exports@0.2.4", "", { "dependencies": { "parse-statements": "1.0.11" } }, "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ=="], "parse-statements": ["parse-statements@1.0.11", "", {}, "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA=="], + "parse5": ["parse5@5.1.1", "", {}, "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug=="], + + "parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@6.0.1", "", { "dependencies": { "parse5": "^6.0.1" } }, "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA=="], + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="], + + "perfect-debounce": ["perfect-debounce@2.0.0", "", {}, "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow=="], + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], @@ -743,6 +1132,8 @@ "pnpm-workspace-yaml": ["pnpm-workspace-yaml@1.1.1", "", { "dependencies": { "yaml": "^2.8.1" } }, "sha512-nGBB7h3Ped3g9dBrR6d3YNwXCKYsEg8K9J3GMmSrwGEXq3RHeGW44/B4MZW51p4FRMnyxJzTY5feSBbUjRhIHQ=="], + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], @@ -757,6 +1148,8 @@ "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + "rc9": ["rc9@2.1.2", "", { "dependencies": { "defu": "^6.1.4", "destr": "^2.0.3" } }, "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg=="], + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], @@ -769,6 +1162,8 @@ "regjsparser": ["regjsparser@0.12.0", "", { "dependencies": { "jsesc": "~3.0.2" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ=="], + "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], @@ -783,12 +1178,16 @@ "rolldown-plugin-dts": ["rolldown-plugin-dts@0.15.10", "", { "dependencies": { "@babel/generator": "^7.28.3", "@babel/parser": "^7.28.3", "@babel/types": "^7.28.2", "ast-kit": "^2.1.2", "birpc": "^2.5.0", "debug": "^4.4.1", "dts-resolver": "^2.1.2", "get-tsconfig": "^4.10.1" }, "peerDependencies": { "@typescript/native-preview": ">=7.0.0-dev.20250601.1", "rolldown": "^1.0.0-beta.9", "typescript": "^5.0.0", "vue-tsc": "~3.0.3" }, "optionalPeers": ["@typescript/native-preview", "typescript", "vue-tsc"] }, "sha512-8cPVAVQUo9tYAoEpc3jFV9RxSil13hrRRg8cHC9gLXxRMNtWPc1LNMSDXzjyD+5Vny49sDZH77JlXp/vlc4I3g=="], + "rollup": ["rollup@4.50.2", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.50.2", "@rollup/rollup-android-arm64": "4.50.2", "@rollup/rollup-darwin-arm64": "4.50.2", "@rollup/rollup-darwin-x64": "4.50.2", "@rollup/rollup-freebsd-arm64": "4.50.2", "@rollup/rollup-freebsd-x64": "4.50.2", "@rollup/rollup-linux-arm-gnueabihf": "4.50.2", "@rollup/rollup-linux-arm-musleabihf": "4.50.2", "@rollup/rollup-linux-arm64-gnu": "4.50.2", "@rollup/rollup-linux-arm64-musl": "4.50.2", "@rollup/rollup-linux-loong64-gnu": "4.50.2", "@rollup/rollup-linux-ppc64-gnu": "4.50.2", "@rollup/rollup-linux-riscv64-gnu": "4.50.2", "@rollup/rollup-linux-riscv64-musl": "4.50.2", "@rollup/rollup-linux-s390x-gnu": "4.50.2", "@rollup/rollup-linux-x64-gnu": "4.50.2", "@rollup/rollup-linux-x64-musl": "4.50.2", "@rollup/rollup-openharmony-arm64": "4.50.2", "@rollup/rollup-win32-arm64-msvc": "4.50.2", "@rollup/rollup-win32-ia32-msvc": "4.50.2", "@rollup/rollup-win32-x64-msvc": "4.50.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w=="], + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], "safe-regex": ["safe-regex@2.1.1", "", { "dependencies": { "regexp-tree": "~0.1.1" } }, "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A=="], + "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], + "scslre": ["scslre@0.3.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.8.0", "refa": "^0.12.0", "regexp-ast-analysis": "^0.7.0" } }, "sha512-3A6sD0WYP7+QrjbfNA2FN3FsOaGGFoekCVgTyypy53gPxhbkCIjtO6YWgdrfM+n/8sI8JeXZOIxsHjMTNxQ4nQ=="], "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], @@ -797,8 +1196,18 @@ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], + + "skin-tone": ["skin-tone@2.0.0", "", { "dependencies": { "unicode-emoji-modifier-base": "^1.0.0" } }, "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA=="], + "smol-toml": ["smol-toml@1.4.2", "", {}, "sha512-rInDH6lCNiEyn3+hH8KVGFdbjc099j47+OSgbMrfDYX1CmXLfdKd7qi6IfcWj2wFxvSVkuI46M+wPGYfEOEj6g=="], + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + "spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], "spdx-expression-parse": ["spdx-expression-parse@4.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ=="], @@ -807,31 +1216,65 @@ "stable-hash-x": ["stable-hash-x@0.2.0", "", {}, "sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ=="], + "stack-trace": ["stack-trace@0.0.10", "", {}, "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg=="], + + "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], + + "std-env": ["std-env@3.9.0", "", {}, "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw=="], + "stream-events": ["stream-events@1.0.5", "", { "dependencies": { "stubs": "^3.0.0" } }, "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg=="], "stream-shift": ["stream-shift@1.0.3", "", {}, "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="], + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "strip-indent": ["strip-indent@4.0.0", "", { "dependencies": { "min-indent": "^1.0.1" } }, "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA=="], "strip-json-comments": ["strip-json-comments@5.0.2", "", {}, "sha512-4X2FR3UwhNUE9G49aIsJW5hRRR3GXGTBTZRMfv568O60ojM8HcWjV/VxAxCDW3SUND33O6ZY66ZuRcdkj73q2g=="], + "strip-literal": ["strip-literal@3.0.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA=="], + "strnum": ["strnum@1.0.5", "", {}, "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA=="], "stubs": ["stubs@3.0.0", "", {}, "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw=="], "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "supports-hyperlinks": ["supports-hyperlinks@3.2.0", "", { "dependencies": { "has-flag": "^4.0.0", "supports-color": "^7.0.0" } }, "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig=="], + "synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="], "tapable": ["tapable@2.2.1", "", {}, "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ=="], "teeny-request": ["teeny-request@9.0.0", "", { "dependencies": { "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "node-fetch": "^2.6.9", "stream-events": "^1.0.5", "uuid": "^9.0.0" } }, "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g=="], + "test-exclude": ["test-exclude@7.0.1", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^10.4.1", "minimatch": "^9.0.4" } }, "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg=="], + + "text-hex": ["text-hex@1.0.0", "", {}, "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg=="], + + "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], + + "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], + + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], + "tinyexec": ["tinyexec@1.0.1", "", {}, "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw=="], - "tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + + "tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="], + + "tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="], + + "tinyspy": ["tinyspy@4.0.3", "", {}, "sha512-t2T/WLB2WRgZ9EpE4jgPJ9w+i66UZfDc8wHh0xrwiRNN+UwH98GIJkTeZqX9rg0i0ptwzqW+uYeIF0T4F8LR7A=="], "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], @@ -839,6 +1282,8 @@ "tree-kill": ["tree-kill@1.2.2", "", { "bin": { "tree-kill": "cli.js" } }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], + "triple-beam": ["triple-beam@1.4.1", "", {}, "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg=="], + "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], "ts-declaration-location": ["ts-declaration-location@1.0.7", "", { "dependencies": { "picomatch": "^4.0.2" }, "peerDependencies": { "typescript": ">=4.0.0" } }, "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA=="], @@ -849,17 +1294,21 @@ "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + "type-fest": ["type-fest@4.2.0", "", {}, "sha512-5zknd7Dss75pMSED270A1RQS3KloqRJA9XbXLe0eCxyw7xXFb3rd+9B0UQ/0E+LQT6lnrLviEolYORlRWamn4w=="], + "typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="], - "typescript-eslint": ["typescript-eslint@8.42.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.42.0", "@typescript-eslint/parser": "8.42.0", "@typescript-eslint/typescript-estree": "8.42.0", "@typescript-eslint/utils": "8.42.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ozR/rQn+aQXQxh1YgbCzQWDFrsi9mcg+1PM3l/z5o1+20P7suOIaNg515bpr/OYt6FObz/NHcBstydDLHWeEKg=="], + "typescript-eslint": ["typescript-eslint@8.44.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.44.0", "@typescript-eslint/parser": "8.44.0", "@typescript-eslint/typescript-estree": "8.44.0", "@typescript-eslint/utils": "8.44.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ib7mCkYuIzYonCq9XWF5XNw+fkj2zg629PSa9KNIQ47RXFF763S5BIX4wqz1+FLPogTZoiw8KmCiRPRa8bL3qw=="], "ufo": ["ufo@1.6.1", "", {}, "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="], "unconfig": ["unconfig@7.3.3", "", { "dependencies": { "@quansync/fs": "^0.1.5", "defu": "^6.1.4", "jiti": "^2.5.1", "quansync": "^0.2.11" } }, "sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA=="], - "undici": ["undici@7.15.0", "", {}, "sha512-7oZJCPvvMvTd0OlqWsIxTuItTpJBpU1tcbVl24FMn3xt3+VSunwUasmfPJRE57oNO1KsZ4PgA1xTdAX4hq8NyQ=="], + "undici": ["undici@7.13.0", "", {}, "sha512-l+zSMssRqrzDcb3fjMkjjLGmuiiK2pMIcV++mJaAc9vhjSGpvM7h43QgP+OAMb1GImHmbPyG2tBXeuyG5iY4gA=="], + + "undici-types": ["undici-types@7.12.0", "", {}, "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ=="], - "undici-types": ["undici-types@7.10.0", "", {}, "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag=="], + "unicode-emoji-modifier-base": ["unicode-emoji-modifier-base@1.0.0", "", {}, "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g=="], "unist-util-is": ["unist-util-is@6.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw=="], @@ -879,6 +1328,14 @@ "uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], + "validate-npm-package-name": ["validate-npm-package-name@5.0.1", "", {}, "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ=="], + + "vite": ["vite@7.1.6", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-SRYIB8t/isTwNn8vMB3MR6E+EQZM/WG1aKmmIUCfDXfVvKfc20ZpamngWHKzAmmu9ppsgxsg4b2I7c90JZudIQ=="], + + "vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="], + + "vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="], + "vue-eslint-parser": ["vue-eslint-parser@10.2.0", "", { "dependencies": { "debug": "^4.4.0", "eslint-scope": "^8.2.0", "eslint-visitor-keys": "^4.2.0", "espree": "^10.3.0", "esquery": "^1.6.0", "semver": "^7.6.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw=="], "walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="], @@ -889,16 +1346,32 @@ "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], + + "winston": ["winston@3.17.0", "", { "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", "async": "^3.2.3", "is-stream": "^2.0.0", "logform": "^2.7.0", "one-time": "^1.0.0", "readable-stream": "^3.4.0", "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", "winston-transport": "^4.9.0" } }, "sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw=="], + + "winston-transport": ["winston-transport@4.9.0", "", { "dependencies": { "logform": "^2.7.0", "readable-stream": "^3.6.2", "triple-beam": "^1.3.0" } }, "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A=="], + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], "xml-name-validator": ["xml-name-validator@4.0.0", "", {}, "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw=="], + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + "yaml": ["yaml@2.8.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw=="], "yaml-eslint-parser": ["yaml-eslint-parser@1.3.0", "", { "dependencies": { "eslint-visitor-keys": "^3.0.0", "yaml": "^2.0.0" } }, "sha512-E/+VitOorXSLiAqtTd7Yqax0/pAS3xaYMP+AUUJGOK1OZG3rhcj9fcJOM5HJ2VrP1FrStVCWr1muTfQCdj4tAA=="], + "yargs": ["yargs@16.2.0", "", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], + + "yargs-parser": ["yargs-parser@20.2.9", "", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -907,6 +1380,12 @@ "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], + "@arethetypeswrong/core/typescript": ["typescript@5.6.1-rc", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ=="], + + "@es-joy/jsdoccomment/@typescript-eslint/types": ["@typescript-eslint/types@8.44.0", "", {}, "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA=="], + + "@es-joy/jsdoccomment/jsdoc-type-pratt-parser": ["jsdoc-type-pratt-parser@5.4.0", "", {}, "sha512-F9GQ+F1ZU6qvSrZV8fNFpjDNf614YzR2eF6S0+XbDjAcUI28FSoXnYZFjQmb1kFx3rrJb5PnxUH3/Yti6fcM+g=="], + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "@eslint/config-array/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], @@ -919,27 +1398,49 @@ "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], + "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], + + "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + "@rolldown/binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.3", "", { "dependencies": { "@emnapi/core": "^1.4.5", "@emnapi/runtime": "^1.4.5", "@tybys/wasm-util": "^0.10.0" } }, "sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q=="], + "@swrlab/utils-legacy/luxon": ["luxon@3.7.1", "", {}, "sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg=="], + "@types/request/@types/node": ["@types/node@22.9.0", "", { "dependencies": { "undici-types": "~6.19.8" } }, "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ=="], "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], - "@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="], + "@typescript-eslint/parser/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.42.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.42.0", "@typescript-eslint/tsconfig-utils": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ=="], + + "@typescript-eslint/project-service/@typescript-eslint/types": ["@typescript-eslint/types@8.44.0", "", {}, "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA=="], + + "@typescript-eslint/project-service/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.42.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.42.0", "@typescript-eslint/tsconfig-utils": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ=="], + + "@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.44.0", "", {}, "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA=="], + + "@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw=="], + + "@typescript-eslint/typescript-estree/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.42.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.42.0", "@typescript-eslint/tsconfig-utils": "8.42.0", "@typescript-eslint/types": "8.42.0", "@typescript-eslint/visitor-keys": "8.42.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ku/uYtT4QXY8sl9EDJETD27o3Ewdi72hcXg1ah/kkUgBvAYHLwj2ofswFFNXS+FL5G+AGkxBtvGt8pFBHKlHsQ=="], + "@unrs/resolver-binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], - "agent-base/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], + "@vitest/coverage-v8/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], - "bun-types/@types/node": ["@types/node@22.9.0", "", { "dependencies": { "undici-types": "~6.19.8" } }, "sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ=="], + "agent-base/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], "clean-regexp/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], - "eslint/@eslint/js": ["@eslint/js@9.35.0", "", {}, "sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw=="], + "cli-table3/@colors/colors": ["@colors/colors@1.5.0", "", {}, "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ=="], - "eslint-import-context/get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], + "color/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], "eslint-plugin-es-x/@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.4.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA=="], @@ -947,8 +1448,12 @@ "eslint-plugin-import-x/minimatch": ["minimatch@10.0.1", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ=="], + "eslint-plugin-jsdoc/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + "eslint-plugin-n/globals": ["globals@15.12.0", "", {}, "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ=="], + "eslint-plugin-pnpm/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], + "eslint-plugin-sonarjs/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "eslint-plugin-sonarjs/typescript": ["typescript@5.6.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw=="], @@ -965,6 +1470,8 @@ "gaxios/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + "glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "http-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], "http-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], @@ -973,12 +1480,16 @@ "is-builtin-module/builtin-modules": ["builtin-modules@5.0.0", "", {}, "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg=="], + "istanbul-lib-source-maps/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + "jsonc-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "jsonc-eslint-parser/espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="], "jsonc-eslint-parser/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "marked-terminal/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], "mdast-util-frontmatter/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], @@ -989,29 +1500,83 @@ "mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + "node-crc/@types/node": ["@types/node@18.19.127", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-gSjxjrnKXML/yo0BO099uPixMqfpJU0TKYjpfLU7TrtA2WWDki412Np/RSTPRil1saKBhvVVKzVx/p/6p94nVA=="], + + "parse5-htmlparser2-tree-adapter/parse5": ["parse5@6.0.1", "", {}, "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="], + + "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], - "rolldown-plugin-dts/get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], + "string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "teeny-request/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], "teeny-request/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="], + "test-exclude/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "tsdown/tinyglobby": ["tinyglobby@0.2.14", "", { "dependencies": { "fdir": "^6.4.4", "picomatch": "^4.0.2" } }, "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ=="], + + "typescript-eslint/@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.44.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.44.0", "@typescript-eslint/type-utils": "8.44.0", "@typescript-eslint/utils": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.44.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-EGDAOGX+uwwekcS0iyxVDmRV9HX6FLSM5kzrAToLTsr9OWCIKG/y3lQheCq18yZ5Xh78rRKJiEpP0ZaCs4ryOQ=="], + + "typescript-eslint/@typescript-eslint/parser": ["@typescript-eslint/parser@8.44.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.44.0", "@typescript-eslint/types": "8.44.0", "@typescript-eslint/typescript-estree": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-VGMpFQGUQWYT9LfnPcX8ouFojyrZ/2w3K5BucvxL/spdNehccKhB4jUyB1yBCXpr2XFm0jkECxgrpXBW2ipoAw=="], + + "typescript-eslint/@typescript-eslint/utils": ["@typescript-eslint/utils@8.44.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.44.0", "@typescript-eslint/types": "8.44.0", "@typescript-eslint/typescript-estree": "8.44.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-nktOlVcg3ALo0mYlV+L7sWUD58KG4CMj1rb2HUVOO4aL3K/6wcD+NERqd0rrA5Vg06b42YhF6cFxeixsp9Riqg=="], + + "vite-node/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "vitest/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "vitest/tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + "vue-eslint-parser/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], "yaml-eslint-parser/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "@rolldown/binding-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], "@types/request/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], - "@typescript-eslint/typescript-estree/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "@typescript-eslint/parser/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.42.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.42.0", "@typescript-eslint/types": "^8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg=="], + + "@typescript-eslint/parser/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.42.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ=="], + + "@typescript-eslint/parser/@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="], + + "@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.42.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.42.0", "@typescript-eslint/types": "^8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg=="], + + "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.42.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ=="], + + "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="], + + "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.42.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.42.0", "@typescript-eslint/types": "^8.42.0", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vfVpLHAhbPjilrabtOSNcUDmBboQNrJUiNAGoImkZKnMjs2TIcWG33s4Ds0wY3/50aZmTMqJa6PiwkwezaAklg=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.42.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-kHeFUOdwAJfUmYKjR3CLgZSglGHjbNTi1H8sTYRYV2xX6eNz4RyJ2LIgsDLKf8Yi0/GL1WZAC/DgZBeBft8QAQ=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + "@unrs/resolver-binding-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ=="], - "bun-types/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="], + "color/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], "eslint-plugin-es-x/@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], @@ -1033,10 +1598,58 @@ "eslint-plugin-vuejs-accessibility/vue-eslint-parser/semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="], + "glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], + "node-crc/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], + "teeny-request/https-proxy-agent/agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], "teeny-request/https-proxy-agent/debug": ["debug@4.3.7", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ=="], + + "test-exclude/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0" } }, "sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA=="], + + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "@typescript-eslint/typescript-estree": "8.44.0", "@typescript-eslint/utils": "8.44.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-9cwsoSxJ8Sak67Be/hD2RNt/fsqmWnNE1iHohG8lxqLSNY8xNfyY7wloo5zpW3Nu9hxVgURevqfcH6vvKCt6yg=="], + + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw=="], + + "typescript-eslint/@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + + "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0" } }, "sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA=="], + + "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.44.0", "", {}, "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA=="], + + "typescript-eslint/@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw=="], + + "typescript-eslint/@typescript-eslint/parser/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "@typescript-eslint/visitor-keys": "8.44.0" } }, "sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA=="], + + "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.44.0", "", {}, "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA=="], + + "@typescript-eslint/parser/@typescript-eslint/typescript-estree/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.44.0", "", {}, "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA=="], + + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.44.0", "", {}, "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA=="], + + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "typescript-eslint/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.44.0", "", {}, "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA=="], + + "typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.44.0", "", { "dependencies": { "@typescript-eslint/types": "8.44.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw=="], } } diff --git a/eslint.config.js b/eslint.config.js index bf95ae1..7d72f8d 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,6 +1,31 @@ -import { audiolab } from '@swrlab/style-guide/eslint.js' +import { audiolab } from '@swrlab/style-guide/eslint' export default audiolab({ + typescript: true, prettier: true, comments: true, + jsonc: true, + markdown: true, + yaml: true, }) + .append({ + name: 'markdown/disabled-rules', + // files: ['**/*.md'], + rules: { + 'sonarjs/unused-import': 'off', + }, + }) + .append({ + name: 'jsonc/allow-comments-in-other-tsconfigs', + files: ['tsconfig.base.json'], + rules: { + 'jsonc/no-comments': 'off', + }, + }) + .append({ + name: 'disabled-rules', + rules: { + // TODO: figure out how to tell sonarjs eslint that we use asset instead of expect? + 'sonarjs/assertions-in-tests': 'off', + }, + }) diff --git a/knip.json b/knip.json new file mode 100644 index 0000000..541195f --- /dev/null +++ b/knip.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://unpkg.com/knip@5/schema.json", + "workspaces": { + "packages/*": { + "entry": ["index.{js,ts}", "src/index.{js,ts}"], + "project": "**/*.{js,mjs,ts}" + } + } +} diff --git a/package.json b/package.json index 10202d6..5d8c18c 100644 --- a/package.json +++ b/package.json @@ -1,135 +1,48 @@ { - "name": "@swrlab/utils", + "name": "node-utils-workspace", "version": "3.0.0-beta.3", - "description": "Wrapping common SWR Audio Lab utils", + "private": true, + "packageManager": "bun@1.2.22", + "description": "SWR Audio Lab utilities collection for Node.js.", "type": "module", - "license": "MIT", + "license": "ISC", "repository": { "type": "git", "url": "git+https://github.com/swrlab/node-utils.git" }, "author": "SWR Audio Lab ", - "files": [ - "bin", - "dist" + "workspaces": [ + "packages/*" ], - "main": "./dist/index.js", - "module": "./dist/index.js", - "types": "./dist/index.d.ts", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "./ard": { - "types": "./dist/ard.d.ts", - "default": "./dist/ard.js" - }, - "./array": { - "types": "./dist/array.d.ts", - "default": "./dist/array.js" - }, - "./date": { - "types": "./dist/date.d.ts", - "default": "./dist/date.js" - }, - "./env": { - "types": "./dist/env.d.ts", - "default": "./dist/env.js" - }, - "./helper": { - "types": "./dist/helper.d.ts", - "default": "./dist/helper.js" - }, - "./number": { - "types": "./dist/number.d.ts", - "default": "./dist/number.js" - }, - "./object": { - "types": "./dist/object.d.ts", - "default": "./dist/object.js" - }, - "./predicate": { - "types": "./dist/predicate.d.ts", - "default": "./dist/predicate.js" - }, - "./storage": { - "types": "./dist/storage.d.ts", - "default": "./dist/storage.js" - }, - "./string": { - "types": "./dist/string.d.ts", - "default": "./dist/string.js" - }, - "./packages/ard": { - "types": "./dist/packages/ard.d.ts", - "default": "./dist/packages/ard.js" - }, - "./packages/date": { - "types": "./dist/packages/date.d.ts", - "default": "./dist/packages/date.js" - }, - "./packages/helpers": { - "types": "./dist/packages/helpers.d.ts", - "default": "./dist/packages/helpers.js" - }, - "./packages/numbers": { - "types": "./dist/packages/numbers.d.ts", - "default": "./dist/packages/numbers.js" - }, - "./packages/storage-wrapper": { - "types": "./dist/packages/storage-wrapper.d.ts", - "default": "./dist/packages/storage-wrapper.js" - }, - "./packages/strings": { - "types": "./dist/packages/strings.d.ts", - "default": "./dist/packages/strings.js" - }, - "./packages/undici": { - "types": "./dist/packages/undici.d.ts", - "default": "./dist/packages/undici.js" - } - }, - "bin": { - "ard-coreId": "bin/ard-coreId.mjs" - }, - "publishConfig": { - "access": "public", - "provenance": true - }, "scripts": { - "ard:coreId": "bun ./bin/ard-coreId.mjs", - "attw": "bunx @arethetypeswrong/cli --pack . --profile esm-only", - "build": "tsdown", + "ard:coreId": "bun ./packages/utils/src/ard/coreId.ts", + "attw": "attw --pack . --profile esm-only", + "biome": "biome check", + "build": "bun run --filter './packages/{utils,storage,legacy}' build", + "check": "bun run lint && bun run format:check && bun run typecheck", "format": "prettier --write .", + "format:check": "prettier --check .", + "format:check:beta": "prettier --experimental-cli --config-path ./prettier.config.js --check .", "knip": "knip", "lint": "eslint", "lint:fix": "eslint --fix", - "release": "bunx bumpp", - "test": "bun run typecheck && bun run test:bun && bun run test:legacy", - "test:bun": "bun test ./test/**test*.ts", - "test:dist": "bun test ./test/dist-legacy/*test*.mjs", - "test:dist:node": "node --test ./test/dist-legacy/*.mjs", - "test:legacy": "bun test ./test/legacy/*.test.mjs", - "test:legacy:node": "node --test ./test/legacy/*.mjs", - "test:node": "node --test ./test/**.test.ts", + "release": "bumpp", + "test": "bun run --filter './packages/{utils,storage,legacy}' test", + "test:bun": "bun run --filter './packages/utils' test:bun", + "test:node": "bun run --filter '*' test:node", "typecheck": "tsc --noEmit" }, - "dependencies": { - "luxon": "3.7.2", - "undici": "7.15.0" - }, "devDependencies": { - "@google-cloud/storage": "^7.17.0", - "@swrlab/style-guide": "^2.0.7", - "@types/bun": "^1.2.21", - "@types/luxon": "^3.7.1", - "@types/node": "^24.3.1", + "@arethetypeswrong/cli": "^0.18.2", + "@biomejs/biome": "2.2.4", + "@swrlab/style-guide": "^2.0.8", + "@types/node": "^24.5.2", + "bumpp": "^10.2.3", "eslint": "^9.35.0", "knip": "^5.63.1", "prettier": "^3.6.2", - "tsdown": "^0.14.2", - "typescript": "^5.9.2" + "typescript": "^5.9.2", + "vitest": "^3.2.4" }, "devEngines": { "runtime": { @@ -139,11 +52,10 @@ }, "packageManager": { "name": "bun", - "onFail": "ignore" + "onFail": "warn" } }, "engines": { - "node": "^22.18.0 || ^24.6.0" - }, - "prettier": "@swrlab/style-guide/prettier.js" + "node": "^22.18.0 || >= 24.6.0" + } } diff --git a/packages/date/package.json b/packages/date/package.json new file mode 100644 index 0000000..a4cec41 --- /dev/null +++ b/packages/date/package.json @@ -0,0 +1,67 @@ +{ + "name": "@swrlab/date", + "version": "3.0.0-beta.3", + "packageManager": "bun@1.2.22", + "description": "SWR Audio Lab date utilities for Node.js.", + "type": "module", + "license": "ISC", + "repository": { + "type": "git", + "url": "git+https://github.com/swrlab/node-utils.git", + "directory": "packages/date" + }, + "author": "SWR Audio Lab ", + "files": [ + "dist" + ], + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./ard": { + "types": "./dist/ard.d.ts", + "default": "./dist/ard.js" + } + }, + "publishConfig": { + "access": "public", + "provenance": true + }, + "scripts": { + "attw": "bunx @arethetypeswrong/cli --pack . --profile esm-only", + "build": "tsdown", + "release": "bunx bumpp", + "test": "bun run typecheck && bun run test:bun && bun run test:compare", + "test:bun": "bun test ./test/index.test.ts", + "test:compare": "bun test ./test/compare.test.ts", + "test:compare:node": "node --test ./test/compare.test.ts", + "test:node": "node --test ./test/*.test.ts", + "typecheck": "tsc --noEmit" + }, + "dependencies": {}, + "devDependencies": { + "@types/luxon": "^3.7.1", + "@types/node": "^24.3.1", + "luxon": "3.7.2", + "tsdown": "^0.14.2", + "typescript": "^5.9.2" + }, + "devEngines": { + "runtime": { + "name": "node", + "version": "^22.18.0 || >= 24.6", + "onFail": "warn" + }, + "packageManager": { + "name": "bun", + "onFail": "warn" + } + }, + "engines": { + "node": "^22.18.0 || >= 24.6.0" + } +} diff --git a/packages/date/src/index.ts b/packages/date/src/index.ts new file mode 100644 index 0000000..a9b0be1 --- /dev/null +++ b/packages/date/src/index.ts @@ -0,0 +1,281 @@ +import { DateTime } from 'luxon' + +// docs for luxon shortcuts: https://moment.github.io/luxon/#/formatting?id=table-of-tokens +const DEFAULT_LOCALE = 'en' +const LOCAL_TIMEZONE = 'Europe/Amsterdam' +const DATE_HOUR_MINUTES_FORMAT = 'ccc, d. LLLL yyyy - h:mma' +const DATE_HOUR_MINUTES_FORMAT_24H = 'ccc, d. LLLL yyyy - HH:mm' + +/** + * Export DateTime from Luxon + * @returns {DateTime} DateTime + * + * @example + * ```ts + * import { DateTime } from '@frytg/dates' + * + * DateTime.fromMillis(1719859200000) + * ``` + */ +export { DateTime } + +/** + * Convert date to local time + * @param {DateTime} date - date object to convert + * @param {string} [timezone] - timezone (default: Europe/Amsterdam) + * @returns {DateTime} date in local time + * + * @example + * ```ts + * import { toLocal } from '@frytg/dates' + * + * toLocal(getNow()) + * ``` + */ +export const toLocal = (date: DateTime, timezone: string = LOCAL_TIMEZONE): DateTime => date.setZone(timezone) + +/** + * Converts ms timestamp to s + * @param {number} ms - ms timestamp + * @returns {number} unix timestamp + * + * @example + * ```ts + * import { msToUnix } from '@frytg/dates' + * + * msToUnix(getMs()) + * ``` + */ +export const msToUnix = (ms: number): number => Number.parseInt(`${ms / 1000}`, 10) + +/** + * Provide util to get current date object + * @returns {DateTime} current date object + * + * @example + * ```ts + * import { getNow } from '@frytg/dates' + * + * getNow() + * ``` + */ +export const getNow = (): DateTime => DateTime.now() + +/** + * Internal util to get DateTime object + * @param {DateTime} [date] - date object + * @returns {DateTime} DateTime object + */ +const getDateTime = (date?: DateTime): DateTime => (date instanceof DateTime ? date : getNow()) + +/** + * Get unix timestamp + * @param {DateTime} [date] - date object + * @returns {number} unix timestamp + * + * @example + * ```ts + * import { getUnix } from '@frytg/dates' + * + * getUnix() + * getUnix(getNow()) + * ``` + */ +export const getUnix = (date?: DateTime): number => msToUnix(getDateTime(date).valueOf()) + +/** + * Get ms (milliseconds) timestamp + * @param {DateTime} [date] - date object + * @returns {number} ms timestamp + * + * @example + * ```ts + * import { getMs } from '@frytg/dates' + * + * getMs() + * getMs(getNow()) + * ``` + */ +export const getMs = (date?: DateTime): number => getDateTime(date).valueOf() + +/** + * Get ISO string in UTC timezone + * @param {DateTime} [date] - date object + * @returns {string} ISO string + * + * @example + * ```ts + * import { getISO } from '@frytg/dates' + * + * getISO() + * getISO(getNow()) + * ``` + */ +export const getISO = (date?: DateTime): string | null => getDateTime(date).toUTC().toISO() + +/** + * Get ISO string (alias for {@link getISO}) + * @param {DateTime} [date] - date object + * @returns {string} ISO string + */ +export const getIso: typeof getISO = getISO + +/** + * Calculate offset from previous ms timestamp + * @param {number} ms - ms timestamp + * @returns {number} offset + * + * @example + * ```ts + * import { getMsOffset } from '@frytg/dates' + * + * getMsOffset(getMs()) + * ``` + */ +export const getMsOffset = (ms: number): number => getMs() - ms + +/** + * Get relative time + * @param {DateTime} date - date object + * @param {string} [locale] - locale (default: en) + * @param {string} [timezone] - timezone (default: Europe/Amsterdam) + * @returns {string} relative time + * + * @example + * ```ts + * import { getRelative } from '@frytg/dates' + * + * getRelative(getNow()) + * getRelative(getNow(), 'nl-NL') + * getRelative(getNow(), 'nl-NL', 'Europe/Amsterdam') + * ``` + */ +export const getRelative = ( + date: DateTime, + locale: string = DEFAULT_LOCALE, + timezone: string = LOCAL_TIMEZONE +): string | null => date.setZone(timezone).toRelative({ locale }) + +/** + * Get year-month-day (YYYYMMDD or YYYY-MM-DD) + * @param {DateTime} [date] - date object + * @param {boolean} [withDashes] - with dashes (default: false) + * @returns {string | number} year-month-day + * + * @example + * ```ts + * import { getYearMonthDay } from '@frytg/dates' + * + * getYearMonthDay(getNow()) // YYYYMMDD + * getYearMonthDay(getNow(), true) // YYYY-MM-DD + * ``` + */ +export const getYearMonthDay = (date?: DateTime, withDashes: boolean = false): string | number => + withDashes ? getDateTime(date).toFormat('yyyy-LL-dd') : Number.parseInt(getDateTime(date).toFormat('yyyyLLdd'), 10) + +/** + * Parse ISO string + * @param {string} iso - ISO string + * @returns {DateTime} date object + * + * @example + * ```ts + * import { parseISO } from '@frytg/dates' + * + * parseISO(getISO()) + * parseISO('2024-11-23T10:00:00.000Z') + * ``` + */ +export const parseISO = (iso: string): DateTime => DateTime.fromISO(iso) + +/** + * Parse ISO string (alias for {@link parseISO}) + * @param {string} iso - ISO string + * @returns {DateTime} date object + */ +export const parseIso: typeof parseISO = parseISO + +/** + * Format the date in a human readable way (like 'Mon, 23. Nov 2024 - 10:00AM') + * @param {DateTime} date - date object + * @param {string} [locale] - locale (default: en) + * @param {string} [timezone] - timezone (default: Europe/Amsterdam) + * @param {boolean} [prefer24h] - prefer 24h format (default: false) + * @returns {string} readable date + * + * @example + * ```ts + * import { getDateHourMinutes } from '@frytg/dates' + * + * getDateHourMinutes(getNow()) + * getDateHourMinutes(getNow(), 'nl') + * getDateHourMinutes(getNow(), 'nl', 'Europe/Amsterdam') + * getDateHourMinutes(getNow(), 'nl', 'Europe/Amsterdam', true) + * ``` + */ +export const getDateHourMinutes = ( + date: DateTime, + locale: string = DEFAULT_LOCALE, + timezone: string = LOCAL_TIMEZONE, + prefer24h: boolean = false +): string => + date + .setZone(timezone) + .setLocale(locale) + .toFormat(prefer24h ? DATE_HOUR_MINUTES_FORMAT_24H : DATE_HOUR_MINUTES_FORMAT) + +/** + * Get full relative time (combines {@link getDateHourMinutes} and {@link getRelative}) + * @param {DateTime} date - date object + * @param {string} [locale] - locale (default: en) + * @param {string} [timezone] - timezone (default: Europe/Amsterdam) + * @param {boolean} [prefer24h] - prefer 24h format (default: false) + * @returns {string} full relative time + * + * @example + * ```ts + * import { getFullRelativeTime } from '@frytg/dates' + * + * getFullRelativeTime(getNow()) + * getFullRelativeTime(getNow(), 'nl') + * getFullRelativeTime(getNow(), 'nl', 'Europe/Amsterdam') + * getFullRelativeTime(getNow(), 'nl', 'Europe/Amsterdam', true) + * ``` + */ +export const getFullRelativeTime = ( + date: DateTime, + locale: string = DEFAULT_LOCALE, + timezone: string = LOCAL_TIMEZONE, + prefer24h: boolean = false +): string => `${getDateHourMinutes(date, locale, timezone, prefer24h)} (${getRelative(date, locale, timezone)})` + +/** + * Format a duration in milliseconds to a human readable narrow string. + * + * @param {number} duration - the duration in milliseconds + * @returns {string} the formatted duration (e.g. `1m 39s`) + * + * @example + * ```ts + * import { formatDuration } from '@frytg/dates' + * + * formatDuration(1000) // 1s + * + * const startTs = getMs() + * // do something... + * formatDuration(getMsOffset(startTs)) // time taken + * ``` + */ +export const formatDuration = (duration: number): string => { + const millis = Math.abs(duration) + return [ + { unit: 'd', value: Math.trunc(millis / 86400000) }, + { unit: 'h', value: Math.trunc(millis / 3600000) % 24 }, + { unit: 'm', value: Math.trunc(millis / 60000) % 60 }, + { unit: 's', value: Math.trunc(millis / 1000) % 60 }, + { unit: 'ms', value: Math.trunc(millis) % 1000 }, + ] + .filter((x) => x.value) + .map((x) => `${x.value}${x.unit}`) + .join(' ') +} diff --git a/packages/date/test/compare.test.ts b/packages/date/test/compare.test.ts new file mode 100644 index 0000000..6bebfd1 --- /dev/null +++ b/packages/date/test/compare.test.ts @@ -0,0 +1,67 @@ +import assert from 'node:assert' +import { describe, it } from 'node:test' +import * as date from '../../legacy/src/date.ts' + +const testDate = '2038-01-19T03:14:08.000' +const relativeTime = 2147483647000 - Date.now() +const relativeYears = Math.trunc(relativeTime / (1000 * 60 * 60 * 24 * 365)) + +// Test DateTime Package +describe('Test DateTime Package', () => { + describe('Test getDateHourMinutes', () => { + const testResult = 'Di, 19. Januar 2038 - 03:14 Uhr' + it(`getDateHourMinutes('${testDate}') = '${testResult}'`, () => { + assert.equal(date.getDateHourMinutes(testDate), testResult) + }) + }) + + describe('Test getDayMonthYear', () => { + const testResult = 'Di, 19. Januar 2038' + it(`getDayMonthYear('${testDate}') = '${testResult}'`, () => { + assert.equal(date.getDayMonthYear(testDate), testResult) + }) + }) + + describe('Test getFullRelativeTime', () => { + const testResult = `Di, 19. Januar 2038 - 03:14 Uhr (in ${relativeYears} Jahren)` + it(`getFullRelativeTime('${testDate}') = '${testResult}'`, () => { + assert.equal(date.getFullRelativeTime(testDate), testResult) + }) + }) + + describe('Test getHourMinutes', () => { + const testResult = '03:14' + it(`getHourMinutes('${testDate}') = '${testResult}'`, () => { + assert.equal(date.getHourMinutes(testDate), testResult) + }) + }) + + describe('Test getIsoRelativeTime', () => { + const testResult = `${testDate} (in ${relativeYears} Jahren)` + it(`getIsoRelativeTime('${testDate}') = '${testResult}'`, () => { + assert.equal(date.getIsoRelativeTime(testDate), testResult) + }) + }) + + describe('Test getRelativeTime', () => { + const testResult = `in ${relativeYears} Jahren` + it(`getRelativeTime('${testDate}') = '${testResult}'`, () => { + assert.equal(date.getRelativeTime(testDate), testResult) + }) + }) + + describe('Test getYearMonthDay', () => { + const testResult = '20380119' + it(`getYearMonthDay('${testDate}') = '${testResult}'`, () => { + assert.equal(date.getYearMonthDay(testDate), testResult) + }) + }) + + describe('Test revYearMonthDay', () => { + const test = '20380119' + const testResult = '19012038' + it(`revYearMonthDay('${test}') = '${testResult}'`, () => { + assert.equal(date.revYearMonthDay(test), testResult) + }) + }) +}) diff --git a/packages/date/test/index.test.ts b/packages/date/test/index.test.ts new file mode 100644 index 0000000..ef6f3e1 --- /dev/null +++ b/packages/date/test/index.test.ts @@ -0,0 +1,181 @@ +import assert from 'node:assert/strict' +import { it, suite, test } from 'node:test' +import { + DateTime, + getDateHourMinutes, + getFullRelativeTime, + getISO, + getIso, + getMs, + getMsOffset, + getNow, + getRelative, + getUnix, + getYearMonthDay, + msToUnix, + parseISO, + parseIso, + toLocal, +} from './../src/index.ts' + +const assertEquals: typeof assert.equal = assert.equal + +test('toLocal() converts date to Amsterdam timezone', () => { + const utcDate = DateTime.fromISO('2024-03-15T12:00:00Z') + const localDate = toLocal(utcDate) + assertEquals(localDate.zoneName, 'Europe/Amsterdam') +}) + +test('msToUnix() converts milliseconds to unix timestamp', () => { + const ms = 1647345600000 + assertEquals(msToUnix(ms), 1647345600) +}) + +test('getNow() returns current DateTime', () => { + const now = getNow() + assert(now instanceof DateTime) + assert(Math.abs(now.toMillis() - Date.now()) < 1000) // Within 1 second +}) + +test('getUnix() returns unix timestamp', () => { + const now = DateTime.fromMillis(1647345600000) // March 15, 2024 12:00:00 UTC + assertEquals(getUnix(now), 1647345600) +}) + +test('getMs() returns millisecond timestamp', () => { + const now = DateTime.fromMillis(1647345600000) // March 15, 2024 12:00:00 UTC + assertEquals(getMs(now), 1647345600000) +}) + +test('getISO() returns ISO string in UTC', () => { + const date = DateTime.fromISO('2024-03-15T12:00:00+01:00') + assertEquals(getISO(date), '2024-03-15T11:00:00.000Z') +}) + +test('getIso() is an alias for getISO()', () => { + const date = DateTime.fromISO('2024-03-15T12:00:00+01:00') + assertEquals(getIso(date), getISO(date)) +}) + +test('getMsOffset() calculates offset from previous timestamp', () => { + const now = getMs() + const earlier = now - 1000 // 1 second ago + assert(getMsOffset(earlier) >= 1000) +}) + +test('getRelative() returns relative time string', () => { + const now = getNow() + const yesterday = now.minus({ days: 1 }) + assertEquals(getRelative(yesterday), '1 day ago') +}) + +test('getYearMonthDay() formats date correctly', () => { + const date = DateTime.fromISO('2024-03-15T12:00:00Z') + assertEquals(getYearMonthDay(date), 20240315) + assertEquals(getYearMonthDay(date, true), '2024-03-15') +}) + +test('parseISO() parses ISO string correctly', () => { + const isoString = '2024-03-15T12:00:00.000Z' + const parsed = parseISO(isoString) + assert(parsed instanceof DateTime) + assertEquals(parsed.toUTC().toISO(), isoString) +}) + +test('parseIso() is an alias for parseISO()', () => { + const isoString = '2024-03-15T12:00:00.000Z' + assertEquals(parseIso(isoString).toISO(), parseISO(isoString).toISO()) +}) + +suite('getDateHourMinutes()', () => { + it('should format date in human readable way', () => { + const input = '2024-03-15T12:00:00Z' + const date = DateTime.fromISO(input) + const formatted = getDateHourMinutes(date) + console.info(input, '>>>', formatted) + assert(formatted.includes('Mar')) + assert(formatted.includes('2024')) + }) + + it('should format date in human readable way (24h)', () => { + const input = '2024-03-15T14:00:00Z' + const date = DateTime.fromISO(input) + const formatted = getDateHourMinutes(date, 'en', 'UTC', true) + console.info(input, '>>>', formatted) + assert(formatted.includes('Mar')) + assert(formatted.includes('2024')) + assert(formatted.includes('14:00')) + }) + + it('should format date in human readable way (timezones)', () => { + const input = '2024-03-15T14:00:00Z' + const date = DateTime.fromISO(input) + const formatted = getDateHourMinutes(date, 'en', 'UTC+01:00', true) + console.info(input, '>>>', formatted) + assert(formatted.includes('15:00')) + }) +}) + +suite('getFullRelativeTime()', () => { + it('should combine date and relative time', () => { + const input = '2024-03-15T12:00:00Z' + const date = DateTime.fromISO(input) + const fullRelative = getFullRelativeTime(date) + console.info(input, '>>>', fullRelative) + assert(fullRelative.includes('Mar')) + assert(fullRelative.includes('2024')) + assert(fullRelative.includes('ago')) + }) + + it('should use locale (NL)', () => { + const input = '2024-03-01T12:00:00Z' + const date = DateTime.fromISO(input) + const fullRelative = getFullRelativeTime(date, 'nl') + console.info(input, '>>>', fullRelative) + assert(fullRelative.includes('maart')) + assert(fullRelative.includes('2024')) + assert(fullRelative.includes('geleden')) + }) + + it('should use locale (FR)', () => { + const input = '2024-03-01T12:00:00Z' + const date = DateTime.fromISO(input) + const fullRelative = getFullRelativeTime(date, 'fr') + console.info(input, '>>>', fullRelative) + assert(fullRelative.includes('mars')) + assert(fullRelative.includes('2024')) + assert(fullRelative.includes('il y a')) + }) + + it('should use locale (DE)', () => { + const input = '2024-03-01T12:00:00Z' + const date = DateTime.fromISO(input) + const fullRelative = getFullRelativeTime(date, 'de') + console.info(input, '>>>', fullRelative) + assert(fullRelative.includes('März')) + assert(fullRelative.includes('2024')) + assert(fullRelative.includes('vor')) + }) + + it('should use timezone (UTC+01:00)', () => { + const input = '2024-03-01T12:00:00Z' + const date = DateTime.fromISO(input) + const fullRelative = getFullRelativeTime(date, 'en', 'UTC+01:00') + console.info(input, '>>>', fullRelative) + assert(fullRelative.includes('Mar')) + assert(fullRelative.includes('2024')) + assert(fullRelative.includes(' 1:00')) + assert(fullRelative.includes('ago')) + }) + + it('should use 24h format (DE, UTC+01:00)', () => { + const input = '2024-03-01T12:00:00Z' + const date = DateTime.fromISO(input) + const fullRelative = getFullRelativeTime(date, 'de', 'UTC+01:00', true) + console.info(input, '>>>', fullRelative) + assert(fullRelative.includes('März')) + assert(fullRelative.includes('2024')) + assert(fullRelative.includes('13:00')) + assert(fullRelative.includes('vor')) + }) +}) diff --git a/packages/date/tsconfig.json b/packages/date/tsconfig.json new file mode 100644 index 0000000..d805bd5 --- /dev/null +++ b/packages/date/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src", + "noEmit": true, + "outDir": "./dist" + }, + "include": ["src/**/*"], + "exclude": ["**/dist/**"] +} diff --git a/packages/legacy/README.md b/packages/legacy/README.md new file mode 100644 index 0000000..ebdb7a7 --- /dev/null +++ b/packages/legacy/README.md @@ -0,0 +1,20 @@ +# Deprecated: node-utils + +> Previous generation of Node.js utilities and wrappers. + +> [!IMPORTANT] +> Please use the newer version `@latest` if possible. + +## Development + +### NPM Publish + +The previous or _legacy_ version remains at Version 3 (`v3`). + +The newer versions are `v4` and higher. + +Publishing this with the npm dist-tag `legacy` (the default npm dist-tag is `latest`). + +```sh +npm publish --tag legacy --provenance false +``` diff --git a/packages/legacy/package.json b/packages/legacy/package.json new file mode 100644 index 0000000..cda2f0d --- /dev/null +++ b/packages/legacy/package.json @@ -0,0 +1,69 @@ +{ + "name": "@swrlab/utils-legacy", + "version": "3.0.0-beta.3", + "packageManager": "bun@1.2.22", + "description": "Previous generation of SWR Audio Lab utilities for Node.js.", + "type": "module", + "license": "ISC", + "repository": { + "type": "git", + "url": "git+https://github.com/swrlab/node-utils.git", + "directory": "packages/legacy" + }, + "author": "SWR Audio Lab ", + "files": [ + "dist" + ], + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./packages/*": { + "types": "./dist/packages/*", + "default": "./dist/packages/*" + } + }, + "publishConfig": { + "access": "public", + "provenance": true + }, + "scripts": { + "build": "tsdown", + "test": "bun run test:bun", + "test:bun": "bun test ./test/*test.ts", + "test:dist": "bun test ./test/dist-legacy/*test.mjs", + "test:dist:node": "node --test ./test/dist-legacy/*.mjs", + "test:node": "node --test ./test/*.test.ts" + }, + "dependencies": { + "@google-cloud/storage": "^7.16.0", + "@swrlab/storage": "workspace:*", + "@swrlab/utils": "workspace:*", + "luxon": "3.7.1", + "node-crc": "https://github.com/swrlab/node-crc#v2.1.0", + "undici": "7.13.0" + }, + "devDependencies": { + "@types/node": "^24.3.1", + "tsdown": "^0.14.2", + "typescript": "^5.9.2" + }, + "devEngines": { + "runtime": { + "name": "node", + "version": "^22.18.0 || >= 24.6", + "onFail": "warn" + }, + "packageManager": { + "name": "bun", + "onFail": "warn" + } + }, + "engines": { + "node": "^22.18.0 || >= 24.6.0" + } +} diff --git a/packages/legacy/src/ard.ts b/packages/legacy/src/ard.ts new file mode 100644 index 0000000..7fc5ab8 --- /dev/null +++ b/packages/legacy/src/ard.ts @@ -0,0 +1 @@ +export { createHashedId } from '@swrlab/utils/ard' diff --git a/packages/legacy/src/date.ts b/packages/legacy/src/date.ts new file mode 100644 index 0000000..d957380 --- /dev/null +++ b/packages/legacy/src/date.ts @@ -0,0 +1,24 @@ +import { getDateHourMinutes as getDateHourMinutesNew } from './date/getDateHourMinutes.ts' +import { getDayMonthYear as getDayMonthYearNew } from './date/getDayMonthYear.ts' +import { getFullRelativeTimeLegacy } from './date/getFullRelativeTime.ts' +import { getHourMinutes } from './date/getHourMinutes.ts' +import { getIsoRelativeTime } from './date/getIsoRelativeTime.ts' +import { getRelativeTime } from './date/getRelativeTime.ts' +import { getYearMonthDay } from './date/getYearMonthDay.ts' +import { toDayMonthYear as revYearMonthDay } from './date/toDayMonthYear.ts' +import { formatDateTimeString, type ISODateString, shortenWeekday } from './date/utils.ts' + +const getDateHourMinutes = (date: ISODateString): string => formatDateTimeString(getDateHourMinutesNew(date)) +const getDayMonthYear = (date: ISODateString): string => shortenWeekday(getDayMonthYearNew(date)) +const getFullRelativeTime = (date: ISODateString): string => getFullRelativeTimeLegacy(date) + +export { + getDateHourMinutes, + getDayMonthYear, + getFullRelativeTime, + getHourMinutes, + getIsoRelativeTime, + getRelativeTime, + getYearMonthDay, + revYearMonthDay, +} diff --git a/src/date/README.md b/packages/legacy/src/date/README.md similarity index 100% rename from src/date/README.md rename to packages/legacy/src/date/README.md diff --git a/src/date/getDateHourMinutes.ts b/packages/legacy/src/date/getDateHourMinutes.ts similarity index 100% rename from src/date/getDateHourMinutes.ts rename to packages/legacy/src/date/getDateHourMinutes.ts diff --git a/src/date/getDayMonthYear.ts b/packages/legacy/src/date/getDayMonthYear.ts similarity index 100% rename from src/date/getDayMonthYear.ts rename to packages/legacy/src/date/getDayMonthYear.ts diff --git a/src/date/getFullRelativeTime.ts b/packages/legacy/src/date/getFullRelativeTime.ts similarity index 100% rename from src/date/getFullRelativeTime.ts rename to packages/legacy/src/date/getFullRelativeTime.ts diff --git a/src/date/getHourMinutes.ts b/packages/legacy/src/date/getHourMinutes.ts similarity index 100% rename from src/date/getHourMinutes.ts rename to packages/legacy/src/date/getHourMinutes.ts diff --git a/src/date/getIsoRelativeTime.ts b/packages/legacy/src/date/getIsoRelativeTime.ts similarity index 100% rename from src/date/getIsoRelativeTime.ts rename to packages/legacy/src/date/getIsoRelativeTime.ts diff --git a/src/date/getRelativeTime.ts b/packages/legacy/src/date/getRelativeTime.ts similarity index 100% rename from src/date/getRelativeTime.ts rename to packages/legacy/src/date/getRelativeTime.ts diff --git a/src/date/getYearMonthDay.ts b/packages/legacy/src/date/getYearMonthDay.ts similarity index 100% rename from src/date/getYearMonthDay.ts rename to packages/legacy/src/date/getYearMonthDay.ts diff --git a/src/date/index.ts b/packages/legacy/src/date/index.ts similarity index 62% rename from src/date/index.ts rename to packages/legacy/src/date/index.ts index 2ee334f..4653715 100644 --- a/src/date/index.ts +++ b/packages/legacy/src/date/index.ts @@ -1,17 +1,13 @@ /** * @fileoverview Date formatting utilities. - * @category date * @module date */ -import { getDateHourMinutes } from './getDateHourMinutes.ts' -import { getDayMonthYear } from './getDayMonthYear.ts' -export { getDateHourMinutesLegacy } from './getDateHourMinutes.ts' +export { getDateHourMinutes, getDateHourMinutesLegacy } from './getDateHourMinutes.ts' +export { getDayMonthYear } from './getDayMonthYear.ts' export { getFullRelativeTime, getFullRelativeTimeLegacy } from './getFullRelativeTime.ts' export { getHourMinutes } from './getHourMinutes.ts' export { getIsoRelativeTime } from './getIsoRelativeTime.ts' export { getRelativeTime } from './getRelativeTime.ts' export { getYearMonthDay } from './getYearMonthDay.ts' -export { getDateHourMinutes } -export { getDayMonthYear } export { toDayMonthYear } from './toDayMonthYear.ts' diff --git a/src/date/toDayMonthYear.ts b/packages/legacy/src/date/toDayMonthYear.ts similarity index 100% rename from src/date/toDayMonthYear.ts rename to packages/legacy/src/date/toDayMonthYear.ts diff --git a/src/date/utils.ts b/packages/legacy/src/date/utils.ts similarity index 100% rename from src/date/utils.ts rename to packages/legacy/src/date/utils.ts diff --git a/packages/legacy/src/helpers.ts b/packages/legacy/src/helpers.ts new file mode 100644 index 0000000..5e166c3 --- /dev/null +++ b/packages/legacy/src/helpers.ts @@ -0,0 +1,3 @@ +export { arrayToObjectCount } from '@swrlab/utils/array' +export { sleep } from '@swrlab/utils/helper' +export { getJsonKeys } from '@swrlab/utils/object' diff --git a/packages/legacy/src/index.ts b/packages/legacy/src/index.ts new file mode 100644 index 0000000..f193118 --- /dev/null +++ b/packages/legacy/src/index.ts @@ -0,0 +1,19 @@ +import * as ard from './ard.ts' +import * as date from './date.ts' +import * as helpers from './helpers.ts' +import * as numbers from './numbers.ts' +import * as storage from './storage-wrapper.ts' +import * as strings from './strings.ts' +import * as undici from './undici.ts' + +const api: Record = { + ard, + date, + helpers, + numbers, + storage, + strings, + undici, +} + +export default api diff --git a/packages/legacy/src/numbers.ts b/packages/legacy/src/numbers.ts new file mode 100644 index 0000000..98f2e4f --- /dev/null +++ b/packages/legacy/src/numbers.ts @@ -0,0 +1,13 @@ +export { + addLeadingZero, + addTrailingZeros, + getAverage, + getDiff, + getRandomInRangLegacy as getRandomInRange, + getRandomInRange as getRandomInRangeNew, + getSum, + isEven, + normalize, + roundTo, + toReadable, +} from '@swrlab/utils/number' diff --git a/src/legacy/storage-wrapper.ts b/packages/legacy/src/storage-wrapper.ts similarity index 68% rename from src/legacy/storage-wrapper.ts rename to packages/legacy/src/storage-wrapper.ts index 26cafc5..1231b3a 100644 --- a/src/legacy/storage-wrapper.ts +++ b/packages/legacy/src/storage-wrapper.ts @@ -1,7 +1,8 @@ -import type { StorageConfig, StorageWrapperInstance } from '../storage/utils.ts' -import * as google from '../storage/google.ts' +import type { StorageConfig, StorageWrapperInstance } from '@swrlab/storage' +import { createUri, createUrl, deleteFile, google, list, load, move, save } from '@swrlab/storage' -import { createUri, createUrl, deleteFile, list, load, move, save } from '../storage/index.ts' +// export const Storage = google.Storage +export { Storage } from '@google-cloud/storage' /** * Create a Google Cloud Storage Wrapper. diff --git a/packages/legacy/src/strings.ts b/packages/legacy/src/strings.ts new file mode 100644 index 0000000..f70b0ec --- /dev/null +++ b/packages/legacy/src/strings.ts @@ -0,0 +1,4 @@ +export { isEmptyArray, notEmptyArray } from '@swrlab/utils/array' +export { getObjectLength, isEmptyObject, notEmptyObject } from '@swrlab/utils/object' +export { isArray, isNull, isObject, isUndefined, notNullOrUndefined } from '@swrlab/utils/predicate' +export { capitalize, isEmptyString, isIncluded, pluralize, removeDoubleSpaces, toHex } from '@swrlab/utils/string' diff --git a/src/legacy/undici.ts b/packages/legacy/src/undici.ts similarity index 97% rename from src/legacy/undici.ts rename to packages/legacy/src/undici.ts index 52f54d6..c067b19 100644 --- a/src/legacy/undici.ts +++ b/packages/legacy/src/undici.ts @@ -4,7 +4,8 @@ import type { HeaderRecord } from 'undici/types/header.js' import { Buffer } from 'node:buffer' import process from 'node:process' import undici from 'undici' -import pkg from '../../package.json' with { type: 'json' } +import pkg from '../package.json' with { type: 'json' } + const { name, version } = pkg const userAgent: string = process.env.USER_AGENT || `${name.replace('@', '')}/${version}` @@ -50,7 +51,7 @@ type OptionsExtension = { * @type {BodyInit} * @defaultValue `null` */ - body?: any + body?: BodyInit /** * (Optional) Request Headers. @@ -132,14 +133,14 @@ const request = async ( const contentType = headers['content-type'] // parse json if set - let json + let json: object | undefined try { json = contentType?.indexOf('application/json') !== -1 ? JSON.parse(string) : null } catch { json = null } - return Promise.resolve({ + return { /** @deprecated modern fetch uses `Response.status` instead. */ statusCode, /** @deprecated modern fetch has a `Response.ok` value. */ @@ -157,7 +158,7 @@ const request = async ( buffer, /** @deprecated Modern fetch has the `Response.json()`. */ json, - }) + } } /** diff --git a/test/legacy/ard.test.mjs b/packages/legacy/test/ard.test.mjs similarity index 83% rename from test/legacy/ard.test.mjs rename to packages/legacy/test/ard.test.mjs index 2908f82..884db7a 100644 --- a/test/legacy/ard.test.mjs +++ b/packages/legacy/test/ard.test.mjs @@ -1,5 +1,5 @@ import { describe, it } from 'node:test' -import { createHashedId } from '../../src/legacy/ard.ts' +import { createHashedId } from '../src/ard.ts' import { expect } from './utils.mjs' describe('Test ARD Package', () => { diff --git a/test/legacy/date.test.mjs b/packages/legacy/test/date.test.mjs similarity index 97% rename from test/legacy/date.test.mjs rename to packages/legacy/test/date.test.mjs index f8c4e76..6cf49bb 100644 --- a/test/legacy/date.test.mjs +++ b/packages/legacy/test/date.test.mjs @@ -1,5 +1,5 @@ import { describe, it } from 'node:test' -import * as date from '../../src/legacy/date.ts' +import * as date from '../src/date.ts' import { expect } from './utils.mjs' const testDate = '2038-01-19T03:14:08.000' diff --git a/test/date.test.ts b/packages/legacy/test/date.test.ts similarity index 100% rename from test/date.test.ts rename to packages/legacy/test/date.test.ts diff --git a/test/date.utils.test.ts b/packages/legacy/test/date.utils.test.ts similarity index 100% rename from test/date.utils.test.ts rename to packages/legacy/test/date.utils.test.ts diff --git a/test/dist-legacy/ard.test.mjs b/packages/legacy/test/dist/ard.test.mjs similarity index 100% rename from test/dist-legacy/ard.test.mjs rename to packages/legacy/test/dist/ard.test.mjs diff --git a/test/dist-legacy/date.test.mjs b/packages/legacy/test/dist/date.test.mjs similarity index 100% rename from test/dist-legacy/date.test.mjs rename to packages/legacy/test/dist/date.test.mjs diff --git a/test/dist-legacy/helpers.test.mjs b/packages/legacy/test/dist/helpers.test.mjs similarity index 100% rename from test/dist-legacy/helpers.test.mjs rename to packages/legacy/test/dist/helpers.test.mjs diff --git a/test/dist-legacy/numbers.test.mjs b/packages/legacy/test/dist/numbers.test.mjs similarity index 100% rename from test/dist-legacy/numbers.test.mjs rename to packages/legacy/test/dist/numbers.test.mjs diff --git a/test/dist-legacy/strings.test.mjs b/packages/legacy/test/dist/strings.test.mjs similarity index 100% rename from test/dist-legacy/strings.test.mjs rename to packages/legacy/test/dist/strings.test.mjs diff --git a/test/dist-legacy/utils.mjs b/packages/legacy/test/dist/utils.mjs similarity index 100% rename from test/dist-legacy/utils.mjs rename to packages/legacy/test/dist/utils.mjs diff --git a/test/legacy/helpers.test.mjs b/packages/legacy/test/helpers.test.mjs similarity index 95% rename from test/legacy/helpers.test.mjs rename to packages/legacy/test/helpers.test.mjs index 9b7f385..ec26537 100644 --- a/test/legacy/helpers.test.mjs +++ b/packages/legacy/test/helpers.test.mjs @@ -1,5 +1,5 @@ import { describe, it } from 'node:test' -import * as helpers from '../../src/legacy/helpers.ts' +import * as helpers from '../src/helpers.ts' import { expect } from './utils.mjs' describe('Test Helpers Package', () => { diff --git a/test/legacy/numbers.test.mjs b/packages/legacy/test/numbers.test.mjs similarity index 98% rename from test/legacy/numbers.test.mjs rename to packages/legacy/test/numbers.test.mjs index 1b18934..9691510 100644 --- a/test/legacy/numbers.test.mjs +++ b/packages/legacy/test/numbers.test.mjs @@ -1,5 +1,5 @@ import { describe, it } from 'node:test' -import * as numbers from '../../src/legacy/numbers.ts' +import * as numbers from '../src/numbers.ts' import { expect } from './utils.mjs' describe('Test Numbers Package', () => { diff --git a/test/legacy/strings.test.mjs b/packages/legacy/test/strings.test.mjs similarity index 98% rename from test/legacy/strings.test.mjs rename to packages/legacy/test/strings.test.mjs index 63c3ba8..962c5f2 100644 --- a/test/legacy/strings.test.mjs +++ b/packages/legacy/test/strings.test.mjs @@ -1,5 +1,5 @@ import { describe, it } from 'node:test' -import * as strings from '../../src/legacy/strings.ts' +import * as strings from '../src/strings.ts' import { expect } from './utils.mjs' describe('Test Strings Package', () => { diff --git a/test/legacy/utils.mjs b/packages/legacy/test/utils.mjs similarity index 100% rename from test/legacy/utils.mjs rename to packages/legacy/test/utils.mjs diff --git a/packages/legacy/tsconfig.json b/packages/legacy/tsconfig.json new file mode 100644 index 0000000..435d58b --- /dev/null +++ b/packages/legacy/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist" + }, + "include": ["src/**/*"], + "exclude": ["**/dist/**"] +} diff --git a/packages/logger/package.json b/packages/logger/package.json new file mode 100644 index 0000000..2cf97f2 --- /dev/null +++ b/packages/logger/package.json @@ -0,0 +1,64 @@ +{ + "name": "@swrlab/logger", + "version": "3.0.0-beta.3", + "packageManager": "bun@1.2.22", + "description": "SWR Audio Lab logging utilities for Node.js.", + "type": "module", + "license": "ISC", + "repository": { + "type": "git", + "url": "git+https://github.com/swrlab/node-utils.git", + "directory": "packages/logger" + }, + "author": "SWR Audio Lab ", + "files": [ + "dist" + ], + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./package.json": "./package.json" + }, + "publishConfig": { + "access": "public", + "provenance": true + }, + "scripts": { + "attw": "bunx @arethetypeswrong/cli --pack . --profile esm-only", + "build": "tsdown", + "test": "bun run typecheck && bun run test:bun && bun run test:legacy", + "test:bun": "bun test ./test/**test*.ts", + "test:node": "node --test ./test/**.test.ts", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "winston": "^3.17.0" + }, + "devDependencies": { + "@types/luxon": "^3.7.1", + "@types/node": "^24.3.1", + "consola": "^3.4.2", + "luxon": "3.7.2", + "tsdown": "^0.14.2", + "typescript": "^5.9.2" + }, + "devEngines": { + "runtime": { + "name": "node", + "version": "^22.18.0 || >= 24.6", + "onFail": "warn" + }, + "packageManager": { + "name": "bun", + "onFail": "warn" + } + }, + "engines": { + "node": "^22.18.0 || >= 24.6.0" + } +} diff --git a/packages/storage/package.json b/packages/storage/package.json new file mode 100644 index 0000000..3e5214b --- /dev/null +++ b/packages/storage/package.json @@ -0,0 +1,60 @@ +{ + "name": "@swrlab/storage", + "version": "3.0.0-beta.3", + "packageManager": "bun@1.2.22", + "description": "SWR Audio Lab storage utilities for Node.js.", + "type": "module", + "license": "ISC", + "repository": { + "type": "git", + "url": "git+https://github.com/swrlab/node-utils.git", + "directory": "packages/storage" + }, + "author": "SWR Audio Lab ", + "files": [ + "dist" + ], + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "publishConfig": { + "access": "public", + "provenance": true + }, + "scripts": { + "attw": "bunx @arethetypeswrong/cli --pack . --profile esm-only", + "build": "tsdown", + "test": "bun run typecheck && bun run test:bun && bun run test:node", + "test:bun": "bun test ./test/**test*.ts", + "test:node": "node --test ./test/**.test.ts", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "@google-cloud/storage": "^7.17.0" + }, + "devDependencies": { + "@types/node": "^24.3.1", + "tsdown": "^0.14.2", + "typescript": "^5.9.2" + }, + "devEngines": { + "runtime": { + "name": "node", + "version": "^22.18.0 || >= 24.6", + "onFail": "warn" + }, + "packageManager": { + "name": "bun", + "onFail": "warn" + } + }, + "engines": { + "node": "^22.18.0 || >= 24.6.0" + } +} diff --git a/src/storage/createUri.ts b/packages/storage/src/createUri.ts similarity index 100% rename from src/storage/createUri.ts rename to packages/storage/src/createUri.ts diff --git a/src/storage/google.ts b/packages/storage/src/google.ts similarity index 96% rename from src/storage/google.ts rename to packages/storage/src/google.ts index 70dd48b..dbcb12e 100644 --- a/src/storage/google.ts +++ b/packages/storage/src/google.ts @@ -3,7 +3,10 @@ import type { Buffer } from 'node:buffer' import type { CloudStorageUrl } from './utils.ts' import { Storage } from '@google-cloud/storage' -let storage: Storage | undefined = undefined +// TODO: Remove in next mayor bump. Used for legacy imports only. +export { Storage } + +let storage: Storage | undefined const parseURI = (uri: string): { bucket: string; file: string } => { const structure = uri.slice(5).split('/') diff --git a/src/storage/index.ts b/packages/storage/src/index.ts similarity index 95% rename from src/storage/index.ts rename to packages/storage/src/index.ts index 1ea8f1a..0e8d03f 100644 --- a/src/storage/index.ts +++ b/packages/storage/src/index.ts @@ -12,6 +12,8 @@ import * as localFs from './local.ts' import { isCloudStorageUrl, isHttpUrl, validateUrl } from './utils.ts' export * as createUri from './createUri.ts' +export type { CloudStorageUrl, StorageConfig, StorageWrapperInstance } from './utils.ts' +export { google, isCloudStorageUrl, isHttpUrl, localFs, validateUrl } export const createUrl = async (url: string, ttl: number): Promise => { validateUrl(url) diff --git a/src/storage/local.ts b/packages/storage/src/local.ts similarity index 72% rename from src/storage/local.ts rename to packages/storage/src/local.ts index 3e926cd..001297c 100644 --- a/src/storage/local.ts +++ b/packages/storage/src/local.ts @@ -1,6 +1,5 @@ import fs from 'node:fs/promises' -/* eslint-disable security/detect-non-literal-fs-filename -- it's assumed to be fine */ export const deleteFile = async (filePath: string): Promise => await fs.unlink(filePath) export const listFiles = async (path: string): Promise => await fs.readdir(path, 'utf-8') @@ -9,5 +8,3 @@ export const readFile = async (uri: string): Promise => await fs.readFil export const writeFile = async (uri: string, contents: string): Promise => await fs.writeFile(uri, contents, 'utf-8') - -/* eslint-enable security/detect-non-literal-fs-filename -- let's run again */ diff --git a/src/storage/utils.ts b/packages/storage/src/utils.ts similarity index 98% rename from src/storage/utils.ts rename to packages/storage/src/utils.ts index ccd815c..27e877d 100644 --- a/src/storage/utils.ts +++ b/packages/storage/src/utils.ts @@ -67,7 +67,7 @@ export const isValidUrl = (urlString: string): urlString is KnownURL => { * @throws {Error} - If the given url is invalid. * @returns {void | never} - Never returns anything. */ -export const validateUrl = (url: string): void | never => { +export const validateUrl = (url: string): undefined | never => { if (!isValidUrl(url)) { throw new Error('not implemented') } diff --git a/test/storage/utils.test.ts b/packages/storage/test/storage.utils.test.ts similarity index 95% rename from test/storage/utils.test.ts rename to packages/storage/test/storage.utils.test.ts index 7e58dd9..f7ae0d1 100644 --- a/test/storage/utils.test.ts +++ b/packages/storage/test/storage.utils.test.ts @@ -1,6 +1,6 @@ import assert from 'node:assert' import { describe, test } from 'node:test' -import { isCloudStorage, isHttp, isValidUrl } from '../../src/storage/utils.ts' +import { isCloudStorage, isHttp, isValidUrl } from '../src/utils.ts' describe('storage utils', () => { describe('isHttp protocol', () => { diff --git a/packages/storage/tsconfig.json b/packages/storage/tsconfig.json new file mode 100644 index 0000000..d805bd5 --- /dev/null +++ b/packages/storage/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src", + "noEmit": true, + "outDir": "./dist" + }, + "include": ["src/**/*"], + "exclude": ["**/dist/**"] +} diff --git a/bin/ard-coreId.mjs b/packages/utils/bin/ard-coreId.mjs old mode 100644 new mode 100755 similarity index 100% rename from bin/ard-coreId.mjs rename to packages/utils/bin/ard-coreId.mjs diff --git a/packages/utils/package.json b/packages/utils/package.json new file mode 100644 index 0000000..a0e021a --- /dev/null +++ b/packages/utils/package.json @@ -0,0 +1,97 @@ +{ + "name": "@swrlab/utils", + "version": "3.0.0-beta.3", + "packageManager": "bun@1.2.22", + "description": "SWR Audio Lab utilities for Node.js.", + "type": "module", + "license": "ISC", + "repository": { + "type": "git", + "url": "git+https://github.com/swrlab/node-utils.git", + "directory": "packages/utils" + }, + "author": "SWR Audio Lab ", + "files": [ + "bin", + "dist" + ], + "main": "./dist/index.js", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "./ard": { + "types": "./dist/ard.d.ts", + "default": "./dist/ard.js" + }, + "./array": { + "types": "./dist/array.d.ts", + "default": "./dist/array.js" + }, + "./env": { + "types": "./dist/env.d.ts", + "default": "./dist/env.js" + }, + "./helper": { + "types": "./dist/helper.d.ts", + "default": "./dist/helper.js" + }, + "./number": { + "types": "./dist/number.d.ts", + "default": "./dist/number.js" + }, + "./object": { + "types": "./dist/object.d.ts", + "default": "./dist/object.js" + }, + "./predicate": { + "types": "./dist/predicate.d.ts", + "default": "./dist/predicate.js" + }, + "./string": { + "types": "./dist/string.d.ts", + "default": "./dist/string.js" + } + }, + "bin": { + "ard-coreId": "bin/ard-coreId.mjs" + }, + "publishConfig": { + "access": "public", + "provenance": true + }, + "scripts": { + "ard:coreId": "bun ./bin/ard-coreId.mjs", + "attw": "bunx @arethetypeswrong/cli --pack . --profile node16", + "build": "tsdown", + "knip": "knip", + "test": "vitest run --coverage --typecheck", + "typecheck": "tsc --noEmit" + }, + "dependencies": {}, + "devDependencies": { + "@types/node": "^24.3.1", + "@vitest/coverage-v8": "3.2.4", + "knip": "^5.63.1", + "tsdown": "^0.14.2", + "typescript": "^5.9.2", + "vitest": "^3.2.4" + }, + "devEngines": { + "runtime": { + "name": "node", + "version": "^22.18.0 || >= 24.6", + "onFail": "warn" + }, + "packageManager": { + "name": "bun", + "onFail": "warn" + } + }, + "engines": { + "node": "^22.18.0 || >= 24.6.0" + } +} diff --git a/src/ard/coreId.ts b/packages/utils/src/ard/coreId.ts similarity index 91% rename from src/ard/coreId.ts rename to packages/utils/src/ard/coreId.ts index 3878be6..009943c 100644 --- a/src/ard/coreId.ts +++ b/packages/utils/src/ard/coreId.ts @@ -15,3 +15,7 @@ export const coreId = (): void => { console.info('OUTPUT (CRC64-ECMA182):') console.info(createHashedId(input)) } + +if (import.meta.main) { + coreId() +} diff --git a/src/ard/createHashedId.ts b/packages/utils/src/ard/createHashedId.ts similarity index 100% rename from src/ard/createHashedId.ts rename to packages/utils/src/ard/createHashedId.ts diff --git a/src/ard/index.ts b/packages/utils/src/ard/index.ts similarity index 100% rename from src/ard/index.ts rename to packages/utils/src/ard/index.ts diff --git a/src/array/README.md b/packages/utils/src/array/README.md similarity index 100% rename from src/array/README.md rename to packages/utils/src/array/README.md diff --git a/src/array/arrayToObjectCount.ts b/packages/utils/src/array/arrayToObjectCount.ts similarity index 80% rename from src/array/arrayToObjectCount.ts rename to packages/utils/src/array/arrayToObjectCount.ts index 4f4c29b..8434645 100644 --- a/src/array/arrayToObjectCount.ts +++ b/packages/utils/src/array/arrayToObjectCount.ts @@ -6,7 +6,6 @@ */ export const arrayToObjectCount = (array: string[]): Record => array.reduce((obj: Record, name: string) => { - // eslint-disable-next-line security/detect-object-injection -- this seems safe obj[name] = obj[name] ? ++obj[name] : 1 return obj }, {}) diff --git a/src/array/index.ts b/packages/utils/src/array/index.ts similarity index 100% rename from src/array/index.ts rename to packages/utils/src/array/index.ts diff --git a/src/array/isEmptyArray.ts b/packages/utils/src/array/isEmptyArray.ts similarity index 100% rename from src/array/isEmptyArray.ts rename to packages/utils/src/array/isEmptyArray.ts diff --git a/src/array/notEmptyArray.ts b/packages/utils/src/array/notEmptyArray.ts similarity index 100% rename from src/array/notEmptyArray.ts rename to packages/utils/src/array/notEmptyArray.ts diff --git a/src/env.ts b/packages/utils/src/env.ts similarity index 98% rename from src/env.ts rename to packages/utils/src/env.ts index 6a652ac..9faf5e5 100644 --- a/src/env.ts +++ b/packages/utils/src/env.ts @@ -49,7 +49,7 @@ export function getEnv(key: string, config: EnvConfig = {}): T { // @ts-expect-error - Insert mocked values from vitest test. const env = globalThis.__VitestMockEnv ?? process.env - // eslint-disable-next-line security/detect-object-injection -- There is no unsafe user-input. + const value = env[key] if (value === undefined) { diff --git a/src/helpers/README.md b/packages/utils/src/helpers/README.md similarity index 100% rename from src/helpers/README.md rename to packages/utils/src/helpers/README.md diff --git a/src/helpers/index.ts b/packages/utils/src/helpers/index.ts similarity index 100% rename from src/helpers/index.ts rename to packages/utils/src/helpers/index.ts diff --git a/src/helpers/request.ts b/packages/utils/src/helpers/request.ts similarity index 94% rename from src/helpers/request.ts rename to packages/utils/src/helpers/request.ts index 06de3b1..9eba2aa 100644 --- a/src/helpers/request.ts +++ b/packages/utils/src/helpers/request.ts @@ -1,9 +1,7 @@ import process from 'node:process' - import pkg from '../../package.json' with { type: 'json' } -const { name, version } = pkg -const userAgent: string = process.env.USER_AGENT || `${name.replace('@', '')}/${version}` +const { name, version } = pkg /** 7 seconds (in milliseconds) */ const DEFAULT_TIMEOUT: number = 7e3 @@ -41,6 +39,7 @@ export const request = async ( resource: string | URL | Request, options: RequestInit & OptionsTimeout & OptionsReject = {} ): Promise => { + const userAgent: string = process.env.USER_AGENT || `${name.replace('@', '')}/${version}` const requestOptions = { ...options, signal: options.signal ?? AbortSignal.timeout(options?.timeout ?? DEFAULT_TIMEOUT), diff --git a/src/helpers/sleep.ts b/packages/utils/src/helpers/sleep.ts similarity index 100% rename from src/helpers/sleep.ts rename to packages/utils/src/helpers/sleep.ts diff --git a/src/index.ts b/packages/utils/src/index.ts similarity index 87% rename from src/index.ts rename to packages/utils/src/index.ts index 1b47e6e..841b802 100644 --- a/src/index.ts +++ b/packages/utils/src/index.ts @@ -1,5 +1,5 @@ export * from './ard/index.ts' -export * from './date/index.ts' +export * from './array/index.ts' export * from './env.ts' export * from './helpers/index.ts' export * from './number/index.ts' diff --git a/src/number/README.md b/packages/utils/src/number/README.md similarity index 100% rename from src/number/README.md rename to packages/utils/src/number/README.md diff --git a/src/number/addLeadingZero.ts b/packages/utils/src/number/addLeadingZero.ts similarity index 80% rename from src/number/addLeadingZero.ts rename to packages/utils/src/number/addLeadingZero.ts index d8706e5..22a056e 100644 --- a/src/number/addLeadingZero.ts +++ b/packages/utils/src/number/addLeadingZero.ts @@ -2,6 +2,7 @@ * Add leading zero if not existent. * * @param {number} value - The number value. + * @deprecated Use `value.toString().padStart(2, '0')` instead. * @returns {string} - The number as string with a leading zero prepended if needed. */ export const addLeadingZero = (value: number): string => value.toString().padStart(2, '0') diff --git a/src/number/addTrailingZeros.ts b/packages/utils/src/number/addTrailingZeros.ts similarity index 82% rename from src/number/addTrailingZeros.ts rename to packages/utils/src/number/addTrailingZeros.ts index 7423961..00e9b70 100644 --- a/src/number/addTrailingZeros.ts +++ b/packages/utils/src/number/addTrailingZeros.ts @@ -1,6 +1,7 @@ /** * Add a given number of trailing zeros to a number. * + * @deprecated Use `num.toFixed(length)` or `num.toLocaleString('de-DE`, { minimumFractionDigits: length, maximumFractionDigits: length })` instead. * @param {number | string} num - The number to be appended zeros. * @param {number} length - The final number length. * @param {string} [delimiter] - Number delimeter. Defaults to `.`. diff --git a/src/number/getAverage.ts b/packages/utils/src/number/getAverage.ts similarity index 87% rename from src/number/getAverage.ts rename to packages/utils/src/number/getAverage.ts index 649a56d..3dd2d6f 100644 --- a/src/number/getAverage.ts +++ b/packages/utils/src/number/getAverage.ts @@ -13,5 +13,5 @@ export const getAverage = (arr: number[], decimals = 2): number => sum(arr, deci // The rounding should occur afterwards to reduce the error. // And ideally, the rounding is done by the caller themself. -export const getAverageNew = (arr: number[], decimals = 2): number => +export const average = (arr: number[], decimals = 2): number => roundTo(arr.reduce((sum, num) => sum + num, 0) / arr.length, decimals) diff --git a/src/number/getDiff.ts b/packages/utils/src/number/getDiff.ts similarity index 100% rename from src/number/getDiff.ts rename to packages/utils/src/number/getDiff.ts diff --git a/src/number/getRandomInRange.ts b/packages/utils/src/number/getRandomInRange.ts similarity index 100% rename from src/number/getRandomInRange.ts rename to packages/utils/src/number/getRandomInRange.ts diff --git a/src/number/getSum.ts b/packages/utils/src/number/getSum.ts similarity index 86% rename from src/number/getSum.ts rename to packages/utils/src/number/getSum.ts index 619cafa..65c3d99 100644 --- a/src/number/getSum.ts +++ b/packages/utils/src/number/getSum.ts @@ -10,7 +10,7 @@ import { roundTo } from './roundTo.ts' */ export const getSum = (arr: number[], decimals = 2): number => arr.reduce((sum, n) => roundTo(sum + n, decimals), 0) -export const getSumNew = (arr: number[], decimals = 2): number => +export const sum = (arr: number[], decimals = 2): number => roundTo( arr.reduce((sum, n) => sum + n, 0), decimals diff --git a/src/number/index.ts b/packages/utils/src/number/index.ts similarity index 69% rename from src/number/index.ts rename to packages/utils/src/number/index.ts index 1b97b91..ad4b1da 100644 --- a/src/number/index.ts +++ b/packages/utils/src/number/index.ts @@ -6,10 +6,10 @@ export { addLeadingZero } from './addLeadingZero.ts' export { addTrailingZeros } from './addTrailingZeros.ts' -export { getAverage } from './getAverage.ts' +export { average, getAverage } from './getAverage.ts' export { getDiff } from './getDiff.ts' -export { getRandomInRange } from './getRandomInRange.ts' -export { getSum } from './getSum.ts' +export { getRandomInRange, getRandomInRangLegacy } from './getRandomInRange.ts' +export { getSum, sum } from './getSum.ts' export { isEven } from './isEven.ts' export { normalize } from './normalize.ts' export { roundTo } from './roundTo.ts' diff --git a/src/number/isEven.ts b/packages/utils/src/number/isEven.ts similarity index 100% rename from src/number/isEven.ts rename to packages/utils/src/number/isEven.ts diff --git a/src/number/normalize.ts b/packages/utils/src/number/normalize.ts similarity index 100% rename from src/number/normalize.ts rename to packages/utils/src/number/normalize.ts diff --git a/src/number/roundTo.ts b/packages/utils/src/number/roundTo.ts similarity index 100% rename from src/number/roundTo.ts rename to packages/utils/src/number/roundTo.ts diff --git a/src/number/toReadable.ts b/packages/utils/src/number/toReadable.ts similarity index 68% rename from src/number/toReadable.ts rename to packages/utils/src/number/toReadable.ts index 665946a..ea683ab 100644 --- a/src/number/toReadable.ts +++ b/packages/utils/src/number/toReadable.ts @@ -1,4 +1,6 @@ -import { DEFAULT_LOCALE } from '../date/utils.ts' +// TODO: use date package from workspace +// import { DEFAULT_LOCALE } from '../date/utils.ts' +const DEFAULT_LOCALE = 'de' /** * Converts the given number into a german readable format. diff --git a/src/object/README.md b/packages/utils/src/object/README.md similarity index 100% rename from src/object/README.md rename to packages/utils/src/object/README.md diff --git a/src/object/getJsonKeys.ts b/packages/utils/src/object/getJsonKeys.ts similarity index 82% rename from src/object/getJsonKeys.ts rename to packages/utils/src/object/getJsonKeys.ts index 85d1143..5814189 100644 --- a/src/object/getJsonKeys.ts +++ b/packages/utils/src/object/getJsonKeys.ts @@ -10,7 +10,7 @@ export const getJsonKeys = (json: any): string[] => { const keys = [] for (const key in json) { - if (Object.prototype.hasOwnProperty.call(json, key)) { + if (Object.hasOwn(json, key)) { keys.push(key) } } diff --git a/src/object/getObjectLength.ts b/packages/utils/src/object/getObjectLength.ts similarity index 100% rename from src/object/getObjectLength.ts rename to packages/utils/src/object/getObjectLength.ts diff --git a/src/object/index.ts b/packages/utils/src/object/index.ts similarity index 100% rename from src/object/index.ts rename to packages/utils/src/object/index.ts diff --git a/src/object/isEmptyObject.ts b/packages/utils/src/object/isEmptyObject.ts similarity index 100% rename from src/object/isEmptyObject.ts rename to packages/utils/src/object/isEmptyObject.ts diff --git a/src/object/notEmptyObject.ts b/packages/utils/src/object/notEmptyObject.ts similarity index 100% rename from src/object/notEmptyObject.ts rename to packages/utils/src/object/notEmptyObject.ts diff --git a/src/predicate/README.md b/packages/utils/src/predicate/README.md similarity index 100% rename from src/predicate/README.md rename to packages/utils/src/predicate/README.md diff --git a/src/predicate/index.ts b/packages/utils/src/predicate/index.ts similarity index 100% rename from src/predicate/index.ts rename to packages/utils/src/predicate/index.ts diff --git a/src/predicate/isArray.ts b/packages/utils/src/predicate/isArray.ts similarity index 100% rename from src/predicate/isArray.ts rename to packages/utils/src/predicate/isArray.ts diff --git a/src/predicate/isNull.ts b/packages/utils/src/predicate/isNull.ts similarity index 100% rename from src/predicate/isNull.ts rename to packages/utils/src/predicate/isNull.ts diff --git a/src/predicate/isObject.ts b/packages/utils/src/predicate/isObject.ts similarity index 100% rename from src/predicate/isObject.ts rename to packages/utils/src/predicate/isObject.ts diff --git a/src/predicate/isUndefined.ts b/packages/utils/src/predicate/isUndefined.ts similarity index 100% rename from src/predicate/isUndefined.ts rename to packages/utils/src/predicate/isUndefined.ts diff --git a/src/predicate/notNullOrUndefined.ts b/packages/utils/src/predicate/notNullOrUndefined.ts similarity index 100% rename from src/predicate/notNullOrUndefined.ts rename to packages/utils/src/predicate/notNullOrUndefined.ts diff --git a/src/string/README.md b/packages/utils/src/string/README.md similarity index 96% rename from src/string/README.md rename to packages/utils/src/string/README.md index 3d873ef..37751fe 100644 --- a/src/string/README.md +++ b/packages/utils/src/string/README.md @@ -28,7 +28,7 @@ npm add @swrlab/utils Import the library: ```js -import { toBase64, parseBase64 } from ('@swrlab/utils/string') +import { parseBase64, toBase64 } from '@swrlab/utils/string' ``` Then use the toolkit: @@ -48,7 +48,7 @@ parseBase64('MTIzNDU2Nzg5') Import the library: ```js -import { capitalize } from ('@swrlab/utils/string') +import { capitalize } from '@swrlab/utils/string' ``` Then use the toolkit: diff --git a/src/string/base64.ts b/packages/utils/src/string/base64.ts similarity index 100% rename from src/string/base64.ts rename to packages/utils/src/string/base64.ts diff --git a/src/string/capitalize.ts b/packages/utils/src/string/capitalize.ts similarity index 100% rename from src/string/capitalize.ts rename to packages/utils/src/string/capitalize.ts diff --git a/src/string/crc64.ts b/packages/utils/src/string/crc64.ts similarity index 96% rename from src/string/crc64.ts rename to packages/utils/src/string/crc64.ts index 5c73902..2d260de 100644 --- a/src/string/crc64.ts +++ b/packages/utils/src/string/crc64.ts @@ -51,6 +51,7 @@ const step = (v: bigint): bigint => * @returns {bigint[]} - An array of 256 BigInts. */ const createTable = (): bigint[] => + // biome-ignore lint/suspicious/noAssignInExpressions: here it's ok _table ?? (_table = Array.from({ length: 256 }, (_, i) => Array.from({ length: 8 }).reduce(step, BigInt(i) << 56n))) /** @@ -81,6 +82,7 @@ const updateCrc = // Shift current CRC left by 8 bits (a.k.a multiply by 256). ((crc << 8n) ^ // XOR with the precomputed table value. + // biome-ignore lint/style/noNonNullAssertion: here it's safe since no user input. table[ Number( // Take the top 8 bits of the current CRC. diff --git a/src/string/index.ts b/packages/utils/src/string/index.ts similarity index 100% rename from src/string/index.ts rename to packages/utils/src/string/index.ts diff --git a/src/string/isEmptyString.ts b/packages/utils/src/string/isEmptyString.ts similarity index 100% rename from src/string/isEmptyString.ts rename to packages/utils/src/string/isEmptyString.ts diff --git a/src/string/isIncluded.ts b/packages/utils/src/string/isIncluded.ts similarity index 100% rename from src/string/isIncluded.ts rename to packages/utils/src/string/isIncluded.ts diff --git a/src/string/pluralize.ts b/packages/utils/src/string/pluralize.ts similarity index 100% rename from src/string/pluralize.ts rename to packages/utils/src/string/pluralize.ts diff --git a/src/string/removeDoubleSpaces.ts b/packages/utils/src/string/removeDoubleSpaces.ts similarity index 100% rename from src/string/removeDoubleSpaces.ts rename to packages/utils/src/string/removeDoubleSpaces.ts diff --git a/src/string/toHex.ts b/packages/utils/src/string/toHex.ts similarity index 100% rename from src/string/toHex.ts rename to packages/utils/src/string/toHex.ts diff --git a/packages/utils/test/ard.test.ts b/packages/utils/test/ard.test.ts new file mode 100644 index 0000000..64f8829 --- /dev/null +++ b/packages/utils/test/ard.test.ts @@ -0,0 +1,40 @@ +import { afterEach, describe, expect, it, vi } from 'vitest' +import { coreId } from '../src/ard/coreId.ts' +import { createHashedId } from '../src/ard/index.ts' + +describe('createHashedId', () => { + it('should return the correct hashed Id', () => { + expect(createHashedId('test')).toBe('0c171b2e54a30c11') + }) +}) + +describe('coreId', () => { + const consoleErrorMock = vi.spyOn(globalThis.console, 'error').mockImplementation(() => undefined) + const consoleInfoMock = vi.spyOn(globalThis.console, 'info').mockImplementation(() => undefined) + + afterEach(() => { + consoleErrorMock.mockReset() + consoleInfoMock.mockReset() + }) + + it('should call console.error since no input value is passed in', () => { + coreId() + expect(consoleErrorMock).toHaveBeenCalledTimes(1) + expect(consoleInfoMock).not.toHaveBeenCalled() + }) + + it('should return the hashed arg input as checksum as last console.info call', () => { + // just making sure the mockReset works + expect(consoleErrorMock).toHaveBeenCalledTimes(0) + // mocking 'node:process' + // eslint-disable-next-line node/prefer-global/process -- it's just for mocking + globalThis.process.argv = ['2', '4', 'input'] + // vi.mock('node:process', () => { + // return { default: { argv: ['3', '6', 'asdf'] } } + // }) + coreId() + expect(consoleErrorMock).not.toHaveBeenCalled() + expect(consoleInfoMock).toHaveBeenCalledTimes(5) + expect(consoleInfoMock).toHaveBeenLastCalledWith(createHashedId('input')) + }) +}) diff --git a/test/array.test.ts b/packages/utils/test/array.test.ts similarity index 87% rename from test/array.test.ts rename to packages/utils/test/array.test.ts index 2434916..3388ca0 100644 --- a/test/array.test.ts +++ b/packages/utils/test/array.test.ts @@ -1,8 +1,7 @@ -import assert from 'node:assert' -import { describe, test } from 'node:test' +import { assert, describe, test } from 'vitest' import { arrayToObjectCount, isEmptyArray, notEmptyArray } from '../src/array/index.ts' -describe('array utils', () => { +describe('array utilities', () => { test('arrayToObjectCount', () => { const test = ['foo', 'bar', 'bar'] const result = { bar: 2, foo: 1 } diff --git a/test/base64.test.ts b/packages/utils/test/base64.test.ts similarity index 67% rename from test/base64.test.ts rename to packages/utils/test/base64.test.ts index a6827f9..5f1be5b 100644 --- a/test/base64.test.ts +++ b/packages/utils/test/base64.test.ts @@ -1,5 +1,4 @@ -import assert from 'node:assert/strict' -import { describe, it } from 'node:test' +import { assert, describe, it } from 'vitest' import { parseBase64, toBase64 } from '../src/string/base64.ts' describe('toBase64', () => { @@ -11,20 +10,19 @@ describe('toBase64', () => { assert.equal(toBase64('hello'), 'aGVsbG8=') }) it('should throw a TypeError if a number is passed', () => { + // Node.js version of assert.throws: + // assert.throws(() => toBase64(undefined), { name: 'TypeError', message: /The first argument/ }) // @ts-expect-error - undefined won't work, but is fine for testing. - assert.throws(() => toBase64(undefined), { name: 'TypeError', message: /The first argument/ }) + assert.throws(() => toBase64(undefined), TypeError, /The first argument/) // @ts-expect-error - A number won't work, but is fine for testing. - assert.throws(() => toBase64(123456789), { name: 'TypeError', code: 'ERR_INVALID_ARG_TYPE' }) + assert.throws(() => toBase64(123456789), TypeError, 'The first argument must be of type string') }) }) describe('parseBase64', () => { it('should throw a TypeError on undefined', () => { // @ts-expect-error - A number won't work, but is fine for testing. - assert.throws(() => parseBase64(undefined), { - name: 'TypeError', - message: /The first argument must be of type/, - }) + assert.throws(() => parseBase64(undefined), TypeError, /The first argument must be of type/) }) it('should decode an empty base64 to an empty string', () => { assert.equal(parseBase64(''), '') diff --git a/test/crc.test.ts b/packages/utils/test/crc.test.ts similarity index 96% rename from test/crc.test.ts rename to packages/utils/test/crc.test.ts index 631c9ff..daac4c0 100644 --- a/test/crc.test.ts +++ b/packages/utils/test/crc.test.ts @@ -1,6 +1,5 @@ -import assert from 'node:assert/strict' import { Buffer } from 'node:buffer' -import { describe, test } from 'node:test' +import { assert, describe, test } from 'vitest' import { crc64, crc64String } from '../src/string/crc64.ts' // Standard check string for CRC algorithms diff --git a/test/env.test.ts b/packages/utils/test/env.test.ts similarity index 67% rename from test/env.test.ts rename to packages/utils/test/env.test.ts index 37c3cfa..a315819 100644 --- a/test/env.test.ts +++ b/packages/utils/test/env.test.ts @@ -1,27 +1,27 @@ -import assert from 'node:assert/strict' -import { after, before, describe, it } from 'node:test' -import { getEnv, getEnvBase64, getEnvBoolean, getEnvString } from './../src/env.ts' +import { afterAll as after, assert, beforeAll as before, describe, it } from 'vitest' +import { getEnv, getEnvBase64, getEnvBoolean, getEnvString, MissingEnvVarError } from './../src/env.ts' describe('no env values available', () => { it('should throw an error for missing required values', () => { - assert.throws(() => getEnv('MISSING', { type: 'string', required: true }), { - name: 'MissingEnvVarError', - }) + // Node.js version of assert + // assert.throws(() => getEnv('MISSING', { type: 'string', required: true }), { name: 'MissingEnvVarError', }) + assert.throws(() => getEnv('MISSING', { type: 'string', required: true }), MissingEnvVarError) }) it('should throw an error for missing required values (even with defaultValue)', () => { - assert.throws(() => getEnv('MISSING', { type: 'string', required: true, defaultValue: 'hi' }), { - name: 'MissingEnvVarError', - }) + assert.throws( + () => getEnv('MISSING', { type: 'string', required: true, defaultValue: 'hi' }), + MissingEnvVarError + ) }) it('should return the defaultValue for optional values', () => { assert.equal(getEnv('MISSING', { type: 'string', required: false, defaultValue: 'def' }), 'def') }) describe('functions with `required` set to `true` by default', () => { it('should throw an error for getEnvString when the value is missing', () => { - assert.throws(() => getEnvString('MISSING'), { name: 'MissingEnvVarError' }) + assert.throws(() => getEnvString('MISSING'), MissingEnvVarError) }) it('should throw an error for getEnvBase64 when the value is missing', () => { - assert.throws(() => getEnvBase64('MISSING'), { name: 'MissingEnvVarError' }) + assert.throws(() => getEnvBase64('MISSING'), MissingEnvVarError) }) }) describe('functions with `required` set to `false` by default', () => { @@ -52,9 +52,7 @@ describe('mocked env values', () => { globalThis.__VitestMockEnv = undefined }) it('should throw an error for missing required values', () => { - assert.throws(() => getEnv('MISSING', { type: 'string', required: true }), { - name: 'MissingEnvVarError', - }) + assert.throws(() => getEnv('MISSING', { type: 'string', required: true }), MissingEnvVarError) }) it('should return the mocked exsiting value', () => { assert.deepEqual(getEnv('FOO', { type: 'string', required: true }), mocked.FOO) @@ -65,21 +63,16 @@ describe('mocked env values', () => { assert.deepEqual(value, { dts: true }) }) it('should throw a SyntaxError for invalid json data', () => { - assert.throws(() => getEnvBase64('BASE64_BROKEN'), { - message: /SyntaxError:.*Unexpected/, - }) - assert.throws(() => getEnvBase64('BASE64_BROKEN'), { message: /variable BASE64_BROKEN as/ }) + assert.throws(() => getEnvBase64('BASE64_BROKEN'), /SyntaxError:.*Unexpected/) + assert.throws(() => getEnvBase64('BASE64_BROKEN'), /variable BASE64_BROKEN as/) }) }) describe('getEnvJSON', () => { it('should throw a SyntaxError for an empty value', () => { - assert.throws(() => getEnvBase64('EMPTY_JSON'), { - name: 'Error', - message: /EMPTY_JSON.*SyntaxError: /, - }) + assert.throws(() => getEnvBase64('EMPTY_JSON'), /EMPTY_JSON.*SyntaxError: /) }) it('should throw a SyntaxError for mal-formed json', () => { - assert.throws(() => getEnvBase64('BROKEN_JSON'), { message: /SyntaxError:.*Unexpected/ }) + assert.throws(() => getEnvBase64('BROKEN_JSON'), /SyntaxError:.*Unexpected/) }) }) }) diff --git a/packages/utils/test/helpers.test.ts b/packages/utils/test/helpers.test.ts new file mode 100644 index 0000000..8f75627 --- /dev/null +++ b/packages/utils/test/helpers.test.ts @@ -0,0 +1,75 @@ +import { afterEach, assert, beforeEach, describe, expect, it, vi } from 'vitest' +import { request, sleep } from '../src/helpers/index.ts' + +describe('helpers', () => { + describe('request', () => { + let newFetch = vi.fn(() => ({ ok: true, json: true })) + + beforeEach(() => { + newFetch = vi.fn(() => ({ ok: true, json: true })) + vi.stubGlobal('fetch', newFetch) + }) + + afterEach(() => { + vi.unstubAllGlobals() + vi.unstubAllEnvs() + }) + + describe('user-agent', () => { + const url = 'http://localhost/ua' + it('should use the default user-agent with package name', async () => { + expect(newFetch).not.toBeCalled() + await request(url) + expect(newFetch).toBeCalledWith(url, { + headers: { + 'user-agent': 'swrlab/utils/3.0.0-beta.3', + }, + signal: expect.any(AbortSignal), + }) + }) + + it('should pass the user agent from env as header', async () => { + vi.stubEnv('USER_AGENT', 'new-UA/1.0') + expect(newFetch).not.toBeCalled() + await request(url) + expect(newFetch).toBeCalledWith(url, { + headers: { + 'user-agent': 'new-UA/1.0', + }, + signal: expect.any(AbortSignal), + }) + }) + }) + + describe('timeout', () => { + const url = 'http://localhost/to' + const timeout = vi.fn(() => undefined) + beforeEach(() => { + vi.stubGlobal('AbortSignal', { timeout }) + }) + afterEach(() => { + vi.unstubAllGlobals() + }) + it('should use the default timeout value when not timeout entry is passed', async () => { + await request(url) + expect(timeout).toBeCalledWith(7000) + }) + + it('should use the default user-agent with package name', async () => { + await request(url, { timeout: 1234 }) + expect(timeout).toBeCalledWith(1234) + }) + }) + }) + + // skip sleep test, since it works and takes "too long" + describe.skip('sleep', () => { + it('will sleep for one second', async () => { + const time = 1e3 + const before = Date.now() + await sleep(time) + const after = Date.now() + assert(after - before >= time) + }) + }) +}) diff --git a/packages/utils/test/number.test.ts b/packages/utils/test/number.test.ts new file mode 100644 index 0000000..88685c0 --- /dev/null +++ b/packages/utils/test/number.test.ts @@ -0,0 +1,211 @@ +import { assert, describe, it } from 'vitest' +import * as number from '../src/number/index.ts' + +describe('number utils', () => { + describe('addLeadingZero', () => { + it('prepends a zero for one-digit numbers', () => { + assert.equal(number.addLeadingZero(1), '01') + }) + + it('does not change anything for two-digit numbers', () => { + assert.equal(number.addLeadingZero(10), '10') + }) + }) + + describe('Number.toFixed', () => { + it("toFixed(1, 5) = '1.00000'", () => { + assert.equal((1).toFixed(5), '1.00000') + }) + it("1.1.toFixed(5) = '1.10000'", () => { + assert.equal((1.1).toFixed(5), '1.10000') + }) + it("toFixed('1.2', 5) = '1.20000'", () => { + assert.strictEqual((1.2).toFixed(5), '1.20000') + }) + }) + + describe('Number.toLocaleString minimumFractionDigits', () => { + it("1.toFixed(5) = '1,00000'", () => { + assert.strictEqual((1).toLocaleString('en'), '1') + assert.strictEqual((1).toLocaleString('de'), '1') + assert.strictEqual((1).toLocaleString('es'), '1') + assert.strictEqual((2.5).toLocaleString('en'), '2.5') + assert.strictEqual((2.5).toLocaleString('de'), '2,5') + assert.strictEqual((2.5).toLocaleString('de-DE'), '2,5') + assert.strictEqual( + (1).toLocaleString('en-US', { minimumFractionDigits: 5, maximumFractionDigits: 5 }), + '1.00000' + ) + assert.strictEqual( + (1).toLocaleString('de-DE', { minimumFractionDigits: 5, maximumFractionDigits: 5 }), + '1,00000' + ) + }) + }) + + describe('addTrailingZeros', () => { + it("addTrailingZeros(1, 5) = '1.00000'", () => { + assert.equal(number.addTrailingZeros(1, 5), '1.00000') + }) + + it("addTrailingZeros(1.1, 5) = '1.10000'", () => { + assert.equal(number.addTrailingZeros(1.1, 5), '1.10000') + }) + + it("addTrailingZeros('1.2', 5) = '1.20000'", () => { + assert.equal(number.addTrailingZeros('1.2', 5), '1.20000') + }) + + it("addTrailingZeros(2, 2, ',') = '2,00'", () => { + assert.equal(number.addTrailingZeros(2, 2, ','), '2,00') + }) + + it("addTrailingZeros(2.1, 2, ',') = '2,10'", () => { + assert.equal(number.addTrailingZeros(2.1, 2, ','), '2,10') + }) + + it("addTrailingZeros('2,2', 2, ','') = '2,20'", () => { + assert.equal(number.addTrailingZeros('2,2', 2, ','), '2,20') + }) + }) + + describe('getAverage (legacy method)', () => { + it('should return the average as Integer if possible', () => { + assert.equal(number.getAverage([1, 2, 3]), 2) + }) + + it('should return the average as float', () => { + assert.equal(number.getAverage([1.2, 2.4, 3.6], 1), 2.4) + }) + + it('should round the inputs', () => { + // here is the rounding behaviour different (it happens before already) + assert.equal(number.getAverage([1.22, 2.44, 3.66], 2), 2.44) + assert.equal(number.getAverage([1.22, 2.44, 3.66], 1), 2.433333333333333) + assert.equal(number.getAverage([1.45, 2.44, 3.66], 1), 2.5) + }) + }) + + describe('average', () => { + it('should return the average as Integer if possible', () => { + assert.equal(number.average([1, 2, 3]), 2) + }) + + it('should return the average as float', () => { + assert.equal(number.average([1.2, 2.4, 3.6], 1), 2.4) + }) + + it('should round the result only', () => { + assert.equal(number.average([1.22, 2.44, 3.66], 2), 2.44) + assert.equal(number.average([1.22, 2.44, 3.66], 1), 2.4) + assert.equal(number.average([1.45, 2.44, 3.66], 1), 2.5) + }) + }) + + describe('getDiff', () => { + it('getDiff(2, 1) = 1', () => { + assert.equal(number.getDiff(2, 1), 1) + }) + + it('getDiff(1, 2) = -1', () => { + assert.equal(number.getDiff(1, 2), -1) + }) + }) + + describe('getRandomInRange', () => { + it('getRandomInRange(1, 5) = 1,2,3,4 or 5', () => { + assert([1, 2, 3, 4, 5].includes(number.getRandomInRange(1, 5))) + }) + + it('getRandomInRange(5, 9) = 5,6,7,8 or 9', () => { + assert([5, 6, 7, 8, 9].includes(number.getRandomInRange(5, 9))) + }) + }) + + describe('getSum', () => { + it('should calculate the sum of integers', () => { + assert.equal(number.getSum([1, 2, 3]), 6) + }) + + it('should calculate the sum of floats', () => { + assert.equal(number.getSum([1.2, 2.4, 3.6], 1), 7.2) + }) + + it('should round the input', () => { + assert.equal(number.getSum([1.5, 2.5, 3.6], 1), 7.6) + assert.equal(number.getSum([1.5, 2.5, 3.6], 0), 9) + assert.equal(number.getSum([2.46, 4.46, 8.46], 2), 15.38) + assert.equal(number.getSum([2.46, 4.46, 8.46], 1), 15.5) + assert.equal(number.getSum([2.46, 4.46, 8.46], 0), 14) + }) + }) + describe('sum', () => { + it('should calculate the sum of integers', () => { + assert.equal(number.sum([1, 2, 3]), 6) + }) + + it('should calculate the sum of floats', () => { + assert.equal(number.sum([1.2, 2.4, 3.6], 1), 7.2) + }) + + it('should round afterwards', () => { + assert.equal(number.sum([1.5, 2.5, 3.6], 1), 7.6) + assert.equal(number.sum([1.5, 2.5, 3.6], 0), 8) + assert.equal(number.sum([2.46, 4.46, 8.46], 2), 15.38) + assert.equal(number.sum([2.46, 4.46, 8.46], 1), 15.4) + assert.equal(number.sum([2.46, 4.46, 8.46], 0), 15) + }) + }) + + describe('isEven', () => { + it('is true for even numbers', () => { + assert(number.isEven(2)) + assert(number.isEven(4)) + }) + + it('is false for uneven numbers', () => { + assert.equal(number.isEven(1), false) + assert.equal(number.isEven(11), false) + }) + }) + + describe('normalize', () => { + it('normalize(2, 100) = 0.02', () => { + assert.equal(number.normalize(2, 100), 0.02) + }) + + it('normalize(80, 100) = 0.8', () => { + assert.equal(number.normalize(80, 100), 0.8) + }) + }) + + describe('roundTo', () => { + it('roundTo(1.23456) = 1.23', () => { + assert.equal(number.roundTo(1.23456), 1.23) + }) + + it('roundTo(1.23456, 4) = 1.2346', () => { + assert.equal(number.roundTo(1.23456, 4), 1.2346) + }) + + it('roundTo(234.23456, 4) = 234.2346', () => { + assert.equal(number.roundTo(234.23456, 4), 234.2346) + }) + + it('roundTo(234.2345671, 4) = 234.2346', () => { + assert.equal(number.roundTo(234.2345671, 4), 234.2346) + }) + it('roundTo(234.2344671, 3) = 234.234', () => { + assert.equal(number.roundTo(234.2344671, 3), 234.234) + }) + it('roundTo(234.2343671, 3) = 234.234', () => { + assert.equal(number.roundTo(234.2343671, 3), 234.234) + }) + }) + + describe('toReadable', () => { + it("toReadable(1234567) = '1.234.567'", () => { + assert.equal(number.toReadable(1234567), '1.234.567') + }) + }) +}) diff --git a/test/object.test.ts b/packages/utils/test/object.test.ts similarity index 58% rename from test/object.test.ts rename to packages/utils/test/object.test.ts index 6516f9e..af4e4f1 100644 --- a/test/object.test.ts +++ b/packages/utils/test/object.test.ts @@ -1,18 +1,17 @@ -import assert from 'node:assert' -import { describe, it, test } from 'node:test' +import { assert, describe, it } from 'vitest' import { getJsonKeys, getObjectLength, isEmptyObject, notEmptyObject } from '../src/object/index.ts' describe('object utils', () => { describe('getObjectLength', () => { - test('empty object', () => { + it('should return 0 for empty object', () => { assert.strictEqual(getObjectLength({}), 0, 'empty objects should have a length of zero.') }) - test('object with one key', () => { + it('should return 1 for an object with one entry', () => { assert.strictEqual(getObjectLength({ hello: 'world' }), 1) }) - test('obect with two keys', () => { + it('should return 2 for an object with two entries', () => { assert.equal( getObjectLength({ hello: 'world', @@ -21,7 +20,7 @@ describe('object utils', () => { 2 ) }) - test('obect with nested object', () => { + it('should return 2 for a nested object that has two top entries', () => { assert.equal( getObjectLength({ hello: 'world', @@ -32,16 +31,18 @@ describe('object utils', () => { }) }) - test('getJsonKeys', () => { - const test = { hello: 'world', foo: 'bar' } - const result = ['hello', 'foo'] - const testResult = getJsonKeys(test) - assert.equal(testResult[0], result[0]) - assert.equal(testResult[1], result[1]) - // just using `Object.keys` - const testResultSimple = Object.keys(test) - assert.equal(testResultSimple[0], result[0]) - assert.equal(testResultSimple[1], result[1]) + describe('getJsonKeys', () => { + it('should return the keys of an object', () => { + const test = { hello: 'world', foo: 'bar' } + const result = ['hello', 'foo'] + const testResult = getJsonKeys(test) + assert.equal(testResult[0], result[0]) + assert.equal(testResult[1], result[1]) + // just using `Object.keys` + const testResultSimple = Object.keys(test) + assert.equal(testResultSimple[0], result[0]) + assert.equal(testResultSimple[1], result[1]) + }) }) describe('isEmptyObject', () => { @@ -55,15 +56,15 @@ describe('object utils', () => { }) describe('notEmptyObject', () => { - test('non empty objects return `true`', () => { + it('should return true for non empty objects', () => { assert.equal(notEmptyObject({ hello: 'world' }), true, 'a non-empty object must be true') }) - test('empty objects', () => { + it('should return false for an empty object', () => { assert.equal(notEmptyObject({}), false, 'non empty objects must be false') }) - it('is `false` for non-objects', () => { + it('should return false for non-objects', () => { // @ts-expect-error for testing `false` is alright assert.equal(notEmptyObject(false), false) assert.equal(notEmptyObject([]), false) diff --git a/test/predicate.test.ts b/packages/utils/test/predicate.test.ts similarity index 62% rename from test/predicate.test.ts rename to packages/utils/test/predicate.test.ts index 3c04384..2a55ca7 100644 --- a/test/predicate.test.ts +++ b/packages/utils/test/predicate.test.ts @@ -1,23 +1,22 @@ -import assert from 'node:assert' -import { describe, it, test } from 'node:test' +import { assert, describe, it } from 'vitest' import { isArray, isNull, isObject, isPlainObject, isUndefined, notNullOrUndefined } from '../src/predicate/index.ts' describe('predicate utils', () => { describe('isArray', () => { - it("isArray(['hello world']) = true", () => { + it('should return true for an array with one element in it', () => { assert.equal(isArray(['hello world']), true) }) - it("isArray({ hello: 'world' }) = false", () => { + it('should return false when passing an object', () => { assert.equal(isArray({ hello: 'world' }), false) }) - test('valid arrays', () => { + it('should return true for any array', () => { assert(isArray([])) assert(isArray([0])) assert(isArray([false])) }) - test('non arrays', () => { + it('should return false for all non-array values', () => { assert(!isArray(true)) assert(!isArray(false)) assert(!isArray('')) @@ -29,11 +28,11 @@ describe('predicate utils', () => { }) describe('isNull', () => { - test('null returns `true`', () => { + it('should return `true` for null', () => { assert(isNull(null)) }) - test('non null values all return `false`', () => { + it('should return `false` for non-null values', () => { assert.equal(isNull(undefined), false) assert.equal(isNull(''), false) assert.equal(isNull(false), false) @@ -44,15 +43,17 @@ describe('predicate utils', () => { }) describe('isObject', () => { - it("isObject({ hello: 'world' }) = true", () => { + it('should return true for an object', () => { assert.equal(isObject({ hello: 'world' }), true) }) - it("isObject('hello world') = false", () => { + it('should return false for non-objects like strings', () => { assert.equal(isObject('hello world'), false) + assert.equal(isObject(123), false) + assert.equal(isObject(true), false) }) - it('is true with functions', () => assert(isObject(() => {}))) + it('should return true for functions as value', () => assert(isObject(() => {}))) }) describe('isPlainObject', () => { @@ -83,16 +84,24 @@ describe('predicate utils', () => { }) describe('Test notNullOrUndefined', () => { - it("notNullOrUndefined('hello world') = true", () => { + it('should return true for strings and numbers', () => { assert.equal(notNullOrUndefined('hello world'), true) + assert.equal(notNullOrUndefined(123), true) }) - it('notNullOrUndefined(null) = false', () => { + it('should return true booleans', () => { + assert.equal(notNullOrUndefined(true), true) + assert.equal(notNullOrUndefined(false), true) + }) + + it('should return false when passing null', () => { assert.equal(notNullOrUndefined(null), false) }) - it('notNullOrUndefined(undefined) = false', () => { + it('should return false when passing undefined', () => { assert.equal(notNullOrUndefined(undefined), false) + let undefVar: unknown + assert.equal(notNullOrUndefined(undefVar), false) }) }) }) diff --git a/test/string.test.ts b/packages/utils/test/string.test.ts similarity index 57% rename from test/string.test.ts rename to packages/utils/test/string.test.ts index 68b7ef9..e6cdce3 100644 --- a/test/string.test.ts +++ b/packages/utils/test/string.test.ts @@ -1,26 +1,41 @@ -import assert from 'node:assert' -import { describe, it, test } from 'node:test' +import { assert, describe, it } from 'vitest' import { capitalize, isEmptyString, isIncluded, pluralize, removeDoubleSpaces, toHex } from '../src/string/index.ts' describe('string utils', () => { describe('capitalize', () => { - test("don't capitalize anything on an empty string", () => { + it("don't capitalize anything on an empty string", () => { assert.equal(capitalize(''), '') }) - test('capitalize one letter', () => { + it('capitalize one letter', () => { assert.equal(capitalize('a'), 'A') }) - test('capitalize only the first letter', () => { + it('capitalize only the first letter', () => { assert.equal(capitalize('apple'), 'Apple') }) - test('capitalize only the first word', () => { + it('capitalize only the first word', () => { assert.equal(capitalize('happy tree friends'), 'Happy tree friends') }) }) - test('isEmptyString', () => { - assert.equal(isEmptyString(''), true, '`true` was expected for an empty string') - assert.equal(isEmptyString('hello world'), false, '`false` was expected for a non empty string') + describe('isEmptyString', () => { + it('should return true if the string is empty', () => { + assert.equal(isEmptyString(''), true, '`true` was expected for an empty string') + assert.equal(isEmptyString(``), true, '`true` was expected for an empty template-string') + }) + + it('should return false if the string is not empty', () => { + assert.equal(isEmptyString('hello world'), false, '`false` was expected for a non empty string') + assert.equal(isEmptyString(`hello world`), false, '`false` was expected for a non empty template-string') + }) + + it('should return false for non-strings', () => { + // @ts-expect-error - isEmptyString only accepts strings + assert.equal(isEmptyString(null), false) + // @ts-expect-error - isEmptyString only accepts strings + assert.equal(isEmptyString(undefined), false) + // @ts-expect-error - isEmptyString only accepts strings + assert.equal(isEmptyString(false), false) + }) }) describe('isIncluded', () => { @@ -70,7 +85,13 @@ describe('string utils', () => { }) }) - test('toHex', () => { - assert.equal(toHex('hello world'), '68656c6c6f20776f726c64', 'The hex value did not match the expected value.') + describe('toHex', () => { + it('should return the correct hex value of the given input string', () => { + assert.equal( + toHex('hello world'), + '68656c6c6f20776f726c64', + 'The hex value did not match the expected value.' + ) + }) }) }) diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json new file mode 100644 index 0000000..435d58b --- /dev/null +++ b/packages/utils/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist" + }, + "include": ["src/**/*"], + "exclude": ["**/dist/**"] +} diff --git a/packages/utils/tsdown.config.ts b/packages/utils/tsdown.config.ts new file mode 100644 index 0000000..f63934b --- /dev/null +++ b/packages/utils/tsdown.config.ts @@ -0,0 +1,18 @@ +import { defineConfig } from 'tsdown' + +export default defineConfig({ + entry: { + index: 'src/index.ts', + + ard: 'src/ard/index.ts', + 'ard-coreId': 'src/ard/coreId.ts', + + array: 'src/array/index.ts', + env: 'src/env.ts', + helper: 'src/helpers/index.ts', + number: 'src/number/index.ts', + object: 'src/object/index.ts', + predicate: 'src/predicate/index.ts', + string: 'src/string/index.ts', + }, +}) diff --git a/packages/utils/vitest.config.ts b/packages/utils/vitest.config.ts new file mode 100644 index 0000000..4c83245 --- /dev/null +++ b/packages/utils/vitest.config.ts @@ -0,0 +1,9 @@ +import { coverageConfigDefaults, defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + coverage: { + exclude: [...coverageConfigDefaults.exclude, '**/tsdown.config.ts', '**/bin/*', '**/src/index.ts'], + }, + }, +}) diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 0000000..7678a4b --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,12 @@ +import audiolabPretterConfig from '@swrlab/style-guide/prettier.js' + +/** + * @see https://prettier.io/docs/configuration + * @type {import('prettier').Config} + */ +const config = { + ...audiolabPretterConfig, + printWidth: 120, +} + +export default config diff --git a/src/legacy/ard.ts b/src/legacy/ard.ts deleted file mode 100644 index 910833f..0000000 --- a/src/legacy/ard.ts +++ /dev/null @@ -1 +0,0 @@ -export { createHashedId } from '../ard/index.ts' diff --git a/src/legacy/date.ts b/src/legacy/date.ts deleted file mode 100644 index 3ea75b1..0000000 --- a/src/legacy/date.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { getDateHourMinutes as getDateHourMinutesNew } from '../date/getDateHourMinutes.ts' -import { getDayMonthYear as getDayMonthYearNew } from '../date/getDayMonthYear.ts' -import { getFullRelativeTimeLegacy } from '../date/getFullRelativeTime.ts' -import { getHourMinutes } from '../date/getHourMinutes.ts' -import { getIsoRelativeTime } from '../date/getIsoRelativeTime.ts' -import { getRelativeTime } from '../date/getRelativeTime.ts' -import { getYearMonthDay } from '../date/getYearMonthDay.ts' -import { toDayMonthYear as revYearMonthDay } from '../date/toDayMonthYear.ts' -import { formatDateTimeString, type ISODateString, shortenWeekday } from '../date/utils.ts' - -const getDateHourMinutes = (date: ISODateString): string => formatDateTimeString(getDateHourMinutesNew(date)) -const getDayMonthYear = (date: ISODateString): string => shortenWeekday(getDayMonthYearNew(date)) -const getFullRelativeTime = (date: ISODateString): string => getFullRelativeTimeLegacy(date) - -export { - getDateHourMinutes, - getDayMonthYear, - getFullRelativeTime, - getHourMinutes, - getIsoRelativeTime, - getRelativeTime, - getYearMonthDay, - revYearMonthDay, -} diff --git a/src/legacy/helpers.ts b/src/legacy/helpers.ts deleted file mode 100644 index 4d95b22..0000000 --- a/src/legacy/helpers.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { arrayToObjectCount } from '../array/arrayToObjectCount.ts' -export { sleep } from '../helpers/sleep.ts' -export { getJsonKeys } from '../object/getJsonKeys.ts' diff --git a/src/legacy/numbers.ts b/src/legacy/numbers.ts deleted file mode 100644 index 9631a0a..0000000 --- a/src/legacy/numbers.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { addLeadingZero } from '../number/addLeadingZero.ts' -import { addTrailingZeros } from '../number/addTrailingZeros.ts' -import { getAverage } from '../number/getAverage.ts' -import { getDiff } from '../number/getDiff.ts' -import { getRandomInRange } from '../number/getRandomInRange.ts' -import { getSum } from '../number/getSum.ts' -import { isEven } from '../number/isEven.ts' -import { normalize } from '../number/normalize.ts' -import { roundTo } from '../number/roundTo.ts' -import { toReadable } from '../number/toReadable.ts' - -export { - addLeadingZero, - addTrailingZeros, - getAverage, - getDiff, - getRandomInRange, - getSum, - isEven, - normalize, - roundTo, - toReadable, -} diff --git a/src/legacy/strings.ts b/src/legacy/strings.ts deleted file mode 100644 index 4417eb7..0000000 --- a/src/legacy/strings.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { isEmptyArray } from '../array/isEmptyArray.ts' -import { notEmptyArray } from '../array/notEmptyArray.ts' -import { getObjectLength } from '../object/getObjectLength.ts' -import { isEmptyObject } from '../object/isEmptyObject.ts' -import { notEmptyObject } from '../object/notEmptyObject.ts' -import { isArray } from '../predicate/isArray.ts' -import { isNull } from '../predicate/isNull.ts' -import { isObject } from '../predicate/isObject.ts' -import { isUndefined } from '../predicate/isUndefined.ts' -import { notNullOrUndefined } from '../predicate/notNullOrUndefined.ts' -import { capitalize } from '../string/capitalize.ts' -import { isEmptyString } from '../string/isEmptyString.ts' -import { isIncluded } from '../string/isIncluded.ts' -import { pluralize } from '../string/pluralize.ts' -import { removeDoubleSpaces } from '../string/removeDoubleSpaces.ts' -import { toHex } from '../string/toHex.ts' - -export { - capitalize, - getObjectLength, - isArray, - isEmptyArray, - isEmptyObject, - isEmptyString, - isIncluded, - isNull, - isObject, - isUndefined, - notEmptyArray, - notEmptyObject, - notNullOrUndefined, - pluralize, - removeDoubleSpaces, - toHex, -} diff --git a/src/storage/createUrl.ts b/src/storage/createUrl.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/storage/delete.ts b/src/storage/delete.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/storage/list.ts b/src/storage/list.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/storage/load.ts b/src/storage/load.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/storage/move.ts b/src/storage/move.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/storage/save.ts b/src/storage/save.ts deleted file mode 100644 index e69de29..0000000 diff --git a/test/ard.test.bun.ts b/test/ard.test.bun.ts deleted file mode 100644 index 7d01f99..0000000 --- a/test/ard.test.bun.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @fileoverview A port of the ard test to bun using bun's `expect` (that behaves like jest). - * NOTE: This file cannot be run in nodejs, since node does not know `bun:test`. - */ -import { describe, expect, it } from 'bun:test' -import { createHashedId } from '../src/ard/index.ts' - -describe('Test ARD Package', () => { - describe('Test ARD-CoreID Hash', () => { - it("createHashedId('test') = 0c171b2e54a30c11", () => { - expect(createHashedId('test')).toEqual('0c171b2e54a30c11') - }) - }) -}) diff --git a/test/ard.test.ts b/test/ard.test.ts deleted file mode 100644 index 7fd0c76..0000000 --- a/test/ard.test.ts +++ /dev/null @@ -1,9 +0,0 @@ -import assert from 'node:assert' -import { describe, test } from 'node:test' -import { createHashedId } from '../src/ard/index.ts' - -describe('ard utils', () => { - test('createHashedId', () => { - assert.equal(createHashedId('test'), '0c171b2e54a30c11', 'expected hash for the input `test` does not match.') - }) -}) diff --git a/test/helpers.test.ts b/test/helpers.test.ts deleted file mode 100644 index 46a4581..0000000 --- a/test/helpers.test.ts +++ /dev/null @@ -1,16 +0,0 @@ -import assert from 'node:assert' -import { describe, it, skip } from 'node:test' -import { sleep } from '../src/helpers/index.ts' - -describe('helpers', () => { - // skip sleep test, since it works and takes "too long" - skip('sleep', () => { - it('will sleep for one second', async () => { - const time = 1e3 - const before = Date.now() - await sleep(time) - const after = Date.now() - assert(after - before >= time) - }) - }) -}) diff --git a/test/number.test.ts b/test/number.test.ts deleted file mode 100644 index 3ad454d..0000000 --- a/test/number.test.ts +++ /dev/null @@ -1,133 +0,0 @@ -import assert from 'node:assert' -import { describe, it, test } from 'node:test' -import * as number from '../src/number/index.ts' - -describe('number utils', () => { - describe('addLeadingZero', () => { - it('prepends a zero for one-digit numbers', () => { - assert.equal(number.addLeadingZero(1), '01') - }) - - it('does not change anything for two-digit numbers', () => { - assert.equal(number.addLeadingZero(10), '10') - }) - }) - - describe('addTrailingZeros', () => { - it("addTrailingZeros(1, 5) = '1.00000'", () => { - assert.equal(number.addTrailingZeros(1, 5), '1.00000') - }) - - it("addTrailingZeros(1.1, 5) = '1.10000'", () => { - assert.equal(number.addTrailingZeros(1.1, 5), '1.10000') - }) - - it("addTrailingZeros('1.2', 5) = '1.20000'", () => { - assert.equal(number.addTrailingZeros('1.2', 5), '1.20000') - }) - - it("addTrailingZeros(2, 2, ',') = '2,00'", () => { - assert.equal(number.addTrailingZeros(2, 2, ','), '2,00') - }) - - it("addTrailingZeros(2.1, 2, ',') = '2,10'", () => { - assert.equal(number.addTrailingZeros(2.1, 2, ','), '2,10') - }) - - it("addTrailingZeros('2,2', 2, ','') = '2,20'", () => { - assert.equal(number.addTrailingZeros('2,2', 2, ','), '2,20') - }) - }) - - describe('getAverage', () => { - it('getAverage([1, 2, 3]) = 2', () => { - assert.equal(number.getAverage([1, 2, 3]), 2) - }) - - it('getAverage([1.2, 2.4, 3.6], 1) = 2.4', () => { - assert.equal(number.getAverage([1.2, 2.4, 3.6], 1), 2.4) - }) - }) - - describe('getDiff', () => { - it('getDiff(2, 1) = 1', () => { - assert.equal(number.getDiff(2, 1), 1) - }) - - it('getDiff(1, 2) = -1', () => { - assert.equal(number.getDiff(1, 2), -1) - }) - }) - - describe('getRandomInRange', () => { - it('getRandomInRange(1, 5) = 1,2,3,4 or 5', () => { - assert([1, 2, 3, 4, 5].includes(number.getRandomInRange(1, 5))) - }) - - it('getRandomInRange(5, 9) = 5,6,7,8 or 9', () => { - assert([5, 6, 7, 8, 9].includes(number.getRandomInRange(5, 9))) - }) - }) - - describe('getSum', () => { - it('getSum([1, 2, 3]) = 6', () => { - assert.equal(number.getSum([1, 2, 3]), 6) - }) - - it('getSum([1.2, 2.4, 3.6], 1) = 7.2', () => { - assert.equal(number.getSum([1.2, 2.4, 3.6], 1), 7.2) - }) - }) - - describe('isEven', () => { - test('even numbers', () => { - assert(number.isEven(2)) - assert(number.isEven(4)) - }) - - test('uneven numbers', () => { - assert.equal(number.isEven(1), false) - assert.equal(number.isEven(11), false) - }) - }) - - describe('normalize', () => { - it('normalize(2, 100) = 0.02', () => { - assert.equal(number.normalize(2, 100), 0.02) - }) - - it('normalize(80, 100) = 0.8', () => { - assert.equal(number.normalize(80, 100), 0.8) - }) - }) - - describe('roundTo', () => { - it('roundTo(1.23456) = 1.23', () => { - assert.equal(number.roundTo(1.23456), 1.23) - }) - - it('roundTo(1.23456, 4) = 1.2346', () => { - assert.equal(number.roundTo(1.23456, 4), 1.2346) - }) - - it('roundTo(234.23456, 4) = 234.2346', () => { - assert.equal(number.roundTo(234.23456, 4), 234.2346) - }) - - it('roundTo(234.2345671, 4) = 234.2346', () => { - assert.equal(number.roundTo(234.2345671, 4), 234.2346) - }) - it('roundTo(234.2344671, 3) = 234.234', () => { - assert.equal(number.roundTo(234.2344671, 3), 234.234) - }) - it('roundTo(234.2343671, 3) = 234.234', () => { - assert.equal(number.roundTo(234.2343671, 3), 234.234) - }) - }) - - describe('toReadable', () => { - it("toReadable(1234567) = '1.234.567'", () => { - assert.equal(number.toReadable(1234567), '1.234.567') - }) - }) -}) diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..d4c12ca --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,37 @@ +{ + "compilerOptions": { + "incremental": true, + "composite": true, + "target": "esnext", + "module": "nodenext", + + "resolveJsonModule": true, + + "allowImportingTsExtensions": true, + + "strict": true, + "exactOptionalPropertyTypes": true, + + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + + "noImplicitReturns": true, + + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "declaration": true, + "declarationMap": true, + "isolatedDeclarations": true, + "noEmitOnError": true, + + "sourceMap": true, + "erasableSyntaxOnly": true, + "forceConsistentCasingInFileNames": true, + "isolatedModules": true, + "verbatimModuleSyntax": true, + "rewriteRelativeImportExtensions": true, + "skipLibCheck": true, + "noUncheckedSideEffectImports": true + } +} diff --git a/tsconfig.json b/tsconfig.json index 5fc09ea..e11b56a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,44 +1,16 @@ { + "extends": "./tsconfig.base.json", "compilerOptions": { - "target": "esnext", - "rootDir": "src", - "module": "nodenext", - // "lib": ["esnext"], - // "types": ["node"], - "resolveJsonModule": true, - - "allowImportingTsExtensions": true, - - // "noPropertyAccessFromIndexSignature": true, - - // Recommended Options - "strict": true, - "exactOptionalPropertyTypes": true, - - "noFallthroughCasesInSwitch": true, - "noImplicitOverride": true, - // Style Options - "noImplicitReturns": true, - // "noEmit": true, - - // Stricter Typechecking Options - "noUncheckedIndexedAccess": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "declaration": true, - "declarationMap": true, - "isolatedDeclarations": true, - "outDir": "dist", - // Other Outputs - "sourceMap": true, - "erasableSyntaxOnly": true, - "isolatedModules": true, - "verbatimModuleSyntax": true, // --> isolatedModules - "rewriteRelativeImportExtensions": true, - // "jsx": "react-jsx", - // "moduleDetection": "force", - "skipLibCheck": true, - "noUncheckedSideEffectImports": true + "noEmit": true }, - "include": ["src/**/*"] + "references": [ + // { "path": "./packages/date/tsconfig.json" }, + // { "path": "./packages/logger/tsconfig.json" }, + { "path": "./packages/legacy" }, + { "path": "./packages/storage" }, + { "path": "./packages/utils" } + ], + "include": [] + // "include": ["**/*.ts"], + // "exclude": ["node_modules", "packages"] } diff --git a/tsdown.config.ts b/tsdown.config.ts deleted file mode 100644 index 7be7200..0000000 --- a/tsdown.config.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { defineConfig } from 'tsdown' - -export default defineConfig({ - entry: { - index: 'src/index.ts', - - ard: 'src/ard/index.ts', - 'ard-coreId': 'src/ard/coreId.ts', - array: 'src/array/index.ts', - date: 'src/date/index.ts', - env: 'src/env.ts', - helper: 'src/helpers/index.ts', - number: 'src/number/index.ts', - object: 'src/object/index.ts', - predicate: 'src/predicate/index.ts', - storage: 'src/storage/index.ts', - string: 'src/string/index.ts', - - // legacy - 'packages/ard': './src/legacy/ard.ts', - 'packages/date': './src/legacy/date.ts', - 'packages/helpers': './src/legacy/helpers.ts', - 'packages/numbers': './src/legacy/numbers.ts', - 'packages/storage-wrapper': './src/legacy/storage-wrapper.ts', - 'packages/strings': './src/legacy/strings.ts', - 'packages/undici': './src/legacy/undici.ts', - }, -})