From 6c013a44a6075cc4cc6c6c68b6a917447ae60e0f Mon Sep 17 00:00:00 2001 From: Alberto Quiles Date: Sat, 3 Oct 2026 12:02:44 +0200 Subject: [PATCH] feat: add collections consts, types and validators - fix #3 --- .github/workflows/build.yml | 6 + .github/workflows/publish.yml | 6 + deno.lock | 2680 ++++++++++++++++++++++++ package.json | 8 +- src/consts/collection.consts.ts | 36 + src/consts/main.ts | 2 +- src/types/collection.types.ts | 39 + src/types/furniture.types.ts | 61 + src/types/main.ts | 3 +- src/utils/__tests__/collection.test.ts | 317 +++ src/utils/__tests__/furniture.test.ts | 238 +++ src/utils/collection.utils.ts | 269 +++ src/utils/furniture.utils.ts | 314 +++ src/utils/main.ts | 3 +- src/utils/validation.utils.ts | 55 + tsconfig.json | 11 +- 16 files changed, 4039 insertions(+), 9 deletions(-) create mode 100644 deno.lock create mode 100644 src/consts/collection.consts.ts create mode 100644 src/types/collection.types.ts create mode 100644 src/types/furniture.types.ts create mode 100644 src/utils/__tests__/collection.test.ts create mode 100644 src/utils/__tests__/furniture.test.ts create mode 100644 src/utils/collection.utils.ts create mode 100644 src/utils/furniture.utils.ts create mode 100644 src/utils/validation.utils.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bf14317..8df060b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,6 +24,12 @@ jobs: - name: run prettier checker run: yarn run prettier:check + - name: run type checker + run: yarn run typecheck + + - name: check browser bundle + run: yarn run bundle:check + - name: run tests run: yarn run test diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9cb613d..8c2ca84 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -36,6 +36,12 @@ jobs: - name: run prettier checker run: yarn run prettier:check + - name: run type checker + run: yarn run typecheck + + - name: check browser bundle + run: yarn run bundle:check + - name: run tests run: yarn run test diff --git a/deno.lock b/deno.lock new file mode 100644 index 0000000..a538712 --- /dev/null +++ b/deno.lock @@ -0,0 +1,2680 @@ +{ + "version": "5", + "specifiers": { + "npm:@babel/core@^7.26.0": "7.29.7", + "npm:@babel/preset-env@^7.26.0": "7.29.7_@babel+core@7.29.7", + "npm:@babel/preset-typescript@^7.26.0": "7.29.7_@babel+core@7.29.7", + "npm:babel-jest@^29.7.0": "29.7.0_@babel+core@7.29.7", + "npm:esbuild@0.23.0": "0.23.0", + "npm:jest@^29.7.0": "29.7.0", + "npm:jsr@~0.13.2": "0.13.5", + "npm:prettier@3.3.3": "3.3.3", + "npm:typescript@5.6.3": "5.6.3" + }, + "npm": { + "@babel/code-frame@7.29.7": { + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dependencies": [ + "@babel/helper-validator-identifier", + "js-tokens", + "picocolors" + ] + }, + "@babel/compat-data@7.29.7": { + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==" + }, + "@babel/core@7.29.7": { + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dependencies": [ + "@babel/code-frame", + "@babel/generator", + "@babel/helper-compilation-targets", + "@babel/helper-module-transforms", + "@babel/helpers", + "@babel/parser", + "@babel/template", + "@babel/traverse", + "@babel/types", + "@jridgewell/remapping", + "convert-source-map", + "debug", + "gensync", + "json5", + "semver@6.3.1" + ] + }, + "@babel/generator@7.29.8": { + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dependencies": [ + "@babel/parser", + "@babel/types", + "@jridgewell/gen-mapping", + "@jridgewell/trace-mapping", + "jsesc" + ] + }, + "@babel/helper-annotate-as-pure@7.29.7": { + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", + "dependencies": [ + "@babel/types" + ] + }, + "@babel/helper-compilation-targets@7.29.7": { + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dependencies": [ + "@babel/compat-data", + "@babel/helper-validator-option", + "browserslist", + "lru-cache", + "semver@6.3.1" + ] + }, + "@babel/helper-create-class-features-plugin@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", + "dependencies": [ + "@babel/core", + "@babel/helper-annotate-as-pure", + "@babel/helper-member-expression-to-functions", + "@babel/helper-optimise-call-expression", + "@babel/helper-replace-supers", + "@babel/helper-skip-transparent-expression-wrappers", + "@babel/traverse", + "semver@6.3.1" + ] + }, + "@babel/helper-create-regexp-features-plugin@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", + "dependencies": [ + "@babel/core", + "@babel/helper-annotate-as-pure", + "regexpu-core", + "semver@6.3.1" + ] + }, + "@babel/helper-define-polyfill-provider@0.6.8_@babel+core@7.29.7": { + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", + "dependencies": [ + "@babel/core", + "@babel/helper-compilation-targets", + "@babel/helper-plugin-utils", + "debug", + "lodash.debounce", + "resolve" + ] + }, + "@babel/helper-globals@7.29.7": { + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==" + }, + "@babel/helper-member-expression-to-functions@7.29.7": { + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", + "dependencies": [ + "@babel/traverse", + "@babel/types" + ] + }, + "@babel/helper-module-imports@7.29.7": { + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dependencies": [ + "@babel/traverse", + "@babel/types" + ] + }, + "@babel/helper-module-transforms@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dependencies": [ + "@babel/core", + "@babel/helper-module-imports", + "@babel/helper-validator-identifier", + "@babel/traverse" + ] + }, + "@babel/helper-optimise-call-expression@7.29.7": { + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", + "dependencies": [ + "@babel/types" + ] + }, + "@babel/helper-plugin-utils@7.29.7": { + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==" + }, + "@babel/helper-remap-async-to-generator@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", + "dependencies": [ + "@babel/core", + "@babel/helper-annotate-as-pure", + "@babel/helper-wrap-function", + "@babel/traverse" + ] + }, + "@babel/helper-replace-supers@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-member-expression-to-functions", + "@babel/helper-optimise-call-expression", + "@babel/traverse" + ] + }, + "@babel/helper-skip-transparent-expression-wrappers@7.29.7": { + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", + "dependencies": [ + "@babel/traverse", + "@babel/types" + ] + }, + "@babel/helper-string-parser@7.29.7": { + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==" + }, + "@babel/helper-validator-identifier@7.29.7": { + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==" + }, + "@babel/helper-validator-option@7.29.7": { + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==" + }, + "@babel/helper-wrap-function@7.29.7": { + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", + "dependencies": [ + "@babel/template", + "@babel/traverse", + "@babel/types" + ] + }, + "@babel/helpers@7.29.7": { + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dependencies": [ + "@babel/template", + "@babel/types" + ] + }, + "@babel/parser@7.29.9": { + "integrity": "sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==", + "dependencies": [ + "@babel/types" + ], + "bin": true + }, + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/traverse" + ] + }, + "@babel/plugin-bugfix-safari-class-field-initializer-scope@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/helper-skip-transparent-expression-wrappers" + ] + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/helper-skip-transparent-expression-wrappers", + "@babel/plugin-transform-optional-chaining" + ] + }, + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/traverse" + ] + }, + "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2_@babel+core@7.29.7": { + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dependencies": [ + "@babel/core" + ] + }, + "@babel/plugin-syntax-async-generators@7.8.4_@babel+core@7.29.7": { + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-bigint@7.8.3_@babel+core@7.29.7": { + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-class-properties@7.12.13_@babel+core@7.29.7": { + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-class-static-block@7.14.5_@babel+core@7.29.7": { + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-import-assertions@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-import-attributes@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-import-meta@7.10.4_@babel+core@7.29.7": { + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-json-strings@7.8.3_@babel+core@7.29.7": { + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-jsx@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-logical-assignment-operators@7.10.4_@babel+core@7.29.7": { + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-nullish-coalescing-operator@7.8.3_@babel+core@7.29.7": { + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-numeric-separator@7.10.4_@babel+core@7.29.7": { + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-object-rest-spread@7.8.3_@babel+core@7.29.7": { + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-optional-catch-binding@7.8.3_@babel+core@7.29.7": { + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-optional-chaining@7.8.3_@babel+core@7.29.7": { + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-private-property-in-object@7.14.5_@babel+core@7.29.7": { + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-top-level-await@7.14.5_@babel+core@7.29.7": { + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-typescript@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-syntax-unicode-sets-regex@7.18.6_@babel+core@7.29.7": { + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dependencies": [ + "@babel/core", + "@babel/helper-create-regexp-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-arrow-functions@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-async-generator-functions@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/helper-remap-async-to-generator", + "@babel/traverse" + ] + }, + "@babel/plugin-transform-async-to-generator@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", + "dependencies": [ + "@babel/core", + "@babel/helper-module-imports", + "@babel/helper-plugin-utils", + "@babel/helper-remap-async-to-generator" + ] + }, + "@babel/plugin-transform-block-scoped-functions@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-block-scoping@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-class-properties@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", + "dependencies": [ + "@babel/core", + "@babel/helper-create-class-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-class-static-block@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", + "dependencies": [ + "@babel/core", + "@babel/helper-create-class-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-classes@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", + "dependencies": [ + "@babel/core", + "@babel/helper-annotate-as-pure", + "@babel/helper-compilation-targets", + "@babel/helper-globals", + "@babel/helper-plugin-utils", + "@babel/helper-replace-supers", + "@babel/traverse" + ] + }, + "@babel/plugin-transform-computed-properties@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/template" + ] + }, + "@babel/plugin-transform-destructuring@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/traverse" + ] + }, + "@babel/plugin-transform-dotall-regex@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-create-regexp-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-duplicate-keys@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", + "dependencies": [ + "@babel/core", + "@babel/helper-create-regexp-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-dynamic-import@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-explicit-resource-management@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/plugin-transform-destructuring" + ] + }, + "@babel/plugin-transform-exponentiation-operator@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-export-namespace-from@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-for-of@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/helper-skip-transparent-expression-wrappers" + ] + }, + "@babel/plugin-transform-function-name@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", + "dependencies": [ + "@babel/core", + "@babel/helper-compilation-targets", + "@babel/helper-plugin-utils", + "@babel/traverse" + ] + }, + "@babel/plugin-transform-json-strings@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-literals@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-logical-assignment-operators@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-member-expression-literals@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-modules-amd@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", + "dependencies": [ + "@babel/core", + "@babel/helper-module-transforms", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-modules-commonjs@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-module-transforms", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-modules-systemjs@7.29.8_@babel+core@7.29.7": { + "integrity": "sha512-6iSnEK0zlkLKU4heofK/AdmRD4e2SHVpJMtrwnTCzhnaM98ria4rTrOXBBi45BTTYnJtO8txnPsX4fChYXkmeA==", + "dependencies": [ + "@babel/core", + "@babel/helper-module-transforms", + "@babel/helper-plugin-utils", + "@babel/helper-validator-identifier", + "@babel/traverse" + ] + }, + "@babel/plugin-transform-modules-umd@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", + "dependencies": [ + "@babel/core", + "@babel/helper-module-transforms", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-named-capturing-groups-regex@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-create-regexp-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-new-target@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-nullish-coalescing-operator@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-numeric-separator@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-object-rest-spread@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", + "dependencies": [ + "@babel/core", + "@babel/helper-compilation-targets", + "@babel/helper-plugin-utils", + "@babel/plugin-transform-destructuring", + "@babel/plugin-transform-parameters", + "@babel/traverse" + ] + }, + "@babel/plugin-transform-object-super@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/helper-replace-supers" + ] + }, + "@babel/plugin-transform-optional-catch-binding@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-optional-chaining@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/helper-skip-transparent-expression-wrappers" + ] + }, + "@babel/plugin-transform-parameters@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-private-methods@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", + "dependencies": [ + "@babel/core", + "@babel/helper-create-class-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-private-property-in-object@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", + "dependencies": [ + "@babel/core", + "@babel/helper-annotate-as-pure", + "@babel/helper-create-class-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-property-literals@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-regenerator@7.29.8_@babel+core@7.29.7": { + "integrity": "sha512-0UpIXPtdDtMXfnV2OJAVMLpj3H/92vmkA6lpSRakmycJvj3VUy6Xs1dM8tXRugupykr5WB+LpiVl0J8LMVg2mg==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-regexp-modifiers@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-create-regexp-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-reserved-words@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-shorthand-properties@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-spread@7.29.8_@babel+core@7.29.7": { + "integrity": "sha512-4S9ksMGVWUshvgK0mKfvZky7leuG5/uoFVwMpAomJ8bMoDJiNHRVmc1EglwW/CmGVSqqWpEbXm9FmbRit22qoA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/helper-skip-transparent-expression-wrappers" + ] + }, + "@babel/plugin-transform-sticky-regex@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-template-literals@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-typeof-symbol@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-typescript@7.29.9_@babel+core@7.29.7": { + "integrity": "sha512-FFwIwzU+7SCOuxxV4YtJql6T9981ZVTm+FHO5GhVsRqCTdy0WwrEZh3l42ARpXruJUDGOptdduHW6Zr7pNPLNg==", + "dependencies": [ + "@babel/core", + "@babel/helper-annotate-as-pure", + "@babel/helper-create-class-features-plugin", + "@babel/helper-plugin-utils", + "@babel/helper-skip-transparent-expression-wrappers", + "@babel/plugin-syntax-typescript" + ] + }, + "@babel/plugin-transform-unicode-escapes@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-unicode-property-regex@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", + "dependencies": [ + "@babel/core", + "@babel/helper-create-regexp-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-unicode-regex@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", + "dependencies": [ + "@babel/core", + "@babel/helper-create-regexp-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/plugin-transform-unicode-sets-regex@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", + "dependencies": [ + "@babel/core", + "@babel/helper-create-regexp-features-plugin", + "@babel/helper-plugin-utils" + ] + }, + "@babel/preset-env@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", + "dependencies": [ + "@babel/compat-data", + "@babel/core", + "@babel/helper-compilation-targets", + "@babel/helper-plugin-utils", + "@babel/helper-validator-option", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key", + "@babel/plugin-bugfix-safari-class-field-initializer-scope", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly", + "@babel/plugin-proposal-private-property-in-object", + "@babel/plugin-syntax-import-assertions", + "@babel/plugin-syntax-import-attributes", + "@babel/plugin-syntax-unicode-sets-regex", + "@babel/plugin-transform-arrow-functions", + "@babel/plugin-transform-async-generator-functions", + "@babel/plugin-transform-async-to-generator", + "@babel/plugin-transform-block-scoped-functions", + "@babel/plugin-transform-block-scoping", + "@babel/plugin-transform-class-properties", + "@babel/plugin-transform-class-static-block", + "@babel/plugin-transform-classes", + "@babel/plugin-transform-computed-properties", + "@babel/plugin-transform-destructuring", + "@babel/plugin-transform-dotall-regex", + "@babel/plugin-transform-duplicate-keys", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex", + "@babel/plugin-transform-dynamic-import", + "@babel/plugin-transform-explicit-resource-management", + "@babel/plugin-transform-exponentiation-operator", + "@babel/plugin-transform-export-namespace-from", + "@babel/plugin-transform-for-of", + "@babel/plugin-transform-function-name", + "@babel/plugin-transform-json-strings", + "@babel/plugin-transform-literals", + "@babel/plugin-transform-logical-assignment-operators", + "@babel/plugin-transform-member-expression-literals", + "@babel/plugin-transform-modules-amd", + "@babel/plugin-transform-modules-commonjs", + "@babel/plugin-transform-modules-systemjs", + "@babel/plugin-transform-modules-umd", + "@babel/plugin-transform-named-capturing-groups-regex", + "@babel/plugin-transform-new-target", + "@babel/plugin-transform-nullish-coalescing-operator", + "@babel/plugin-transform-numeric-separator", + "@babel/plugin-transform-object-rest-spread", + "@babel/plugin-transform-object-super", + "@babel/plugin-transform-optional-catch-binding", + "@babel/plugin-transform-optional-chaining", + "@babel/plugin-transform-parameters", + "@babel/plugin-transform-private-methods", + "@babel/plugin-transform-private-property-in-object", + "@babel/plugin-transform-property-literals", + "@babel/plugin-transform-regenerator", + "@babel/plugin-transform-regexp-modifiers", + "@babel/plugin-transform-reserved-words", + "@babel/plugin-transform-shorthand-properties", + "@babel/plugin-transform-spread", + "@babel/plugin-transform-sticky-regex", + "@babel/plugin-transform-template-literals", + "@babel/plugin-transform-typeof-symbol", + "@babel/plugin-transform-unicode-escapes", + "@babel/plugin-transform-unicode-property-regex", + "@babel/plugin-transform-unicode-regex", + "@babel/plugin-transform-unicode-sets-regex", + "@babel/preset-modules", + "babel-plugin-polyfill-corejs2", + "babel-plugin-polyfill-corejs3", + "babel-plugin-polyfill-regenerator", + "core-js-compat", + "semver@6.3.1" + ] + }, + "@babel/preset-modules@0.1.6-no-external-plugins_@babel+core@7.29.7": { + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/types", + "esutils" + ] + }, + "@babel/preset-typescript@7.29.7_@babel+core@7.29.7": { + "integrity": "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ==", + "dependencies": [ + "@babel/core", + "@babel/helper-plugin-utils", + "@babel/helper-validator-option", + "@babel/plugin-syntax-jsx", + "@babel/plugin-transform-modules-commonjs", + "@babel/plugin-transform-typescript" + ] + }, + "@babel/template@7.29.7": { + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dependencies": [ + "@babel/code-frame", + "@babel/parser", + "@babel/types" + ] + }, + "@babel/traverse@7.29.8": { + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dependencies": [ + "@babel/code-frame", + "@babel/generator", + "@babel/helper-globals", + "@babel/parser", + "@babel/template", + "@babel/types", + "debug" + ] + }, + "@babel/types@7.29.8": { + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dependencies": [ + "@babel/helper-string-parser", + "@babel/helper-validator-identifier" + ] + }, + "@bcoe/v8-coverage@0.2.3": { + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" + }, + "@esbuild/aix-ppc64@0.23.0": { + "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", + "os": ["aix"], + "cpu": ["ppc64"] + }, + "@esbuild/android-arm64@0.23.0": { + "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", + "os": ["android"], + "cpu": ["arm64"] + }, + "@esbuild/android-arm@0.23.0": { + "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", + "os": ["android"], + "cpu": ["arm"] + }, + "@esbuild/android-x64@0.23.0": { + "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", + "os": ["android"], + "cpu": ["x64"] + }, + "@esbuild/darwin-arm64@0.23.0": { + "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", + "os": ["darwin"], + "cpu": ["arm64"] + }, + "@esbuild/darwin-x64@0.23.0": { + "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", + "os": ["darwin"], + "cpu": ["x64"] + }, + "@esbuild/freebsd-arm64@0.23.0": { + "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", + "os": ["freebsd"], + "cpu": ["arm64"] + }, + "@esbuild/freebsd-x64@0.23.0": { + "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", + "os": ["freebsd"], + "cpu": ["x64"] + }, + "@esbuild/linux-arm64@0.23.0": { + "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", + "os": ["linux"], + "cpu": ["arm64"] + }, + "@esbuild/linux-arm@0.23.0": { + "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", + "os": ["linux"], + "cpu": ["arm"] + }, + "@esbuild/linux-ia32@0.23.0": { + "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", + "os": ["linux"], + "cpu": ["ia32"] + }, + "@esbuild/linux-loong64@0.23.0": { + "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", + "os": ["linux"], + "cpu": ["loong64"] + }, + "@esbuild/linux-mips64el@0.23.0": { + "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", + "os": ["linux"], + "cpu": ["mips64el"] + }, + "@esbuild/linux-ppc64@0.23.0": { + "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", + "os": ["linux"], + "cpu": ["ppc64"] + }, + "@esbuild/linux-riscv64@0.23.0": { + "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", + "os": ["linux"], + "cpu": ["riscv64"] + }, + "@esbuild/linux-s390x@0.23.0": { + "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", + "os": ["linux"], + "cpu": ["s390x"] + }, + "@esbuild/linux-x64@0.23.0": { + "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", + "os": ["linux"], + "cpu": ["x64"] + }, + "@esbuild/netbsd-x64@0.23.0": { + "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", + "os": ["netbsd"], + "cpu": ["x64"] + }, + "@esbuild/openbsd-arm64@0.23.0": { + "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "os": ["openbsd"], + "cpu": ["arm64"] + }, + "@esbuild/openbsd-x64@0.23.0": { + "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", + "os": ["openbsd"], + "cpu": ["x64"] + }, + "@esbuild/sunos-x64@0.23.0": { + "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", + "os": ["sunos"], + "cpu": ["x64"] + }, + "@esbuild/win32-arm64@0.23.0": { + "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", + "os": ["win32"], + "cpu": ["arm64"] + }, + "@esbuild/win32-ia32@0.23.0": { + "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", + "os": ["win32"], + "cpu": ["ia32"] + }, + "@esbuild/win32-x64@0.23.0": { + "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", + "os": ["win32"], + "cpu": ["x64"] + }, + "@istanbuljs/load-nyc-config@1.1.0": { + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dependencies": [ + "camelcase@5.3.1", + "find-up", + "get-package-type", + "js-yaml", + "resolve-from" + ] + }, + "@istanbuljs/schema@0.1.6": { + "integrity": "sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==" + }, + "@jest/console@29.7.0": { + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dependencies": [ + "@jest/types", + "@types/node", + "chalk", + "jest-message-util", + "jest-util", + "slash" + ] + }, + "@jest/core@29.7.0": { + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dependencies": [ + "@jest/console", + "@jest/reporters", + "@jest/test-result", + "@jest/transform", + "@jest/types", + "@types/node", + "ansi-escapes", + "chalk", + "ci-info", + "exit", + "graceful-fs", + "jest-changed-files", + "jest-config", + "jest-haste-map", + "jest-message-util", + "jest-regex-util", + "jest-resolve", + "jest-resolve-dependencies", + "jest-runner", + "jest-runtime", + "jest-snapshot", + "jest-util", + "jest-validate", + "jest-watcher", + "micromatch", + "pretty-format", + "slash", + "strip-ansi" + ] + }, + "@jest/environment@29.7.0": { + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dependencies": [ + "@jest/fake-timers", + "@jest/types", + "@types/node", + "jest-mock" + ] + }, + "@jest/expect-utils@29.7.0": { + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dependencies": [ + "jest-get-type" + ] + }, + "@jest/expect@29.7.0": { + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dependencies": [ + "expect", + "jest-snapshot" + ] + }, + "@jest/fake-timers@29.7.0": { + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dependencies": [ + "@jest/types", + "@sinonjs/fake-timers", + "@types/node", + "jest-message-util", + "jest-mock", + "jest-util" + ] + }, + "@jest/globals@29.7.0": { + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dependencies": [ + "@jest/environment", + "@jest/expect", + "@jest/types", + "jest-mock" + ] + }, + "@jest/reporters@29.7.0": { + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dependencies": [ + "@bcoe/v8-coverage", + "@jest/console", + "@jest/test-result", + "@jest/transform", + "@jest/types", + "@jridgewell/trace-mapping", + "@types/node", + "chalk", + "collect-v8-coverage", + "exit", + "glob", + "graceful-fs", + "istanbul-lib-coverage", + "istanbul-lib-instrument@6.0.3", + "istanbul-lib-report", + "istanbul-lib-source-maps", + "istanbul-reports", + "jest-message-util", + "jest-util", + "jest-worker", + "slash", + "string-length", + "strip-ansi", + "v8-to-istanbul" + ] + }, + "@jest/schemas@29.6.3": { + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": [ + "@sinclair/typebox" + ] + }, + "@jest/source-map@29.6.3": { + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dependencies": [ + "@jridgewell/trace-mapping", + "callsites", + "graceful-fs" + ] + }, + "@jest/test-result@29.7.0": { + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dependencies": [ + "@jest/console", + "@jest/types", + "@types/istanbul-lib-coverage", + "collect-v8-coverage" + ] + }, + "@jest/test-sequencer@29.7.0": { + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dependencies": [ + "@jest/test-result", + "graceful-fs", + "jest-haste-map", + "slash" + ] + }, + "@jest/transform@29.7.0": { + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dependencies": [ + "@babel/core", + "@jest/types", + "@jridgewell/trace-mapping", + "babel-plugin-istanbul", + "chalk", + "convert-source-map", + "fast-json-stable-stringify", + "graceful-fs", + "jest-haste-map", + "jest-regex-util", + "jest-util", + "micromatch", + "pirates", + "slash", + "write-file-atomic" + ] + }, + "@jest/types@29.6.3": { + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": [ + "@jest/schemas", + "@types/istanbul-lib-coverage", + "@types/istanbul-reports", + "@types/node", + "@types/yargs", + "chalk" + ] + }, + "@jridgewell/gen-mapping@0.3.13": { + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dependencies": [ + "@jridgewell/sourcemap-codec", + "@jridgewell/trace-mapping" + ] + }, + "@jridgewell/remapping@2.3.5": { + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dependencies": [ + "@jridgewell/gen-mapping", + "@jridgewell/trace-mapping" + ] + }, + "@jridgewell/resolve-uri@3.1.2": { + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==" + }, + "@jridgewell/sourcemap-codec@1.6.0": { + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==" + }, + "@jridgewell/trace-mapping@0.3.31": { + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dependencies": [ + "@jridgewell/resolve-uri", + "@jridgewell/sourcemap-codec" + ] + }, + "@sinclair/typebox@0.27.12": { + "integrity": "sha512-hhyNJ+nbR6ZR7pToHvllEFun9TL0sbL+tk/ON75lo+Xas054uez98qRbsuNt7MBCyZKK4+8Yli/OAGZhmfBZ/g==" + }, + "@sinonjs/commons@3.0.1": { + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dependencies": [ + "type-detect" + ] + }, + "@sinonjs/fake-timers@10.3.0": { + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dependencies": [ + "@sinonjs/commons" + ] + }, + "@types/babel__core@7.20.5": { + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dependencies": [ + "@babel/parser", + "@babel/types", + "@types/babel__generator", + "@types/babel__template", + "@types/babel__traverse" + ] + }, + "@types/babel__generator@7.27.0": { + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dependencies": [ + "@babel/types" + ] + }, + "@types/babel__template@7.4.4": { + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dependencies": [ + "@babel/parser", + "@babel/types" + ] + }, + "@types/babel__traverse@7.28.0": { + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dependencies": [ + "@babel/types" + ] + }, + "@types/graceful-fs@4.1.9": { + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dependencies": [ + "@types/node" + ] + }, + "@types/istanbul-lib-coverage@2.0.6": { + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==" + }, + "@types/istanbul-lib-report@3.0.3": { + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dependencies": [ + "@types/istanbul-lib-coverage" + ] + }, + "@types/istanbul-reports@3.0.4": { + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dependencies": [ + "@types/istanbul-lib-report" + ] + }, + "@types/node@26.6.4": { + "integrity": "sha512-ldVPDCzj7fsaGZrLB0NuHuTvJcsNasysBAqMolr/cgxrLd1xbqxIr3XJiPnHHJUCxj5sNF1vnRj9aWnrVh5Jcg==", + "dependencies": [ + "undici-types" + ] + }, + "@types/stack-utils@2.0.3": { + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==" + }, + "@types/yargs-parser@21.0.3": { + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==" + }, + "@types/yargs@17.0.35": { + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dependencies": [ + "@types/yargs-parser" + ] + }, + "ansi-escapes@4.3.2": { + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": [ + "type-fest" + ] + }, + "ansi-regex@5.0.1": { + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles@4.3.0": { + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": [ + "color-convert" + ] + }, + "ansi-styles@5.2.0": { + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==" + }, + "anymatch@3.1.3": { + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": [ + "normalize-path", + "picomatch" + ] + }, + "argparse@1.0.10": { + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": [ + "sprintf-js" + ] + }, + "babel-jest@29.7.0_@babel+core@7.29.7": { + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dependencies": [ + "@babel/core", + "@jest/transform", + "@types/babel__core", + "babel-plugin-istanbul", + "babel-preset-jest", + "chalk", + "graceful-fs", + "slash" + ] + }, + "babel-plugin-istanbul@6.1.1": { + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dependencies": [ + "@babel/helper-plugin-utils", + "@istanbuljs/load-nyc-config", + "@istanbuljs/schema", + "istanbul-lib-instrument@5.2.1", + "test-exclude" + ] + }, + "babel-plugin-jest-hoist@29.6.3": { + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dependencies": [ + "@babel/template", + "@babel/types", + "@types/babel__core", + "@types/babel__traverse" + ] + }, + "babel-plugin-polyfill-corejs2@0.4.17_@babel+core@7.29.7": { + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", + "dependencies": [ + "@babel/compat-data", + "@babel/core", + "@babel/helper-define-polyfill-provider", + "semver@6.3.1" + ] + }, + "babel-plugin-polyfill-corejs3@0.14.2_@babel+core@7.29.7": { + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", + "dependencies": [ + "@babel/core", + "@babel/helper-define-polyfill-provider", + "core-js-compat" + ] + }, + "babel-plugin-polyfill-regenerator@0.6.8_@babel+core@7.29.7": { + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", + "dependencies": [ + "@babel/core", + "@babel/helper-define-polyfill-provider" + ] + }, + "babel-preset-current-node-syntax@1.2.0_@babel+core@7.29.7": { + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dependencies": [ + "@babel/core", + "@babel/plugin-syntax-async-generators", + "@babel/plugin-syntax-bigint", + "@babel/plugin-syntax-class-properties", + "@babel/plugin-syntax-class-static-block", + "@babel/plugin-syntax-import-attributes", + "@babel/plugin-syntax-import-meta", + "@babel/plugin-syntax-json-strings", + "@babel/plugin-syntax-logical-assignment-operators", + "@babel/plugin-syntax-nullish-coalescing-operator", + "@babel/plugin-syntax-numeric-separator", + "@babel/plugin-syntax-object-rest-spread", + "@babel/plugin-syntax-optional-catch-binding", + "@babel/plugin-syntax-optional-chaining", + "@babel/plugin-syntax-private-property-in-object", + "@babel/plugin-syntax-top-level-await" + ] + }, + "babel-preset-jest@29.6.3_@babel+core@7.29.7": { + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dependencies": [ + "@babel/core", + "babel-plugin-jest-hoist", + "babel-preset-current-node-syntax" + ] + }, + "balanced-match@1.0.2": { + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "baseline-browser-mapping@2.11.27": { + "integrity": "sha512-ElY12DaROGuan+lMmZ8Cvo/ZUbXPe7Enc/9VU/b1T3Kp4dwytRcNdR8DoSJN5SNJT/CuvcCA0DHDVmMOCePdRQ==", + "bin": true + }, + "brace-expansion@1.1.21": { + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", + "dependencies": [ + "balanced-match", + "concat-map" + ] + }, + "braces@3.0.3": { + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": [ + "fill-range" + ] + }, + "browserslist@4.29.3": { + "integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==", + "dependencies": [ + "baseline-browser-mapping", + "caniuse-lite", + "electron-to-chromium", + "node-releases", + "update-browserslist-db" + ], + "bin": true + }, + "bser@2.1.1": { + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dependencies": [ + "node-int64" + ] + }, + "buffer-from@1.1.2": { + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "callsites@3.1.0": { + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + }, + "camelcase@5.3.1": { + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "camelcase@6.3.0": { + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "caniuse-lite@1.0.30001814": { + "integrity": "sha512-/Uaf1lAzr59XcMpW0o96WoEfr+VXK2OX4U9AgFoiSHsVJ4HppnIFUjtYzsyDH2+tgANaQb2/oxYGwCPapN1FpA==" + }, + "chalk@4.1.2": { + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": [ + "ansi-styles@4.3.0", + "supports-color@7.2.0" + ] + }, + "char-regex@1.0.2": { + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==" + }, + "ci-info@3.9.0": { + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==" + }, + "cjs-module-lexer@1.4.3": { + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==" + }, + "cliui@8.0.1": { + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": [ + "string-width", + "strip-ansi", + "wrap-ansi" + ] + }, + "co@4.6.0": { + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==" + }, + "collect-v8-coverage@1.0.3": { + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==" + }, + "color-convert@2.0.1": { + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": [ + "color-name" + ] + }, + "color-name@1.1.4": { + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "concat-map@0.0.1": { + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "convert-source-map@2.0.0": { + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "core-js-compat@3.50.0": { + "integrity": "sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==", + "dependencies": [ + "browserslist" + ] + }, + "create-jest@29.7.0": { + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dependencies": [ + "@jest/types", + "chalk", + "exit", + "graceful-fs", + "jest-config", + "jest-util", + "prompts" + ], + "bin": true + }, + "cross-spawn@7.0.6": { + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": [ + "path-key", + "shebang-command", + "which" + ] + }, + "debug@4.4.3": { + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dependencies": [ + "ms" + ] + }, + "dedent@1.7.2": { + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==" + }, + "deepmerge@4.3.1": { + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" + }, + "detect-newline@3.1.0": { + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==" + }, + "diff-sequences@29.6.3": { + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==" + }, + "electron-to-chromium@1.5.444": { + "integrity": "sha512-5ss/uJfoDYDHT0lfJzT6FbcskIzROIOPf0BbbFkGcvDzoJU7i//9GDrwwIHQVmIsrAGiF3ihpADBRIsrEFt1rQ==" + }, + "emittery@0.13.1": { + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==" + }, + "emoji-regex@8.0.0": { + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "error-ex@1.3.4": { + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dependencies": [ + "is-arrayish" + ] + }, + "es-errors@1.3.0": { + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "esbuild@0.23.0": { + "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", + "optionalDependencies": [ + "@esbuild/aix-ppc64", + "@esbuild/android-arm", + "@esbuild/android-arm64", + "@esbuild/android-x64", + "@esbuild/darwin-arm64", + "@esbuild/darwin-x64", + "@esbuild/freebsd-arm64", + "@esbuild/freebsd-x64", + "@esbuild/linux-arm", + "@esbuild/linux-arm64", + "@esbuild/linux-ia32", + "@esbuild/linux-loong64", + "@esbuild/linux-mips64el", + "@esbuild/linux-ppc64", + "@esbuild/linux-riscv64", + "@esbuild/linux-s390x", + "@esbuild/linux-x64", + "@esbuild/netbsd-x64", + "@esbuild/openbsd-arm64", + "@esbuild/openbsd-x64", + "@esbuild/sunos-x64", + "@esbuild/win32-arm64", + "@esbuild/win32-ia32", + "@esbuild/win32-x64" + ], + "scripts": true, + "bin": true + }, + "escalade@3.2.0": { + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==" + }, + "escape-string-regexp@2.0.0": { + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==" + }, + "esprima@4.0.1": { + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": true + }, + "esutils@2.0.3": { + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "execa@5.1.1": { + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dependencies": [ + "cross-spawn", + "get-stream", + "human-signals", + "is-stream", + "merge-stream", + "npm-run-path", + "onetime", + "signal-exit", + "strip-final-newline" + ] + }, + "exit@0.1.2": { + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==" + }, + "expect@29.7.0": { + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dependencies": [ + "@jest/expect-utils", + "jest-get-type", + "jest-matcher-utils", + "jest-message-util", + "jest-util" + ] + }, + "fast-json-stable-stringify@2.1.0": { + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fb-watchman@2.0.2": { + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dependencies": [ + "bser" + ] + }, + "fill-range@7.1.1": { + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": [ + "to-regex-range" + ] + }, + "find-up@4.1.0": { + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": [ + "locate-path", + "path-exists" + ] + }, + "fs.realpath@1.0.0": { + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents@2.3.3": { + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "os": ["darwin"], + "scripts": true + }, + "function-bind@1.1.2": { + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "gensync@1.0.0-beta.2": { + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "get-caller-file@2.0.5": { + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + }, + "get-package-type@0.1.0": { + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==" + }, + "get-stream@6.0.1": { + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "glob@7.2.3": { + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": [ + "fs.realpath", + "inflight", + "inherits", + "minimatch", + "once", + "path-is-absolute" + ], + "deprecated": true + }, + "graceful-fs@4.2.11": { + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "has-flag@4.0.0": { + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "hasown@2.0.4": { + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dependencies": [ + "function-bind" + ] + }, + "html-escaper@2.0.2": { + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==" + }, + "human-signals@2.1.0": { + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + }, + "import-local@3.2.0": { + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dependencies": [ + "pkg-dir", + "resolve-cwd" + ], + "bin": true + }, + "imurmurhash@0.1.4": { + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==" + }, + "inflight@1.0.6": { + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": [ + "once", + "wrappy" + ], + "deprecated": true + }, + "inherits@2.0.4": { + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-arrayish@0.2.1": { + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" + }, + "is-core-module@2.17.0": { + "integrity": "sha512-J/vG0zBCbIKOQFfufSwyXdMrsohyJIUNkrnmo6WZGzoM7tr/lsbfW5b2BvisL6zsyMzK9UxV9L6c7AoFbyXHOA==", + "dependencies": [ + "hasown" + ] + }, + "is-fullwidth-code-point@3.0.0": { + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-generator-fn@2.1.0": { + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==" + }, + "is-number@7.0.0": { + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-stream@2.0.1": { + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "isexe@2.0.0": { + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "istanbul-lib-coverage@3.2.2": { + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==" + }, + "istanbul-lib-instrument@5.2.1": { + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dependencies": [ + "@babel/core", + "@babel/parser", + "@istanbuljs/schema", + "istanbul-lib-coverage", + "semver@6.3.1" + ] + }, + "istanbul-lib-instrument@6.0.3": { + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dependencies": [ + "@babel/core", + "@babel/parser", + "@istanbuljs/schema", + "istanbul-lib-coverage", + "semver@7.8.5" + ] + }, + "istanbul-lib-report@3.0.1": { + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dependencies": [ + "istanbul-lib-coverage", + "make-dir", + "supports-color@7.2.0" + ] + }, + "istanbul-lib-source-maps@4.0.1": { + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dependencies": [ + "debug", + "istanbul-lib-coverage", + "source-map" + ] + }, + "istanbul-reports@3.2.0": { + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dependencies": [ + "html-escaper", + "istanbul-lib-report" + ] + }, + "jest-changed-files@29.7.0": { + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dependencies": [ + "execa", + "jest-util", + "p-limit@3.1.0" + ] + }, + "jest-circus@29.7.0": { + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dependencies": [ + "@jest/environment", + "@jest/expect", + "@jest/test-result", + "@jest/types", + "@types/node", + "chalk", + "co", + "dedent", + "is-generator-fn", + "jest-each", + "jest-matcher-utils", + "jest-message-util", + "jest-runtime", + "jest-snapshot", + "jest-util", + "p-limit@3.1.0", + "pretty-format", + "pure-rand", + "slash", + "stack-utils" + ] + }, + "jest-cli@29.7.0": { + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dependencies": [ + "@jest/core", + "@jest/test-result", + "@jest/types", + "chalk", + "create-jest", + "exit", + "import-local", + "jest-config", + "jest-util", + "jest-validate", + "yargs" + ], + "bin": true + }, + "jest-config@29.7.0_@types+node@26.6.4": { + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dependencies": [ + "@babel/core", + "@jest/test-sequencer", + "@jest/types", + "@types/node", + "babel-jest", + "chalk", + "ci-info", + "deepmerge", + "glob", + "graceful-fs", + "jest-circus", + "jest-environment-node", + "jest-get-type", + "jest-regex-util", + "jest-resolve", + "jest-runner", + "jest-util", + "jest-validate", + "micromatch", + "parse-json", + "pretty-format", + "slash", + "strip-json-comments" + ], + "optionalPeers": [ + "@types/node" + ] + }, + "jest-diff@29.7.0": { + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dependencies": [ + "chalk", + "diff-sequences", + "jest-get-type", + "pretty-format" + ] + }, + "jest-docblock@29.7.0": { + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dependencies": [ + "detect-newline" + ] + }, + "jest-each@29.7.0": { + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dependencies": [ + "@jest/types", + "chalk", + "jest-get-type", + "jest-util", + "pretty-format" + ] + }, + "jest-environment-node@29.7.0": { + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dependencies": [ + "@jest/environment", + "@jest/fake-timers", + "@jest/types", + "@types/node", + "jest-mock", + "jest-util" + ] + }, + "jest-get-type@29.6.3": { + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==" + }, + "jest-haste-map@29.7.0": { + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dependencies": [ + "@jest/types", + "@types/graceful-fs", + "@types/node", + "anymatch", + "fb-watchman", + "graceful-fs", + "jest-regex-util", + "jest-util", + "jest-worker", + "micromatch", + "walker" + ], + "optionalDependencies": [ + "fsevents" + ] + }, + "jest-leak-detector@29.7.0": { + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dependencies": [ + "jest-get-type", + "pretty-format" + ] + }, + "jest-matcher-utils@29.7.0": { + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dependencies": [ + "chalk", + "jest-diff", + "jest-get-type", + "pretty-format" + ] + }, + "jest-message-util@29.7.0": { + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dependencies": [ + "@babel/code-frame", + "@jest/types", + "@types/stack-utils", + "chalk", + "graceful-fs", + "micromatch", + "pretty-format", + "slash", + "stack-utils" + ] + }, + "jest-mock@29.7.0": { + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dependencies": [ + "@jest/types", + "@types/node", + "jest-util" + ] + }, + "jest-pnp-resolver@1.2.3_jest-resolve@29.7.0": { + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dependencies": [ + "jest-resolve" + ], + "optionalPeers": [ + "jest-resolve" + ] + }, + "jest-regex-util@29.6.3": { + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==" + }, + "jest-resolve-dependencies@29.7.0": { + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dependencies": [ + "jest-regex-util", + "jest-snapshot" + ] + }, + "jest-resolve@29.7.0": { + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dependencies": [ + "chalk", + "graceful-fs", + "jest-haste-map", + "jest-pnp-resolver", + "jest-util", + "jest-validate", + "resolve", + "resolve.exports", + "slash" + ] + }, + "jest-runner@29.7.0": { + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dependencies": [ + "@jest/console", + "@jest/environment", + "@jest/test-result", + "@jest/transform", + "@jest/types", + "@types/node", + "chalk", + "emittery", + "graceful-fs", + "jest-docblock", + "jest-environment-node", + "jest-haste-map", + "jest-leak-detector", + "jest-message-util", + "jest-resolve", + "jest-runtime", + "jest-util", + "jest-watcher", + "jest-worker", + "p-limit@3.1.0", + "source-map-support" + ] + }, + "jest-runtime@29.7.0": { + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dependencies": [ + "@jest/environment", + "@jest/fake-timers", + "@jest/globals", + "@jest/source-map", + "@jest/test-result", + "@jest/transform", + "@jest/types", + "@types/node", + "chalk", + "cjs-module-lexer", + "collect-v8-coverage", + "glob", + "graceful-fs", + "jest-haste-map", + "jest-message-util", + "jest-mock", + "jest-regex-util", + "jest-resolve", + "jest-snapshot", + "jest-util", + "slash", + "strip-bom" + ] + }, + "jest-snapshot@29.7.0": { + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dependencies": [ + "@babel/core", + "@babel/generator", + "@babel/plugin-syntax-jsx", + "@babel/plugin-syntax-typescript", + "@babel/types", + "@jest/expect-utils", + "@jest/transform", + "@jest/types", + "babel-preset-current-node-syntax", + "chalk", + "expect", + "graceful-fs", + "jest-diff", + "jest-get-type", + "jest-matcher-utils", + "jest-message-util", + "jest-util", + "natural-compare", + "pretty-format", + "semver@7.8.5" + ] + }, + "jest-util@29.7.0": { + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dependencies": [ + "@jest/types", + "@types/node", + "chalk", + "ci-info", + "graceful-fs", + "picomatch" + ] + }, + "jest-validate@29.7.0": { + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dependencies": [ + "@jest/types", + "camelcase@6.3.0", + "chalk", + "jest-get-type", + "leven", + "pretty-format" + ] + }, + "jest-watcher@29.7.0": { + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dependencies": [ + "@jest/test-result", + "@jest/types", + "@types/node", + "ansi-escapes", + "chalk", + "emittery", + "jest-util", + "string-length" + ] + }, + "jest-worker@29.7.0": { + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dependencies": [ + "@types/node", + "jest-util", + "merge-stream", + "supports-color@8.1.1" + ] + }, + "jest@29.7.0": { + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dependencies": [ + "@jest/core", + "@jest/types", + "import-local", + "jest-cli" + ], + "bin": true + }, + "js-tokens@4.0.0": { + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml@3.15.2": { + "integrity": "sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==", + "dependencies": [ + "argparse", + "esprima" + ], + "bin": true + }, + "jsesc@3.1.0": { + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "bin": true + }, + "json-parse-even-better-errors@2.3.1": { + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" + }, + "json5@2.2.3": { + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": true + }, + "jsr@0.13.5": { + "integrity": "sha512-qQP20ZcG28pYes7bCq3uuvixl1TL1EpJzwLPfoQadSyWk9j2AID66qhW8+aXpRDRFDvDkXFnONsSRhpnnQAupg==", + "dependencies": [ + "node-stream-zip", + "semiver" + ], + "bin": true + }, + "kleur@3.0.3": { + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" + }, + "leven@3.1.0": { + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + }, + "lines-and-columns@1.2.4": { + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "locate-path@5.0.0": { + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": [ + "p-locate" + ] + }, + "lodash.debounce@4.0.8": { + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "lru-cache@5.1.1": { + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": [ + "yallist" + ] + }, + "make-dir@4.0.0": { + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dependencies": [ + "semver@7.8.5" + ] + }, + "makeerror@1.0.12": { + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dependencies": [ + "tmpl" + ] + }, + "merge-stream@2.0.0": { + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "micromatch@4.0.8": { + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": [ + "braces", + "picomatch" + ] + }, + "mimic-fn@2.1.0": { + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "minimatch@3.1.5": { + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dependencies": [ + "brace-expansion" + ] + }, + "ms@2.1.3": { + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "natural-compare@1.4.0": { + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node-int64@0.4.0": { + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" + }, + "node-releases@2.0.57": { + "integrity": "sha512-kQK9LGGFiHtrWiNhZtA7Qbw17AQz+dmsEKODRIVTXA9+e5MS/2gZEBhYJt13GrAz5/IOZKddH/0Z3TP/Zgo+yw==" + }, + "node-stream-zip@1.16.0": { + "integrity": "sha512-ObaRrRoR8T68wF6suxHd7R4XQNamij6ZQHrwG7Dx1D2zeHcDNLsIOBcWrIwtDm7AsCXBguaPHgXhcjxDa2szrg==" + }, + "normalize-path@3.0.0": { + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "npm-run-path@4.0.1": { + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dependencies": [ + "path-key" + ] + }, + "once@1.4.0": { + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": [ + "wrappy" + ] + }, + "onetime@5.1.2": { + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": [ + "mimic-fn" + ] + }, + "p-limit@2.3.0": { + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": [ + "p-try" + ] + }, + "p-limit@3.1.0": { + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": [ + "yocto-queue" + ] + }, + "p-locate@4.1.0": { + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": [ + "p-limit@2.3.0" + ] + }, + "p-try@2.2.0": { + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + }, + "parse-json@5.2.0": { + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dependencies": [ + "@babel/code-frame", + "error-ex", + "json-parse-even-better-errors", + "lines-and-columns" + ] + }, + "path-exists@4.0.0": { + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + }, + "path-is-absolute@1.0.1": { + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key@3.1.1": { + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse@1.0.7": { + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "picocolors@1.1.1": { + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "picomatch@2.3.2": { + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==" + }, + "pirates@4.0.7": { + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==" + }, + "pkg-dir@4.2.0": { + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dependencies": [ + "find-up" + ] + }, + "prettier@3.3.3": { + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "bin": true + }, + "pretty-format@29.7.0": { + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": [ + "@jest/schemas", + "ansi-styles@5.2.0", + "react-is" + ] + }, + "prompts@2.4.2": { + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": [ + "kleur", + "sisteransi" + ] + }, + "pure-rand@6.1.0": { + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==" + }, + "react-is@18.3.1": { + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "regenerate-unicode-properties@10.3.0": { + "integrity": "sha512-9ns8odR8e9q3otKeHj3DE80jZYKg6zVeZKE+zQmRKXFoVUcuiTGeO6iusDhPRoIQQPVPRvH+SfBhrTud4eczuw==", + "dependencies": [ + "regenerate" + ] + }, + "regenerate@1.4.2": { + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "regexpu-core@6.5.2": { + "integrity": "sha512-zkmVH92DlzjSFc4xKGZp/2BXIFrDIdBQBC8gUXKCsMgKYb1bkCkxfSuoW1werDjaTEMTbULkHtKFHe1L+Abnaw==", + "dependencies": [ + "regenerate", + "regenerate-unicode-properties", + "regjsgen", + "regjsparser", + "unicode-match-property-ecmascript", + "unicode-match-property-value-ecmascript" + ] + }, + "regjsgen@0.8.0": { + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==" + }, + "regjsparser@0.13.3": { + "integrity": "sha512-ycwFAS14Jw4mppvmK4GR/J6u3WpWpjkEApehuHtLc/8VpPNpDMbQ4WjqwplXifGeyKOzHSFLmSPqzksDQE2Sfg==", + "dependencies": [ + "jsesc" + ], + "bin": true + }, + "require-directory@2.1.1": { + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" + }, + "resolve-cwd@3.0.0": { + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dependencies": [ + "resolve-from" + ] + }, + "resolve-from@5.0.0": { + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" + }, + "resolve.exports@2.0.3": { + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==" + }, + "resolve@1.22.12": { + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dependencies": [ + "es-errors", + "is-core-module", + "path-parse", + "supports-preserve-symlinks-flag" + ], + "bin": true + }, + "semiver@1.1.0": { + "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==" + }, + "semver@6.3.1": { + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": true + }, + "semver@7.8.5": { + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "bin": true + }, + "shebang-command@2.0.0": { + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": [ + "shebang-regex" + ] + }, + "shebang-regex@3.0.0": { + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "signal-exit@3.0.7": { + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "sisteransi@1.0.5": { + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "slash@3.0.0": { + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "source-map-support@0.5.13": { + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dependencies": [ + "buffer-from", + "source-map" + ] + }, + "source-map@0.6.1": { + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "sprintf-js@1.0.3": { + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "stack-utils@2.0.6": { + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dependencies": [ + "escape-string-regexp" + ] + }, + "string-length@4.0.2": { + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dependencies": [ + "char-regex", + "strip-ansi" + ] + }, + "string-width@4.2.3": { + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": [ + "emoji-regex", + "is-fullwidth-code-point", + "strip-ansi" + ] + }, + "strip-ansi@6.0.1": { + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": [ + "ansi-regex" + ] + }, + "strip-bom@4.0.0": { + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==" + }, + "strip-final-newline@2.0.0": { + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "strip-json-comments@3.1.1": { + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + }, + "supports-color@7.2.0": { + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": [ + "has-flag" + ] + }, + "supports-color@8.1.1": { + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": [ + "has-flag" + ] + }, + "supports-preserve-symlinks-flag@1.0.0": { + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "test-exclude@6.0.0": { + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dependencies": [ + "@istanbuljs/schema", + "glob", + "minimatch" + ] + }, + "tmpl@1.0.5": { + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" + }, + "to-regex-range@5.0.1": { + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": [ + "is-number" + ] + }, + "type-detect@4.0.8": { + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-fest@0.21.3": { + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" + }, + "typescript@5.6.3": { + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "bin": true + }, + "undici-types@8.9.0": { + "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==" + }, + "unicode-canonical-property-names-ecmascript@2.0.1": { + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==" + }, + "unicode-match-property-ecmascript@2.0.0": { + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": [ + "unicode-canonical-property-names-ecmascript", + "unicode-property-aliases-ecmascript" + ] + }, + "unicode-match-property-value-ecmascript@2.2.1": { + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==" + }, + "unicode-property-aliases-ecmascript@2.2.0": { + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==" + }, + "update-browserslist-db@1.3.3_browserslist@4.29.3": { + "integrity": "sha512-pJ2sYawQS0R/WI928Gj5GlPhTGzbMelq0+4INtSYNDV9ErKJcX6xjGWkoG/VnB3dpUm00zALaqkrUD77pO5TDQ==", + "dependencies": [ + "browserslist", + "escalade", + "picocolors" + ], + "bin": true + }, + "v8-to-istanbul@9.3.0": { + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dependencies": [ + "@jridgewell/trace-mapping", + "@types/istanbul-lib-coverage", + "convert-source-map" + ] + }, + "walker@1.0.8": { + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dependencies": [ + "makeerror" + ] + }, + "which@2.0.2": { + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": [ + "isexe" + ], + "bin": true + }, + "wrap-ansi@7.0.0": { + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": [ + "ansi-styles@4.3.0", + "string-width", + "strip-ansi" + ] + }, + "wrappy@1.0.2": { + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "write-file-atomic@4.0.2": { + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dependencies": [ + "imurmurhash", + "signal-exit" + ] + }, + "y18n@5.0.8": { + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + }, + "yallist@3.1.1": { + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yargs-parser@21.1.1": { + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + }, + "yargs@17.7.3": { + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "dependencies": [ + "cliui", + "escalade", + "get-caller-file", + "require-directory", + "string-width", + "y18n", + "yargs-parser" + ] + }, + "yocto-queue@0.1.0": { + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" + } + }, + "workspace": { + "packageJson": { + "dependencies": [ + "npm:@babel/core@^7.26.0", + "npm:@babel/preset-env@^7.26.0", + "npm:@babel/preset-typescript@^7.26.0", + "npm:babel-jest@^29.7.0", + "npm:esbuild@0.23.0", + "npm:jest@^29.7.0", + "npm:jsr@~0.13.2", + "npm:prettier@3.3.3", + "npm:typescript@5.6.3" + ] + } + } +} diff --git a/package.json b/package.json index 55d9e18..68756ee 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,11 @@ { "scripts": { "deps": "deno run -A index.ts", - "test": "jest --passWithNoTests", + "test": "jest", "test:watch": "jest --watch", "test:coverage": "jest --coverage", + "typecheck": "tsc -p tsconfig.json", + "bundle:check": "esbuild index.ts --bundle --platform=browser --format=esm --log-level=warning > /dev/null", "prettier:check": "prettier -c ./", "prettier:write": "prettier --write .", "publish": "npx jsr publish --allow-dirty", @@ -16,7 +18,9 @@ "@babel/preset-typescript": "^7.26.0", "babel-jest": "^29.7.0", "jest": "^29.7.0", - "prettier": "3.3.3" + "prettier": "3.3.3", + "esbuild": "0.23.0", + "typescript": "5.6.3" }, "jest": { "testRegex": ".test.ts", diff --git a/src/consts/collection.consts.ts b/src/consts/collection.consts.ts new file mode 100644 index 0000000..f85964d --- /dev/null +++ b/src/consts/collection.consts.ts @@ -0,0 +1,36 @@ +export const COLLECTION_RESERVED_NAMESPACES = ["default", "openhotel"]; + +export const COLLECTION_ID_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/; +export const COLLECTION_ID_MAX_LENGTH = 32; + +export const COLLECTION_HOTEL_VERSION_REGEX = + /^v?\d+\.\d+\.\d+(-[a-z]+(\.\d+)?)?$/; + +export const COLLECTION_FORMAT_VERSION = 1; + +export const COLLECTION_LABEL_MAX_LENGTH = 64; +export const COLLECTION_DESCRIPTION_MAX_LENGTH = 256; +export const COLLECTION_LICENSE_MAX_LENGTH = 64; + +export const COLLECTION_MAX_FURNITURE = 250; +export const COLLECTION_FURNITURE_MAX_SIZE = 1024 * 1024; +export const COLLECTION_FURNITURE_MAX_UNCOMPRESSED_SIZE = 4 * 1024 * 1024; + +export const COLLECTION_LANG_CODE_REGEX = /^[a-z]{2}$/; +export const COLLECTION_LANG_NAME_MAX_LENGTH = 64; +export const COLLECTION_LANG_DESCRIPTION_MAX_LENGTH = 256; + +export const COLLECTION_FURNITURE_FILES = [ + "data.yml", + "sheet.json", + "sprite.png", + "lang.yml", +]; + +export const COLLECTION_FURNITURE_TYPES = ["furniture", "frame"]; +export const COLLECTION_FURNITURE_DIRECTIONS = [ + "north", + "east", + "south", + "west", +]; diff --git a/src/consts/main.ts b/src/consts/main.ts index cb0ff5c..a1f0bec 100644 --- a/src/consts/main.ts +++ b/src/consts/main.ts @@ -1 +1 @@ -export {}; +export * from "./collection.consts.ts"; diff --git a/src/types/collection.types.ts b/src/types/collection.types.ts new file mode 100644 index 0000000..39ee300 --- /dev/null +++ b/src/types/collection.types.ts @@ -0,0 +1,39 @@ +export type CollectionCategory = { + label: string; + description?: string; +}; + +export type CollectionMetadata = { + id: string; + category: CollectionCategory; + license?: string; + minHotelVersion: string; +}; + +export type CollectionManifestFurniture = { + id: string; + revision: string; + sha256: string; +}; + +export type CollectionManifest = { + id: string; + version: number; + author: string; + license?: string; + minHotelVersion: string; + formatVersion: number; + category: CollectionCategory; + furniture: CollectionManifestFurniture[]; + signature?: string; +}; + +export type CollectionFurnitureImmutableData = { + type: string; + size: { width: number; height: number; depth: number }; + directions: string[]; +}; + +export type FurnitureSource = + | { source: "local" } + | { source: "onet"; collection: string; version: number }; diff --git a/src/types/furniture.types.ts b/src/types/furniture.types.ts new file mode 100644 index 0000000..5441a30 --- /dev/null +++ b/src/types/furniture.types.ts @@ -0,0 +1,61 @@ +export type FurnitureDataFileBounds = { + width: number; + height: number; +}; + +export type FurnitureDataFileTexture = { + texture: string; + pivot?: { x: number; y: number }; + position?: { x: number; z: number }; + zIndex?: number; + bounds?: FurnitureDataFileBounds; + actions?: Record; +}; + +export type FurnitureDataFileAction = { + id: string; + label: string; + states: string[]; + defaultState: string; +}; + +export type FurnitureDataFile = { + id: string; + type: string; + revision: string; + icon: { + texture: string; + bounds?: FurnitureDataFileBounds; + }; + size: { width: number; height: number; depth: number }; + direction: Partial>; + actions?: FurnitureDataFileAction[]; +}; + +export type FurnitureSheetFileFrame = { + frame: { x: number; y: number; w: number; h: number }; + sourceSize?: { w: number; h: number }; + spriteSourceSize?: { x: number; y: number; w: number; h: number }; + anchor?: { x: number; y: number }; + rotated?: boolean; + trimmed?: boolean; + __key?: string; +}; + +export type FurnitureSheetFile = { + frames: Record; + animations?: Record; + meta: { + image: string; + size: { w: number; h: number }; + format?: string; + scale?: string | number; + }; +}; + +export type FurnitureLangItem = { + name: string; + description: string; +}; + +export type FurnitureLang = Record; diff --git a/src/types/main.ts b/src/types/main.ts index cb0ff5c..21a403d 100644 --- a/src/types/main.ts +++ b/src/types/main.ts @@ -1 +1,2 @@ -export {}; +export * from "./collection.types.ts"; +export * from "./furniture.types.ts"; diff --git a/src/utils/__tests__/collection.test.ts b/src/utils/__tests__/collection.test.ts new file mode 100644 index 0000000..ef5c7e0 --- /dev/null +++ b/src/utils/__tests__/collection.test.ts @@ -0,0 +1,317 @@ +import { expect, describe, it } from "@jest/globals"; +import { + getCollectionFurnitureListErrors, + getCollectionManifestErrors, + getCollectionManifestPayload, + getCollectionMetadataErrors, + getSha256, + getStableJson, + isValidCollectionFurnitureId, + isValidCollectionId, + isValidHotelVersion, + verifyCollectionManifest, +} from "../collection.utils.ts"; +import type { CollectionManifest } from "../../types/main.ts"; + +const PUBLIC_KEY = "MC8uZMUTGtSzRzgrCvpCSZt0OPLGkBVujh0PkQSFBbA"; +const OTHER_PUBLIC_KEY = "11qYAYKxCrfVS_7TyWQHOg7hcvPapiMlrwIaaPcHURo"; + +const getManifest = (): CollectionManifest => ({ + id: "xmas", + version: 2, + author: "account-id", + license: undefined, + minHotelVersion: "0.9.0", + formatVersion: 1, + category: { label: "Xmas", description: undefined }, + furniture: [ + { + id: "xmas@tree-0", + revision: "01JABCDEFGHJKMNPQRSTVWXYZ0", + sha256: "a".repeat(64), + }, + { + id: "xmas@tree-1", + revision: "01JABCDEFGHJKMNPQRSTVWXYZ1", + sha256: "b".repeat(64), + }, + ], + signature: + "ZENd555RYiUFfk8MKCc2P9HCXGAeRR8h2Ep9ocbz8eHwviT0DFGXiwCJcYPeIOHN6RV+JOo7g5vsQ1TGP1BOAQ==", +}); + +describe("utils", () => { + describe("collection", () => { + describe("getSha256", () => { + it("returns the hex sha256", async () => { + expect(await getSha256(new TextEncoder().encode("abc"))).toEqual( + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", + ); + }); + }); + + describe("getStableJson", () => { + it("sorts keys at any depth", () => { + expect( + getStableJson({ b: 1, a: { d: [1, { f: 1, e: 2 }], c: 2 } }), + ).toEqual('{"a":{"c":2,"d":[1,{"e":2,"f":1}]},"b":1}'); + }); + + it("skips undefined values in objects and turns them into null in lists", () => { + expect(getStableJson({ a: undefined, b: [undefined, 1] })).toEqual( + '{"b":[null,1]}', + ); + }); + + it("keeps primitives as JSON", () => { + expect(getStableJson("a")).toEqual('"a"'); + expect(getStableJson(1)).toEqual("1"); + expect(getStableJson(null)).toEqual("null"); + expect(getStableJson(true)).toEqual("true"); + }); + }); + + describe("isValidHotelVersion", () => { + it("accepts versions", () => { + for (const version of ["0.9.0", "v1.2.3", "1.0.0-beta", "1.0.0-rc.1"]) + expect(isValidHotelVersion(version)).toBe(true); + }); + + it("rejects anything else", () => { + for (const version of ["1.0", "latest", "1.0.0-", undefined, 100]) + expect(isValidHotelVersion(version)).toBe(false); + }); + }); + + describe("isValidCollectionId", () => { + it("accepts kebab-case ids", () => { + expect(isValidCollectionId("xmas")).toBe(true); + expect(isValidCollectionId("my-things-2")).toBe(true); + }); + + it("rejects invalid, too long and reserved ids", () => { + for (const id of [ + "Xmas", + "my_things", + "-xmas", + "xmas-", + "a".repeat(33), + "default", + "openhotel", + "", + undefined, + ]) + expect(isValidCollectionId(id)).toBe(false); + }); + }); + + describe("isValidCollectionFurnitureId", () => { + it("accepts @", () => { + expect(isValidCollectionFurnitureId("xmas", "xmas@tree-0")).toBe(true); + }); + + it("rejects other collections and invalid names", () => { + for (const id of [ + "flags@pirate", + "xmas@", + "xmas@Tree", + "xmas@tree@0", + "xmas", + undefined, + ]) + expect(isValidCollectionFurnitureId("xmas", id)).toBe(false); + }); + }); + + describe("getCollectionMetadataErrors", () => { + it("returns no errors for a valid collection.yml", () => { + expect( + getCollectionMetadataErrors({ + id: "xmas", + category: { label: "Xmas", description: "Christmas furniture" }, + license: "CC-BY-NC-SA-4.0", + minHotelVersion: "0.9.0", + }), + ).toEqual([]); + }); + + it("returns every error", () => { + expect( + getCollectionMetadataErrors({ + id: "default", + category: { label: "", description: "a".repeat(257) }, + license: "", + minHotelVersion: "latest", + }), + ).toEqual([ + "id 'default' is not valid", + "minHotelVersion is not a valid version", + "category.label is not valid", + "category.description is not valid", + "license is not valid", + ]); + }); + + it("doesn't throw with empty values", () => { + expect(getCollectionMetadataErrors(undefined)).toHaveLength(3); + }); + }); + + describe("getCollectionFurnitureListErrors", () => { + it("returns no errors for a valid list", () => { + expect( + getCollectionFurnitureListErrors("xmas", [ + "xmas@tree-0", + "xmas@tree-1", + ]), + ).toEqual([]); + }); + + it("returns duplicated and invalid ids", () => { + expect( + getCollectionFurnitureListErrors("xmas", [ + "xmas@tree-0", + "xmas@tree-0", + "flags@pirate", + ]), + ).toEqual([ + "xmas@tree-0: id is duplicated", + "flags@pirate: id must be 'xmas@'", + ]); + }); + + it("requires between 1 and 250 furniture", () => { + const error = "a collection must have between 1 and 250 furniture"; + expect(getCollectionFurnitureListErrors("xmas", [])).toEqual([error]); + expect( + getCollectionFurnitureListErrors( + "xmas", + Array.from({ length: 251 }, (_, index) => `xmas@tree-${index}`), + ), + ).toEqual([error]); + }); + }); + + describe("getCollectionManifestErrors", () => { + it("returns no errors for a valid manifest", () => { + expect(getCollectionManifestErrors(getManifest())).toEqual([]); + }); + + it("allows unknown keys", () => { + expect( + getCollectionManifestErrors({ ...getManifest(), newField: true }), + ).toEqual([]); + }); + + it("returns every error", () => { + expect( + getCollectionManifestErrors({ + ...getManifest(), + version: 0, + author: "", + formatVersion: 2, + signature: 1, + furniture: [ + { id: "xmas@tree-0", revision: "", sha256: "a".repeat(64) }, + { id: "xmas@tree-0", revision: "01J", sha256: "nope" }, + { id: "flags@pirate", revision: "01J", sha256: "a".repeat(64) }, + "xmas@tree-2", + ], + }), + ).toEqual([ + "version must be an integer >= 1", + "author is not valid", + "formatVersion '2' is not supported", + "signature is not valid", + "furniture[0].revision is not valid", + "furniture[1].id 'xmas@tree-0' is duplicated", + "furniture[1].sha256 is not valid", + "furniture[2].id must be 'xmas@'", + "furniture[3] must be an object", + ]); + }); + + it("requires a furniture list", () => { + expect( + getCollectionManifestErrors({ ...getManifest(), furniture: [] }), + ).toEqual(["furniture must be a list of 1 to 250 items"]); + }); + + it("rejects anything that is not an object", () => { + expect(getCollectionManifestErrors(null)).toEqual([ + "manifest must be an object", + ]); + }); + }); + + describe("getCollectionManifestPayload", () => { + it("is the stable json without the signature", () => { + expect( + new TextDecoder().decode(getCollectionManifestPayload(getManifest())), + ).toEqual( + '{"author":"account-id","category":{"label":"Xmas"},"formatVersion":1,"furniture":[{"id":"xmas@tree-0","revision":"01JABCDEFGHJKMNPQRSTVWXYZ0","sha256":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},{"id":"xmas@tree-1","revision":"01JABCDEFGHJKMNPQRSTVWXYZ1","sha256":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}],"id":"xmas","minHotelVersion":"0.9.0","version":2}', + ); + }); + }); + + describe("verifyCollectionManifest", () => { + it("verifies a manifest signed by onet", async () => { + expect( + await verifyCollectionManifest(getManifest(), [PUBLIC_KEY]), + ).toBe(true); + }); + + it("accepts any of the keys", async () => { + expect( + await verifyCollectionManifest(getManifest(), [ + OTHER_PUBLIC_KEY, + PUBLIC_KEY, + ]), + ).toBe(true); + }); + + it("ignores key order in the manifest", async () => { + const { signature, furniture, ...manifest } = getManifest(); + expect( + await verifyCollectionManifest( + { signature, furniture, ...manifest } as CollectionManifest, + [PUBLIC_KEY], + ), + ).toBe(true); + }); + + it("rejects a modified manifest", async () => { + const manifest = getManifest(); + manifest.furniture[0].sha256 = "c".repeat(64); + expect(await verifyCollectionManifest(manifest, [PUBLIC_KEY])).toBe( + false, + ); + }); + + it("rejects another key", async () => { + expect( + await verifyCollectionManifest(getManifest(), [OTHER_PUBLIC_KEY]), + ).toBe(false); + }); + + it("rejects missing or broken signatures and keys", async () => { + expect( + await verifyCollectionManifest( + { ...getManifest(), signature: undefined }, + [PUBLIC_KEY], + ), + ).toBe(false); + expect( + await verifyCollectionManifest( + { ...getManifest(), signature: "not base64!" }, + [PUBLIC_KEY], + ), + ).toBe(false); + expect( + await verifyCollectionManifest(getManifest(), ["not a key"]), + ).toBe(false); + expect(await verifyCollectionManifest(getManifest(), [])).toBe(false); + }); + }); + }); +}); diff --git a/src/utils/__tests__/furniture.test.ts b/src/utils/__tests__/furniture.test.ts new file mode 100644 index 0000000..9452cc1 --- /dev/null +++ b/src/utils/__tests__/furniture.test.ts @@ -0,0 +1,238 @@ +import { expect, describe, it } from "@jest/globals"; +import { + getFurnitureDataErrors, + getFurnitureFilesErrors, + getFurnitureImmutableData, + getFurnitureLangErrors, + getFurnitureSheetErrors, + getFurnitureSheetFrames, +} from "../furniture.utils.ts"; +import type { FurnitureDataFile } from "../../types/main.ts"; + +const FURNITURE_ID = "xmas@tree-0"; + +const getLang = (): any => ({ + en: { name: "Tree", description: "A christmas tree" }, + es: { name: "Árbol", description: "" }, +}); + +const getSheet = (): any => ({ + frames: { + icon: { frame: { x: 0, y: 0, w: 10, h: 10 } }, + "tree-north": { + frame: { x: 10, y: 0, w: 20, h: 40 }, + sourceSize: { w: 20, h: 40 }, + rotated: false, + trimmed: false, + }, + "tree-south": { frame: { x: 30, y: 0, w: 20, h: 40 } }, + }, + meta: { image: "sprite.png", size: { w: 50, h: 40 }, scale: "1" }, +}); + +const getData = (): any => ({ + id: FURNITURE_ID, + type: "furniture", + revision: "01JABCDEFGHJKMNPQRSTVWXYZ0", + icon: { texture: "icon", bounds: { width: 10, height: 10 } }, + size: { width: 1, height: 2, depth: 1 }, + direction: { + south: { + textures: [ + { + texture: "tree-south", + pivot: { x: -10, y: 5 }, + position: { x: 0, z: 0 }, + zIndex: 1, + bounds: { width: 20, height: 40 }, + }, + ], + }, + north: { textures: [{ texture: "tree-north" }] }, + }, +}); + +const FRAMES = ["icon", "tree-north", "tree-south"]; + +describe("utils", () => { + describe("furniture", () => { + describe("getFurnitureLangErrors", () => { + it("returns no errors for a valid lang.yml", () => { + expect(getFurnitureLangErrors(getLang())).toEqual([]); + }); + + it("requires at least one language", () => { + for (const lang of [{}, undefined, [], "en"]) + expect(getFurnitureLangErrors(lang)).toEqual([ + "lang.yml must have at least one language", + ]); + }); + + it("returns every error", () => { + expect( + getFurnitureLangErrors({ + eng: { name: "Tree", description: "" }, + es: { name: "", description: "a".repeat(257) }, + fr: { name: "Arbre", description: "", label: "Arbre" }, + de: "Baum", + }), + ).toEqual([ + "lang.yml.eng is not a valid language code", + "lang.yml.es.name is not valid", + "lang.yml.es.description is not valid", + "lang.yml.fr.label is not allowed", + "lang.yml.de must be an object", + ]); + }); + }); + + describe("getFurnitureSheetErrors", () => { + it("returns no errors for a valid sheet.json", () => { + expect(getFurnitureSheetErrors(getSheet())).toEqual([]); + }); + + it("returns every error", () => { + const sheet = getSheet(); + sheet.meta.image = "other.png"; + sheet.animations = []; + sheet.frames.icon.frame.x = -1; + sheet.frames["tree-north"].extra = true; + sheet.frames["tree-south"].frame = { x: 0, y: 0 }; + expect(getFurnitureSheetErrors(sheet)).toEqual([ + "sheet.json.meta.image must be 'sprite.png'", + "sheet.json.animations must be an object", + "sheet.json.frames.icon.frame must be integers >= 0", + "sheet.json.frames.tree-north.extra is not allowed", + "sheet.json.frames.tree-south.frame.w is required", + "sheet.json.frames.tree-south.frame.h is required", + ]); + }); + + it("requires frames and meta", () => { + expect(getFurnitureSheetErrors({ other: 1 })).toEqual([ + "sheet.json.frames is required", + "sheet.json.meta is required", + "sheet.json.other is not allowed", + ]); + }); + }); + + describe("getFurnitureSheetFrames", () => { + it("returns the frame names", () => { + expect(getFurnitureSheetFrames(getSheet())).toEqual(FRAMES); + }); + + it("returns an empty list without a valid structure", () => { + expect(getFurnitureSheetFrames(undefined)).toEqual([]); + expect(getFurnitureSheetFrames({ frames: [], meta: {} })).toEqual([]); + }); + }); + + describe("getFurnitureDataErrors", () => { + it("returns no errors for a valid data.yml", () => { + expect(getFurnitureDataErrors(FURNITURE_ID, getData(), FRAMES)).toEqual( + [], + ); + }); + + it("returns every error", () => { + const data = getData(); + data.id = "xmas@tree-1"; + data.type = "wall"; + data.icon.texture = "missing"; + data.size.depth = -1; + data.direction.east = { textures: "tree-east" }; + data.direction.up = { textures: [] }; + expect(getFurnitureDataErrors(FURNITURE_ID, data, FRAMES)).toEqual([ + "data.yml.id must be 'xmas@tree-0'", + "data.yml.type must be one of furniture, frame", + "data.yml.icon.texture 'missing' is not a frame of sheet.json", + "data.yml.size.depth must be an integer >= 0", + "data.yml.direction.up is not allowed", + ]); + }); + + it("checks every texture", () => { + const data = getData(); + data.direction.east = { textures: "tree-east" }; + data.direction.south.textures.push( + { texture: "tree-south", zIndex: 1.5, pivot: { x: 0 } }, + { texture: "tree-south", position: { x: 0, y: 0 }, hitArea: [] }, + ); + expect(getFurnitureDataErrors(FURNITURE_ID, data, FRAMES)).toEqual([ + "data.yml.direction.south.textures[1].zIndex must be an integer >= -Infinity", + "data.yml.direction.south.textures[1].pivot.y is required", + "data.yml.direction.south.textures[2].hitArea is not allowed", + "data.yml.direction.east.textures must be a list", + ]); + }); + + it("requires the main keys", () => { + expect( + getFurnitureDataErrors(FURNITURE_ID, { id: FURNITURE_ID }, FRAMES), + ).toEqual([ + "data.yml.type is required", + "data.yml.revision is required", + "data.yml.icon is required", + "data.yml.size is required", + "data.yml.direction is required", + ]); + }); + }); + + describe("getFurnitureFilesErrors", () => { + it("returns no errors for valid files", () => { + expect( + getFurnitureFilesErrors(FURNITURE_ID, { + data: getData(), + sheet: getSheet(), + lang: getLang(), + }), + ).toEqual([]); + }); + + it("checks the textures against the frames of sheet.json", () => { + const sheet = getSheet(); + delete sheet.frames.icon; + expect( + getFurnitureFilesErrors(FURNITURE_ID, { + data: getData(), + sheet, + lang: getLang(), + }), + ).toEqual([ + "data.yml.icon.texture 'icon' is not a frame of sheet.json", + ]); + }); + + it("returns the errors of lang.yml, sheet.json and data.yml in order", () => { + expect( + getFurnitureFilesErrors(FURNITURE_ID, { + data: { ...getData(), type: "wall" }, + sheet: { ...getSheet(), meta: undefined }, + lang: {}, + }), + ).toEqual([ + "lang.yml must have at least one language", + "sheet.json.meta is required", + "data.yml.type must be one of furniture, frame", + "data.yml.icon.texture 'icon' is not a frame of sheet.json", + "data.yml.direction.south.textures[0].texture 'tree-south' is not a frame of sheet.json", + "data.yml.direction.north.textures[0].texture 'tree-north' is not a frame of sheet.json", + ]); + }); + }); + + describe("getFurnitureImmutableData", () => { + it("returns type, size and sorted directions", () => { + expect( + getFurnitureImmutableData(getData() as FurnitureDataFile), + ).toEqual({ + type: "furniture", + size: { width: 1, height: 2, depth: 1 }, + directions: ["north", "south"], + }); + }); + }); + }); +}); diff --git a/src/utils/collection.utils.ts b/src/utils/collection.utils.ts new file mode 100644 index 0000000..81e1141 --- /dev/null +++ b/src/utils/collection.utils.ts @@ -0,0 +1,269 @@ +import { + COLLECTION_DESCRIPTION_MAX_LENGTH, + COLLECTION_FORMAT_VERSION, + COLLECTION_HOTEL_VERSION_REGEX, + COLLECTION_ID_MAX_LENGTH, + COLLECTION_ID_REGEX, + COLLECTION_LABEL_MAX_LENGTH, + COLLECTION_LICENSE_MAX_LENGTH, + COLLECTION_MAX_FURNITURE, + COLLECTION_RESERVED_NAMESPACES, +} from "../consts/collection.consts.ts"; +import type { CollectionManifest } from "../types/main.ts"; +import { + isInteger, + isObject, + isOptionalText, + isText, +} from "./validation.utils.ts"; + +const SHA256_REGEX = /^[a-f0-9]{64}$/; + +export const getSha256 = async (data: Uint8Array): Promise => + Array.from( + new Uint8Array(await crypto.subtle.digest("SHA-256", data as BufferSource)), + ) + .map((byte) => byte.toString(16).padStart(2, "0")) + .join(""); + +export const getStableJson = (value: unknown): string => { + if (Array.isArray(value)) { + return `[${value.map((item) => getStableJson(item ?? null)).join(",")}]`; + } + + if (value && typeof value === "object") { + const object = value as Record; + return `{${Object.keys(object) + .filter((key) => object[key] !== undefined) + .sort() + .map((key) => `${JSON.stringify(key)}:${getStableJson(object[key])}`) + .join(",")}}`; + } + + return JSON.stringify(value); +}; + +export const isValidHotelVersion = (version: unknown): boolean => + typeof version === "string" && COLLECTION_HOTEL_VERSION_REGEX.test(version); + +export const isValidCollectionId = (id: unknown): id is string => + typeof id === "string" && + id.length <= COLLECTION_ID_MAX_LENGTH && + COLLECTION_ID_REGEX.test(id) && + !COLLECTION_RESERVED_NAMESPACES.includes(id); + +export const isValidCollectionFurnitureId = ( + collectionId: string, + furnitureId: unknown, +): furnitureId is string => { + if (typeof furnitureId !== "string") return false; + + const [prefix, name, ...rest] = furnitureId.split("@"); + return ( + prefix === collectionId && + !rest.length && + COLLECTION_ID_REGEX.test(name ?? "") + ); +}; + +const $checkCategory = (errors: string[], category: unknown) => { + const $category = isObject(category) ? category : {}; + + if (!isText($category.label, COLLECTION_LABEL_MAX_LENGTH)) { + errors.push("category.label is not valid"); + } + + if ( + !isOptionalText($category.description, COLLECTION_DESCRIPTION_MAX_LENGTH) + ) { + errors.push("category.description is not valid"); + } +}; + +const $checkLicense = (errors: string[], license: unknown) => { + if (!isOptionalText(license, COLLECTION_LICENSE_MAX_LENGTH)) { + errors.push("license is not valid"); + } +}; + +export const getCollectionMetadataErrors = (metadata: unknown): string[] => { + const errors: string[] = []; + const { id, category, license, minHotelVersion } = isObject(metadata) + ? metadata + : ({} as Record); + + if (!isValidCollectionId(id)) { + errors.push(`id '${id}' is not valid`); + } + + if (!isValidHotelVersion(minHotelVersion)) { + errors.push("minHotelVersion is not a valid version"); + } + + $checkCategory(errors, category); + $checkLicense(errors, license); + + return errors; +}; + +export const getCollectionFurnitureListErrors = ( + collectionId: string, + furnitureIds: string[], +): string[] => { + const errors: string[] = []; + + if (!furnitureIds.length || furnitureIds.length > COLLECTION_MAX_FURNITURE) { + errors.push( + `a collection must have between 1 and ${COLLECTION_MAX_FURNITURE} furniture`, + ); + } + + const ids = new Set(); + for (const furnitureId of furnitureIds) { + if (ids.has(furnitureId)) { + errors.push(`${furnitureId}: id is duplicated`); + } + ids.add(furnitureId); + + if (!isValidCollectionFurnitureId(collectionId, furnitureId)) { + errors.push(`${furnitureId}: id must be '${collectionId}@'`); + } + } + + return errors; +}; + +export const getCollectionManifestErrors = (manifest: unknown): string[] => { + if (!isObject(manifest)) return ["manifest must be an object"]; + + const errors: string[] = []; + const { + id, + version, + author, + license, + minHotelVersion, + formatVersion, + category, + furniture, + signature, + } = manifest; + + if (!isValidCollectionId(id)) { + errors.push(`id '${id}' is not valid`); + } + + if (!isInteger(version, 1)) { + errors.push("version must be an integer >= 1"); + } + + if (typeof author !== "string" || !author) { + errors.push("author is not valid"); + } + + $checkLicense(errors, license); + + if (!isValidHotelVersion(minHotelVersion)) { + errors.push("minHotelVersion is not a valid version"); + } + + if (formatVersion !== COLLECTION_FORMAT_VERSION) { + errors.push(`formatVersion '${formatVersion}' is not supported`); + } + + $checkCategory(errors, category); + + if ( + signature !== undefined && + (typeof signature !== "string" || !signature) + ) { + errors.push("signature is not valid"); + } + + if ( + !Array.isArray(furniture) || + !furniture.length || + furniture.length > COLLECTION_MAX_FURNITURE + ) { + errors.push( + `furniture must be a list of 1 to ${COLLECTION_MAX_FURNITURE} items`, + ); + return errors; + } + + const ids = new Set(); + furniture.forEach((item: unknown, index: number) => { + const path = `furniture[${index}]`; + + if (!isObject(item)) { + errors.push(`${path} must be an object`); + return; + } + + if (!isValidCollectionFurnitureId(id, item.id)) { + errors.push(`${path}.id must be '${id}@'`); + } else if (ids.has(item.id)) { + errors.push(`${path}.id '${item.id}' is duplicated`); + } else { + ids.add(item.id); + } + + if (typeof item.revision !== "string" || !item.revision) { + errors.push(`${path}.revision is not valid`); + } + + if (typeof item.sha256 !== "string" || !SHA256_REGEX.test(item.sha256)) { + errors.push(`${path}.sha256 is not valid`); + } + }); + + return errors; +}; + +export const getCollectionManifestPayload = ({ + signature, + ...manifest +}: CollectionManifest): Uint8Array => + new TextEncoder().encode(getStableJson(manifest)); + +const $decodeBase64 = (text: string): Uint8Array => + Uint8Array.from(atob(text), (char) => char.charCodeAt(0)); + +export const verifyCollectionManifest = async ( + manifest: CollectionManifest, + publicKeys: string[], +): Promise => { + if (typeof manifest?.signature !== "string") return false; + + let signature: Uint8Array; + try { + signature = $decodeBase64(manifest.signature); + } catch { + return false; + } + + const payload = getCollectionManifestPayload(manifest); + + for (const x of publicKeys) { + try { + const publicKey = await crypto.subtle.importKey( + "jwk", + { kty: "OKP", crv: "Ed25519", x }, + "Ed25519", + false, + ["verify"], + ); + + const isValid = await crypto.subtle.verify( + "Ed25519", + publicKey, + signature as BufferSource, + payload as BufferSource, + ); + + if (isValid) return true; + } catch {} + } + + return false; +}; diff --git a/src/utils/furniture.utils.ts b/src/utils/furniture.utils.ts new file mode 100644 index 0000000..7c8d6fd --- /dev/null +++ b/src/utils/furniture.utils.ts @@ -0,0 +1,314 @@ +import { + COLLECTION_FURNITURE_DIRECTIONS, + COLLECTION_FURNITURE_TYPES, + COLLECTION_LANG_CODE_REGEX, + COLLECTION_LANG_DESCRIPTION_MAX_LENGTH, + COLLECTION_LANG_NAME_MAX_LENGTH, +} from "../consts/collection.consts.ts"; +import type { + CollectionFurnitureImmutableData, + FurnitureDataFile, +} from "../types/main.ts"; +import { + checkIntegers, + checkKeys, + isInteger, + isObject, + isText, +} from "./validation.utils.ts"; + +const $checkLang = (errors: string[], lang: unknown) => { + const path = "lang.yml"; + + if (!isObject(lang) || !Object.keys(lang).length) { + errors.push(`${path} must have at least one language`); + return; + } + + for (const [code, item] of Object.entries(lang)) { + const $path = `${path}.${code}`; + + if (!COLLECTION_LANG_CODE_REGEX.test(code)) { + errors.push(`${$path} is not a valid language code`); + } + + const hasValidLangKeys = checkKeys(errors, $path, item, [ + "name", + "description", + ]); + if (!hasValidLangKeys) continue; + + if (!isText(item.name, COLLECTION_LANG_NAME_MAX_LENGTH)) { + errors.push(`${$path}.name is not valid`); + } + + if ( + typeof item.description !== "string" || + item.description.length > COLLECTION_LANG_DESCRIPTION_MAX_LENGTH + ) { + errors.push(`${$path}.description is not valid`); + } + } +}; + +const $checkSheet = (errors: string[], sheet: unknown): string[] => { + const path = "sheet.json"; + + const hasValidSheetKeys = checkKeys( + errors, + path, + sheet, + ["frames", "meta"], + ["animations"], + ); + + if (!hasValidSheetKeys) { + return []; + } + + const hasValidMetaKeys = checkKeys( + errors, + `${path}.meta`, + sheet.meta, + ["image", "size"], + ["format", "scale"], + ); + + if (hasValidMetaKeys && sheet.meta.image !== "sprite.png") { + errors.push(`${path}.meta.image must be 'sprite.png'`); + } + + if ("animations" in sheet && !isObject(sheet.animations)) { + errors.push(`${path}.animations must be an object`); + } + + if (!isObject(sheet.frames)) { + errors.push(`${path}.frames must be an object`); + return []; + } + + for (const [name, frame] of Object.entries(sheet.frames)) { + const $path = `${path}.frames.${name}`; + + const hasValidFrameKeys = checkKeys( + errors, + $path, + frame, + ["frame"], + [ + "sourceSize", + "spriteSourceSize", + "anchor", + "rotated", + "trimmed", + "__key", + ], + ); + + if (!hasValidFrameKeys) continue; + + const hasValidRectKeys = checkKeys(errors, `${$path}.frame`, frame.frame, [ + "x", + "y", + "w", + "h", + ]); + if (!hasValidRectKeys) continue; + + const { x, y, w, h } = frame.frame; + if (![x, y, w, h].every((value) => isInteger(value, 0))) { + errors.push(`${$path}.frame must be integers >= 0`); + } + } + + return Object.keys(sheet.frames); +}; + +const $checkData = ( + errors: string[], + furnitureId: string, + data: unknown, + frames: string[], +) => { + const path = "data.yml"; + + const hasValidDataKeys = checkKeys( + errors, + path, + data, + ["id", "type", "revision", "icon", "size", "direction"], + ["actions"], + ); + + if (!hasValidDataKeys) return; + + if (data.id !== furnitureId) { + errors.push(`${path}.id must be '${furnitureId}'`); + } + + if (!COLLECTION_FURNITURE_TYPES.includes(data.type)) { + errors.push( + `${path}.type must be one of ${COLLECTION_FURNITURE_TYPES.join(", ")}`, + ); + } + + const checkTexture = ($path: string, texture: unknown) => { + if (typeof texture !== "string" || !frames.includes(texture)) { + errors.push(`${$path} '${texture}' is not a frame of sheet.json`); + } + }; + + const checkBounds = ($path: string, bounds: unknown) => { + const hasValidBoundsKeys = checkKeys(errors, $path, bounds, [ + "width", + "height", + ]); + + if (hasValidBoundsKeys) { + checkIntegers(errors, $path, bounds, ["width", "height"], 0); + } + }; + + const hasValidIconKeys = checkKeys( + errors, + `${path}.icon`, + data.icon, + ["texture"], + ["bounds"], + ); + + if (hasValidIconKeys) { + checkTexture(`${path}.icon.texture`, data.icon.texture); + + if ("bounds" in data.icon) { + checkBounds(`${path}.icon.bounds`, data.icon.bounds); + } + } + + const hasValidSizeKeys = checkKeys(errors, `${path}.size`, data.size, [ + "width", + "height", + "depth", + ]); + + if (hasValidSizeKeys) { + checkIntegers(errors, `${path}.size`, data.size, Object.keys(data.size), 0); + } + + const hasValidDirectionKeys = checkKeys( + errors, + `${path}.direction`, + data.direction, + [], + [...COLLECTION_FURNITURE_DIRECTIONS], + ); + + if (!hasValidDirectionKeys) return; + + for (const [direction, directionData] of Object.entries(data.direction)) { + const $path = `${path}.direction.${direction}`; + + if (!checkKeys(errors, $path, directionData, ["textures"])) continue; + if (!Array.isArray(directionData.textures)) { + errors.push(`${$path}.textures must be a list`); + continue; + } + + directionData.textures.forEach((texture: unknown, index: number) => { + const $$path = `${$path}.textures[${index}]`; + if ( + !checkKeys( + errors, + $$path, + texture, + ["texture"], + ["pivot", "position", "zIndex", "bounds", "actions"], + ) + ) + return; + + checkTexture(`${$$path}.texture`, texture.texture); + checkIntegers(errors, $$path, texture, ["zIndex"]); + + if ("bounds" in texture) { + checkBounds(`${$$path}.bounds`, texture.bounds); + } + + if ( + "pivot" in texture && + checkKeys(errors, `${$$path}.pivot`, texture.pivot, ["x", "y"]) + ) { + checkIntegers(errors, `${$$path}.pivot`, texture.pivot, ["x", "y"]); + } + + if ( + "position" in texture && + checkKeys(errors, `${$$path}.position`, texture.position, ["x", "z"]) + ) { + checkIntegers(errors, `${$$path}.position`, texture.position, [ + "x", + "z", + ]); + } + }); + } +}; + +export const getFurnitureLangErrors = (lang: unknown): string[] => { + const errors: string[] = []; + $checkLang(errors, lang); + return errors; +}; + +export const getFurnitureSheetErrors = (sheet: unknown): string[] => { + const errors: string[] = []; + $checkSheet(errors, sheet); + return errors; +}; + +export const getFurnitureSheetFrames = (sheet: unknown): string[] => + $checkSheet([], sheet); + +export const getFurnitureDataErrors = ( + furnitureId: string, + data: unknown, + frames: string[], +): string[] => { + const errors: string[] = []; + $checkData(errors, furnitureId, data, frames); + return errors; +}; + +export const getFurnitureFilesErrors = ( + furnitureId: string, + { + data, + sheet, + lang, + }: { + data: unknown; + sheet: unknown; + lang: unknown; + }, +): string[] => { + const errors: string[] = []; + + $checkLang(errors, lang); + const frames = $checkSheet(errors, sheet); + $checkData(errors, furnitureId, data, frames); + + return errors; +}; + +export const getFurnitureImmutableData = ( + data: FurnitureDataFile, +): CollectionFurnitureImmutableData => ({ + type: data.type, + size: { + width: data.size.width, + height: data.size.height, + depth: data.size.depth, + }, + directions: Object.keys(data.direction).sort(), + // actions: [], // TODO: implement actions validation, not sure if should be part of immutable data or not +}); diff --git a/src/utils/main.ts b/src/utils/main.ts index cb0ff5c..3dcfa95 100644 --- a/src/utils/main.ts +++ b/src/utils/main.ts @@ -1 +1,2 @@ -export {}; +export * from "./collection.utils.ts"; +export * from "./furniture.utils.ts"; diff --git a/src/utils/validation.utils.ts b/src/utils/validation.utils.ts new file mode 100644 index 0000000..42b40d1 --- /dev/null +++ b/src/utils/validation.utils.ts @@ -0,0 +1,55 @@ +export const isObject = (value: unknown): value is Record => + Boolean(value) && typeof value === "object" && !Array.isArray(value); + +export const isInteger = (value: unknown, min = -Infinity): value is number => + Number.isInteger(value) && (value as number) >= min; + +export const isText = (value: unknown, maxLength: number): value is string => + typeof value === "string" && value.length > 0 && value.length <= maxLength; + +export const isOptionalText = (value: unknown, maxLength: number): boolean => + value === undefined || isText(value, maxLength); + +export const checkKeys = ( + errors: string[], + path: string, + value: unknown, + required: string[], + optional: string[] = [], +): value is Record => { + if (!isObject(value)) { + errors.push(`${path} must be an object`); + return false; + } + + const allowed = [...required, ...optional]; + const length = errors.length; + + for (const key of required) { + if (value[key] === undefined) { + errors.push(`${path}.${key} is required`); + } + } + + for (const key of Object.keys(value)) { + if (!allowed.includes(key)) { + errors.push(`${path}.${key} is not allowed`); + } + } + + return errors.length === length; +}; + +export const checkIntegers = ( + errors: string[], + path: string, + value: Record, + keys: string[], + min = -Infinity, +) => { + for (const key of keys) { + if (key in value && !isInteger(value[key], min)) { + errors.push(`${path}.${key} must be an integer >= ${min}`); + } + } +}; diff --git a/tsconfig.json b/tsconfig.json index 96c1683..ea8274f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,15 +1,18 @@ { "compilerOptions": { - "moduleResolution": "node", + "moduleResolution": "bundler", "module": "ES2022", "target": "ES2022", "esModuleInterop": true, "sourceMap": false, "noUnusedLocals": true, + "noEmit": true, + "strict": true, + "types": [], "lib": ["ES2022", "dom"], - "baseUrl": "./src/", - "rootDir": "./src", "allowImportingTsExtensions": true, "resolveJsonModule": true - } + }, + "include": ["index.ts", "src"], + "exclude": ["src/**/__tests__"] }