diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf51549..8912e20 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,10 +27,7 @@ jobs: run: pnpm run build - name: Lint - run: | - pnpm run format:check - pnpm run eslint + run: pnpm run check - name: Test - # NOTE: see jest.config.ts `collectCoverageFrom` - run: pnpm run coverage + run: pnpm run test:coverage diff --git a/.github/workflows/concat_cacerts.yml b/.github/workflows/concat_cacerts.yml index ad94e44..bee163f 100644 --- a/.github/workflows/concat_cacerts.yml +++ b/.github/workflows/concat_cacerts.yml @@ -34,7 +34,7 @@ jobs: script: | const {concatCaCerts} = await import("${{ github.workspace }}/dist/ghw_concat_cacerts.js") - await concatCaCerts(github, core, context) + concatCaCerts(github, core, context) - name: Commit changes run: | diff --git a/.gitignore b/.gitignore index 68165b4..28b41e1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,15 +3,15 @@ coverage/ dist/ temp/ tmp/ -.jest-tmp/ +.test-tmp pr/ tsconfig.tsbuildinfo # used by tests -images/jest-tmp -images1/jest-tmp -not-in-manifest-images/jest-tmp -not-in-manifest-images1/jest-tmp +images/test-tmp +images1/test-tmp +not-in-manifest-images/test-tmp +not-in-manifest-images1/test-tmp # MacOS indexing files .DS_Store diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index c31c075..0000000 --- a/.prettierignore +++ /dev/null @@ -1,10 +0,0 @@ -pnpm-lock.yaml -.cache/ -images/ -images1/ -not-in-manifest-images/ -not-in-manifest-images1/ -index.json -index1.json -cacerts/ -cacerts.pem diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..d79ba07 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["biomejs.biome", "vitest.explorer"] +} diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..71ff2aa --- /dev/null +++ b/biome.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true }, + "formatter": { + "indentStyle": "space", + "indentWidth": 4, + "lineWidth": 150, + "bracketSpacing": false + }, + "files": { + "ignore": [ + "package.json", + "./index.json", + "./index1.json", + "./.cache", + "./cacerts", + "./images", + "./images1", + "./not-in-manifest-images", + "./not-in-manifest-images1" + ] + }, + "linter": { + "rules": { + "suspicious": { + "useAwait": "error", + "noExportsInTest": "off" + }, + "style": { + "noNonNullAssertion": "warn", + "noParameterAssign": "warn", + "useNamingConvention": { + "level": "error", + "options": { + "strictCase": false, + "conventions": [ + { + "selector": { + "kind": "objectLiteralProperty" + }, + "formats": ["snake_case", "camelCase", "CONSTANT_CASE", "PascalCase"] + }, + { + "selector": { + "kind": "typeProperty" + }, + "formats": ["snake_case", "camelCase", "CONSTANT_CASE", "PascalCase"] + }, + { + "selector": { + "kind": "const" + }, + "formats": ["camelCase", "CONSTANT_CASE"] + } + ] + } + } + } + } + } +} diff --git a/eslint.config.mjs b/eslint.config.mjs deleted file mode 100644 index 8254533..0000000 --- a/eslint.config.mjs +++ /dev/null @@ -1,35 +0,0 @@ -import eslint from '@eslint/js'; -import eslintConfigPrettier from 'eslint-config-prettier'; -import tseslint from 'typescript-eslint'; - -export default tseslint.config( - eslint.configs.recommended, - ...tseslint.configs.recommended, - { - files: ['**/*.ts'], - languageOptions: { - ecmaVersion: 'latest', - sourceType: 'script', - parserOptions: { - projectService: { - allowDefaultProject: ['eslint.config.mjs', 'prettier.config.mjs'], - }, - }, - }, - rules: { - '@typescript-eslint/await-thenable': 'error', - '@typescript-eslint/ban-ts-comment': 'error', - '@typescript-eslint/explicit-function-return-type': 'error', - '@typescript-eslint/no-explicit-any': 'error', - '@typescript-eslint/no-unused-vars': 'error', - 'array-bracket-spacing': ['error', 'never'], - '@typescript-eslint/return-await': ['error', 'always'], - 'object-curly-spacing': ['error', 'never'], - '@typescript-eslint/no-floating-promises': 'error', - }, - }, - { - ignores: ['tmp', 'dist', 'coverage'], - }, - eslintConfigPrettier, -); diff --git a/package.json b/package.json index c5816ea..d269b4a 100644 --- a/package.json +++ b/package.json @@ -13,13 +13,12 @@ "main": "dist/index.js", "scripts": { "build": "tsc", + "clean": "rm -rf dist coverage *.tsbuildinfo", "start": "node ./dist/index.js", - "format": "prettier --write .", - "format:check": "prettier --check .", - "eslint": "eslint . --max-warnings=0", - "test": "jest test --config=./tests/jest.config.ts --silent --runInBand", - "test:watch": "jest test --watch --config=./tests/jest.config.ts --silent --runInBand", - "coverage": "jest test --config=./tests/jest.config.ts --silent --runInBand --coverage" + "check": "biome check", + "test": "vitest run --config ./tests/vitest.config.mts", + "test:coverage": "vitest run --config ./tests/vitest.config.mts --coverage", + "test:watch": "vitest watch --config ./tests/vitest.config.mts" }, "keywords": [ "zigbee", @@ -49,19 +48,11 @@ "devDependencies": { "@actions/core": "^1.11.1", "@actions/github": "^6.0.0", - "@eslint/core": "^0.12.0", - "@eslint/js": "^9.23.0", - "@ianvs/prettier-plugin-sort-imports": "^4.4.1", + "@biomejs/biome": "^1.9.4", "@octokit/rest": "^21.1.1", - "@types/jest": "^29.5.14", "@types/node": "^22.13.11", - "eslint": "^9.23.0", - "eslint-config-prettier": "^10.1.1", - "jest": "^29.7.0", - "prettier": "^3.5.3", - "ts-jest": "^29.2.6", - "ts-node": "^10.9.2", + "@vitest/coverage-v8": "^3.0.9", "typescript": "^5.8.2", - "typescript-eslint": "^8.27.0" + "vitest": "^3.0.9" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 72d18a6..a96f079 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,48 +18,24 @@ importers: '@actions/github': specifier: ^6.0.0 version: 6.0.0 - '@eslint/core': - specifier: ^0.12.0 - version: 0.12.0 - '@eslint/js': - specifier: ^9.23.0 - version: 9.23.0 - '@ianvs/prettier-plugin-sort-imports': - specifier: ^4.4.1 - version: 4.4.1(prettier@3.5.3) + '@biomejs/biome': + specifier: ^1.9.4 + version: 1.9.4 '@octokit/rest': specifier: ^21.1.1 version: 21.1.1 - '@types/jest': - specifier: ^29.5.14 - version: 29.5.14 '@types/node': specifier: ^22.13.11 version: 22.13.11 - eslint: - specifier: ^9.23.0 - version: 9.23.0 - eslint-config-prettier: - specifier: ^10.1.1 - version: 10.1.1(eslint@9.23.0) - jest: - specifier: ^29.7.0 - version: 29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)) - prettier: - specifier: ^3.5.3 - version: 3.5.3 - ts-jest: - specifier: ^29.2.6 - version: 29.2.6(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)))(typescript@5.8.2) - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@22.13.11)(typescript@5.8.2) + '@vitest/coverage-v8': + specifier: ^3.0.9 + version: 3.0.9(vitest@3.0.9(@types/node@22.13.11)) typescript: specifier: ^5.8.2 version: 5.8.2 - typescript-eslint: - specifier: ^8.27.0 - version: 8.27.0(eslint@9.23.0)(typescript@5.8.2) + vitest: + specifier: ^3.0.9 + version: 3.0.9(@types/node@22.13.11) packages: @@ -82,40 +58,6 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} - '@babel/code-frame@7.26.2': - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.26.8': - resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.26.10': - resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.26.10': - resolution: {integrity: sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.26.5': - resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.25.9': - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.26.0': - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.26.5': - resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} - engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.25.9': resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} @@ -124,200 +66,226 @@ packages: resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-option@7.25.9': - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.26.10': - resolution: {integrity: sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==} - engines: {node: '>=6.9.0'} - '@babel/parser@7.26.10': resolution: {integrity: sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-syntax-async-generators@7.8.4': - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-bigint@7.8.3': - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-properties@7.12.13': - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-class-static-block@7.14.5': - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-attributes@7.26.0': - resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-import-meta@7.10.4': - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-json-strings@7.8.3': - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-jsx@7.25.9': - resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4': - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-numeric-separator@7.10.4': - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-object-rest-spread@7.8.3': - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3': - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-optional-chaining@7.8.3': - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-private-property-in-object@7.14.5': - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-top-level-await@7.14.5': - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-syntax-typescript@7.25.9': - resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/template@7.26.9': - resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.26.10': - resolution: {integrity: sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==} - engines: {node: '>=6.9.0'} - '@babel/types@7.26.10': resolution: {integrity: sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==} engines: {node: '>=6.9.0'} - '@bcoe/v8-coverage@0.2.3': - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} - '@cspotcode/source-map-support@0.8.1': - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} + '@biomejs/biome@1.9.4': + resolution: {integrity: sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==} + engines: {node: '>=14.21.3'} + hasBin: true - '@eslint-community/eslint-utils@4.5.1': - resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@biomejs/cli-darwin-arm64@1.9.4': + resolution: {integrity: sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [darwin] - '@eslint-community/regexpp@4.12.1': - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@biomejs/cli-darwin-x64@1.9.4': + resolution: {integrity: sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [darwin] - '@eslint/config-array@0.19.2': - resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@biomejs/cli-linux-arm64-musl@1.9.4': + resolution: {integrity: sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] - '@eslint/config-helpers@0.2.0': - resolution: {integrity: sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@biomejs/cli-linux-arm64@1.9.4': + resolution: {integrity: sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] - '@eslint/core@0.12.0': - resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@biomejs/cli-linux-x64-musl@1.9.4': + resolution: {integrity: sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] - '@eslint/eslintrc@3.3.1': - resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@biomejs/cli-linux-x64@1.9.4': + resolution: {integrity: sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] - '@eslint/js@9.23.0': - resolution: {integrity: sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@biomejs/cli-win32-arm64@1.9.4': + resolution: {integrity: sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [win32] - '@eslint/object-schema@2.1.6': - resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@biomejs/cli-win32-x64@1.9.4': + resolution: {integrity: sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [win32] - '@eslint/plugin-kit@0.2.7': - resolution: {integrity: sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@esbuild/aix-ppc64@0.25.1': + resolution: {integrity: sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.1': + resolution: {integrity: sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.1': + resolution: {integrity: sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.1': + resolution: {integrity: sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.1': + resolution: {integrity: sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.1': + resolution: {integrity: sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.1': + resolution: {integrity: sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.1': + resolution: {integrity: sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.1': + resolution: {integrity: sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.1': + resolution: {integrity: sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.1': + resolution: {integrity: sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.1': + resolution: {integrity: sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.1': + resolution: {integrity: sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.1': + resolution: {integrity: sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.1': + resolution: {integrity: sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.1': + resolution: {integrity: sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.1': + resolution: {integrity: sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.1': + resolution: {integrity: sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.1': + resolution: {integrity: sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.1': + resolution: {integrity: sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.1': + resolution: {integrity: sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.25.1': + resolution: {integrity: sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.1': + resolution: {integrity: sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.1': + resolution: {integrity: sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.1': + resolution: {integrity: sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] '@fastify/busboy@2.1.1': resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} engines: {node: '>=14'} - '@humanfs/core@0.19.1': - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - - '@humanfs/node@0.16.6': - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} - engines: {node: '>=18.18.0'} - - '@humanwhocodes/module-importer@1.0.1': - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - - '@humanwhocodes/retry@0.3.1': - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} - engines: {node: '>=18.18'} - - '@humanwhocodes/retry@0.4.2': - resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} - engines: {node: '>=18.18'} - - '@ianvs/prettier-plugin-sort-imports@4.4.1': - resolution: {integrity: sha512-F0/Hrcfpy8WuxlQyAWJTEren/uxKhYonOGY4OyWmwRdeTvkh9mMSCxowZLjNkhwi/2ipqCgtXwwOk7tW0mWXkA==} - peerDependencies: - '@vue/compiler-sfc': 2.7.x || 3.x - prettier: 2 || 3 - peerDependenciesMeta: - '@vue/compiler-sfc': - optional: true - '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} @@ -326,80 +294,10 @@ packages: resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} engines: {node: '>=18.0.0'} - '@istanbuljs/load-nyc-config@1.1.0': - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - '@istanbuljs/schema@0.1.3': resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} - '@jest/console@29.7.0': - resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/core@29.7.0': - resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - '@jest/environment@29.7.0': - resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/expect-utils@29.7.0': - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/expect@29.7.0': - resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/fake-timers@29.7.0': - resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/globals@29.7.0': - resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/reporters@29.7.0': - resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - '@jest/schemas@29.6.3': - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/source-map@29.6.3': - resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/test-result@29.7.0': - resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/test-sequencer@29.7.0': - resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/transform@29.7.0': - resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - '@jest/types@29.6.3': - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -418,21 +316,6 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - '@jridgewell/trace-mapping@0.3.9': - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - - '@nodelib/fs.scandir@2.1.5': - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - - '@nodelib/fs.stat@2.0.5': - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - '@nodelib/fs.walk@1.2.8': - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - '@octokit/auth-token@4.0.0': resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} engines: {node: '>= 18'} @@ -531,139 +414,144 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@sinclair/typebox@0.27.8': - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + '@rollup/rollup-android-arm-eabi@4.36.0': + resolution: {integrity: sha512-jgrXjjcEwN6XpZXL0HUeOVGfjXhPyxAbbhD0BlXUB+abTOpbPiN5Wb3kOT7yb+uEtATNYF5x5gIfwutmuBA26w==} + cpu: [arm] + os: [android] - '@sinonjs/commons@3.0.1': - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + '@rollup/rollup-android-arm64@4.36.0': + resolution: {integrity: sha512-NyfuLvdPdNUfUNeYKUwPwKsE5SXa2J6bCt2LdB/N+AxShnkpiczi3tcLJrm5mA+eqpy0HmaIY9F6XCa32N5yzg==} + cpu: [arm64] + os: [android] - '@sinonjs/fake-timers@10.3.0': - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@rollup/rollup-darwin-arm64@4.36.0': + resolution: {integrity: sha512-JQ1Jk5G4bGrD4pWJQzWsD8I1n1mgPXq33+/vP4sk8j/z/C2siRuxZtaUA7yMTf71TCZTZl/4e1bfzwUmFb3+rw==} + cpu: [arm64] + os: [darwin] - '@tsconfig/node10@1.0.11': - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + '@rollup/rollup-darwin-x64@4.36.0': + resolution: {integrity: sha512-6c6wMZa1lrtiRsbDziCmjE53YbTkxMYhhnWnSW8R/yqsM7a6mSJ3uAVT0t8Y/DGt7gxUWYuFM4bwWk9XCJrFKA==} + cpu: [x64] + os: [darwin] - '@tsconfig/node12@1.0.11': - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + '@rollup/rollup-freebsd-arm64@4.36.0': + resolution: {integrity: sha512-KXVsijKeJXOl8QzXTsA+sHVDsFOmMCdBRgFmBb+mfEb/7geR7+C8ypAml4fquUt14ZyVXaw2o1FWhqAfOvA4sg==} + cpu: [arm64] + os: [freebsd] - '@tsconfig/node14@1.0.3': - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + '@rollup/rollup-freebsd-x64@4.36.0': + resolution: {integrity: sha512-dVeWq1ebbvByI+ndz4IJcD4a09RJgRYmLccwlQ8bPd4olz3Y213uf1iwvc7ZaxNn2ab7bjc08PrtBgMu6nb4pQ==} + cpu: [x64] + os: [freebsd] - '@tsconfig/node16@1.0.4': - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@rollup/rollup-linux-arm-gnueabihf@4.36.0': + resolution: {integrity: sha512-bvXVU42mOVcF4le6XSjscdXjqx8okv4n5vmwgzcmtvFdifQ5U4dXFYaCB87namDRKlUL9ybVtLQ9ztnawaSzvg==} + cpu: [arm] + os: [linux] - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + '@rollup/rollup-linux-arm-musleabihf@4.36.0': + resolution: {integrity: sha512-JFIQrDJYrxOnyDQGYkqnNBtjDwTgbasdbUiQvcU8JmGDfValfH1lNpng+4FWlhaVIR4KPkeddYjsVVbmJYvDcg==} + cpu: [arm] + os: [linux] - '@types/babel__generator@7.6.8': - resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + '@rollup/rollup-linux-arm64-gnu@4.36.0': + resolution: {integrity: sha512-KqjYVh3oM1bj//5X7k79PSCZ6CvaVzb7Qs7VMWS+SlWB5M8p3FqufLP9VNp4CazJ0CsPDLwVD9r3vX7Ci4J56A==} + cpu: [arm64] + os: [linux] - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + '@rollup/rollup-linux-arm64-musl@4.36.0': + resolution: {integrity: sha512-QiGnhScND+mAAtfHqeT+cB1S9yFnNQ/EwCg5yE3MzoaZZnIV0RV9O5alJAoJKX/sBONVKeZdMfO8QSaWEygMhw==} + cpu: [arm64] + os: [linux] - '@types/babel__traverse@7.20.6': - resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@rollup/rollup-linux-loongarch64-gnu@4.36.0': + resolution: {integrity: sha512-1ZPyEDWF8phd4FQtTzMh8FQwqzvIjLsl6/84gzUxnMNFBtExBtpL51H67mV9xipuxl1AEAerRBgBwFNpkw8+Lg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.36.0': + resolution: {integrity: sha512-VMPMEIUpPFKpPI9GZMhJrtu8rxnp6mJR3ZzQPykq4xc2GmdHj3Q4cA+7avMyegXy4n1v+Qynr9fR88BmyO74tg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.36.0': + resolution: {integrity: sha512-ttE6ayb/kHwNRJGYLpuAvB7SMtOeQnVXEIpMtAvx3kepFQeowVED0n1K9nAdraHUPJ5hydEMxBpIR7o4nrm8uA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.36.0': + resolution: {integrity: sha512-4a5gf2jpS0AIe7uBjxDeUMNcFmaRTbNv7NxI5xOCs4lhzsVyGR/0qBXduPnoWf6dGC365saTiwag8hP1imTgag==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.36.0': + resolution: {integrity: sha512-5KtoW8UWmwFKQ96aQL3LlRXX16IMwyzMq/jSSVIIyAANiE1doaQsx/KRyhAvpHlPjPiSU/AYX/8m+lQ9VToxFQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.36.0': + resolution: {integrity: sha512-sycrYZPrv2ag4OCvaN5js+f01eoZ2U+RmT5as8vhxiFz+kxwlHrsxOwKPSA8WyS+Wc6Epid9QeI/IkQ9NkgYyQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.36.0': + resolution: {integrity: sha512-qbqt4N7tokFwwSVlWDsjfoHgviS3n/vZ8LK0h1uLG9TYIRuUTJC88E1xb3LM2iqZ/WTqNQjYrtmtGmrmmawB6A==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.36.0': + resolution: {integrity: sha512-t+RY0JuRamIocMuQcfwYSOkmdX9dtkr1PbhKW42AMvaDQa+jOdpUYysroTF/nuPpAaQMWp7ye+ndlmmthieJrQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.36.0': + resolution: {integrity: sha512-aRXd7tRZkWLqGbChgcMMDEHjOKudo1kChb1Jt1IfR8cY/KIpgNviLeJy5FUb9IpSuQj8dU2fAYNMPW/hLKOSTw==} + cpu: [x64] + os: [win32] '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - '@types/graceful-fs@4.1.9': - resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} - - '@types/istanbul-lib-coverage@2.0.6': - resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - - '@types/istanbul-lib-report@3.0.3': - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - - '@types/istanbul-reports@3.0.4': - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - - '@types/jest@29.5.14': - resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} - - '@types/json-schema@7.0.15': - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - '@types/node@22.13.11': resolution: {integrity: sha512-iEUCUJoU0i3VnrCmgoWCXttklWcvoCIx4jzcP22fioIVSdTmjgoEvmAO/QPw6TcS9k5FrNgn4w7q5lGOd1CT5g==} - '@types/stack-utils@2.0.3': - resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} - - '@types/yargs-parser@21.0.3': - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - - '@types/yargs@17.0.33': - resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - - '@typescript-eslint/eslint-plugin@8.27.0': - resolution: {integrity: sha512-4henw4zkePi5p252c8ncBLzLce52SEUz2Ebj8faDnuUXz2UuHEONYcJ+G0oaCF+bYCWVZtrGzq3FD7YXetmnSA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vitest/coverage-v8@3.0.9': + resolution: {integrity: sha512-15OACZcBtQ34keIEn19JYTVuMFTlFrClclwWjHo/IRPg/8ELpkgNTl0o7WLP9WO9XGH6+tip9CPYtEOrIDJvBA==} peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + '@vitest/browser': 3.0.9 + vitest: 3.0.9 + peerDependenciesMeta: + '@vitest/browser': + optional: true - '@typescript-eslint/parser@8.27.0': - resolution: {integrity: sha512-XGwIabPallYipmcOk45DpsBSgLC64A0yvdAkrwEzwZ2viqGqRUJ8eEYoPz0CWnutgAFbNMPdsGGvzjSmcWVlEA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vitest/expect@3.0.9': + resolution: {integrity: sha512-5eCqRItYgIML7NNVgJj6TVCmdzE7ZVgJhruW0ziSQV4V7PvLkDL1bBkBdcTs/VuIz0IxPb5da1IDSqc1TR9eig==} + + '@vitest/mocker@3.0.9': + resolution: {integrity: sha512-ryERPIBOnvevAkTq+L1lD+DTFBRcjueL9lOUfXsLfwP92h4e+Heb+PjiqS3/OURWPtywfafK0kj++yDFjWUmrA==} peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true - '@typescript-eslint/scope-manager@8.27.0': - resolution: {integrity: sha512-8oI9GwPMQmBryaaxG1tOZdxXVeMDte6NyJA4i7/TWa4fBwgnAXYlIQP+uYOeqAaLJ2JRxlG9CAyL+C+YE9Xknw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vitest/pretty-format@3.0.9': + resolution: {integrity: sha512-OW9F8t2J3AwFEwENg3yMyKWweF7oRJlMyHOMIhO5F3n0+cgQAJZBjNgrF8dLwFTEXl5jUqBLXd9QyyKv8zEcmA==} - '@typescript-eslint/type-utils@8.27.0': - resolution: {integrity: sha512-wVArTVcz1oJOIEJxui/nRhV0TXzD/zMSOYi/ggCfNq78EIszddXcJb7r4RCp/oBrjt8n9A0BSxRMKxHftpDxDA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' + '@vitest/runner@3.0.9': + resolution: {integrity: sha512-NX9oUXgF9HPfJSwl8tUZCMP1oGx2+Sf+ru6d05QjzQz4OwWg0psEzwY6VexP2tTHWdOkhKHUIZH+fS6nA7jfOw==} - '@typescript-eslint/types@8.27.0': - resolution: {integrity: sha512-/6cp9yL72yUHAYq9g6DsAU+vVfvQmd1a8KyA81uvfDE21O2DwQ/qxlM4AR8TSdAu+kJLBDrEHKC5/W2/nxsY0A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@vitest/snapshot@3.0.9': + resolution: {integrity: sha512-AiLUiuZ0FuA+/8i19mTYd+re5jqjEc2jZbgJ2up0VY0Ddyyxg/uUtBDpIFAy4uzKaQxOW8gMgBdAJJ2ydhu39A==} - '@typescript-eslint/typescript-estree@8.27.0': - resolution: {integrity: sha512-BnKq8cqPVoMw71O38a1tEb6iebEgGA80icSxW7g+kndx0o6ot6696HjG7NdgfuAVmVEtwXUr3L8R9ZuVjoQL6A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <5.9.0' + '@vitest/spy@3.0.9': + resolution: {integrity: sha512-/CcK2UDl0aQ2wtkp3YVWldrpLRNCfVcIOFGlVGKO4R5eajsH393Z1yiXLVQ7vWsj26JOEjeZI0x5sm5P4OGUNQ==} - '@typescript-eslint/utils@8.27.0': - resolution: {integrity: sha512-njkodcwH1yvmo31YWgRHNb/x1Xhhq4/m81PhtvmRngD8iHPehxffz1SNCO+kwaePhATC+kOa/ggmvPoPza5i0Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' - - '@typescript-eslint/visitor-keys@8.27.0': - resolution: {integrity: sha512-WsXQwMkILJvffP6z4U3FYJPlbf/j07HIxmDjZpbNvBJkMfvwXj5ACRkkHwBDvLBbDbtX5TdU64/rcvKJ/vuInQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} - - acorn@8.14.1: - resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} - engines: {node: '>=0.4.0'} - hasBin: true - - ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - - ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} + '@vitest/utils@3.0.9': + resolution: {integrity: sha512-ilHM5fHhZ89MCp5aAaM9uhfl1c2JdxVxl3McqsdVyVNN6JffnEen8UMCdRTzOhGXNQGo5GNL9QugHrz727Wnng==} ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -677,54 +565,13 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - - arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - - argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - - async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - - babel-jest@29.7.0: - resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - - babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - - babel-plugin-jest-hoist@29.6.3: - resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - babel-preset-current-node-syntax@1.1.0: - resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} - peerDependencies: - '@babel/core': ^7.0.0 - - babel-preset-jest@29.6.3: - resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.0.0 + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -735,76 +582,25 @@ packages: before-after-hook@3.0.2: resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} - brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - browserslist@4.24.4: - resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} - bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - - bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - - buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - - callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - - camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - - camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - - caniuse-lite@1.0.30001706: - resolution: {integrity: sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==} - - chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - - char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} chownr@3.0.0: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} - ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - - cjs-module-lexer@1.4.3: - resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} - - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - - co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - - collect-v8-coverage@1.0.2: - resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -812,20 +608,6 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - create-jest@29.7.0: - resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - - create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -839,316 +621,64 @@ packages: supports-color: optional: true - dedent@1.5.3: - resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - - deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - - deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} deprecation@2.3.1: resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} - detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - - diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true - - electron-to-chromium@1.5.123: - resolution: {integrity: sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==} - - emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-string-regexp@2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - - escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - - eslint-config-prettier@10.1.1: - resolution: {integrity: sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - - eslint-scope@8.3.0: - resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - - eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - eslint@9.23.0: - resolution: {integrity: sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - - espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} + esbuild@0.25.1: + resolution: {integrity: sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==} + engines: {node: '>=18'} hasBin: true - esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - - estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - - esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - - execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - - exit@0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} - - expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + expect-type@1.2.0: + resolution: {integrity: sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==} + engines: {node: '>=12.0.0'} fast-content-type-parse@2.0.1: resolution: {integrity: sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==} - fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - - fast-glob@3.3.3: - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} - engines: {node: '>=8.6.0'} - - fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - - fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - - fastq@1.19.1: - resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} - - fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - - file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - - filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - - find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - - find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - - flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - - flatted@3.3.3: - resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} - foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - - get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - - glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - - glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - - globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - - globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - - ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - - import-fresh@3.3.1: - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} - engines: {node: '>=6'} - - import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} - hasBin: true - - imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - - is-core-module@2.16.1: - resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} - engines: {node: '>= 0.4'} - - is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - - is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - - is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -1156,20 +686,12 @@ packages: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} - istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - - istanbul-lib-instrument@6.0.3: - resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} - engines: {node: '>=10'} - istanbul-lib-report@3.0.1: resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} engines: {node: '>=10'} - istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} engines: {node: '>=10'} istanbul-reports@3.1.7: @@ -1179,243 +701,22 @@ packages: jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} - jake@10.9.2: - resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} - engines: {node: '>=10'} - hasBin: true - - jest-changed-files@29.7.0: - resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-circus@29.7.0: - resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-cli@29.7.0: - resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - jest-config@29.7.0: - resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - - jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-docblock@29.7.0: - resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-each@29.7.0: - resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-environment-node@29.7.0: - resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-haste-map@29.7.0: - resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-leak-detector@29.7.0: - resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-mock@29.7.0: - resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-pnp-resolver@1.2.3: - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - - jest-regex-util@29.6.3: - resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-resolve-dependencies@29.7.0: - resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-resolve@29.7.0: - resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-runner@29.7.0: - resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-runtime@29.7.0: - resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-snapshot@29.7.0: - resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-validate@29.7.0: - resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-watcher@29.7.0: - resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest-worker@29.7.0: - resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - jest@29.7.0: - resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - - json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - - json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - - kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - - leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - - levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - - locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - - locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - - lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - - lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} - make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - - makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - - merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - - minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -1436,167 +737,46 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - - node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - - node-releases@2.0.19: - resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - - npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - - p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - - p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - - p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - - p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - - p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} - parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - - path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - path-scurry@1.11.1: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - - prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - - prettier@3.5.3: - resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} - engines: {node: '>=14'} - hasBin: true - - pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - - prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - - queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - - resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - - resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - - resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - - resolve.exports@2.0.3: - resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} - engines: {node: '>=10'} - - resolve@1.22.10: - resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} - engines: {node: '>= 0.4'} - hasBin: true - - reusify@1.1.0: - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} rimraf@5.0.10: resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} hasBin: true - run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + rollup@4.36.0: + resolution: {integrity: sha512-zwATAXNQxUcd40zgtQG0ZafcRK4g004WtEl7kbuhTWPvf07PsfohXl39jVUvPF7jvNAIkKPQ2XrsDlWuxBd++Q==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true semver@7.7.1: @@ -1612,37 +792,22 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - - slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} - sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - stack-utils@2.0.6: - resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} - engines: {node: '>=10'} - - string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} + std-env@3.8.1: + resolution: {integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==} string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} @@ -1660,112 +825,40 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} - strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - - strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - - strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - tar@7.4.3: resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} engines: {node: '>=18'} - test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} + test-exclude@7.0.1: + resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} + engines: {node: '>=18'} - tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} - ts-api-utils@2.1.0: - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} - engines: {node: '>=18.12'} - peerDependencies: - typescript: '>=4.8.4' + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + engines: {node: ^18.0.0 || >=20.0.0} - ts-jest@29.2.6: - resolution: {integrity: sha512-yTNZVZqc8lSixm+QGVFcPe6+yj7+TWZwIesuOWvfcn4B9bz5x4NDzVCQQjOs7Hfouu36aEqfEbo9Qpo+gq8dDg==} - engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@babel/core': '>=7.0.0-beta.0 <8' - '@jest/transform': ^29.0.0 - '@jest/types': ^29.0.0 - babel-jest: ^29.0.0 - esbuild: '*' - jest: ^29.0.0 - typescript: '>=4.3 <6' - peerDependenciesMeta: - '@babel/core': - optional: true - '@jest/transform': - optional: true - '@jest/types': - optional: true - babel-jest: - optional: true - esbuild: - optional: true + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} - ts-node@10.9.2: - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} tunnel@0.0.6: resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} - type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - - type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - - type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - - typescript-eslint@8.27.0: - resolution: {integrity: sha512-ZZ/8+Y0rRUMuW1gJaPtLWe4ryHbsPLzzibk5Sq+IFa2aOH1Vo0gPr1fbA6pOnzBke7zC2Da4w8AyCgxKXo3lqA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.9.0' - typescript@5.8.2: resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} engines: {node: '>=14.17'} @@ -1784,33 +877,88 @@ packages: universal-user-agent@7.0.2: resolution: {integrity: sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==} - update-browserslist-db@1.1.3: - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + vite-node@3.0.9: + resolution: {integrity: sha512-w3Gdx7jDcuT9cNn9jExXgOyKmf5UOTb6WMHz8LGAm54eS1Elf5OuBhCxl6zJxGhEeIkgsE1WbHuoL0mj/UXqXg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@6.2.2: + resolution: {integrity: sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: - browserslist: '>= 4.21.0' + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true - uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - - v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - - v8-to-istanbul@9.3.0: - resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} - engines: {node: '>=10.12.0'} - - walker@1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + vitest@3.0.9: + resolution: {integrity: sha512-BbcFDqNyBlfSpATmTtXOAOj71RNKDDvjBM/uPfnxxVGrG+FSH2RQIwgeEngTaTkuU/h0ScFvf+tRcKfYXzBybQ==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.0.9 + '@vitest/ui': 3.0.9 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true - word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} @@ -1823,37 +971,10 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - yallist@5.0.0: resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} engines: {node: '>=18'} - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - - yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - - yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - snapshots: '@actions/core@1.11.1': @@ -1884,267 +1005,133 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 - '@babel/code-frame@7.26.2': - dependencies: - '@babel/helper-validator-identifier': 7.25.9 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/compat-data@7.26.8': {} - - '@babel/core@7.26.10': - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.10 - '@babel/helper-compilation-targets': 7.26.5 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) - '@babel/helpers': 7.26.10 - '@babel/parser': 7.26.10 - '@babel/template': 7.26.9 - '@babel/traverse': 7.26.10 - '@babel/types': 7.26.10 - convert-source-map: 2.0.0 - debug: 4.4.0 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.26.10': - dependencies: - '@babel/parser': 7.26.10 - '@babel/types': 7.26.10 - '@jridgewell/gen-mapping': 0.3.8 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 3.1.0 - - '@babel/helper-compilation-targets@7.26.5': - dependencies: - '@babel/compat-data': 7.26.8 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.4 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-module-imports@7.25.9': - dependencies: - '@babel/traverse': 7.26.10 - '@babel/types': 7.26.10 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.10 - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.26.5': {} - '@babel/helper-string-parser@7.25.9': {} '@babel/helper-validator-identifier@7.25.9': {} - '@babel/helper-validator-option@7.25.9': {} - - '@babel/helpers@7.26.10': - dependencies: - '@babel/template': 7.26.9 - '@babel/types': 7.26.10 - '@babel/parser@7.26.10': dependencies: '@babel/types': 7.26.10 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.10)': - dependencies: - '@babel/core': 7.26.10 - '@babel/helper-plugin-utils': 7.26.5 - - '@babel/template@7.26.9': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.10 - '@babel/types': 7.26.10 - - '@babel/traverse@7.26.10': - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.10 - '@babel/parser': 7.26.10 - '@babel/template': 7.26.9 - '@babel/types': 7.26.10 - debug: 4.4.0 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - '@babel/types@7.26.10': dependencies: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@bcoe/v8-coverage@0.2.3': {} + '@bcoe/v8-coverage@1.0.2': {} - '@cspotcode/source-map-support@0.8.1': - dependencies: - '@jridgewell/trace-mapping': 0.3.9 + '@biomejs/biome@1.9.4': + optionalDependencies: + '@biomejs/cli-darwin-arm64': 1.9.4 + '@biomejs/cli-darwin-x64': 1.9.4 + '@biomejs/cli-linux-arm64': 1.9.4 + '@biomejs/cli-linux-arm64-musl': 1.9.4 + '@biomejs/cli-linux-x64': 1.9.4 + '@biomejs/cli-linux-x64-musl': 1.9.4 + '@biomejs/cli-win32-arm64': 1.9.4 + '@biomejs/cli-win32-x64': 1.9.4 - '@eslint-community/eslint-utils@4.5.1(eslint@9.23.0)': - dependencies: - eslint: 9.23.0 - eslint-visitor-keys: 3.4.3 + '@biomejs/cli-darwin-arm64@1.9.4': + optional: true - '@eslint-community/regexpp@4.12.1': {} + '@biomejs/cli-darwin-x64@1.9.4': + optional: true - '@eslint/config-array@0.19.2': - dependencies: - '@eslint/object-schema': 2.1.6 - debug: 4.4.0 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color + '@biomejs/cli-linux-arm64-musl@1.9.4': + optional: true - '@eslint/config-helpers@0.2.0': {} + '@biomejs/cli-linux-arm64@1.9.4': + optional: true - '@eslint/core@0.12.0': - dependencies: - '@types/json-schema': 7.0.15 + '@biomejs/cli-linux-x64-musl@1.9.4': + optional: true - '@eslint/eslintrc@3.3.1': - dependencies: - ajv: 6.12.6 - debug: 4.4.0 - espree: 10.3.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.1 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color + '@biomejs/cli-linux-x64@1.9.4': + optional: true - '@eslint/js@9.23.0': {} + '@biomejs/cli-win32-arm64@1.9.4': + optional: true - '@eslint/object-schema@2.1.6': {} + '@biomejs/cli-win32-x64@1.9.4': + optional: true - '@eslint/plugin-kit@0.2.7': - dependencies: - '@eslint/core': 0.12.0 - levn: 0.4.1 + '@esbuild/aix-ppc64@0.25.1': + optional: true + + '@esbuild/android-arm64@0.25.1': + optional: true + + '@esbuild/android-arm@0.25.1': + optional: true + + '@esbuild/android-x64@0.25.1': + optional: true + + '@esbuild/darwin-arm64@0.25.1': + optional: true + + '@esbuild/darwin-x64@0.25.1': + optional: true + + '@esbuild/freebsd-arm64@0.25.1': + optional: true + + '@esbuild/freebsd-x64@0.25.1': + optional: true + + '@esbuild/linux-arm64@0.25.1': + optional: true + + '@esbuild/linux-arm@0.25.1': + optional: true + + '@esbuild/linux-ia32@0.25.1': + optional: true + + '@esbuild/linux-loong64@0.25.1': + optional: true + + '@esbuild/linux-mips64el@0.25.1': + optional: true + + '@esbuild/linux-ppc64@0.25.1': + optional: true + + '@esbuild/linux-riscv64@0.25.1': + optional: true + + '@esbuild/linux-s390x@0.25.1': + optional: true + + '@esbuild/linux-x64@0.25.1': + optional: true + + '@esbuild/netbsd-arm64@0.25.1': + optional: true + + '@esbuild/netbsd-x64@0.25.1': + optional: true + + '@esbuild/openbsd-arm64@0.25.1': + optional: true + + '@esbuild/openbsd-x64@0.25.1': + optional: true + + '@esbuild/sunos-x64@0.25.1': + optional: true + + '@esbuild/win32-arm64@0.25.1': + optional: true + + '@esbuild/win32-ia32@0.25.1': + optional: true + + '@esbuild/win32-x64@0.25.1': + optional: true '@fastify/busboy@2.1.1': {} - '@humanfs/core@0.19.1': {} - - '@humanfs/node@0.16.6': - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 - - '@humanwhocodes/module-importer@1.0.1': {} - - '@humanwhocodes/retry@0.3.1': {} - - '@humanwhocodes/retry@0.4.2': {} - - '@ianvs/prettier-plugin-sort-imports@4.4.1(prettier@3.5.3)': - dependencies: - '@babel/generator': 7.26.10 - '@babel/parser': 7.26.10 - '@babel/traverse': 7.26.10 - '@babel/types': 7.26.10 - prettier: 3.5.3 - semver: 7.7.1 - transitivePeerDependencies: - - supports-color - '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -2158,178 +1145,8 @@ snapshots: dependencies: minipass: 7.1.2 - '@istanbuljs/load-nyc-config@1.1.0': - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - '@istanbuljs/schema@0.1.3': {} - '@jest/console@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@types/node': 22.13.11 - chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2))': - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.13.11 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - - '@jest/environment@29.7.0': - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.13.11 - jest-mock: 29.7.0 - - '@jest/expect-utils@29.7.0': - dependencies: - jest-get-type: 29.6.3 - - '@jest/expect@29.7.0': - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/fake-timers@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.13.11 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - '@jest/globals@29.7.0': - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/reporters@29.7.0': - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 22.13.11 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.7 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.3.0 - transitivePeerDependencies: - - supports-color - - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.8 - - '@jest/source-map@29.6.3': - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.11 - - '@jest/test-result@29.7.0': - dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.2 - - '@jest/test-sequencer@29.7.0': - dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - slash: 3.0.0 - - '@jest/transform@29.7.0': - dependencies: - '@babel/core': 7.26.10 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.8 - pirates: 4.0.6 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - - '@jest/types@29.6.3': - dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 22.13.11 - '@types/yargs': 17.0.33 - chalk: 4.1.2 - '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -2347,23 +1164,6 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping@0.3.9': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.19.1 - '@octokit/auth-token@4.0.0': {} '@octokit/auth-token@5.1.2': {} @@ -2481,177 +1281,126 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@sinclair/typebox@0.27.8': {} + '@rollup/rollup-android-arm-eabi@4.36.0': + optional: true - '@sinonjs/commons@3.0.1': - dependencies: - type-detect: 4.0.8 + '@rollup/rollup-android-arm64@4.36.0': + optional: true - '@sinonjs/fake-timers@10.3.0': - dependencies: - '@sinonjs/commons': 3.0.1 + '@rollup/rollup-darwin-arm64@4.36.0': + optional: true - '@tsconfig/node10@1.0.11': {} + '@rollup/rollup-darwin-x64@4.36.0': + optional: true - '@tsconfig/node12@1.0.11': {} + '@rollup/rollup-freebsd-arm64@4.36.0': + optional: true - '@tsconfig/node14@1.0.3': {} + '@rollup/rollup-freebsd-x64@4.36.0': + optional: true - '@tsconfig/node16@1.0.4': {} + '@rollup/rollup-linux-arm-gnueabihf@4.36.0': + optional: true - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.26.10 - '@babel/types': 7.26.10 - '@types/babel__generator': 7.6.8 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.6 + '@rollup/rollup-linux-arm-musleabihf@4.36.0': + optional: true - '@types/babel__generator@7.6.8': - dependencies: - '@babel/types': 7.26.10 + '@rollup/rollup-linux-arm64-gnu@4.36.0': + optional: true - '@types/babel__template@7.4.4': - dependencies: - '@babel/parser': 7.26.10 - '@babel/types': 7.26.10 + '@rollup/rollup-linux-arm64-musl@4.36.0': + optional: true - '@types/babel__traverse@7.20.6': - dependencies: - '@babel/types': 7.26.10 + '@rollup/rollup-linux-loongarch64-gnu@4.36.0': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.36.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.36.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.36.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.36.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.36.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.36.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.36.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.36.0': + optional: true '@types/estree@1.0.6': {} - '@types/graceful-fs@4.1.9': - dependencies: - '@types/node': 22.13.11 - - '@types/istanbul-lib-coverage@2.0.6': {} - - '@types/istanbul-lib-report@3.0.3': - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 - - '@types/istanbul-reports@3.0.4': - dependencies: - '@types/istanbul-lib-report': 3.0.3 - - '@types/jest@29.5.14': - dependencies: - expect: 29.7.0 - pretty-format: 29.7.0 - - '@types/json-schema@7.0.15': {} - '@types/node@22.13.11': dependencies: undici-types: 6.20.0 - '@types/stack-utils@2.0.3': {} - - '@types/yargs-parser@21.0.3': {} - - '@types/yargs@17.0.33': + '@vitest/coverage-v8@3.0.9(vitest@3.0.9(@types/node@22.13.11))': dependencies: - '@types/yargs-parser': 21.0.3 - - '@typescript-eslint/eslint-plugin@8.27.0(@typescript-eslint/parser@8.27.0(eslint@9.23.0)(typescript@5.8.2))(eslint@9.23.0)(typescript@5.8.2)': - dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.27.0(eslint@9.23.0)(typescript@5.8.2) - '@typescript-eslint/scope-manager': 8.27.0 - '@typescript-eslint/type-utils': 8.27.0(eslint@9.23.0)(typescript@5.8.2) - '@typescript-eslint/utils': 8.27.0(eslint@9.23.0)(typescript@5.8.2) - '@typescript-eslint/visitor-keys': 8.27.0 - eslint: 9.23.0 - graphemer: 1.4.0 - ignore: 5.3.2 - natural-compare: 1.4.0 - ts-api-utils: 2.1.0(typescript@5.8.2) - typescript: 5.8.2 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@8.27.0(eslint@9.23.0)(typescript@5.8.2)': - dependencies: - '@typescript-eslint/scope-manager': 8.27.0 - '@typescript-eslint/types': 8.27.0 - '@typescript-eslint/typescript-estree': 8.27.0(typescript@5.8.2) - '@typescript-eslint/visitor-keys': 8.27.0 + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 1.0.2 debug: 4.4.0 - eslint: 9.23.0 - typescript: 5.8.2 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.1.7 + magic-string: 0.30.17 + magicast: 0.3.5 + std-env: 3.8.1 + test-exclude: 7.0.1 + tinyrainbow: 2.0.0 + vitest: 3.0.9(@types/node@22.13.11) transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.27.0': + '@vitest/expect@3.0.9': dependencies: - '@typescript-eslint/types': 8.27.0 - '@typescript-eslint/visitor-keys': 8.27.0 + '@vitest/spy': 3.0.9 + '@vitest/utils': 3.0.9 + chai: 5.2.0 + tinyrainbow: 2.0.0 - '@typescript-eslint/type-utils@8.27.0(eslint@9.23.0)(typescript@5.8.2)': + '@vitest/mocker@3.0.9(vite@6.2.2(@types/node@22.13.11))': dependencies: - '@typescript-eslint/typescript-estree': 8.27.0(typescript@5.8.2) - '@typescript-eslint/utils': 8.27.0(eslint@9.23.0)(typescript@5.8.2) - debug: 4.4.0 - eslint: 9.23.0 - ts-api-utils: 2.1.0(typescript@5.8.2) - typescript: 5.8.2 - transitivePeerDependencies: - - supports-color + '@vitest/spy': 3.0.9 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 6.2.2(@types/node@22.13.11) - '@typescript-eslint/types@8.27.0': {} - - '@typescript-eslint/typescript-estree@8.27.0(typescript@5.8.2)': + '@vitest/pretty-format@3.0.9': dependencies: - '@typescript-eslint/types': 8.27.0 - '@typescript-eslint/visitor-keys': 8.27.0 - debug: 4.4.0 - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.1 - ts-api-utils: 2.1.0(typescript@5.8.2) - typescript: 5.8.2 - transitivePeerDependencies: - - supports-color + tinyrainbow: 2.0.0 - '@typescript-eslint/utils@8.27.0(eslint@9.23.0)(typescript@5.8.2)': + '@vitest/runner@3.0.9': dependencies: - '@eslint-community/eslint-utils': 4.5.1(eslint@9.23.0) - '@typescript-eslint/scope-manager': 8.27.0 - '@typescript-eslint/types': 8.27.0 - '@typescript-eslint/typescript-estree': 8.27.0(typescript@5.8.2) - eslint: 9.23.0 - typescript: 5.8.2 - transitivePeerDependencies: - - supports-color + '@vitest/utils': 3.0.9 + pathe: 2.0.3 - '@typescript-eslint/visitor-keys@8.27.0': + '@vitest/snapshot@3.0.9': dependencies: - '@typescript-eslint/types': 8.27.0 - eslint-visitor-keys: 4.2.0 + '@vitest/pretty-format': 3.0.9 + magic-string: 0.30.17 + pathe: 2.0.3 - acorn-jsx@5.3.2(acorn@8.14.1): + '@vitest/spy@3.0.9': dependencies: - acorn: 8.14.1 + tinyspy: 3.0.2 - acorn-walk@8.3.4: + '@vitest/utils@3.0.9': dependencies: - acorn: 8.14.1 - - acorn@8.14.1: {} - - ajv@6.12.6: - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - - ansi-escapes@4.3.2: - dependencies: - type-fest: 0.21.3 + '@vitest/pretty-format': 3.0.9 + loupe: 3.1.3 + tinyrainbow: 2.0.0 ansi-regex@5.0.1: {} @@ -2661,79 +1410,9 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@5.2.0: {} - ansi-styles@6.2.1: {} - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - - arg@4.1.3: {} - - argparse@1.0.10: - dependencies: - sprintf-js: 1.0.3 - - argparse@2.0.1: {} - - async@3.2.6: {} - - babel-jest@29.7.0(@babel/core@7.26.10): - dependencies: - '@babel/core': 7.26.10 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.26.10) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-istanbul@6.1.1: - dependencies: - '@babel/helper-plugin-utils': 7.26.5 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - - babel-plugin-jest-hoist@29.6.3: - dependencies: - '@babel/template': 7.26.9 - '@babel/types': 7.26.10 - '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.6 - - babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.10): - dependencies: - '@babel/core': 7.26.10 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.10) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.10) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.10) - '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.10) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.10) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.10) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.10) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.10) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.10) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.10) - - babel-preset-jest@29.6.3(@babel/core@7.26.10): - dependencies: - '@babel/core': 7.26.10 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.10) + assertion-error@2.0.1: {} balanced-match@1.0.2: {} @@ -2741,94 +1420,30 @@ snapshots: before-after-hook@3.0.2: {} - brace-expansion@1.1.11: - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 - braces@3.0.3: + cac@6.7.14: {} + + chai@5.2.0: dependencies: - fill-range: 7.1.1 + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.3 + pathval: 2.0.0 - browserslist@4.24.4: - dependencies: - caniuse-lite: 1.0.30001706 - electron-to-chromium: 1.5.123 - node-releases: 2.0.19 - update-browserslist-db: 1.1.3(browserslist@4.24.4) - - bs-logger@0.2.6: - dependencies: - fast-json-stable-stringify: 2.1.0 - - bser@2.1.1: - dependencies: - node-int64: 0.4.0 - - buffer-from@1.1.2: {} - - callsites@3.1.0: {} - - camelcase@5.3.1: {} - - camelcase@6.3.0: {} - - caniuse-lite@1.0.30001706: {} - - chalk@4.1.2: - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - char-regex@1.0.2: {} + check-error@2.1.1: {} chownr@3.0.0: {} - ci-info@3.9.0: {} - - cjs-module-lexer@1.4.3: {} - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - - co@4.6.0: {} - - collect-v8-coverage@1.0.2: {} - color-convert@2.0.1: dependencies: color-name: 1.1.4 color-name@1.1.4: {} - concat-map@0.0.1: {} - - convert-source-map@2.0.0: {} - - create-jest@29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)): - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - create-require@1.1.1: {} - cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -2839,220 +1454,62 @@ snapshots: dependencies: ms: 2.1.3 - dedent@1.5.3: {} - - deep-is@0.1.4: {} - - deepmerge@4.3.1: {} + deep-eql@5.0.2: {} deprecation@2.3.1: {} - detect-newline@3.1.0: {} - - diff-sequences@29.6.3: {} - - diff@4.0.2: {} - eastasianwidth@0.2.0: {} - ejs@3.1.10: - dependencies: - jake: 10.9.2 - - electron-to-chromium@1.5.123: {} - - emittery@0.13.1: {} - emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} - error-ex@1.3.2: + es-module-lexer@1.6.0: {} + + esbuild@0.25.1: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.1 + '@esbuild/android-arm': 0.25.1 + '@esbuild/android-arm64': 0.25.1 + '@esbuild/android-x64': 0.25.1 + '@esbuild/darwin-arm64': 0.25.1 + '@esbuild/darwin-x64': 0.25.1 + '@esbuild/freebsd-arm64': 0.25.1 + '@esbuild/freebsd-x64': 0.25.1 + '@esbuild/linux-arm': 0.25.1 + '@esbuild/linux-arm64': 0.25.1 + '@esbuild/linux-ia32': 0.25.1 + '@esbuild/linux-loong64': 0.25.1 + '@esbuild/linux-mips64el': 0.25.1 + '@esbuild/linux-ppc64': 0.25.1 + '@esbuild/linux-riscv64': 0.25.1 + '@esbuild/linux-s390x': 0.25.1 + '@esbuild/linux-x64': 0.25.1 + '@esbuild/netbsd-arm64': 0.25.1 + '@esbuild/netbsd-x64': 0.25.1 + '@esbuild/openbsd-arm64': 0.25.1 + '@esbuild/openbsd-x64': 0.25.1 + '@esbuild/sunos-x64': 0.25.1 + '@esbuild/win32-arm64': 0.25.1 + '@esbuild/win32-ia32': 0.25.1 + '@esbuild/win32-x64': 0.25.1 + + estree-walker@3.0.3: dependencies: - is-arrayish: 0.2.1 - - escalade@3.2.0: {} - - escape-string-regexp@2.0.0: {} - - escape-string-regexp@4.0.0: {} - - eslint-config-prettier@10.1.1(eslint@9.23.0): - dependencies: - eslint: 9.23.0 - - eslint-scope@8.3.0: - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - - eslint-visitor-keys@3.4.3: {} - - eslint-visitor-keys@4.2.0: {} - - eslint@9.23.0: - dependencies: - '@eslint-community/eslint-utils': 4.5.1(eslint@9.23.0) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.2 - '@eslint/config-helpers': 0.2.0 - '@eslint/core': 0.12.0 - '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.23.0 - '@eslint/plugin-kit': 0.2.7 - '@humanfs/node': 0.16.6 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.2 '@types/estree': 1.0.6 - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.4.0 - escape-string-regexp: 4.0.0 - eslint-scope: 8.3.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - transitivePeerDependencies: - - supports-color - espree@10.3.0: - dependencies: - acorn: 8.14.1 - acorn-jsx: 5.3.2(acorn@8.14.1) - eslint-visitor-keys: 4.2.0 - - esprima@4.0.1: {} - - esquery@1.6.0: - dependencies: - estraverse: 5.3.0 - - esrecurse@4.3.0: - dependencies: - estraverse: 5.3.0 - - estraverse@5.3.0: {} - - esutils@2.0.3: {} - - execa@5.1.1: - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - - exit@0.1.2: {} - - expect@29.7.0: - dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 + expect-type@1.2.0: {} fast-content-type-parse@2.0.1: {} - fast-deep-equal@3.1.3: {} - - fast-glob@3.3.3: - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - - fast-json-stable-stringify@2.1.0: {} - - fast-levenshtein@2.0.6: {} - - fastq@1.19.1: - dependencies: - reusify: 1.1.0 - - fb-watchman@2.0.2: - dependencies: - bser: 2.1.1 - - file-entry-cache@8.0.0: - dependencies: - flat-cache: 4.0.1 - - filelist@1.0.4: - dependencies: - minimatch: 5.1.6 - - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - - find-up@4.1.0: - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - - find-up@5.0.0: - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - - flat-cache@4.0.1: - dependencies: - flatted: 3.3.3 - keyv: 4.5.4 - - flatted@3.3.3: {} - foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 - fs.realpath@1.0.0: {} - fsevents@2.3.3: optional: true - function-bind@1.1.2: {} - - gensync@1.0.0-beta.2: {} - - get-caller-file@2.0.5: {} - - get-package-type@0.1.0: {} - - get-stream@6.0.1: {} - - glob-parent@5.1.2: - dependencies: - is-glob: 4.0.3 - - glob-parent@6.0.2: - dependencies: - is-glob: 4.0.3 - glob@10.4.5: dependencies: foreground-child: 3.3.1 @@ -3062,109 +1519,27 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 1.11.1 - glob@7.2.3: - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - globals@11.12.0: {} - - globals@14.0.0: {} - - graceful-fs@4.2.11: {} - - graphemer@1.4.0: {} - has-flag@4.0.0: {} - hasown@2.0.2: - dependencies: - function-bind: 1.1.2 - html-escaper@2.0.2: {} - human-signals@2.1.0: {} - - ignore@5.3.2: {} - - import-fresh@3.3.1: - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - - import-local@3.2.0: - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - - imurmurhash@0.1.4: {} - - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - inherits@2.0.4: {} - - is-arrayish@0.2.1: {} - - is-core-module@2.16.1: - dependencies: - hasown: 2.0.2 - - is-extglob@2.1.1: {} - is-fullwidth-code-point@3.0.0: {} - is-generator-fn@2.1.0: {} - - is-glob@4.0.3: - dependencies: - is-extglob: 2.1.1 - - is-number@7.0.0: {} - - is-stream@2.0.1: {} - isexe@2.0.0: {} istanbul-lib-coverage@3.2.2: {} - istanbul-lib-instrument@5.2.1: - dependencies: - '@babel/core': 7.26.10 - '@babel/parser': 7.26.10 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - istanbul-lib-instrument@6.0.3: - dependencies: - '@babel/core': 7.26.10 - '@babel/parser': 7.26.10 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.7.1 - transitivePeerDependencies: - - supports-color - istanbul-lib-report@3.0.1: dependencies: istanbul-lib-coverage: 3.2.2 make-dir: 4.0.0 supports-color: 7.2.0 - istanbul-lib-source-maps@4.0.1: + istanbul-lib-source-maps@5.0.6: dependencies: + '@jridgewell/trace-mapping': 0.3.25 debug: 4.4.0 istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 transitivePeerDependencies: - supports-color @@ -3179,407 +1554,24 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 - jake@10.9.2: - dependencies: - async: 3.2.6 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - - jest-changed-files@29.7.0: - dependencies: - execa: 5.1.1 - jest-util: 29.7.0 - p-limit: 3.1.0 - - jest-circus@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.13.11 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.5.3 - is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.1.0 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-cli@29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)): - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)) - exit: 0.1.2 - import-local: 3.2.0 - jest-config: 29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - jest-config@29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)): - dependencies: - '@babel/core': 7.26.10 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.26.10) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 22.13.11 - ts-node: 10.9.2(@types/node@22.13.11)(typescript@5.8.2) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - jest-diff@29.7.0: - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-docblock@29.7.0: - dependencies: - detect-newline: 3.1.0 - - jest-each@29.7.0: - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 - - jest-environment-node@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.13.11 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - jest-get-type@29.6.3: {} - - jest-haste-map@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.9 - '@types/node': 22.13.11 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 - micromatch: 4.0.8 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - - jest-leak-detector@29.7.0: - dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-matcher-utils@29.7.0: - dependencies: - chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - - jest-message-util@29.7.0: - dependencies: - '@babel/code-frame': 7.26.2 - '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - stack-utils: 2.0.6 - - jest-mock@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/node': 22.13.11 - jest-util: 29.7.0 - - jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): - optionalDependencies: - jest-resolve: 29.7.0 - - jest-regex-util@29.6.3: {} - - jest-resolve-dependencies@29.7.0: - dependencies: - jest-regex-util: 29.6.3 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - jest-resolve@29.7.0: - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.10 - resolve.exports: 2.0.3 - slash: 3.0.0 - - jest-runner@29.7.0: - dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.13.11 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.11 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - - jest-runtime@29.7.0: - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.13.11 - chalk: 4.1.2 - cjs-module-lexer: 1.4.3 - collect-v8-coverage: 1.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - - jest-snapshot@29.7.0: - dependencies: - '@babel/core': 7.26.10 - '@babel/generator': 7.26.10 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10) - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.10) - '@babel/types': 7.26.10 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.10) - chalk: 4.1.2 - expect: 29.7.0 - graceful-fs: 4.2.11 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 - semver: 7.7.1 - transitivePeerDependencies: - - supports-color - - jest-util@29.7.0: - dependencies: - '@jest/types': 29.6.3 - '@types/node': 22.13.11 - chalk: 4.1.2 - ci-info: 3.9.0 - graceful-fs: 4.2.11 - picomatch: 2.3.1 - - jest-validate@29.7.0: - dependencies: - '@jest/types': 29.6.3 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.6.3 - leven: 3.1.0 - pretty-format: 29.7.0 - - jest-watcher@29.7.0: - dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.13.11 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.7.0 - string-length: 4.0.2 - - jest-worker@29.7.0: - dependencies: - '@types/node': 22.13.11 - jest-util: 29.7.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - - jest@29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)): - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)) - '@jest/types': 29.6.3 - import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - - js-tokens@4.0.0: {} - - js-yaml@3.14.1: - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - - js-yaml@4.1.0: - dependencies: - argparse: 2.0.1 - - jsesc@3.1.0: {} - - json-buffer@3.0.1: {} - - json-parse-even-better-errors@2.3.1: {} - - json-schema-traverse@0.4.1: {} - - json-stable-stringify-without-jsonify@1.0.1: {} - - json5@2.2.3: {} - - keyv@4.5.4: - dependencies: - json-buffer: 3.0.1 - - kleur@3.0.3: {} - - leven@3.1.0: {} - - levn@0.4.1: - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - - lines-and-columns@1.2.4: {} - - locate-path@5.0.0: - dependencies: - p-locate: 4.1.0 - - locate-path@6.0.0: - dependencies: - p-locate: 5.0.0 - - lodash.memoize@4.1.2: {} - - lodash.merge@4.6.2: {} + loupe@3.1.3: {} lru-cache@10.4.3: {} - lru-cache@5.1.1: + magic-string@0.30.17: dependencies: - yallist: 3.1.1 + '@jridgewell/sourcemap-codec': 1.5.0 + + magicast@0.3.5: + dependencies: + '@babel/parser': 7.26.10 + '@babel/types': 7.26.10 + source-map-js: 1.2.1 make-dir@4.0.0: dependencies: semver: 7.7.1 - make-error@1.3.6: {} - - makeerror@1.0.12: - dependencies: - tmpl: 1.0.5 - - merge-stream@2.0.0: {} - - merge2@1.4.1: {} - - micromatch@4.0.8: - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - - mimic-fn@2.1.0: {} - - minimatch@3.1.2: - dependencies: - brace-expansion: 1.1.11 - - minimatch@5.1.6: - dependencies: - brace-expansion: 2.0.1 - minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 @@ -3595,141 +1587,61 @@ snapshots: ms@2.1.3: {} - natural-compare@1.4.0: {} - - node-int64@0.4.0: {} - - node-releases@2.0.19: {} - - normalize-path@3.0.0: {} - - npm-run-path@4.0.1: - dependencies: - path-key: 3.1.1 + nanoid@3.3.11: {} once@1.4.0: dependencies: wrappy: 1.0.2 - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - optionator@0.9.4: - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - - p-limit@2.3.0: - dependencies: - p-try: 2.2.0 - - p-limit@3.1.0: - dependencies: - yocto-queue: 0.1.0 - - p-locate@4.1.0: - dependencies: - p-limit: 2.3.0 - - p-locate@5.0.0: - dependencies: - p-limit: 3.1.0 - - p-try@2.2.0: {} - package-json-from-dist@1.0.1: {} - parent-module@1.0.1: - dependencies: - callsites: 3.1.0 - - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.26.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - - path-exists@4.0.0: {} - - path-is-absolute@1.0.1: {} - path-key@3.1.1: {} - path-parse@1.0.7: {} - path-scurry@1.11.1: dependencies: lru-cache: 10.4.3 minipass: 7.1.2 + pathe@2.0.3: {} + + pathval@2.0.0: {} + picocolors@1.1.1: {} - picomatch@2.3.1: {} - - pirates@4.0.6: {} - - pkg-dir@4.2.0: + postcss@8.5.3: dependencies: - find-up: 4.1.0 - - prelude-ls@1.2.1: {} - - prettier@3.5.3: {} - - pretty-format@29.7.0: - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - - prompts@2.4.2: - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - - punycode@2.3.1: {} - - pure-rand@6.1.0: {} - - queue-microtask@1.2.3: {} - - react-is@18.3.1: {} - - require-directory@2.1.1: {} - - resolve-cwd@3.0.0: - dependencies: - resolve-from: 5.0.0 - - resolve-from@4.0.0: {} - - resolve-from@5.0.0: {} - - resolve.exports@2.0.3: {} - - resolve@1.22.10: - dependencies: - is-core-module: 2.16.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - reusify@1.1.0: {} + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 rimraf@5.0.10: dependencies: glob: 10.4.5 - run-parallel@1.2.0: + rollup@4.36.0: dependencies: - queue-microtask: 1.2.3 - - semver@6.3.1: {} + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.36.0 + '@rollup/rollup-android-arm64': 4.36.0 + '@rollup/rollup-darwin-arm64': 4.36.0 + '@rollup/rollup-darwin-x64': 4.36.0 + '@rollup/rollup-freebsd-arm64': 4.36.0 + '@rollup/rollup-freebsd-x64': 4.36.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.36.0 + '@rollup/rollup-linux-arm-musleabihf': 4.36.0 + '@rollup/rollup-linux-arm64-gnu': 4.36.0 + '@rollup/rollup-linux-arm64-musl': 4.36.0 + '@rollup/rollup-linux-loongarch64-gnu': 4.36.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.36.0 + '@rollup/rollup-linux-riscv64-gnu': 4.36.0 + '@rollup/rollup-linux-s390x-gnu': 4.36.0 + '@rollup/rollup-linux-x64-gnu': 4.36.0 + '@rollup/rollup-linux-x64-musl': 4.36.0 + '@rollup/rollup-win32-arm64-msvc': 4.36.0 + '@rollup/rollup-win32-ia32-msvc': 4.36.0 + '@rollup/rollup-win32-x64-msvc': 4.36.0 + fsevents: 2.3.3 semver@7.7.1: {} @@ -3739,31 +1651,15 @@ snapshots: shebang-regex@3.0.0: {} - signal-exit@3.0.7: {} + siginfo@2.0.0: {} signal-exit@4.1.0: {} - sisteransi@1.0.5: {} + source-map-js@1.2.1: {} - slash@3.0.0: {} + stackback@0.0.2: {} - source-map-support@0.5.13: - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - - source-map@0.6.1: {} - - sprintf-js@1.0.3: {} - - stack-utils@2.0.6: - dependencies: - escape-string-regexp: 2.0.0 - - string-length@4.0.2: - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 + std-env@3.8.1: {} string-width@4.2.3: dependencies: @@ -3785,22 +1681,10 @@ snapshots: dependencies: ansi-regex: 6.1.0 - strip-bom@4.0.0: {} - - strip-final-newline@2.0.0: {} - - strip-json-comments@3.1.1: {} - supports-color@7.2.0: dependencies: has-flag: 4.0.0 - supports-color@8.1.1: - dependencies: - has-flag: 4.0.0 - - supports-preserve-symlinks-flag@1.0.0: {} - tar@7.4.3: dependencies: '@isaacs/fs-minipass': 4.0.1 @@ -3810,79 +1694,24 @@ snapshots: mkdirp: 3.0.1 yallist: 5.0.0 - test-exclude@6.0.0: + test-exclude@7.0.1: dependencies: '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 + glob: 10.4.5 + minimatch: 9.0.5 - tmpl@1.0.5: {} + tinybench@2.9.0: {} - to-regex-range@5.0.1: - dependencies: - is-number: 7.0.0 + tinyexec@0.3.2: {} - ts-api-utils@2.1.0(typescript@5.8.2): - dependencies: - typescript: 5.8.2 + tinypool@1.0.2: {} - ts-jest@29.2.6(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)))(typescript@5.8.2): - dependencies: - bs-logger: 0.2.6 - ejs: 3.1.10 - fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@22.13.11)(ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2)) - jest-util: 29.7.0 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.7.1 - typescript: 5.8.2 - yargs-parser: 21.1.1 - optionalDependencies: - '@babel/core': 7.26.10 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.26.10) + tinyrainbow@2.0.0: {} - ts-node@10.9.2(@types/node@22.13.11)(typescript@5.8.2): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 22.13.11 - acorn: 8.14.1 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.8.2 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 + tinyspy@3.0.2: {} tunnel@0.0.6: {} - type-check@0.4.0: - dependencies: - prelude-ls: 1.2.1 - - type-detect@4.0.8: {} - - type-fest@0.21.3: {} - - typescript-eslint@8.27.0(eslint@9.23.0)(typescript@5.8.2): - dependencies: - '@typescript-eslint/eslint-plugin': 8.27.0(@typescript-eslint/parser@8.27.0(eslint@9.23.0)(typescript@5.8.2))(eslint@9.23.0)(typescript@5.8.2) - '@typescript-eslint/parser': 8.27.0(eslint@9.23.0)(typescript@5.8.2) - '@typescript-eslint/utils': 8.27.0(eslint@9.23.0)(typescript@5.8.2) - eslint: 9.23.0 - typescript: 5.8.2 - transitivePeerDependencies: - - supports-color - typescript@5.8.2: {} undici-types@6.20.0: {} @@ -3895,33 +1724,82 @@ snapshots: universal-user-agent@7.0.2: {} - update-browserslist-db@1.1.3(browserslist@4.24.4): + vite-node@3.0.9(@types/node@22.13.11): dependencies: - browserslist: 4.24.4 - escalade: 3.2.0 - picocolors: 1.1.1 + cac: 6.7.14 + debug: 4.4.0 + es-module-lexer: 1.6.0 + pathe: 2.0.3 + vite: 6.2.2(@types/node@22.13.11) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml - uri-js@4.4.1: + vite@6.2.2(@types/node@22.13.11): dependencies: - punycode: 2.3.1 + esbuild: 0.25.1 + postcss: 8.5.3 + rollup: 4.36.0 + optionalDependencies: + '@types/node': 22.13.11 + fsevents: 2.3.3 - v8-compile-cache-lib@3.0.1: {} - - v8-to-istanbul@9.3.0: + vitest@3.0.9(@types/node@22.13.11): dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.6 - convert-source-map: 2.0.0 - - walker@1.0.8: - dependencies: - makeerror: 1.0.12 + '@vitest/expect': 3.0.9 + '@vitest/mocker': 3.0.9(vite@6.2.2(@types/node@22.13.11)) + '@vitest/pretty-format': 3.0.9 + '@vitest/runner': 3.0.9 + '@vitest/snapshot': 3.0.9 + '@vitest/spy': 3.0.9 + '@vitest/utils': 3.0.9 + chai: 5.2.0 + debug: 4.4.0 + expect-type: 1.2.0 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.8.1 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 6.2.2(@types/node@22.13.11) + vite-node: 3.0.9(@types/node@22.13.11) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.13.11 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml which@2.0.2: dependencies: isexe: 2.0.0 - word-wrap@1.2.5: {} + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 wrap-ansi@7.0.0: dependencies: @@ -3937,29 +1815,4 @@ snapshots: wrappy@1.0.2: {} - write-file-atomic@4.0.2: - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - - y18n@5.0.8: {} - - yallist@3.1.1: {} - yallist@5.0.0: {} - - yargs-parser@21.1.1: {} - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - - yn@3.1.1: {} - - yocto-queue@0.1.0: {} diff --git a/prettier.config.mjs b/prettier.config.mjs deleted file mode 100644 index c8df44d..0000000 --- a/prettier.config.mjs +++ /dev/null @@ -1,28 +0,0 @@ -import sortImports from '@ianvs/prettier-plugin-sort-imports'; - -export default { - plugins: [sortImports], - semi: true, - trailingComma: 'all', - singleQuote: true, - printWidth: 150, - bracketSpacing: false, - endOfLine: 'lf', - tabWidth: 4, - importOrder: [ - '', - '^(node:)', - '', - '', - '', - '^[.]', - '', - '', - '', - '', - '', - '^zigbee', - '', - '^[.]', - ], -}; diff --git a/src/autodl/gammatroniques.ts b/src/autodl/gammatroniques.ts index 48f8f63..de1db7a 100644 --- a/src/autodl/gammatroniques.ts +++ b/src/autodl/gammatroniques.ts @@ -1,10 +1,10 @@ -import {getJson, readCacheJson, writeCacheJson} from '../common.js'; -import {processFirmwareImage} from '../process_firmware_image.js'; +import {getJson, readCacheJson, writeCacheJson} from "../common.js"; +import {processFirmwareImage} from "../process_firmware_image.js"; type ImagesJsonBuildPart = { path: string; // .bin offset: number; - type?: 'app' | 'storage'; + type?: "app" | "storage"; ota?: string; // .ota }; type ImagesJsonBuild = { @@ -21,11 +21,11 @@ type ImagesJson = { builds: ImagesJsonBuild[]; }; -const NAME = 'GammaTroniques'; +const NAME = "GammaTroniques"; // const LOG_PREFIX = `[${NAME}]`; -const BASE_URL = 'https://update.gammatroniques.fr/'; -const MANIFEST_URL_PATH = `/manifest.json`; -const MODEL_IDS: [urlId: string, modelId: string][] = [['ticmeter', 'TICMeter']]; +const BASE_URL = "https://update.gammatroniques.fr/"; +const MANIFEST_URL_PATH = "/manifest.json"; +const MODEL_IDS: [urlId: string, modelId: string][] = [["ticmeter", "TICMeter"]]; function isDifferent(newData: ImagesJson, cachedData?: ImagesJson): boolean { return Boolean(process.env.IGNORE_CACHE) || !cachedData || cachedData.version !== newData.version; @@ -62,14 +62,14 @@ export async function download(): Promise { writeCacheJson(cacheFileName, page); - const appUrl: ImagesJsonBuildPart | undefined = page.builds[0].parts.find((part) => part.type === 'app'); + const appUrl: ImagesJsonBuildPart | undefined = page.builds[0].parts.find((part) => part.type === "app"); if (!appUrl || !appUrl.ota) { console.error(`${logPrefix} No image found.`); continue; } - const firmwareFileName = appUrl.ota.split('/').pop()!; + const firmwareFileName = appUrl.ota.split("/").pop()!; await processFirmwareImage(NAME, firmwareFileName, appUrl.ota, {modelId}); } diff --git a/src/autodl/github.ts b/src/autodl/github.ts index 6dc7303..edda927 100644 --- a/src/autodl/github.ts +++ b/src/autodl/github.ts @@ -1,7 +1,7 @@ -import type {ExtraMetas} from '../types.js'; +import type {ExtraMetas} from "../types.js"; -import {getJson, getLatestImage, readCacheJson, writeCacheJson} from '../common.js'; -import {processFirmwareImage} from '../process_firmware_image.js'; +import {getJson, getLatestImage, readCacheJson, writeCacheJson} from "../common.js"; +import {processFirmwareImage} from "../process_firmware_image.js"; type ReleaseAssetJson = { url: string; diff --git a/src/autodl/hue.ts b/src/autodl/hue.ts index 4e3af6d..e31525f 100644 --- a/src/autodl/hue.ts +++ b/src/autodl/hue.ts @@ -1,5 +1,5 @@ -import {getJson, getLatestImage, readCacheJson, writeCacheJson} from '../common.js'; -import {processFirmwareImage} from '../process_firmware_image.js'; +import {getJson, getLatestImage, readCacheJson, writeCacheJson} from "../common.js"; +import {processFirmwareImage} from "../process_firmware_image.js"; type ImageJson = { createdAt: string; @@ -13,34 +13,34 @@ type ImageJson = { }; type PageJson = {updates: ImageJson[]}; -const NAME = 'Hue'; -const BASE_URL = 'https://firmware.meethue.com/v1/checkupdate?version=0&deviceTypeId='; +const NAME = "Hue"; +const BASE_URL = "https://firmware.meethue.com/v1/checkupdate?version=0&deviceTypeId="; const DEVICE_TYPE_IDS: string[] = [ - '100b-111', - '100b-112', + "100b-111", + "100b-112", // '100b-113', - '100b-114', - '100b-115', + "100b-114", + "100b-115", // '100b-116', - '100b-117', - '100b-118', + "100b-117", + "100b-118", // '100b-119', - '100b-11a', + "100b-11a", // '100b-11b', // '100b-11c', - '100b-11d', - '100b-11e', - '100b-11f', - '100b-120', + "100b-11d", + "100b-11e", + "100b-11f", + "100b-120", // '100b-121', // '100b-122', - '100b-123', + "100b-123", // '100b-124', - '100b-125', + "100b-125", // '100b-126', - '100b-127', + "100b-127", // '100b-128', - '100b-129', + "100b-129", // '100b-12a', // '100b-12b', // '100b-12c', @@ -98,7 +98,7 @@ export async function download(): Promise { continue; } - const firmwareFileName = image.binaryUrl.split('/').pop()!; + const firmwareFileName = image.binaryUrl.split("/").pop()!; await processFirmwareImage(NAME, firmwareFileName, image.binaryUrl, {releaseNotes: image.releaseNotes || undefined}); } diff --git a/src/autodl/ikea.ts b/src/autodl/ikea.ts index 8ae681c..0001304 100644 --- a/src/autodl/ikea.ts +++ b/src/autodl/ikea.ts @@ -1,5 +1,5 @@ -import {getJson, readCacheJson, writeCacheJson} from '../common.js'; -import {processFirmwareImage} from '../process_firmware_image.js'; +import {getJson, readCacheJson, writeCacheJson} from "../common.js"; +import {processFirmwareImage} from "../process_firmware_image.js"; type GatewayImageJson = { fw_binary_url: string; @@ -16,7 +16,9 @@ type GatewayImageJson = { }; type DeviceImageJson = { fw_binary_url: string; + // biome-ignore lint/style/useNamingConvention: fw_file_version_LSB: number; + // biome-ignore lint/style/useNamingConvention: fw_file_version_MSB: number; fw_filesize: number; fw_image_type: number; @@ -25,16 +27,16 @@ type DeviceImageJson = { }; type ImagesJson = (GatewayImageJson | DeviceImageJson)[]; -const NAME = 'IKEA'; +const NAME = "IKEA"; const LOG_PREFIX = `[${NAME}]`; -const PRODUCTION_FIRMWARE_URL = 'http://fw.ota.homesmart.ikea.net/feed/version_info.json'; +const PRODUCTION_FIRMWARE_URL = "http://fw.ota.homesmart.ikea.net/feed/version_info.json"; // const TEST_FIRMWARE_URL = 'http://fw.test.ota.homesmart.ikea.net/feed/version_info.json'; -export const RELEASE_NOTES_URL = 'https://ww8.ikea.com/ikeahomesmart/releasenotes/releasenotes.html'; +export const RELEASE_NOTES_URL = "https://ww8.ikea.com/ikeahomesmart/releasenotes/releasenotes.html"; function findInCache(image: DeviceImageJson, cachedData?: ImagesJson): DeviceImageJson | undefined { // `fw_type` compare ensures always `DeviceImagesJson` return cachedData?.find( - (d) => d.fw_type == image.fw_type && d.fw_image_type == image.fw_image_type && d.fw_manufacturer_id == image.fw_manufacturer_id, + (d) => d.fw_type === image.fw_type && d.fw_image_type === image.fw_image_type && d.fw_manufacturer_id === image.fw_manufacturer_id, ) as DeviceImageJson | undefined; } @@ -67,7 +69,7 @@ export async function download(): Promise { continue; } - const firmwareFileName = image.fw_binary_url.split('/').pop()!; + const firmwareFileName = image.fw_binary_url.split("/").pop()!; if (!isDifferent(image, findInCache(image, cachedData))) { console.log(`[${NAME}:${firmwareFileName}] No change from last run.`); diff --git a/src/autodl/ikea_new.ts b/src/autodl/ikea_new.ts index 3d066e2..7a62d60 100644 --- a/src/autodl/ikea_new.ts +++ b/src/autodl/ikea_new.ts @@ -1,6 +1,6 @@ -import {getJson, readCacheJson, writeCacheJson} from '../common.js'; -import {processFirmwareImage} from '../process_firmware_image.js'; -import {RELEASE_NOTES_URL} from './ikea.js'; +import {getJson, readCacheJson, writeCacheJson} from "../common.js"; +import {processFirmwareImage} from "../process_firmware_image.js"; +import {RELEASE_NOTES_URL} from "./ikea.js"; type GatewayImageJson = { fw_type: 3; @@ -23,15 +23,15 @@ type DeviceImageJson = { type ImagesJson = (GatewayImageJson | DeviceImageJson)[]; // same name as `ikea.ts` to keep everything in same folder -const NAME = 'IKEA'; +const NAME = "IKEA"; const CACHE_FILENAME = `${NAME}_new`; const LOG_PREFIX = `[${NAME}_new]`; // requires cacerts/ikea_new.pem -const FIRMWARE_URL = 'https://fw.ota.homesmart.ikea.com/check/update/prod'; +const FIRMWARE_URL = "https://fw.ota.homesmart.ikea.com/check/update/prod"; function findInCache(image: DeviceImageJson, cachedData?: ImagesJson): DeviceImageJson | undefined { // `fw_type` compare ensures always `DeviceImagesJson` - return cachedData?.find((d) => d.fw_type == image.fw_type && d.fw_image_type == image.fw_image_type) as DeviceImageJson | undefined; + return cachedData?.find((d) => d.fw_type === image.fw_type && d.fw_image_type === image.fw_image_type) as DeviceImageJson | undefined; } function isDifferent(newData: DeviceImageJson, cachedData?: DeviceImageJson): boolean { @@ -58,7 +58,7 @@ export async function download(): Promise { continue; } - const firmwareFileName = image.fw_binary_url.split('/').pop()!; + const firmwareFileName = image.fw_binary_url.split("/").pop()!; if (!isDifferent(image, findInCache(image, cachedData))) { console.log(`[${NAME}:${firmwareFileName}] No change from last run.`); diff --git a/src/autodl/inovelli.ts b/src/autodl/inovelli.ts index 2aa10a9..e5056f0 100644 --- a/src/autodl/inovelli.ts +++ b/src/autodl/inovelli.ts @@ -1,9 +1,9 @@ -import {getJson, getLatestImage, readCacheJson, writeCacheJson} from '../common.js'; -import {processFirmwareImage} from '../process_firmware_image.js'; +import {getJson, getLatestImage, readCacheJson, writeCacheJson} from "../common.js"; +import {processFirmwareImage} from "../process_firmware_image.js"; type DeviceImageJson = { version: string; - channel: 'beta' | 'production'; + channel: "beta" | "production"; firmware: string; manufacturer_id: number; image_type: number; @@ -12,15 +12,15 @@ type ModelsJson = { [k: string]: DeviceImageJson[]; }; -const NAME = 'Inovelli'; +const NAME = "Inovelli"; const LOG_PREFIX = `[${NAME}]`; -const FIRMWARE_URL = 'https://files.inovelli.com/firmware/firmware.json'; +const FIRMWARE_URL = "https://files.inovelli.com/firmware/firmware.json"; function sortByVersion(a: DeviceImageJson, b: DeviceImageJson): number { const aRadix = a.version.match(/[a-fA-F]/) ? 16 : 10; const bRadix = b.version.match(/[a-fA-F]/) ? 16 : 10; - const aVersion = parseInt(a.version, aRadix); - const bVersion = parseInt(b.version, bRadix); + const aVersion = Number.parseInt(a.version, aRadix); + const bVersion = Number.parseInt(b.version, bRadix); return aVersion < bVersion ? -1 : aVersion > bVersion ? 1 : 0; } @@ -44,7 +44,7 @@ export async function download(): Promise { const cachedData = readCacheJson(NAME); for (const model in models) { - if (model == '') { + if (model === "") { // ignore empty key (bug) continue; } @@ -55,7 +55,7 @@ export async function download(): Promise { continue; } - const firmwareFileName = image.firmware.split('/').pop()!; + const firmwareFileName = image.firmware.split("/").pop()!; if (cachedData && !isDifferent(image, getLatestImage(cachedData[model], sortByVersion))) { console.log(`[${NAME}:${firmwareFileName}] No change from last run.`); diff --git a/src/autodl/jethome.ts b/src/autodl/jethome.ts index 261e091..a46b8f7 100644 --- a/src/autodl/jethome.ts +++ b/src/autodl/jethome.ts @@ -1,5 +1,5 @@ -import {getJson, readCacheJson, writeCacheJson} from '../common.js'; -import {processFirmwareImage} from '../process_firmware_image.js'; +import {getJson, readCacheJson, writeCacheJson} from "../common.js"; +import {processFirmwareImage} from "../process_firmware_image.js"; type ImageJson = { vendor: string; @@ -13,12 +13,12 @@ type ImageJson = { version: string; date: string; images: { - 'zigbee.ota': { + "zigbee.ota": { url: string; hash: string; filesize: number; }; - 'zigbee.bin': { + "zigbee.bin": { url: string; hash: string; filesize: number; @@ -29,12 +29,12 @@ type ImageJson = { }; }; -const NAME = 'JetHome'; +const NAME = "JetHome"; const LOG_PREFIX = `[${NAME}]`; -const BASE_URL = 'https://fw.jethome.ru'; +const BASE_URL = "https://fw.jethome.ru"; const DEVICE_URL = `${BASE_URL}/api/devices/`; -const MODEL_IDS = ['WS7']; +const MODEL_IDS = ["WS7"]; function getCacheFileName(modelId: string): string { return `${NAME}_${modelId}`; @@ -62,14 +62,14 @@ export async function download(): Promise { // XXX: this is assumed to always be present even for devices that support OTA but without images yet available? if (image?.latest_firmware?.release?.images) { - const firmware = image.latest_firmware.release.images['zigbee.ota']; + const firmware = image.latest_firmware.release.images["zigbee.ota"]; if (!firmware) { continue; } const firmwareUrl = BASE_URL + firmware.url; - const firmwareFileName = firmwareUrl.split('/').pop()!; + const firmwareFileName = firmwareUrl.split("/").pop()!; const cacheFileName = getCacheFileName(modelId); if (!isDifferent(image, readCacheJson(cacheFileName))) { @@ -85,7 +85,6 @@ export async function download(): Promise { }); } else { console.error(`${LOG_PREFIX} No image data for ${modelId}.`); - continue; } } } diff --git a/src/autodl/ledvance.ts b/src/autodl/ledvance.ts index 39e901d..aef3a13 100644 --- a/src/autodl/ledvance.ts +++ b/src/autodl/ledvance.ts @@ -1,5 +1,5 @@ -import {getJson, getLatestImage, readCacheJson, writeCacheJson} from '../common.js'; -import {processFirmwareImage, ProcessFirmwareImageStatus} from '../process_firmware_image.js'; +import {getJson, getLatestImage, readCacheJson, writeCacheJson} from "../common.js"; +import {ProcessFirmwareImageStatus, processFirmwareImage} from "../process_firmware_image.js"; type FirmwareJson = { blob: null; @@ -34,12 +34,12 @@ type ImagesJson = { }; type GroupedImagesJson = Record; -const NAME = 'LEDVANCE'; +const NAME = "LEDVANCE"; const LOG_PREFIX = `[${NAME}]`; -const FIRMWARE_URL = 'https://api.update.ledvance.com/v1/zigbee/firmwares/'; +const FIRMWARE_URL = "https://api.update.ledvance.com/v1/zigbee/firmwares/"; // const UPDATE_CHECK_URL = 'https://api.update.ledvance.com/v1/zigbee/firmwares/newer'; // const UPDATE_CHECK_PARAMS = `?company=${manufCode}&product=${imageType}&version=0.0.0`; -const UPDATE_DOWNLOAD_URL = 'https://api.update.ledvance.com/v1/zigbee/firmwares/download'; +const UPDATE_DOWNLOAD_URL = "https://api.update.ledvance.com/v1/zigbee/firmwares/download"; /** XXX: getting 429 after a few downloads, force more throttling. Seems to trigger after around ~20 requests. */ const FETCH_FAILED_THROTTLE_MS = 60000; const FETCH_FAILED_RETRIES = 3; @@ -98,7 +98,7 @@ export async function download(): Promise { // const fileVersion = parseInt(fileVersionMatch[1], 16); const firmwareUrl = `${UPDATE_DOWNLOAD_URL}?company=${firmware.identity.company}&product=${firmware.identity.product}&version=${getVersionString(firmware)}`; - const firmwareFileName = firmware.fullName.split('/').pop()!; + const firmwareFileName = firmware.fullName.split("/").pop()!; if (cachedDataByProduct && !isDifferent(firmware, getLatestImage(cachedDataByProduct[product], sortByReleased))) { console.log(`[${NAME}:${firmwareFileName}] No change from last run.`); @@ -112,7 +112,7 @@ export async function download(): Promise { releaseNotes: firmware.releaseNotes, }); - if (status === ProcessFirmwareImageStatus.REQUEST_FAILED) { + if (status === ProcessFirmwareImageStatus.RequestFailed) { await new Promise((resolve) => setTimeout(resolve, FETCH_FAILED_THROTTLE_MS)); } else { break; diff --git a/src/autodl/lixee.ts b/src/autodl/lixee.ts index 7afd15e..0c98c4e 100644 --- a/src/autodl/lixee.ts +++ b/src/autodl/lixee.ts @@ -1,9 +1,9 @@ -import * as github from './github.js'; +import * as github from "./github.js"; -const NAME = 'LiXee'; -const FIRMWARE_URL = 'https://api.github.com/repos/fairecasoimeme/Zlinky_TIC/releases'; +const NAME = "LiXee"; +const FIRMWARE_URL = "https://api.github.com/repos/fairecasoimeme/Zlinky_TIC/releases"; /** @see https://github.com/fairecasoimeme/Zlinky_TIC?tab=readme-ov-file#route-or-limited-route-from-v7 */ -const FIRMWARE_EXT = '.ota'; +const FIRMWARE_EXT = ".ota"; const FIRMWARE_LIMITED = `limited${FIRMWARE_EXT}`; export async function writeCache(): Promise { diff --git a/src/autodl/salus.ts b/src/autodl/salus.ts index 5b95a4a..252e229 100644 --- a/src/autodl/salus.ts +++ b/src/autodl/salus.ts @@ -1,5 +1,5 @@ -import {getJson, readCacheJson, writeCacheJson} from '../common.js'; -import {processFirmwareImage} from '../process_firmware_image.js'; +import {getJson, readCacheJson, writeCacheJson} from "../common.js"; +import {processFirmwareImage} from "../process_firmware_image.js"; type ImageJson = { model: string; @@ -10,12 +10,12 @@ type ImagesJson = { versions: ImageJson[]; }; -const NAME = 'SalusControls'; +const NAME = "SalusControls"; const LOG_PREFIX = `[${NAME}]`; -const FIRMWARE_URL = 'https://eu.salusconnect.io/demo/default/status/firmware?timestamp=0'; +const FIRMWARE_URL = "https://eu.salusconnect.io/demo/default/status/firmware?timestamp=0"; function findInCache(image: ImageJson, cachedData?: ImagesJson): ImageJson | undefined { - return cachedData?.versions?.find((d) => d.model == image.model); + return cachedData?.versions?.find((d) => d.model === image.model); } function isDifferent(newData: ImageJson, cachedData?: ImageJson): boolean { @@ -38,14 +38,14 @@ export async function download(): Promise { for (const image of images.versions) { const archiveUrl = image.url; //.replace(/^http:\/\//, 'https://'); - const archiveFileName = archiveUrl.split('/').pop()!; + const archiveFileName = archiveUrl.split("/").pop()!; if (!isDifferent(image, findInCache(image, cachedData))) { console.log(`[${NAME}:${archiveFileName}] No change from last run.`); continue; } - await processFirmwareImage(NAME, archiveFileName, archiveUrl, {manufacturerName: [NAME]}, true, (fileName) => fileName.endsWith('.ota')); + await processFirmwareImage(NAME, archiveFileName, archiveUrl, {manufacturerName: [NAME]}, true, (fileName) => fileName.endsWith(".ota")); } writeCacheJson(NAME, images); diff --git a/src/autodl/ubisys.ts b/src/autodl/ubisys.ts index 58ff73f..a489991 100644 --- a/src/autodl/ubisys.ts +++ b/src/autodl/ubisys.ts @@ -1,7 +1,7 @@ -import url from 'url'; +import url from "node:url"; -import {getLatestImage, getText, readCacheJson, writeCacheJson} from '../common.js'; -import {processFirmwareImage} from '../process_firmware_image.js'; +import {getLatestImage, getText, readCacheJson, writeCacheJson} from "../common.js"; +import {processFirmwareImage} from "../process_firmware_image.js"; type Image = { fileName: string; @@ -14,14 +14,14 @@ type GroupedImages = { [k: string]: Image[]; }; -const NAME = 'Ubisys'; +const NAME = "Ubisys"; const LOG_PREFIX = `[${NAME}]`; -const FIRMWARE_HTML_URL = 'http://fwu.ubisys.de/smarthome/OTA/release/index'; +const FIRMWARE_HTML_URL = "http://fwu.ubisys.de/smarthome/OTA/release/index"; function groupByImageType(arr: Image[]): GroupedImages { return arr.reduce((acc, cur) => { - acc[cur.imageType + (cur.hardwareVersionMax ? cur.hardwareVersionMax : '')] = [ - ...(acc[cur.imageType + (cur.hardwareVersionMax ? cur.hardwareVersionMax : '')] || []), + acc[cur.imageType + (cur.hardwareVersionMax ? cur.hardwareVersionMax : "")] = [ + ...(acc[cur.imageType + (cur.hardwareVersionMax ? cur.hardwareVersionMax : "")] || []), cur, ]; return acc; @@ -37,7 +37,7 @@ function isDifferent(newData: Image, cachedData?: Image): boolean { } function parseText(pageText: string): Image[] { - const lines = pageText.split('\n'); + const lines = pageText.split("\n"); const images: Image[] = []; for (const line of lines) { @@ -48,9 +48,9 @@ function parseText(pageText: string): Image[] { images.push({ fileName: imageMatch[0], imageType: imageMatch[1], - hardwareVersionMin: parseInt(imageMatch[2], 16), - hardwareVersionMax: parseInt(imageMatch[3], 16), - fileVersion: parseInt(imageMatch[4], 16), + hardwareVersionMin: Number.parseInt(imageMatch[2], 16), + hardwareVersionMax: Number.parseInt(imageMatch[3], 16), + fileVersion: Number.parseInt(imageMatch[4], 16), }); } } diff --git a/src/autodl/xyzroe.ts b/src/autodl/xyzroe.ts index ddbd1c2..f167278 100644 --- a/src/autodl/xyzroe.ts +++ b/src/autodl/xyzroe.ts @@ -1,13 +1,13 @@ -import * as github from './github.js'; +import * as github from "./github.js"; -const NAME = 'xyzroe'; -const FIRMWARE_URL = 'https://api.github.com/repos/xyzroe/ZigUSB_C6/releases'; -const FIRMWARE_EXT = '.ota'; +const NAME = "xyzroe"; +const FIRMWARE_URL = "https://api.github.com/repos/xyzroe/ZigUSB_C6/releases"; +const FIRMWARE_EXT = ".ota"; export async function writeCache(): Promise { await github.writeCache(NAME, FIRMWARE_URL); } export async function download(): Promise { - await github.download(NAME, FIRMWARE_URL, [(a): boolean => a.name.endsWith(FIRMWARE_EXT)], {modelId: 'ZigUSB_C6'}); + await github.download(NAME, FIRMWARE_URL, [(a): boolean => a.name.endsWith(FIRMWARE_EXT)], {modelId: "ZigUSB_C6"}); } diff --git a/src/common.ts b/src/common.ts index 5fdc03d..4792852 100644 --- a/src/common.ts +++ b/src/common.ts @@ -1,28 +1,28 @@ -import type {ExtraMetas, ExtraMetasWithFileName, ImageHeader, RepoImageMeta} from './types'; +import type {ExtraMetas, ExtraMetasWithFileName, ImageHeader, RepoImageMeta} from "./types"; -import assert from 'assert'; -import {exec} from 'child_process'; -import {createHash} from 'crypto'; -import {existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync} from 'fs'; -import path from 'path'; +import assert from "node:assert"; +import {exec} from "node:child_process"; +import {createHash} from "node:crypto"; +import {existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync} from "node:fs"; +import path from "node:path"; export const UPGRADE_FILE_IDENTIFIER = Buffer.from([0x1e, 0xf1, 0xee, 0x0b]); -export const BASE_REPO_URL = `https://raw.githubusercontent.com/Koenkk/zigbee-OTA/`; -export const REPO_BRANCH = 'master'; +export const BASE_REPO_URL = "https://raw.githubusercontent.com/Koenkk/zigbee-OTA/"; +export const REPO_BRANCH = "master"; /** Images used by OTA upgrade process */ -export const BASE_IMAGES_DIR = 'images'; +export const BASE_IMAGES_DIR = "images"; /** Images used by OTA downgrade process */ -export const PREV_IMAGES_DIR = 'images1'; +export const PREV_IMAGES_DIR = "images1"; /** Manifest used by OTA upgrade process */ -export const BASE_INDEX_MANIFEST_FILENAME = 'index.json'; +export const BASE_INDEX_MANIFEST_FILENAME = "index.json"; /** Manifest used by OTA downgrade process */ -export const PREV_INDEX_MANIFEST_FILENAME = 'index1.json'; -export const CACHE_DIR = '.cache'; -export const TMP_DIR = 'tmp'; -export const PR_ARTIFACT_DIR = 'pr'; -export const PR_DIFF_FILENAME = 'PR_DIFF'; -export const PR_ERROR_FILENAME = 'PR_ERROR'; -export const PR_NUMBER_FILENAME = 'PR_NUMBER'; +export const PREV_INDEX_MANIFEST_FILENAME = "index1.json"; +export const CACHE_DIR = ".cache"; +export const TMP_DIR = "tmp"; +export const PR_ARTIFACT_DIR = "pr"; +export const PR_DIFF_FILENAME = "PR_DIFF"; +export const PR_ERROR_FILENAME = "PR_ERROR"; +export const PR_NUMBER_FILENAME = "PR_NUMBER"; export const PR_ARTIFACT_DIFF_FILEPATH = path.join(PR_ARTIFACT_DIR, PR_DIFF_FILENAME); export const PR_ARTIFACT_ERROR_FILEPATH = path.join(PR_ARTIFACT_DIR, PR_ERROR_FILENAME); export const PR_ARTIFACT_NUMBER_FILEPATH = path.join(PR_ARTIFACT_DIR, PR_NUMBER_FILENAME); @@ -30,17 +30,17 @@ export const PR_ARTIFACT_NUMBER_FILEPATH = path.join(PR_ARTIFACT_DIR, PR_NUMBER_ * 'ikea_new' first, to prioritize downloads from new URL */ export const ALL_AUTODL_MANUFACTURERS = [ - 'gammatroniques', - 'hue', - 'ikea_new', - 'ikea', - 'inovelli', - 'jethome', - 'ledvance', - 'lixee', - 'salus', - 'ubisys', - 'xyzroe', + "gammatroniques", + "hue", + "ikea_new", + "ikea", + "inovelli", + "jethome", + "ledvance", + "lixee", + "salus", + "ubisys", + "xyzroe", ]; export async function execute(command: string): Promise { @@ -60,11 +60,11 @@ export function primitivesArrayEquals(a: (string | number | boolean)[], b: (stri } export function computeSHA512(buffer: Buffer): string { - const hash = createHash('sha512'); + const hash = createHash("sha512"); hash.update(buffer); - return hash.digest('hex'); + return hash.digest("hex"); } export function getOutDir(folderName: string, basePath: string = BASE_IMAGES_DIR): string { @@ -82,21 +82,21 @@ export function getRepoFirmwareFileUrl(folderName: string, fileName: string, bas } export function writeManifest(fileName: string, firmwareList: RepoImageMeta[]): void { - writeFileSync(fileName, JSON.stringify(firmwareList, undefined, 2), 'utf8'); + writeFileSync(fileName, JSON.stringify(firmwareList, undefined, 2), "utf8"); } export function readManifest(fileName: string): RepoImageMeta[] { - return JSON.parse(readFileSync(fileName, 'utf8')); + return JSON.parse(readFileSync(fileName, "utf8")); } export function writeCacheJson(fileName: string, contents: T, basePath: string = CACHE_DIR): void { - writeFileSync(path.join(basePath, `${fileName}.json`), JSON.stringify(contents), 'utf8'); + writeFileSync(path.join(basePath, `${fileName}.json`), JSON.stringify(contents), "utf8"); } export function readCacheJson(fileName: string, basePath: string = CACHE_DIR): T | undefined { const filePath = path.join(basePath, `${fileName}.json`); - return existsSync(filePath) ? JSON.parse(readFileSync(filePath, 'utf8')) : undefined; + return existsSync(filePath) ? JSON.parse(readFileSync(filePath, "utf8")) : undefined; } export function parseImageHeader(buffer: Buffer): ImageHeader { @@ -110,7 +110,7 @@ export function parseImageHeader(buffer: Buffer): ImageHeader { imageType: buffer.readUInt16LE(12), fileVersion: buffer.readUInt32LE(14), zigbeeStackVersion: buffer.readUInt16LE(18), - otaHeaderString: buffer.toString('utf8', 20, 52), + otaHeaderString: buffer.toString("utf8", 20, 52), totalImageSize: buffer.readUInt32LE(52), }; let headerPos = 56; @@ -132,7 +132,7 @@ export function parseImageHeader(buffer: Buffer): ImageHeader { headerPos += 2; } - assert(UPGRADE_FILE_IDENTIFIER.equals(header.otaUpgradeFileIdentifier), `Invalid upgrade file identifier`); + assert(UPGRADE_FILE_IDENTIFIER.equals(header.otaUpgradeFileIdentifier), "Invalid upgrade file identifier"); return header; } catch (error) { @@ -199,25 +199,27 @@ export function getLatestImage(list: T[] | undefined, compareFn: (a: T, b: T) return sortedList.slice(0, sortedList.length > 1 && process.env.PREV ? -1 : undefined).pop(); } -export const enum ParsedImageStatus { - NEW = 0, - NEWER = 1, - OLDER = 2, - IDENTICAL = 3, +export enum ParsedImageStatus { + New = 0, + Newer = 1, + Older = 2, + Identical = 3, } export function getParsedImageStatus(parsedImage: ImageHeader, match?: RepoImageMeta): ParsedImageStatus { if (match) { if (match.fileVersion > parsedImage.fileVersion) { - return ParsedImageStatus.OLDER; - } else if (match.fileVersion < parsedImage.fileVersion) { - return ParsedImageStatus.NEWER; - } else { - return ParsedImageStatus.IDENTICAL; + return ParsedImageStatus.Older; } - } else { - return ParsedImageStatus.NEW; + + if (match.fileVersion < parsedImage.fileVersion) { + return ParsedImageStatus.Newer; + } + + return ParsedImageStatus.Identical; } + + return ParsedImageStatus.New; } /** @@ -231,8 +233,8 @@ export function getValidMetas(metas: Partial typeof m != 'string')) { + if (metas.manufacturerName != null) { + if ( + !Array.isArray(metas.manufacturerName) || + metas.manufacturerName.length < 1 || + metas.manufacturerName.some((m) => typeof m !== "string") + ) { throw new Error(`Invalid format for 'manufacturerName', expected 'array of string' type.`); } validMetas.manufacturerName = metas.manufacturerName; } - if (metas.maxFileVersion != undefined) { - if (typeof metas.maxFileVersion != 'number') { + if (metas.maxFileVersion != null) { + if (typeof metas.maxFileVersion !== "number") { throw new Error(`Invalid format for 'maxFileVersion', expected 'number' type.`); } validMetas.maxFileVersion = metas.maxFileVersion; } - if (metas.minFileVersion != undefined) { - if (typeof metas.minFileVersion != 'number') { + if (metas.minFileVersion != null) { + if (typeof metas.minFileVersion !== "number") { throw new Error(`Invalid format for 'minFileVersion', expected 'number' type.`); } validMetas.minFileVersion = metas.minFileVersion; } - if (metas.modelId != undefined) { - if (typeof metas.modelId != 'string') { + if (metas.modelId != null) { + if (typeof metas.modelId !== "string") { throw new Error(`Invalid format for 'modelId', expected 'string' type.`); } validMetas.modelId = metas.modelId; } - if (metas.releaseNotes != undefined) { - if (typeof metas.releaseNotes != 'string') { + if (metas.releaseNotes != null) { + if (typeof metas.releaseNotes !== "string") { throw new Error(`Invalid format for 'releaseNotes', expected 'string' type.`); } @@ -337,7 +343,7 @@ export function addImageToPrev( prevManifest.splice(prevMatchIndex, 1); // make sure fileName exists for migration from old system - const prevFileName = prevMatch.fileName ? prevMatch.fileName : prevMatch.url.split('/').pop()!; + const prevFileName = prevMatch.fileName ? prevMatch.fileName : prevMatch.url.split("/").pop()!; rmSync(path.join(prevOutDir, prevFileName), {force: true}); } @@ -380,23 +386,23 @@ export function addImageToBase( const [prevMatchIndex, prevMatch] = findMatchImage(parsedImage, prevManifest, extraMetas); const prevStatus = getParsedImageStatus(parsedImage, prevMatch); - if (prevStatus !== ParsedImageStatus.OLDER && prevStatus !== ParsedImageStatus.NEW) { + if (prevStatus !== ParsedImageStatus.Older && prevStatus !== ParsedImageStatus.New) { console.warn(`${logPrefix} Base image is new/newer but prev image is not older/non-existing.`); } - if (prevStatus !== ParsedImageStatus.NEW) { + if (prevStatus !== ParsedImageStatus.New) { console.log(`${logPrefix} Removing prev image.`); prevManifest.splice(prevMatchIndex, 1); // make sure fileName exists for migration from old system - const prevFileName = prevMatch!.fileName ? prevMatch!.fileName : prevMatch!.url.split('/').pop()!; + const prevFileName = prevMatch!.fileName ? prevMatch!.fileName : prevMatch!.url.split("/").pop()!; rmSync(path.join(prevOutDir, prevFileName), {force: true}); } // relocate base to prev // make sure fileName exists for migration from old system - const baseFileName = baseMatch.fileName ? baseMatch.fileName : baseMatch.url.split('/').pop()!; + const baseFileName = baseMatch.fileName ? baseMatch.fileName : baseMatch.url.split("/").pop()!; const baseFilePath = path.join(baseOutDir, baseFileName); // if for some reason the file is no longer present (should not happen), don't add it to prev since link is broken diff --git a/src/ghw_check_ota_pr.ts b/src/ghw_check_ota_pr.ts index bf5f8d9..6feda4c 100644 --- a/src/ghw_check_ota_pr.ts +++ b/src/ghw_check_ota_pr.ts @@ -1,23 +1,23 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import assert from 'assert'; -import {existsSync, mkdirSync, writeFileSync} from 'fs'; +import assert from "node:assert"; +import {existsSync, mkdirSync, writeFileSync} from "node:fs"; import { BASE_INDEX_MANIFEST_FILENAME, - execute, + PREV_INDEX_MANIFEST_FILENAME, PR_ARTIFACT_DIFF_FILEPATH, PR_ARTIFACT_DIR, PR_ARTIFACT_ERROR_FILEPATH, PR_ARTIFACT_NUMBER_FILEPATH, - PREV_INDEX_MANIFEST_FILENAME, + execute, readManifest, writeManifest, -} from './common.js'; -import {getChangedOtaFiles} from './ghw_get_changed_ota_files.js'; -import {processOtaFiles} from './ghw_process_ota_files.js'; +} from "./common.js"; +import {getChangedOtaFiles} from "./ghw_get_changed_ota_files.js"; +import {processOtaFiles} from "./ghw_process_ota_files.js"; function throwError(comment: string): void { writeFileSync(PR_ARTIFACT_ERROR_FILEPATH, comment); @@ -26,14 +26,14 @@ function throwError(comment: string): void { } export async function checkOtaPR(github: Octokit, core: typeof CoreApi, context: Context): Promise { - assert(context.payload.pull_request, 'Not a pull request'); - assert(!context.payload.pull_request.merged, 'Should not be executed on a merged pull request'); + assert(context.payload.pull_request, "Not a pull request"); + assert(!context.payload.pull_request.merged, "Should not be executed on a merged pull request"); if (!existsSync(PR_ARTIFACT_DIR)) { mkdirSync(PR_ARTIFACT_DIR, {recursive: true}); } - writeFileSync(PR_ARTIFACT_NUMBER_FILEPATH, context.issue.number.toString(10), 'utf8'); + writeFileSync(PR_ARTIFACT_NUMBER_FILEPATH, context.issue.number.toString(10), "utf8"); const baseManifest = readManifest(BASE_INDEX_MANIFEST_FILENAME); const prevManifest = readManifest(PREV_INDEX_MANIFEST_FILENAME); @@ -58,9 +58,9 @@ export async function checkOtaPR(github: Octokit, core: typeof CoreApi, context: core.info(`Prev manifest has ${prevManifest.length} images.`); core.info(`Base manifest has ${baseManifest.length} images.`); - const diff = await execute(`git diff`); + const diff = await execute("git diff"); - core.startGroup('diff'); + core.startGroup("diff"); core.info(diff); core.endGroup(); diff --git a/src/ghw_concat_cacerts.ts b/src/ghw_concat_cacerts.ts index 515904b..8e4ace4 100644 --- a/src/ghw_concat_cacerts.ts +++ b/src/ghw_concat_cacerts.ts @@ -1,29 +1,29 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import {readdirSync, readFileSync, writeFileSync} from 'fs'; -import path from 'path'; +import {readFileSync, readdirSync, writeFileSync} from "node:fs"; +import path from "node:path"; -export const CACERTS_DIR = 'cacerts'; -export const CACERTS_CONCAT_FILEPATH = 'cacerts.pem'; +export const CACERTS_DIR = "cacerts"; +export const CACERTS_CONCAT_FILEPATH = "cacerts.pem"; // eslint-disable-next-line @typescript-eslint/no-unused-vars -export async function concatCaCerts(github: Octokit, core: typeof CoreApi, context: Context): Promise { - let pemContents: string = ''; +export function concatCaCerts(github: Octokit, core: typeof CoreApi, context: Context): void { + let pemContents = ""; for (const pem of readdirSync(CACERTS_DIR)) { - if (!pem.endsWith('.pem')) { + if (!pem.endsWith(".pem")) { continue; } core.startGroup(pem); - pemContents += readFileSync(path.join(CACERTS_DIR, pem), 'utf8'); - pemContents += '\n'; + pemContents += readFileSync(path.join(CACERTS_DIR, pem), "utf8"); + pemContents += "\n"; core.endGroup(); } - writeFileSync(CACERTS_CONCAT_FILEPATH, pemContents, 'utf8'); + writeFileSync(CACERTS_CONCAT_FILEPATH, pemContents, "utf8"); } diff --git a/src/ghw_create_autodl_release.ts b/src/ghw_create_autodl_release.ts index 8d779f7..a0e27eb 100644 --- a/src/ghw_create_autodl_release.ts +++ b/src/ghw_create_autodl_release.ts @@ -1,10 +1,10 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import type {RepoImageMeta} from './types.js'; +import type {RepoImageMeta} from "./types.js"; -import {BASE_IMAGES_DIR, BASE_INDEX_MANIFEST_FILENAME, execute, PREV_IMAGES_DIR, PREV_INDEX_MANIFEST_FILENAME, readManifest} from './common.js'; +import {BASE_IMAGES_DIR, BASE_INDEX_MANIFEST_FILENAME, PREV_IMAGES_DIR, PREV_INDEX_MANIFEST_FILENAME, execute, readManifest} from "./common.js"; // about 3 lines const MAX_RELEASE_NOTES_LENGTH = 380; @@ -19,7 +19,7 @@ function listItemWithReleaseNotes(imagePath: string, releaseNotes?: string): str let listItem = `* ${imagePath}`; if (releaseNotes) { - let notes = releaseNotes.replace(/[#*\r\n]+/g, '').replaceAll('-', '|'); + let notes = releaseNotes.replace(/[#*\r\n]+/g, "").replaceAll("-", "|"); if (notes.length > MAX_RELEASE_NOTES_LENGTH) { notes = `${notes.slice(0, MAX_RELEASE_NOTES_LENGTH)}...`; @@ -33,7 +33,7 @@ function listItemWithReleaseNotes(imagePath: string, releaseNotes?: string): str } export async function createAutodlRelease(github: Octokit, core: typeof CoreApi, context: Context): Promise { - const tagName = new Date().toISOString().replace(/[:.]/g, ''); + const tagName = new Date().toISOString().replace(/[:.]/g, ""); // --exclude-standard => Add the standard Git exclusions: .git/info/exclude, .gitignore in each directory, and the user’s global exclusion file. // --others => Show other (i.e. untracked) files in the output. // -z => \0 line termination on output and do not quote filenames. @@ -44,8 +44,8 @@ export async function createAutodlRelease(github: Octokit, core: typeof CoreApi, core.debug(`git ls-files for ${PREV_IMAGES_DIR}: ${downgradeImagesStr}`); // -1 to remove empty string at end due to \0 termination - const upgradeImages = upgradeImagesStr.split('\0').slice(0, -1); - const downgradeImages = downgradeImagesStr.split('\0').slice(0, -1); + const upgradeImages = upgradeImagesStr.split("\0").slice(0, -1); + const downgradeImages = downgradeImagesStr.split("\0").slice(0, -1); core.info(`Upgrade Images List: ${upgradeImages}`); core.info(`Downgrade Images List: ${downgradeImages}`); @@ -56,12 +56,12 @@ export async function createAutodlRelease(github: Octokit, core: typeof CoreApi, let body: string | undefined; if (upgradeImages.length > 0 || downgradeImages.length > 0) { - body = ''; + body = ""; if (upgradeImages.length > 0) { const listWithReleaseNotes = upgradeImages.map((v) => listItemWithReleaseNotes(v, findReleaseNotes(v, baseManifest))); body += `## New upgrade images from automatic download: -${listWithReleaseNotes.join('\n')} +${listWithReleaseNotes.join("\n")} `; } @@ -69,7 +69,7 @@ ${listWithReleaseNotes.join('\n')} if (downgradeImages.length > 0) { const listWithReleaseNotes = downgradeImages.map((v) => listItemWithReleaseNotes(v, findReleaseNotes(v, prevManifest))); body += `## New downgrade images from automatic download: -${listWithReleaseNotes.join('\n')} +${listWithReleaseNotes.join("\n")} `; } @@ -85,6 +85,6 @@ ${listWithReleaseNotes.join('\n')} prerelease: false, // get changes from PRs generate_release_notes: true, - make_latest: 'true', + make_latest: "true", }); } diff --git a/src/ghw_create_pr_to_default.ts b/src/ghw_create_pr_to_default.ts index 280d422..f9882ce 100644 --- a/src/ghw_create_pr_to_default.ts +++ b/src/ghw_create_pr_to_default.ts @@ -1,10 +1,10 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import assert from 'assert'; +import assert from "node:assert"; -const IGNORE_OTA_WORKFLOW_LABEL = 'ignore-ota-workflow'; +const IGNORE_OTA_WORKFLOW_LABEL = "ignore-ota-workflow"; export async function createPRToDefault( github: Octokit, @@ -45,7 +45,7 @@ export async function createPRToDefault( ref: `heads/${fromBranchName}`, }); - core.notice(`Nothing needed re-processing.`); + core.notice("Nothing needed re-processing."); // don't fail if no commits return; diff --git a/src/ghw_get_changed_ota_files.ts b/src/ghw_get_changed_ota_files.ts index 7356a58..304fbb2 100644 --- a/src/ghw_get_changed_ota_files.ts +++ b/src/ghw_get_changed_ota_files.ts @@ -1,10 +1,10 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import assert from 'assert'; +import assert from "node:assert"; -import {BASE_IMAGES_DIR} from './common.js'; +import {BASE_IMAGES_DIR} from "./common.js"; export async function getChangedOtaFiles( github: Octokit, @@ -20,18 +20,18 @@ export async function getChangedOtaFiles( basehead, }); - assert(compare.data.files && compare.data.files.length > 0, 'No file'); + assert(compare.data.files && compare.data.files.length > 0, "No file"); - core.info(`Changed files: ${compare.data.files.map((f) => f.filename).join(', ')}`); + core.info(`Changed files: ${compare.data.files.map((f) => f.filename).join(", ")}`); const fileList = compare.data.files.filter((f) => f.filename.startsWith(`${BASE_IMAGES_DIR}/`)); if (throwIfFilesOutsideOfImages && fileList.length !== compare.data.files.length) { if (context.payload.pull_request) { - throw new Error(`Detected changes in files outside of \`images\` directory. This is not allowed for a pull request with OTA files.`); - } else { - throw new Error(`Cannot run with files outside of \`images\` directory.`); + throw new Error("Detected changes in files outside of `images` directory. This is not allowed for a pull request with OTA files."); } + + throw new Error("Cannot run with files outside of `images` directory."); } return fileList.map((f) => f.filename); diff --git a/src/ghw_overwrite_cache.ts b/src/ghw_overwrite_cache.ts index dbdc09c..4a1bf5e 100644 --- a/src/ghw_overwrite_cache.ts +++ b/src/ghw_overwrite_cache.ts @@ -1,17 +1,17 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import {existsSync, mkdirSync} from 'fs'; +import {existsSync, mkdirSync} from "node:fs"; -import {ALL_AUTODL_MANUFACTURERS, CACHE_DIR} from './common.js'; +import {ALL_AUTODL_MANUFACTURERS, CACHE_DIR} from "./common.js"; export async function overwriteCache(github: Octokit, core: typeof CoreApi, context: Context, manufacturersCSV?: string): Promise { if (!existsSync(CACHE_DIR)) { mkdirSync(CACHE_DIR, {recursive: true}); } - const manufacturers = manufacturersCSV ? manufacturersCSV.trim().split(',') : ALL_AUTODL_MANUFACTURERS; + const manufacturers = manufacturersCSV ? manufacturersCSV.trim().split(",") : ALL_AUTODL_MANUFACTURERS; for (const manufacturer of manufacturers) { // ignore empty strings diff --git a/src/ghw_process_ota_files.ts b/src/ghw_process_ota_files.ts index f77aa86..56d9e73 100644 --- a/src/ghw_process_ota_files.ts +++ b/src/ghw_process_ota_files.ts @@ -1,34 +1,35 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import type {ExtraMetas, GHExtraMetas, RepoImageMeta} from './types.js'; +import type {ExtraMetas, GHExtraMetas, RepoImageMeta} from "./types.js"; -import assert from 'assert'; -import {readFileSync, renameSync} from 'fs'; -import path from 'path'; +import assert from "node:assert"; +import {readFileSync, renameSync} from "node:fs"; +import path from "node:path"; import { + BASE_IMAGES_DIR, + PREV_IMAGES_DIR, + ParsedImageStatus, + UPGRADE_FILE_IDENTIFIER, addImageToBase, addImageToPrev, - BASE_IMAGES_DIR, findMatchImage, getOutDir, getParsedImageStatus, getValidMetas, - ParsedImageStatus, parseImageHeader, - PREV_IMAGES_DIR, - UPGRADE_FILE_IDENTIFIER, -} from './common.js'; +} from "./common.js"; -const EXTRA_METAS_PR_BODY_START_TAG = '```json'; -const EXTRA_METAS_PR_BODY_END_TAG = '```'; +const EXTRA_METAS_PR_BODY_START_TAG = "```json"; +const EXTRA_METAS_PR_BODY_END_TAG = "```"; function getFileExtraMetas(extraMetas: GHExtraMetas, fileName: string): ExtraMetas { if (Array.isArray(extraMetas)) { const fileExtraMetas = extraMetas.find((m) => m.fileName === fileName) ?? {}; /** @see getValidMetas */ + // biome-ignore lint/performance/noDelete: delete fileExtraMetas.fileName; return fileExtraMetas; @@ -39,16 +40,18 @@ function getFileExtraMetas(extraMetas: GHExtraMetas, fileName: string): ExtraMet } async function getPRBody(github: Octokit, core: typeof CoreApi, context: Context): Promise { - assert(context.payload.pull_request || context.eventName === 'push'); + assert(context.payload.pull_request || context.eventName === "push"); if (context.payload.pull_request) { return context.payload.pull_request.body; - } else if (context.eventName === 'push') { + } + + if (context.eventName === "push") { const pushMsg = context.payload.head_commit.message as string; const prMatch = pushMsg.match(/\(#(\d+)\)/); if (prMatch) { - const prNumber = parseInt(prMatch[1], 10); + const prNumber = Number.parseInt(prMatch[1], 10); try { const pr = await github.rest.pulls.get({ @@ -78,15 +81,15 @@ async function parsePRBodyExtraMetas(github: Octokit, core: typeof CoreApi, cont if (metasStart !== -1 && metasEnd > metasStart) { const metas = JSON.parse(prBody.slice(metasStart + EXTRA_METAS_PR_BODY_START_TAG.length, metasEnd)) as GHExtraMetas; - core.info(`Extra metas from PR body:`); + core.info("Extra metas from PR body:"); core.info(JSON.stringify(metas, undefined, 2)); if (Array.isArray(metas)) { extraMetas = []; for (const meta of metas) { - if (!meta.fileName || typeof meta.fileName != 'string') { - core.info(`Ignoring meta in array with missing/invalid fileName:`); + if (!meta.fileName || typeof meta.fileName !== "string") { + core.info("Ignoring meta in array with missing/invalid fileName:"); core.info(JSON.stringify(meta, undefined, 2)); continue; } @@ -119,14 +122,14 @@ export async function processOtaFiles( core.startGroup(filePath); const logPrefix = `[${filePath}]`; - let failureComment: string = ''; + let failureComment = ""; try { const firmwareFileName = path.basename(filePath); - const manufacturer = filePath.replace(BASE_IMAGES_DIR, '').replace(firmwareFileName, '').replaceAll('/', '').trim(); + const manufacturer = filePath.replace(BASE_IMAGES_DIR, "").replace(firmwareFileName, "").replaceAll("/", "").trim(); if (!manufacturer) { - throw new Error(`File should be in its associated manufacturer subfolder`); + throw new Error("File should be in its associated manufacturer subfolder"); } const firmwareBuffer = Buffer.from(readFileSync(filePath)); @@ -146,14 +149,14 @@ export async function processOtaFiles( const statusToBase = getParsedImageStatus(parsedImage, baseMatch); switch (statusToBase) { - case ParsedImageStatus.OLDER: { + case ParsedImageStatus.Older: { // if prev doesn't have a match, move to prev const [prevMatchIndex, prevMatch] = findMatchImage(parsedImage, prevManifest, fileExtraMetas); const statusToPrev = getParsedImageStatus(parsedImage, prevMatch); switch (statusToPrev) { - case ParsedImageStatus.OLDER: - case ParsedImageStatus.IDENTICAL: { + case ParsedImageStatus.Older: + case ParsedImageStatus.Identical: { failureComment = `Base manifest has higher version: \`\`\`json ${JSON.stringify(baseMatch, undefined, 2)} @@ -169,11 +172,11 @@ ${JSON.stringify(parsedImage, undefined, 2)} break; } - case ParsedImageStatus.NEWER: - case ParsedImageStatus.NEW: { + case ParsedImageStatus.Newer: + case ParsedImageStatus.New: { addImageToPrev( logPrefix, - statusToPrev === ParsedImageStatus.NEWER, + statusToPrev === ParsedImageStatus.Newer, prevManifest, prevMatchIndex, prevMatch!, @@ -197,7 +200,7 @@ ${JSON.stringify(parsedImage, undefined, 2)} break; } - case ParsedImageStatus.IDENTICAL: { + case ParsedImageStatus.Identical: { failureComment = `Conflict with image at index \`${baseMatchIndex}\`: \`\`\`json ${JSON.stringify(baseMatch, undefined, 2)} @@ -209,11 +212,11 @@ ${JSON.stringify(parsedImage, undefined, 2)} break; } - case ParsedImageStatus.NEWER: - case ParsedImageStatus.NEW: { + case ParsedImageStatus.Newer: + case ParsedImageStatus.New: { addImageToBase( logPrefix, - statusToBase === ParsedImageStatus.NEWER, + statusToBase === ParsedImageStatus.Newer, prevManifest, prevOutDir, baseManifest, diff --git a/src/ghw_report_ota_pr.ts b/src/ghw_report_ota_pr.ts index f90f816..49e9657 100644 --- a/src/ghw_report_ota_pr.ts +++ b/src/ghw_report_ota_pr.ts @@ -1,21 +1,21 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import assert from 'assert'; -import {existsSync, readFileSync, writeFileSync} from 'fs'; +import assert from "node:assert"; +import {existsSync, readFileSync, writeFileSync} from "node:fs"; -import {execute, PR_ARTIFACT_DIR, PR_DIFF_FILENAME, PR_ERROR_FILENAME, PR_NUMBER_FILENAME} from './common.js'; +import {PR_ARTIFACT_DIR, PR_DIFF_FILENAME, PR_ERROR_FILENAME, PR_NUMBER_FILENAME, execute} from "./common.js"; export async function reportOtaPR(github: Octokit, core: typeof CoreApi, context: Context): Promise { - assert(context.payload.workflow_run, 'Not a workflow run'); + assert(context.payload.workflow_run, "Not a workflow run"); // XXX: context.payload.workflow_run is not typed... - const workflow_run = context.payload.workflow_run as Awaited>['data']; + const workflowRun = context.payload.workflow_run as Awaited>["data"]; // workflow_run.conclusion: action_required, cancelled, failure, neutral, skipped, stale, success, timed_out, startup_failure, null - if (workflow_run.conclusion !== 'success' && workflow_run.conclusion !== 'failure') { - core.info(`Ignoring workflow run ${workflow_run.html_url} with conclusion ${workflow_run.conclusion}.`); + if (workflowRun.conclusion !== "success" && workflowRun.conclusion !== "failure") { + core.info(`Ignoring workflow run ${workflowRun.html_url} with conclusion ${workflowRun.conclusion}.`); return; } @@ -23,17 +23,17 @@ export async function reportOtaPR(github: Octokit, core: typeof CoreApi, context const artifacts = await github.rest.actions.listWorkflowRunArtifacts({ owner: context.repo.owner, repo: context.repo.repo, - run_id: workflow_run.id, + run_id: workflowRun.id, }); - const matchArtifact = artifacts.data.artifacts.find((artifact) => artifact.name == PR_ARTIFACT_DIR); + const matchArtifact = artifacts.data.artifacts.find((artifact) => artifact.name === PR_ARTIFACT_DIR); - assert(matchArtifact, `No artifact found for ${workflow_run.url}`); + assert(matchArtifact, `No artifact found for ${workflowRun.url}`); const download = await github.rest.actions.downloadArtifact({ owner: context.repo.owner, repo: context.repo.repo, artifact_id: matchArtifact.id, - archive_format: 'zip', + archive_format: "zip", }); const artifactZipFileName = `${PR_ARTIFACT_DIR}.zip`; @@ -43,16 +43,16 @@ export async function reportOtaPR(github: Octokit, core: typeof CoreApi, context core.info(unzipOutput); - assert(existsSync(PR_NUMBER_FILENAME), `Invalid artifact for ${workflow_run.html_url}`); + assert(existsSync(PR_NUMBER_FILENAME), `Invalid artifact for ${workflowRun.html_url}`); - const prNumber = parseInt(readFileSync(PR_NUMBER_FILENAME, 'utf8'), 10); + const prNumber = Number.parseInt(readFileSync(PR_NUMBER_FILENAME, "utf8"), 10); - core.info(`Running for pr#${prNumber} for ${workflow_run.html_url}`); + core.info(`Running for pr#${prNumber} for ${workflowRun.html_url}`); - if (workflow_run.conclusion === 'failure') { - assert(existsSync(PR_ERROR_FILENAME), `Workflow failed but could not find ${PR_ERROR_FILENAME} for ${workflow_run.html_url}`); + if (workflowRun.conclusion === "failure") { + assert(existsSync(PR_ERROR_FILENAME), `Workflow failed but could not find ${PR_ERROR_FILENAME} for ${workflowRun.html_url}`); - const prError = readFileSync(PR_ERROR_FILENAME, 'utf8'); + const prError = readFileSync(PR_ERROR_FILENAME, "utf8"); await github.rest.issues.createComment({ owner: context.repo.owner, @@ -62,10 +62,12 @@ export async function reportOtaPR(github: Octokit, core: typeof CoreApi, context }); throw new Error(prError); - } else if (workflow_run.conclusion === 'success') { - assert(existsSync(PR_DIFF_FILENAME), `Workflow succeeded but could not find ${PR_DIFF_FILENAME} for ${workflow_run.html_url}`); + } - const prDiff = readFileSync(PR_DIFF_FILENAME, 'utf8'); + if (workflowRun.conclusion === "success") { + assert(existsSync(PR_DIFF_FILENAME), `Workflow succeeded but could not find ${PR_DIFF_FILENAME} for ${workflowRun.html_url}`); + + const prDiff = readFileSync(PR_DIFF_FILENAME, "utf8"); core.info(prDiff); await github.rest.issues.createComment({ diff --git a/src/ghw_reprocess_all_images.ts b/src/ghw_reprocess_all_images.ts index e2f95ff..7aefd1c 100644 --- a/src/ghw_reprocess_all_images.ts +++ b/src/ghw_reprocess_all_images.ts @@ -1,49 +1,49 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import type {RepoImageMeta} from './types'; +import type {RepoImageMeta} from "./types"; -import {existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync} from 'fs'; -import path from 'path'; +import {existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, writeFileSync} from "node:fs"; +import path from "node:path"; import { - addImageToBase, - addImageToPrev, BASE_IMAGES_DIR, BASE_INDEX_MANIFEST_FILENAME, BASE_REPO_URL, + PREV_IMAGES_DIR, + PREV_INDEX_MANIFEST_FILENAME, + ParsedImageStatus, + REPO_BRANCH, + UPGRADE_FILE_IDENTIFIER, + addImageToBase, + addImageToPrev, computeSHA512, findMatchImage, getOutDir, getParsedImageStatus, getRepoFirmwareFileUrl, getValidMetas, - ParsedImageStatus, parseImageHeader, - PREV_IMAGES_DIR, - PREV_INDEX_MANIFEST_FILENAME, readManifest, - REPO_BRANCH, - UPGRADE_FILE_IDENTIFIER, writeManifest, -} from './common.js'; +} from "./common.js"; /** These are now handled by autodl */ -const IGNORE_3RD_PARTIES = ['https://github.com/fairecasoimeme/', 'https://github.com/xyzroe/']; +const IGNORE_3RD_PARTIES = ["https://github.com/fairecasoimeme/", "https://github.com/xyzroe/"]; const DIR_3RD_PARTIES = { - 'https://otau.meethue.com/': 'Hue', - 'https://images.tuyaeu.com/': 'Tuya', - 'https://tr-zha.s3.amazonaws.com/': 'ThirdReality', + "https://otau.meethue.com/": "Hue", + "https://images.tuyaeu.com/": "Tuya", + "https://tr-zha.s3.amazonaws.com/": "ThirdReality", // NOTE: no longer valid / unable to access via script // 'https://www.elektroimportoren.no/docs/lib/4512772-Firmware-35.ota': 'Namron', // 'https://deconz.dresden-elektronik.de/': 'DresdenElektronik', }; -export const NOT_IN_BASE_MANIFEST_IMAGES_DIR = 'not-in-manifest-images'; -export const NOT_IN_PREV_MANIFEST_IMAGES_DIR = 'not-in-manifest-images1'; -export const NOT_IN_MANIFEST_FILENAME = 'not-in-manifest.json'; +export const NOT_IN_BASE_MANIFEST_IMAGES_DIR = "not-in-manifest-images"; +export const NOT_IN_PREV_MANIFEST_IMAGES_DIR = "not-in-manifest-images1"; +export const NOT_IN_MANIFEST_FILENAME = "not-in-manifest.json"; function ignore3rdParty(meta: RepoImageMeta): boolean { for (const ignore of IGNORE_3RD_PARTIES) { @@ -67,11 +67,10 @@ async function download3rdParties( github: Octokit, core: typeof CoreApi, context: Context, - /* istanbul ignore next */ - outDirFinder = get3rdPartyDir, + /* v8 ignore next */ outDirFinder = get3rdPartyDir, ): Promise { if (!process.env.NODE_EXTRA_CA_CERTS) { - throw new Error(`Download 3rd Parties requires \`NODE_EXTRA_CA_CERTS=cacerts.pem\`.`); + throw new Error("Download 3rd Parties requires `NODE_EXTRA_CA_CERTS=cacerts.pem`."); } const baseManifest = readManifest(BASE_INDEX_MANIFEST_FILENAME); @@ -101,7 +100,7 @@ async function download3rdParties( continue; } - const fileName = decodeURIComponent(meta.url.split('/').pop()!); + const fileName = decodeURIComponent(meta.url.split("/").pop()!); const outDirName = outDirFinder(meta); if (outDirName) { @@ -130,7 +129,7 @@ async function download3rdParties( const statusToBase = getParsedImageStatus(parsedImage, baseMatch); switch (statusToBase) { - case ParsedImageStatus.OLDER: { + case ParsedImageStatus.Older: { addImageToPrev( `[${fileName}]`, false, // no prev existed before @@ -158,16 +157,16 @@ async function download3rdParties( break; } - case ParsedImageStatus.IDENTICAL: { + case ParsedImageStatus.Identical: { core.warning(`Conflict with image at index \`${baseMatchIndex}\`: ${JSON.stringify(baseMatch)}`); continue; } - case ParsedImageStatus.NEWER: - case ParsedImageStatus.NEW: { + case ParsedImageStatus.Newer: + case ParsedImageStatus.New: { addImageToBase( `[${fileName}]`, - statusToBase === ParsedImageStatus.NEWER, + statusToBase === ParsedImageStatus.Newer, prevManifest, prevOutDir, baseManifest, @@ -196,12 +195,11 @@ async function download3rdParties( } catch (error) { core.error(`Ignoring ${fileName}: ${error}`); - /* istanbul ignore next */ + /* v8 ignore start */ if (firmwareFilePath) { rmSync(firmwareFilePath, {force: true}); } - - continue; + /* v8 ignore stop */ } } else { core.warning(`Ignoring '${fileName}' with no out dir specified.`); @@ -230,12 +228,13 @@ function checkImagesAgainstManifests(github: Octokit, core: typeof CoreApi, cont core.info(`Checking ${manifestName} (currently ${manifest.length} images)...`); for (const subfolderName of readdirSync(imagesDir)) { - // skip removal of anything not desired while running jest tests + // skip removal of anything not desired while running tests // compare should match data.test.ts > IMAGES_TEST_DIR - /* istanbul ignore if */ - if (process.env.JEST_WORKER_ID && subfolderName !== 'jest-tmp') { + /* v8 ignore start */ + if (process.env.VITEST_WORKER_ID && subfolderName !== "test-tmp") { continue; } + /* v8 ignore stop */ const subfolderPath = path.join(imagesDir, subfolderName); @@ -365,25 +364,29 @@ export async function reProcessAllImages( throw new Error(`${NOT_IN_PREV_MANIFEST_IMAGES_DIR} is not empty. Cannot run.`); } - /* istanbul ignore if */ + /* v8 ignore start */ if (!existsSync(BASE_IMAGES_DIR)) { mkdirSync(BASE_IMAGES_DIR, {recursive: true}); } + /* v8 ignore stop */ - /* istanbul ignore if */ + /* v8 ignore start */ if (!existsSync(PREV_IMAGES_DIR)) { mkdirSync(PREV_IMAGES_DIR, {recursive: true}); } + /* v8 ignore stop */ - /* istanbul ignore if */ + /* v8 ignore start */ if (!existsSync(BASE_INDEX_MANIFEST_FILENAME)) { writeManifest(BASE_INDEX_MANIFEST_FILENAME, []); } + /* v8 ignore stop */ - /* istanbul ignore if */ + /* v8 ignore start */ if (!existsSync(PREV_INDEX_MANIFEST_FILENAME)) { writeManifest(PREV_INDEX_MANIFEST_FILENAME, []); } + /* v8 ignore stop */ if (!skipDownload3rdParties) { await download3rdParties(github, core, context, downloadOutDirFinder); diff --git a/src/ghw_run_autodl.ts b/src/ghw_run_autodl.ts index 14fb899..85bd67a 100644 --- a/src/ghw_run_autodl.ts +++ b/src/ghw_run_autodl.ts @@ -1,15 +1,15 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import {existsSync, mkdirSync, rmSync} from 'fs'; +import {existsSync, mkdirSync, rmSync} from "node:fs"; -import {ALL_AUTODL_MANUFACTURERS, BASE_INDEX_MANIFEST_FILENAME, CACHE_DIR, PREV_INDEX_MANIFEST_FILENAME, TMP_DIR, writeManifest} from './common.js'; +import {ALL_AUTODL_MANUFACTURERS, BASE_INDEX_MANIFEST_FILENAME, CACHE_DIR, PREV_INDEX_MANIFEST_FILENAME, TMP_DIR, writeManifest} from "./common.js"; export async function runAutodl(github: Octokit, core: typeof CoreApi, context: Context, manufacturersCSV?: string): Promise { - const manufacturers = manufacturersCSV ? manufacturersCSV.trim().split(',') : ALL_AUTODL_MANUFACTURERS; + const manufacturers = manufacturersCSV ? manufacturersCSV.trim().split(",") : ALL_AUTODL_MANUFACTURERS; - core.info(`Setup...`); + core.info("Setup..."); if (!existsSync(CACHE_DIR)) { mkdirSync(CACHE_DIR, {recursive: true}); @@ -52,7 +52,7 @@ export async function runAutodl(github: Octokit, core: typeof CoreApi, context: core.endGroup(); } - core.info(`Teardown...`); + core.info("Teardown..."); rmSync(TMP_DIR, {recursive: true, force: true}); } diff --git a/src/ghw_update_manifests.ts b/src/ghw_update_manifests.ts index 9cc5735..ec00408 100644 --- a/src/ghw_update_manifests.ts +++ b/src/ghw_update_manifests.ts @@ -1,15 +1,15 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import assert from 'assert'; +import assert from "node:assert"; -import {BASE_INDEX_MANIFEST_FILENAME, PREV_INDEX_MANIFEST_FILENAME, readManifest, writeManifest} from './common.js'; -import {getChangedOtaFiles} from './ghw_get_changed_ota_files.js'; -import {processOtaFiles} from './ghw_process_ota_files.js'; +import {BASE_INDEX_MANIFEST_FILENAME, PREV_INDEX_MANIFEST_FILENAME, readManifest, writeManifest} from "./common.js"; +import {getChangedOtaFiles} from "./ghw_get_changed_ota_files.js"; +import {processOtaFiles} from "./ghw_process_ota_files.js"; export async function updateManifests(github: Octokit, core: typeof CoreApi, context: Context): Promise { - assert(context.eventName === 'push', 'Not a push'); + assert(context.eventName === "push", "Not a push"); const filePaths = await getChangedOtaFiles(github, core, context, `${context.payload.before}...${context.payload.after}`, true); const baseManifest = readManifest(BASE_INDEX_MANIFEST_FILENAME); diff --git a/src/index.ts b/src/index.ts index c0dfafb..002f7f4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,13 +1,13 @@ -export * as common from './common.js'; -export {checkOtaPR} from './ghw_check_ota_pr.js'; -export {concatCaCerts} from './ghw_concat_cacerts.js'; -export {createAutodlRelease} from './ghw_create_autodl_release.js'; -export {createPRToDefault} from './ghw_create_pr_to_default.js'; -export {getChangedOtaFiles} from './ghw_get_changed_ota_files.js'; -export {overwriteCache} from './ghw_overwrite_cache.js'; -export {processOtaFiles} from './ghw_process_ota_files.js'; -export {reportOtaPR} from './ghw_report_ota_pr.js'; -export {reProcessAllImages} from './ghw_reprocess_all_images.js'; -export {runAutodl} from './ghw_run_autodl.js'; -export {updateManifests} from './ghw_update_manifests.js'; -export {processFirmwareImage} from './process_firmware_image.js'; +export * as common from "./common.js"; +export {checkOtaPR} from "./ghw_check_ota_pr.js"; +export {concatCaCerts} from "./ghw_concat_cacerts.js"; +export {createAutodlRelease} from "./ghw_create_autodl_release.js"; +export {createPRToDefault} from "./ghw_create_pr_to_default.js"; +export {getChangedOtaFiles} from "./ghw_get_changed_ota_files.js"; +export {overwriteCache} from "./ghw_overwrite_cache.js"; +export {processOtaFiles} from "./ghw_process_ota_files.js"; +export {reportOtaPR} from "./ghw_report_ota_pr.js"; +export {reProcessAllImages} from "./ghw_reprocess_all_images.js"; +export {runAutodl} from "./ghw_run_autodl.js"; +export {updateManifests} from "./ghw_update_manifests.js"; +export {processFirmwareImage} from "./process_firmware_image.js"; diff --git a/src/print_ota_image_header.ts b/src/print_ota_image_header.ts index d1053a5..1cf4413 100644 --- a/src/print_ota_image_header.ts +++ b/src/print_ota_image_header.ts @@ -1,5 +1,5 @@ -import {readFileSync} from 'fs'; +import {readFileSync} from "node:fs"; -import {parseImageHeader} from './common.js'; +import {parseImageHeader} from "./common.js"; console.log(parseImageHeader(readFileSync(process.argv[2]))); diff --git a/src/process_firmware_image.ts b/src/process_firmware_image.ts index 6710ee9..745a2b5 100644 --- a/src/process_firmware_image.ts +++ b/src/process_firmware_image.ts @@ -1,34 +1,34 @@ -import type {ExtraMetas} from './types'; +import type {ExtraMetas} from "./types"; -import assert from 'assert'; -import {readdirSync, readFileSync, renameSync, rmSync, writeFileSync} from 'fs'; -import path from 'path'; +import assert from "node:assert"; +import {readFileSync, readdirSync, renameSync, rmSync, writeFileSync} from "node:fs"; +import path from "node:path"; -import {extract} from 'tar'; +import {extract} from "tar"; import { - addImageToBase, - addImageToPrev, BASE_IMAGES_DIR, BASE_INDEX_MANIFEST_FILENAME, + PREV_IMAGES_DIR, + PREV_INDEX_MANIFEST_FILENAME, + ParsedImageStatus, + TMP_DIR, + UPGRADE_FILE_IDENTIFIER, + addImageToBase, + addImageToPrev, findMatchImage, getOutDir, getParsedImageStatus, - ParsedImageStatus, parseImageHeader, - PREV_IMAGES_DIR, - PREV_INDEX_MANIFEST_FILENAME, readManifest, - TMP_DIR, - UPGRADE_FILE_IDENTIFIER, writeManifest, -} from './common.js'; +} from "./common.js"; -export const enum ProcessFirmwareImageStatus { - ERROR = -1, - SUCCESS = 0, - REQUEST_FAILED = 1, - TAR_NO_IMAGE = 2, +export enum ProcessFirmwareImageStatus { + Error = -1, + Success = 0, + RequestFailed = 1, + TarNoImage = 2, } async function tarExtract(filePath: string, outDir: string, tarImageFinder: (fileName: string) => boolean): Promise { @@ -71,7 +71,7 @@ export async function processFirmwareImage( firmwareFileName: string, firmwareFileUrl: string, extraMetas: ExtraMetas = {}, - tar: boolean = false, + tar = false, tarImageFinder?: (fileName: string) => boolean, ): Promise { // throttle requests (this is done at the top to ensure always executed) @@ -80,9 +80,9 @@ export async function processFirmwareImage( let firmwareFilePath: string | undefined; const logPrefix = `[${manufacturer}:${firmwareFileName}]`; - if (tar && !firmwareFileName.endsWith('.tar.gz')) { + if (tar && !firmwareFileName.endsWith(".tar.gz")) { // ignore non-archive - return ProcessFirmwareImageStatus.TAR_NO_IMAGE; + return ProcessFirmwareImageStatus.TarNoImage; } const prevManifest = readManifest(PREV_INDEX_MANIFEST_FILENAME); @@ -95,11 +95,11 @@ export async function processFirmwareImage( if (!firmwareFile.ok || !firmwareFile.body) { console.error(`${logPrefix} Invalid response from ${firmwareFileUrl} status=${firmwareFile.status}.`); - return ProcessFirmwareImageStatus.REQUEST_FAILED; + return ProcessFirmwareImageStatus.RequestFailed; } if (tar) { - assert(tarImageFinder, `No image finder function supplied for tar.`); + assert(tarImageFinder, "No image finder function supplied for tar."); const archiveBuffer = Buffer.from(await firmwareFile.arrayBuffer()); const archiveFilePath = path.join(baseOutDir, firmwareFileName); @@ -110,7 +110,7 @@ export async function processFirmwareImage( firmwareFileName = await tarExtract(archiveFilePath, baseOutDir, tarImageFinder); } catch { console.error(`${logPrefix} No image found for ${firmwareFileUrl}.`); - return ProcessFirmwareImageStatus.TAR_NO_IMAGE; + return ProcessFirmwareImageStatus.TarNoImage; } } @@ -121,14 +121,14 @@ export async function processFirmwareImage( const statusToBase = getParsedImageStatus(parsedImage, baseMatch); switch (statusToBase) { - case ParsedImageStatus.OLDER: { + case ParsedImageStatus.Older: { // if prev doesn't have a match, move to prev const [prevMatchIndex, prevMatch] = findMatchImage(parsedImage, prevManifest, extraMetas); const statusToPrev = getParsedImageStatus(parsedImage, prevMatch); switch (statusToPrev) { - case ParsedImageStatus.OLDER: - case ParsedImageStatus.IDENTICAL: { + case ParsedImageStatus.Older: + case ParsedImageStatus.Identical: { console.log( `${logPrefix} Base manifest has higher version and an equal or better match is already present in prev manifest. Ignoring.`, ); @@ -136,11 +136,11 @@ export async function processFirmwareImage( break; } - case ParsedImageStatus.NEWER: - case ParsedImageStatus.NEW: { + case ParsedImageStatus.Newer: + case ParsedImageStatus.New: { addImageToPrev( logPrefix, - statusToPrev === ParsedImageStatus.NEWER, + statusToPrev === ParsedImageStatus.Newer, prevManifest, prevMatchIndex, prevMatch!, @@ -166,17 +166,17 @@ export async function processFirmwareImage( break; } - case ParsedImageStatus.IDENTICAL: { + case ParsedImageStatus.Identical: { console.log(`${logPrefix} Base manifest already has version ${parsedImage.fileVersion}. Ignoring.`); break; } - case ParsedImageStatus.NEWER: - case ParsedImageStatus.NEW: { + case ParsedImageStatus.Newer: + case ParsedImageStatus.New: { addImageToBase( logPrefix, - statusToBase === ParsedImageStatus.NEWER, + statusToBase === ParsedImageStatus.Newer, prevManifest, prevOutDir, baseManifest, @@ -203,12 +203,13 @@ export async function processFirmwareImage( } catch (error) { console.error(`${logPrefix} Failed to save firmware file ${firmwareFileName}: ${(error as Error).stack!}.`); - /* istanbul ignore if */ + /* v8 ignore start */ if (firmwareFilePath) { rmSync(firmwareFilePath, {force: true}); } + /* v8 ignore stop */ - return ProcessFirmwareImageStatus.ERROR; + return ProcessFirmwareImageStatus.Error; } writeManifest(PREV_INDEX_MANIFEST_FILENAME, prevManifest); @@ -217,5 +218,5 @@ export async function processFirmwareImage( console.log(`Prev manifest has ${prevManifest.length} images.`); console.log(`Base manifest has ${baseManifest.length} images.`); - return ProcessFirmwareImageStatus.SUCCESS; + return ProcessFirmwareImageStatus.Success; } diff --git a/src/types.ts b/src/types.ts index dd02d28..a634e3e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -65,10 +65,10 @@ export interface RepoImageMeta extends ImageInfo, ImageMeta { export type ExtraMetas = Omit< RepoImageMeta, - 'fileName' | 'fileVersion' | 'fileSize' | 'url' | 'imageType' | 'manufacturerCode' | 'sha512' | 'otaHeaderString' + "fileName" | "fileVersion" | "fileSize" | "url" | "imageType" | "manufacturerCode" | "sha512" | "otaHeaderString" >; export type ExtraMetasWithFileName = Omit< RepoImageMeta, - 'fileName' | 'fileVersion' | 'fileSize' | 'url' | 'imageType' | 'manufacturerCode' | 'sha512' | 'otaHeaderString' + "fileName" | "fileVersion" | "fileSize" | "url" | "imageType" | "manufacturerCode" | "sha512" | "otaHeaderString" > & {fileName?: string}; export type GHExtraMetas = ExtraMetas | ExtraMetasWithFileName[]; diff --git a/tests/data.test.ts b/tests/data.test.ts index 1271c58..f967778 100644 --- a/tests/data.test.ts +++ b/tests/data.test.ts @@ -5,23 +5,24 @@ * */ -import type {ExtraMetas, RepoImageMeta} from '../src/types'; +import type {ExtraMetas, RepoImageMeta} from "../src/types"; -import {copyFileSync, existsSync, mkdirSync} from 'fs'; -import path from 'path'; +import {copyFileSync, existsSync, mkdirSync} from "node:fs"; +import path from "node:path"; -import * as common from '../src/common'; +import {it} from "vitest"; +import * as common from "../src/common"; -export const IMAGE_V14_1 = 'ZLinky_router_v14.ota'; -export const IMAGE_V14_2 = 'ZLinky_router_v14_limited.ota'; -export const IMAGE_V13_1 = 'ZLinky_router_v13.ota'; -export const IMAGE_V13_2 = 'ZLinky_router_v13_limited.ota'; -export const IMAGE_V12_1 = 'ZLinky_router_v12.ota'; -export const IMAGE_V12_2 = 'ZLinky_router_v12_limited.ota'; -export const IMAGE_INVALID = 'not-a-valid-file.ota'; -export const IMAGE_TAR = '45856_00000006.tar.gz'; -export const IMAGE_TAR_OTA = 'Jasco_5_0_1_OnOff_45856_v6.ota'; -export const IMAGES_TEST_DIR = 'jest-tmp'; +export const IMAGE_V14_1 = "ZLinky_router_v14.ota"; +export const IMAGE_V14_2 = "ZLinky_router_v14_limited.ota"; +export const IMAGE_V13_1 = "ZLinky_router_v13.ota"; +export const IMAGE_V13_2 = "ZLinky_router_v13_limited.ota"; +export const IMAGE_V12_1 = "ZLinky_router_v12.ota"; +export const IMAGE_V12_2 = "ZLinky_router_v12_limited.ota"; +export const IMAGE_INVALID = "not-a-valid-file.ota"; +export const IMAGE_TAR = "45856_00000006.tar.gz"; +export const IMAGE_TAR_OTA = "Jasco_5_0_1_OnOff_45856_v6.ota"; +export const IMAGES_TEST_DIR = "test-tmp"; export const BASE_IMAGES_TEST_DIR_PATH = path.join(common.BASE_IMAGES_DIR, IMAGES_TEST_DIR); export const PREV_IMAGES_TEST_DIR_PATH = path.join(common.PREV_IMAGES_DIR, IMAGES_TEST_DIR); /** @@ -44,8 +45,8 @@ export const IMAGE_V14_1_METAS = { url: `${common.BASE_REPO_URL}${common.REPO_BRANCH}/images/${IMAGES_TEST_DIR}/${IMAGE_V14_1}`, imageType: 1, manufacturerCode: 4151, - sha512: 'cc69b0745c72daf8deda935ba47aa7abd34dfcaaa4bc35bfa0605cd7937b0ecd8582ba0c08110df4f620c8aa87798d201f407d3d7e17198cfef1a4aa13c5013d', - otaHeaderString: 'OM15081-RTR-JN5189-0000000000000', + sha512: "cc69b0745c72daf8deda935ba47aa7abd34dfcaaa4bc35bfa0605cd7937b0ecd8582ba0c08110df4f620c8aa87798d201f407d3d7e17198cfef1a4aa13c5013d", + otaHeaderString: "OM15081-RTR-JN5189-0000000000000", }; /** * - otaUpgradeFileIdentifier: , @@ -67,8 +68,8 @@ export const IMAGE_V14_2_METAS = { url: `${common.BASE_REPO_URL}${common.REPO_BRANCH}/images/${IMAGES_TEST_DIR}/${IMAGE_V14_2}`, imageType: 2, manufacturerCode: 4151, - sha512: 'f851cbff7297ba6223a969ba8da5182f9ef199cf9c8459c8408432e48485c1a8f018f6e1703a42f40143cccd3bf460c0acd92117d899e507a36845f24e970595', - otaHeaderString: 'OM15081-RTR-LIMITED-JN5189-00000', + sha512: "f851cbff7297ba6223a969ba8da5182f9ef199cf9c8459c8408432e48485c1a8f018f6e1703a42f40143cccd3bf460c0acd92117d899e507a36845f24e970595", + otaHeaderString: "OM15081-RTR-LIMITED-JN5189-00000", }; /** * - otaUpgradeFileIdentifier: , @@ -90,8 +91,8 @@ export const IMAGE_V13_1_METAS = { url: `${common.BASE_REPO_URL}${common.REPO_BRANCH}/images1/${IMAGES_TEST_DIR}/${IMAGE_V13_1}`, imageType: 1, manufacturerCode: 4151, - sha512: '4d7ab47dcb24e478e0abb35e691222b7691e77ed5a56de3f9c82e8682730649b1a154110b7207d4391c32eae53a869e20878e880fc153dbe046690b870be8486', - otaHeaderString: 'OM15081-RTR-JN5189-0000000000000', + sha512: "4d7ab47dcb24e478e0abb35e691222b7691e77ed5a56de3f9c82e8682730649b1a154110b7207d4391c32eae53a869e20878e880fc153dbe046690b870be8486", + otaHeaderString: "OM15081-RTR-JN5189-0000000000000", }; /** @@ -121,8 +122,8 @@ export const IMAGE_V13_2_METAS = { url: `${common.BASE_REPO_URL}${common.REPO_BRANCH}/images1/${IMAGES_TEST_DIR}/${IMAGE_V13_2}`, imageType: 2, manufacturerCode: 4151, - sha512: 'dd77b28a3b4664e7ad944fcffaa9eca9f3adb0bbe598e12bdd6eece8070a8cdda6792bed378d173dd5b4532b4cdb88cebda0ef0c432c4c4d6581aa9f2bbba54d', - otaHeaderString: 'OM15081-RTR-LIMITED-JN5189-00000', + sha512: "dd77b28a3b4664e7ad944fcffaa9eca9f3adb0bbe598e12bdd6eece8070a8cdda6792bed378d173dd5b4532b4cdb88cebda0ef0c432c4c4d6581aa9f2bbba54d", + otaHeaderString: "OM15081-RTR-LIMITED-JN5189-00000", }; /** * - otaUpgradeFileIdentifier: , @@ -144,8 +145,8 @@ export const IMAGE_V12_1_METAS = { url: `${common.BASE_REPO_URL}${common.REPO_BRANCH}/images1/${IMAGES_TEST_DIR}/${IMAGE_V12_1}`, imageType: 1, manufacturerCode: 4151, - sha512: '5d7e0a20141b78b85b4b046e623bc2bba24b28563464fe70227e79d0acdd5c0bde2adbd9d2557bd6cdfef2036d964c35c9e1746a8f1356af3325dd96f7a80e56', - otaHeaderString: 'OM15081-RTR-JN5189-0000000000000', + sha512: "5d7e0a20141b78b85b4b046e623bc2bba24b28563464fe70227e79d0acdd5c0bde2adbd9d2557bd6cdfef2036d964c35c9e1746a8f1356af3325dd96f7a80e56", + otaHeaderString: "OM15081-RTR-JN5189-0000000000000", }; /** * - otaUpgradeFileIdentifier: , @@ -167,8 +168,8 @@ export const IMAGE_V12_2_METAS = { url: `${common.BASE_REPO_URL}${common.REPO_BRANCH}/images1/${IMAGES_TEST_DIR}/${IMAGE_V12_2}`, imageType: 2, manufacturerCode: 4151, - sha512: '4e178e56c1559e11734c07abbb95110675df7738f3ca3e5dbc99393325295ff6c66bd63ba55c0ef6043a80608dbec2be7a1e845f31ffd94f1cb63f32f0d48c6e', - otaHeaderString: 'OM15081-RTR-LIMITED-JN5189-00000', + sha512: "4e178e56c1559e11734c07abbb95110675df7738f3ca3e5dbc99393325295ff6c66bd63ba55c0ef6043a80608dbec2be7a1e845f31ffd94f1cb63f32f0d48c6e", + otaHeaderString: "OM15081-RTR-LIMITED-JN5189-00000", }; /** obviously bogus, just for mocking */ export const IMAGE_INVALID_METAS = { @@ -179,8 +180,8 @@ export const IMAGE_INVALID_METAS = { url: `${common.BASE_REPO_URL}${common.REPO_BRANCH}/images/${IMAGES_TEST_DIR}/${IMAGE_INVALID}`, imageType: 1, manufacturerCode: 65535, - sha512: 'abcd', - otaHeaderString: 'nothing', + sha512: "abcd", + otaHeaderString: "nothing", }; /** * - otaUpgradeFileIdentifier: , @@ -202,12 +203,13 @@ export const IMAGE_TAR_METAS = { url: `${common.BASE_REPO_URL}${common.REPO_BRANCH}/images/${IMAGES_TEST_DIR}/${IMAGE_TAR_OTA}`, imageType: 2, manufacturerCode: 4388, - sha512: '3306332e001eab9d71c9360089d450ea21e2c08bac957b523643c042707887e85db0c510f3480bdbcfcfe2398eeaad88d455f346f1e07841e1d690d8c16dc211', - otaHeaderString: 'Jasco 45856 image\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + sha512: "3306332e001eab9d71c9360089d450ea21e2c08bac957b523643c042707887e85db0c510f3480bdbcfcfe2398eeaad88d455f346f1e07841e1d690d8c16dc211", + otaHeaderString: "Jasco 45856 image\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", }; export const getImageOriginalDirPath = (imageName: string): string => { - return path.join('tests', common.BASE_IMAGES_DIR, imageName); + // allow running in vitest explorer + return path.join(path.resolve().endsWith("tests") ? "." : "tests", common.BASE_IMAGES_DIR, imageName); }; export const useImage = (imageName: string, outDir: string = BASE_IMAGES_TEST_DIR_PATH): {filename: string} => { @@ -220,7 +222,7 @@ export const useImage = (imageName: string, outDir: string = BASE_IMAGES_TEST_DI copyFileSync(getImageOriginalDirPath(imageName), realPath); // return as posix for github match - return {filename: path.posix.join(outDir.replaceAll('\\', '/'), imageName)}; + return {filename: path.posix.join(outDir.replaceAll("\\", "/"), imageName)}; }; export const withExtraMetas = (meta: RepoImageMeta, extraMetas: ExtraMetas): RepoImageMeta => { @@ -234,7 +236,9 @@ export const getAdjustedContent = (fileName: string, content: RepoImageMeta[]): // @ts-expect-error override url: `${common.BASE_REPO_URL}${common.REPO_BRANCH}/${common.BASE_IMAGES_DIR}/${IMAGES_TEST_DIR}/${c.fileName}`, }); - } else if (fileName === common.PREV_INDEX_MANIFEST_FILENAME && c.url.includes(`${common.BASE_IMAGES_DIR}`)) { + } + + if (fileName === common.PREV_INDEX_MANIFEST_FILENAME && c.url.includes(`${common.BASE_IMAGES_DIR}`)) { return withExtraMetas(c, { // @ts-expect-error override url: `${common.BASE_REPO_URL}${common.REPO_BRANCH}/${common.PREV_IMAGES_DIR}/${IMAGES_TEST_DIR}/${c.fileName}`, @@ -246,4 +250,4 @@ export const getAdjustedContent = (fileName: string, content: RepoImageMeta[]): }; // required to consider as a 'test suite' -it('passes', () => {}); +it("passes", () => {}); diff --git a/tests/ghw_check_ota_pr.test.ts b/tests/ghw_check_ota_pr.test.ts index 0bb14d7..aa7d9bf 100644 --- a/tests/ghw_check_ota_pr.test.ts +++ b/tests/ghw_check_ota_pr.test.ts @@ -1,17 +1,18 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import type {RepoImageMeta} from '../src/types'; +import type {RepoImageMeta} from "../src/types"; -import {existsSync, readFileSync, rmSync} from 'fs'; -import path from 'path'; +import {existsSync, readFileSync, rmSync} from "node:fs"; +import path from "node:path"; -import * as common from '../src/common'; -import {checkOtaPR} from '../src/ghw_check_ota_pr'; +import {type MockInstance, afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import * as common from "../src/common"; +import {checkOtaPR} from "../src/ghw_check_ota_pr"; import { BASE_IMAGES_TEST_DIR_PATH, - getAdjustedContent, + IMAGES_TEST_DIR, IMAGE_INVALID, IMAGE_V12_1, IMAGE_V12_1_METAS, @@ -22,20 +23,21 @@ import { IMAGE_V14_1_METAS, IMAGE_V14_2, IMAGE_V14_2_METAS, - IMAGES_TEST_DIR, PREV_IMAGES_TEST_DIR_PATH, + getAdjustedContent, useImage, withExtraMetas, -} from './data.test'; +} from "./data.test"; const github = { rest: { repos: { - compareCommitsWithBasehead: jest.fn< - ReturnType, - Parameters, - unknown - >(), + compareCommitsWithBasehead: + vi.fn< + ( + ...args: Parameters + ) => ReturnType + >(), }, }, }; @@ -45,49 +47,51 @@ const core: Partial = { warning: console.warn, error: console.error, notice: console.log, - startGroup: jest.fn(), - endGroup: jest.fn(), + startGroup: vi.fn(), + endGroup: vi.fn(), }; const context: Partial = { payload: { pull_request: { number: 1, head: { - sha: 'abcd', + sha: "abcd", }, base: { - sha: 'zyxw', + sha: "zyxw", }, }, }, issue: { - owner: 'Koenkk', - repo: 'zigbee-OTA', + owner: "Koenkk", + repo: "zigbee-OTA", number: 1, }, repo: { - owner: 'Koenkk', - repo: 'zigbee-OTA', + owner: "Koenkk", + repo: "zigbee-OTA", }, }; -describe('Github Workflow: Check OTA PR', () => { +describe("Github Workflow: Check OTA PR", () => { let baseManifest: RepoImageMeta[]; let prevManifest: RepoImageMeta[]; - let readManifestSpy: jest.SpyInstance; - let writeManifestSpy: jest.SpyInstance; - let addImageToBaseSpy: jest.SpyInstance; - let addImageToPrevSpy: jest.SpyInstance; + let readManifestSpy: MockInstance; + let writeManifestSpy: MockInstance; + let addImageToBaseSpy: MockInstance; + let addImageToPrevSpy: MockInstance; let filePaths: ReturnType[] = []; const getManifest = (fileName: string): RepoImageMeta[] => { if (fileName === common.BASE_INDEX_MANIFEST_FILENAME) { return baseManifest; - } else if (fileName === common.PREV_INDEX_MANIFEST_FILENAME) { - return prevManifest; - } else { - throw new Error(`${fileName} not supported`); } + + if (fileName === common.PREV_INDEX_MANIFEST_FILENAME) { + return prevManifest; + } + + throw new Error(`${fileName} not supported`); }; const setManifest = (fileName: string, content: RepoImageMeta[]): void => { @@ -115,7 +119,7 @@ describe('Github Workflow: Check OTA PR', () => { return newContext; }; - const expectNoChanges = (noReadManifest: boolean = false): void => { + const expectNoChanges = (noReadManifest = false): void => { if (noReadManifest) { expect(readManifestSpy).toHaveBeenCalledTimes(0); } else { @@ -136,16 +140,17 @@ describe('Github Workflow: Check OTA PR', () => { addImageToPrevSpy.mockRestore(); rmSync(BASE_IMAGES_TEST_DIR_PATH, {recursive: true, force: true}); rmSync(PREV_IMAGES_TEST_DIR_PATH, {recursive: true, force: true}); + rmSync(IMAGES_TEST_DIR, {recursive: true, force: true}); }); beforeEach(() => { resetManifests(); filePaths = []; - readManifestSpy = jest.spyOn(common, 'readManifest').mockImplementation(getManifest); - writeManifestSpy = jest.spyOn(common, 'writeManifest').mockImplementation(setManifest); - addImageToBaseSpy = jest.spyOn(common, 'addImageToBase'); - addImageToPrevSpy = jest.spyOn(common, 'addImageToPrev'); + readManifestSpy = vi.spyOn(common, "readManifest").mockImplementation(getManifest); + writeManifestSpy = vi.spyOn(common, "writeManifest").mockImplementation(setManifest); + addImageToBaseSpy = vi.spyOn(common, "addImageToBase"); + addImageToPrevSpy = vi.spyOn(common, "addImageToPrev"); github.rest.repos.compareCommitsWithBasehead.mockImplementation( // @ts-expect-error mock () => ({data: {files: filePaths}}), @@ -167,92 +172,92 @@ describe('Github Workflow: Check OTA PR', () => { // console.log(`SHA512: ${common.computeSHA512(firmwareBuffer)}`); // }) - it('hard failure from outside PR context', async () => { + it("hard failure from outside PR context", async () => { filePaths = [useImage(IMAGE_V14_1)]; await expect(async () => { // @ts-expect-error mock await checkOtaPR(github, core, {payload: {}}); - }).rejects.toThrow(`Not a pull request`); + }).rejects.toThrow("Not a pull request"); expectNoChanges(true); }); - it('hard failure from merged PR context', async () => { + it("hard failure from merged PR context", async () => { filePaths = [useImage(IMAGE_V14_1)]; await expect(async () => { // @ts-expect-error mock await checkOtaPR(github, core, {payload: {pull_request: {merged: true}}}); - }).rejects.toThrow(`Should not be executed on a merged pull request`); + }).rejects.toThrow("Should not be executed on a merged pull request"); expectNoChanges(true); }); - it('hard failure with no file changed', async () => { + it("hard failure with no file changed", async () => { filePaths = []; await expect(async () => { // @ts-expect-error mock await checkOtaPR(github, core, context); - }).rejects.toThrow(`No file`); + }).rejects.toThrow("No file"); expectNoChanges(false); expect(existsSync(common.PR_ARTIFACT_NUMBER_FILEPATH)).toStrictEqual(true); - expect(readFileSync(common.PR_ARTIFACT_NUMBER_FILEPATH, 'utf8')).toStrictEqual(`${context.payload?.pull_request?.number}`); + expect(readFileSync(common.PR_ARTIFACT_NUMBER_FILEPATH, "utf8")).toStrictEqual(`${context.payload?.pull_request?.number}`); expect(existsSync(common.PR_ARTIFACT_DIFF_FILEPATH)).toStrictEqual(false); expect(existsSync(common.PR_ARTIFACT_ERROR_FILEPATH)).toStrictEqual(true); - expect(readFileSync(common.PR_ARTIFACT_ERROR_FILEPATH, 'utf8')).toStrictEqual(`No file`); + expect(readFileSync(common.PR_ARTIFACT_ERROR_FILEPATH, "utf8")).toStrictEqual("No file"); }); - it('failure with file outside of images directory', async () => { + it("failure with file outside of images directory", async () => { filePaths = [useImage(IMAGE_V13_1, PREV_IMAGES_TEST_DIR_PATH), useImage(IMAGE_V14_1)]; await expect(async () => { // @ts-expect-error mock await checkOtaPR(github, core, context); - }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining(`Detected changes in files outside`)})); + }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining("Detected changes in files outside")})); expectNoChanges(false); }); - it('failure when no manufacturer subfolder', async () => { + it("failure when no manufacturer subfolder", async () => { filePaths = [useImage(IMAGE_V14_1, common.BASE_IMAGES_DIR)]; await expect(async () => { // @ts-expect-error mock await checkOtaPR(github, core, context); - }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining(`File should be in its associated manufacturer subfolder`)})); + }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining("File should be in its associated manufacturer subfolder")})); expectNoChanges(false); rmSync(path.join(common.BASE_IMAGES_DIR, IMAGE_V14_1), {force: true}); }); - it('failure with invalid OTA file', async () => { + it("failure with invalid OTA file", async () => { filePaths = [useImage(IMAGE_INVALID)]; await expect(async () => { // @ts-expect-error mock await checkOtaPR(github, core, context); - }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining(`Not a valid OTA file`)})); + }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining("Not a valid OTA file")})); expectNoChanges(false); }); - it('failure with identical OTA file', async () => { + it("failure with identical OTA file", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); filePaths = [useImage(IMAGE_V14_1)]; await expect(async () => { // @ts-expect-error mock await checkOtaPR(github, core, context); - }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining(`Conflict with image at index \`0\``)})); + }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining("Conflict with image at index `0`")})); expectNoChanges(false); }); - it('failure with older OTA file that has identical in prev', async () => { + it("failure with older OTA file that has identical in prev", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); setManifest(common.PREV_INDEX_MANIFEST_FILENAME, [IMAGE_V13_1_METAS]); filePaths = [useImage(IMAGE_V13_1)]; @@ -261,13 +266,13 @@ describe('Github Workflow: Check OTA PR', () => { // @ts-expect-error mock await checkOtaPR(github, core, context); }).rejects.toThrow( - expect.objectContaining({message: expect.stringContaining(`an equal or better match is already present in prev manifest`)}), + expect.objectContaining({message: expect.stringContaining("an equal or better match is already present in prev manifest")}), ); expectNoChanges(false); }); - it('failure with older OTA file that has newer in prev', async () => { + it("failure with older OTA file that has newer in prev", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); setManifest(common.PREV_INDEX_MANIFEST_FILENAME, [IMAGE_V13_1_METAS]); filePaths = [useImage(IMAGE_V12_1)]; @@ -276,13 +281,13 @@ describe('Github Workflow: Check OTA PR', () => { // @ts-expect-error mock await checkOtaPR(github, core, context); }).rejects.toThrow( - expect.objectContaining({message: expect.stringContaining(`an equal or better match is already present in prev manifest`)}), + expect.objectContaining({message: expect.stringContaining("an equal or better match is already present in prev manifest")}), ); expectNoChanges(false); }); - it('success into base', async () => { + it("success into base", async () => { filePaths = [useImage(IMAGE_V14_1)]; // @ts-expect-error mock @@ -295,12 +300,12 @@ describe('Github Workflow: Check OTA PR', () => { expect(writeManifestSpy).toHaveBeenCalledTimes(2); expect(writeManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); expect(existsSync(common.PR_ARTIFACT_NUMBER_FILEPATH)).toStrictEqual(true); - expect(readFileSync(common.PR_ARTIFACT_NUMBER_FILEPATH, 'utf8')).toStrictEqual(`${context.payload?.pull_request?.number}`); + expect(readFileSync(common.PR_ARTIFACT_NUMBER_FILEPATH, "utf8")).toStrictEqual(`${context.payload?.pull_request?.number}`); expect(existsSync(common.PR_ARTIFACT_DIFF_FILEPATH)).toStrictEqual(true); expect(existsSync(common.PR_ARTIFACT_ERROR_FILEPATH)).toStrictEqual(false); }); - it('success into prev', async () => { + it("success into prev", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); filePaths = [useImage(IMAGE_V13_1)]; @@ -316,7 +321,7 @@ describe('Github Workflow: Check OTA PR', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, [IMAGE_V13_1_METAS]); }); - it('success with newer than current without existing prev', async () => { + it("success with newer than current without existing prev", async () => { filePaths = [useImage(IMAGE_V13_1), useImage(IMAGE_V14_1)]; // @ts-expect-error mock @@ -330,7 +335,7 @@ describe('Github Workflow: Check OTA PR', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, [IMAGE_V13_1_METAS]); }); - it('success with newer than current with existing prev', async () => { + it("success with newer than current with existing prev", async () => { filePaths = [useImage(IMAGE_V12_1), useImage(IMAGE_V13_1), useImage(IMAGE_V14_1)]; // @ts-expect-error mock @@ -344,7 +349,7 @@ describe('Github Workflow: Check OTA PR', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, [IMAGE_V13_1_METAS]); }); - it('success with older that is newer than prev', async () => { + it("success with older that is newer than prev", async () => { setManifest(common.PREV_INDEX_MANIFEST_FILENAME, [IMAGE_V12_1_METAS]); filePaths = [useImage(IMAGE_V14_1), useImage(IMAGE_V13_1)]; @@ -359,7 +364,7 @@ describe('Github Workflow: Check OTA PR', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, [IMAGE_V13_1_METAS]); }); - it('success with newer with missing file', async () => { + it("success with newer with missing file", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V13_1_METAS]); filePaths = [useImage(IMAGE_V14_1)]; @@ -374,7 +379,7 @@ describe('Github Workflow: Check OTA PR', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, []); }); - it('success with multiple different files', async () => { + it("success with multiple different files", async () => { filePaths = [useImage(IMAGE_V14_2), useImage(IMAGE_V14_1)]; // @ts-expect-error mock @@ -388,7 +393,7 @@ describe('Github Workflow: Check OTA PR', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, []); }); - it('success with extra metas', async () => { + it("success with extra metas", async () => { filePaths = [useImage(IMAGE_V14_1)]; const newContext = withBody(`Text before start tag \`\`\`json {"manufacturerName": ["lixee"]} \`\`\` Text after end tag`); @@ -401,11 +406,11 @@ describe('Github Workflow: Check OTA PR', () => { expect(addImageToPrevSpy).toHaveBeenCalledTimes(0); expect(writeManifestSpy).toHaveBeenCalledTimes(2); expect(writeManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME, [ - withExtraMetas(IMAGE_V14_1_METAS, {manufacturerName: ['lixee']}), + withExtraMetas(IMAGE_V14_1_METAS, {manufacturerName: ["lixee"]}), ]); }); - it('success with all extra metas', async () => { + it("success with all extra metas", async () => { filePaths = [useImage(IMAGE_V14_1)]; const newContext = withBody(`Text before start tag \`\`\`json @@ -435,16 +440,16 @@ Text after end tag`); force: false, hardwareVersionMax: 2, hardwareVersionMin: 1, - manufacturerName: ['lixee'], + manufacturerName: ["lixee"], maxFileVersion: 5, minFileVersion: 3, - modelId: 'bogus', - releaseNotes: 'bugfixes', + modelId: "bogus", + releaseNotes: "bugfixes", }), ]); }); - it('success with newer than current but minFileVersion keeps both', async () => { + it("success with newer than current but minFileVersion keeps both", async () => { filePaths = [useImage(IMAGE_V13_1), useImage(IMAGE_V14_1)]; const newContext = withBody( `Text before start tag \`\`\`json [{"fileName":"ZLinky_router_v14.ota", "minFileVersion": 16783874}] \`\`\` Text after end tag`, @@ -467,7 +472,7 @@ Text after end tag`); expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, []); }); - it('success with newer than current but maxFileVersion keeps both', async () => { + it("success with newer than current but maxFileVersion keeps both", async () => { filePaths = [useImage(IMAGE_V13_1), useImage(IMAGE_V14_1)]; const newContext = withBody( `Text before start tag \`\`\`json [{"fileName":"ZLinky_router_v13.ota", "maxFileVersion": 16783873}] \`\`\` Text after end tag`, @@ -491,7 +496,7 @@ Text after end tag`); expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, []); }); - it('success with newer than current but maxFileVersion/minFileVersion keeps both', async () => { + it("success with newer than current but maxFileVersion/minFileVersion keeps both", async () => { filePaths = [useImage(IMAGE_V13_1), useImage(IMAGE_V14_1)]; const newContext = withBody( `Text before start tag \`\`\`json [{"fileName":"ZLinky_router_v13.ota", "maxFileVersion": 16783873},{"fileName":"ZLinky_router_v14.ota", "minFileVersion": 16783874}] \`\`\` Text after end tag`, @@ -515,7 +520,7 @@ Text after end tag`); expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, []); }); - it('failure with invalid extra metas', async () => { + it("failure with invalid extra metas", async () => { filePaths = [useImage(IMAGE_V14_1)]; const newContext = withBody(`Text before start tag \`\`\`json {"manufacturerName": "myManuf"} \`\`\` Text after end tag`); @@ -530,17 +535,17 @@ Text after end tag`); }); it.each([ - ['fileName'], - ['originalUrl'], - ['force'], - ['hardwareVersionMax'], - ['hardwareVersionMin'], - ['manufacturerName'], - ['maxFileVersion'], - ['minFileVersion'], - ['modelId'], - ['releaseNotes'], - ])('failure with invalid type for extra meta %s', async (metaName) => { + ["fileName"], + ["originalUrl"], + ["force"], + ["hardwareVersionMax"], + ["hardwareVersionMin"], + ["manufacturerName"], + ["maxFileVersion"], + ["minFileVersion"], + ["modelId"], + ["releaseNotes"], + ])("failure with invalid type for extra meta %s", async (metaName) => { filePaths = [useImage(IMAGE_V14_1)]; // use object since no value type is ever expected to be object const newContext = withBody(`Text before start tag \`\`\`json {"${metaName}": {}} \`\`\` Text after end tag`); @@ -553,7 +558,7 @@ Text after end tag`); expectNoChanges(false); }); - it('success with multiple files and specific extra metas', async () => { + it("success with multiple files and specific extra metas", async () => { filePaths = [useImage(IMAGE_V13_1), useImage(IMAGE_V14_1), useImage(IMAGE_V12_1)]; const newContext = withBody(`Text before start tag \`\`\`json @@ -574,15 +579,15 @@ Text after end tag`); expect(addImageToPrevSpy).toHaveBeenCalledTimes(1); expect(writeManifestSpy).toHaveBeenCalledTimes(2); expect(writeManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME, [ - withExtraMetas(IMAGE_V13_1_METAS_MAIN, {manufacturerName: ['lixee']}), - withExtraMetas(IMAGE_V14_1_METAS, {manufacturerName: ['lixee'], hardwareVersionMin: 2}), + withExtraMetas(IMAGE_V13_1_METAS_MAIN, {manufacturerName: ["lixee"]}), + withExtraMetas(IMAGE_V14_1_METAS, {manufacturerName: ["lixee"], hardwareVersionMin: 2}), ]); expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, [ - withExtraMetas(IMAGE_V12_1_METAS, {manufacturerName: ['lixee']}), + withExtraMetas(IMAGE_V12_1_METAS, {manufacturerName: ["lixee"]}), ]); }); - it('success with multiple files and specific extra metas, ignore without fileName', async () => { + it("success with multiple files and specific extra metas, ignore without fileName", async () => { filePaths = [useImage(IMAGE_V12_1), useImage(IMAGE_V13_1), useImage(IMAGE_V14_1)]; const newContext = withBody(`Text before start tag \`\`\`json @@ -603,7 +608,7 @@ Text after end tag`); expect(writeManifestSpy).toHaveBeenCalledTimes(2); expect(writeManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME, [ IMAGE_V13_1_METAS_MAIN, - withExtraMetas(IMAGE_V14_1_METAS, {manufacturerName: ['lixee'], hardwareVersionMin: 2}), + withExtraMetas(IMAGE_V14_1_METAS, {manufacturerName: ["lixee"], hardwareVersionMin: 2}), ]); expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, [IMAGE_V12_1_METAS]); }); diff --git a/tests/ghw_report_ota_pr.test.ts b/tests/ghw_report_ota_pr.test.ts index db4f9a2..993e20b 100644 --- a/tests/ghw_report_ota_pr.test.ts +++ b/tests/ghw_report_ota_pr.test.ts @@ -1,29 +1,28 @@ // import type CoreApi from '@actions/core'; // import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type {Octokit} from "@octokit/rest"; +import {describe, it, vi} from "vitest"; const github = { rest: { issues: { - createComment: jest.fn< - ReturnType, - Parameters, - unknown - >(), + createComment: + vi.fn<(...args: Parameters) => ReturnType>(), }, pulls: { - createReviewComment: jest.fn< - ReturnType, - Parameters, - unknown - >(), + createReviewComment: + vi.fn< + ( + ...args: Parameters + ) => ReturnType + >(), }, }, }; -describe('Github Workflow: Report OTA PR', () => { - it('passes', async () => { +describe("Github Workflow: Report OTA PR", () => { + it("passes", () => { console.log(github); }); }); diff --git a/tests/ghw_reprocess_all_images.test.ts b/tests/ghw_reprocess_all_images.test.ts index 54406fb..5534753 100644 --- a/tests/ghw_reprocess_all_images.test.ts +++ b/tests/ghw_reprocess_all_images.test.ts @@ -1,22 +1,22 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; -import type {RepoImageMeta} from '../src/types'; +import type {RepoImageMeta} from "../src/types"; -import {copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync} from 'fs'; -import path from 'path'; +import {copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync} from "node:fs"; +import path from "node:path"; -import * as common from '../src/common'; +import {type MockInstance, afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import * as common from "../src/common"; import { NOT_IN_BASE_MANIFEST_IMAGES_DIR, NOT_IN_MANIFEST_FILENAME, NOT_IN_PREV_MANIFEST_IMAGES_DIR, reProcessAllImages, -} from '../src/ghw_reprocess_all_images'; +} from "../src/ghw_reprocess_all_images"; import { BASE_IMAGES_TEST_DIR_PATH, - getAdjustedContent, - getImageOriginalDirPath, + IMAGES_TEST_DIR, IMAGE_INVALID, IMAGE_INVALID_METAS, IMAGE_V12_1, @@ -24,11 +24,12 @@ import { IMAGE_V13_1_METAS, IMAGE_V14_1, IMAGE_V14_1_METAS, - IMAGES_TEST_DIR, PREV_IMAGES_TEST_DIR_PATH, + getAdjustedContent, + getImageOriginalDirPath, useImage, withExtraMetas, -} from './data.test'; +} from "./data.test"; /** not used */ const github = {}; @@ -38,14 +39,14 @@ const core: Partial = { warning: console.warn, error: console.error, notice: console.log, - startGroup: jest.fn(), - endGroup: jest.fn(), + startGroup: vi.fn(), + endGroup: vi.fn(), }; const context: Partial = { payload: {}, repo: { - owner: 'Koenkk', - repo: 'zigbee-OTA', + owner: "Koenkk", + repo: "zigbee-OTA", }, }; @@ -56,7 +57,7 @@ const OLD_META_3RD_PARTY_1_METAS = { fileSize: 258104, manufacturerCode: 4107, imageType: 256, - sha512: 'c63a1eb02ac030f3a76d9e81a4d48695796457d263bb1dae483688134e550d9846c37a3fd0eab2d4670f12f11b79691a5cf2789af0dbd90d703512496190a0a5', + sha512: "c63a1eb02ac030f3a76d9e81a4d48695796457d263bb1dae483688134e550d9846c37a3fd0eab2d4670f12f11b79691a5cf2789af0dbd90d703512496190a0a5", // mock fileName to trigger mocked fetch properly url: `https://otau.meethue.com/storage/ZGB_100B_0100/2dcfe6e6-0177-4c81-a1d9-4d2bd2ea1fb7/${OLD_META_3RD_PARTY_1_REAL_IMAGE}`, }; @@ -67,8 +68,8 @@ const OLD_META_3RD_PARTY_2_METAS = { fileSize: 307682, manufacturerCode: 4417, imageType: 54179, - modelId: 'TS011F', - sha512: '01939ca4fc790432d2c233e19b2440c1e0248d2ce85c9299e0b88928cb2341de675350ac7b78187a25f06a2768f93db0a17c4ba950b60c82c072e0c0833cfcfb', + modelId: "TS011F", + sha512: "01939ca4fc790432d2c233e19b2440c1e0248d2ce85c9299e0b88928cb2341de675350ac7b78187a25f06a2768f93db0a17c4ba950b60c82c072e0c0833cfcfb", // mock fileName to trigger mocked fetch properly url: `https://images.tuyaeu.com/smart/firmware/upgrade/20220907/${OLD_META_3RD_PARTY_2_REAL_IMAGE}`, }; @@ -77,8 +78,8 @@ const OLD_META_3RD_PARTY_IGNORED_METAS = { fileSize: 693230, manufacturerCode: 13379, imageType: 4113, - sha512: '66040fb2b2787bf8ebfc75bc3c7356c7d8b966b4c82282bd7393783b8dc453ec2c8dcb4d7c9fe7c0a83d87739bd3677f205d79edddfa4fa2749305ca987887b1', - url: 'https://github.com/xyzroe/ZigUSB_C6/releases/download/317/ZigUSB_C6.ota', + sha512: "66040fb2b2787bf8ebfc75bc3c7356c7d8b966b4c82282bd7393783b8dc453ec2c8dcb4d7c9fe7c0a83d87739bd3677f205d79edddfa4fa2749305ca987887b1", + url: "https://github.com/xyzroe/ZigUSB_C6/releases/download/317/ZigUSB_C6.ota", }; const NOT_IN_BASE_MANIFEST_IMAGE_DIR_PATH = path.join(NOT_IN_BASE_MANIFEST_IMAGES_DIR, IMAGES_TEST_DIR); const NOT_IN_PREV_MANIFEST_IMAGE_DIR_PATH = path.join(NOT_IN_PREV_MANIFEST_IMAGES_DIR, IMAGES_TEST_DIR); @@ -88,30 +89,36 @@ const NOT_IN_PREV_MANIFEST_FILEPATH = path.join(NOT_IN_PREV_MANIFEST_IMAGES_DIR, const NOT_IN_PREV_MANIFEST_IMAGES_DIR_TMP = `${NOT_IN_PREV_MANIFEST_IMAGES_DIR}-moved-by-jest`; const NOT_IN_BASE_MANIFEST_IMAGES_DIR_TMP = `${NOT_IN_BASE_MANIFEST_IMAGES_DIR}-moved-by-jest`; -describe('Github Workflow: Re-Process All Images', () => { +describe("Github Workflow: Re-Process All Images", () => { let baseManifest: RepoImageMeta[]; let prevManifest: RepoImageMeta[]; let notInBaseManifest: RepoImageMeta[]; let notInPrevManifest: RepoImageMeta[]; - let readManifestSpy: jest.SpyInstance; - let writeManifestSpy: jest.SpyInstance; - let addImageToBaseSpy: jest.SpyInstance; - let addImageToPrevSpy: jest.SpyInstance; - let coreWarningSpy: jest.SpyInstance; - let coreErrorSpy: jest.SpyInstance; + let readManifestSpy: MockInstance; + let writeManifestSpy: MockInstance; + let addImageToBaseSpy: MockInstance; + let addImageToPrevSpy: MockInstance; + let coreWarningSpy: MockInstance; + let coreErrorSpy: MockInstance; const getManifest = (fileName: string): RepoImageMeta[] => { if (fileName === common.BASE_INDEX_MANIFEST_FILENAME) { return baseManifest; - } else if (fileName === common.PREV_INDEX_MANIFEST_FILENAME) { - return prevManifest; - } else if (fileName === path.join(NOT_IN_BASE_MANIFEST_IMAGES_DIR, NOT_IN_MANIFEST_FILENAME)) { - return notInBaseManifest; - } else if (fileName === path.join(NOT_IN_PREV_MANIFEST_IMAGES_DIR, NOT_IN_MANIFEST_FILENAME)) { - return notInPrevManifest; - } else { - throw new Error(`${fileName} not supported`); } + + if (fileName === common.PREV_INDEX_MANIFEST_FILENAME) { + return prevManifest; + } + + if (fileName === path.join(NOT_IN_BASE_MANIFEST_IMAGES_DIR, NOT_IN_MANIFEST_FILENAME)) { + return notInBaseManifest; + } + + if (fileName === path.join(NOT_IN_PREV_MANIFEST_IMAGES_DIR, NOT_IN_MANIFEST_FILENAME)) { + return notInPrevManifest; + } + + throw new Error(`${fileName} not supported`); }; const setManifest = (fileName: string, content: RepoImageMeta[]): void => { @@ -137,8 +144,10 @@ describe('Github Workflow: Re-Process All Images', () => { const withOldMetas = (metas: RepoImageMeta): RepoImageMeta => { const oldMetas = structuredClone(metas); + // biome-ignore lint/performance/noDelete: delete oldMetas.originalUrl; // @ts-expect-error mock + // biome-ignore lint/performance/noDelete: delete oldMetas.sha512; return oldMetas; @@ -179,17 +188,19 @@ describe('Github Workflow: Re-Process All Images', () => { rmSync(NOT_IN_BASE_MANIFEST_IMAGES_DIR, {recursive: true, force: true}); renameSync(NOT_IN_BASE_MANIFEST_IMAGES_DIR_TMP, NOT_IN_BASE_MANIFEST_IMAGES_DIR); } + + rmSync(IMAGES_TEST_DIR, {recursive: true, force: true}); }); beforeEach(() => { resetManifests(); - readManifestSpy = jest.spyOn(common, 'readManifest').mockImplementation(getManifest); - writeManifestSpy = jest.spyOn(common, 'writeManifest').mockImplementation(setManifest); - addImageToBaseSpy = jest.spyOn(common, 'addImageToBase'); - addImageToPrevSpy = jest.spyOn(common, 'addImageToPrev'); - coreWarningSpy = jest.spyOn(core, 'warning'); - coreErrorSpy = jest.spyOn(core, 'error'); + readManifestSpy = vi.spyOn(common, "readManifest").mockImplementation(getManifest); + writeManifestSpy = vi.spyOn(common, "writeManifest").mockImplementation(setManifest); + addImageToBaseSpy = vi.spyOn(common, "addImageToBase"); + addImageToPrevSpy = vi.spyOn(common, "addImageToPrev"); + coreWarningSpy = vi.spyOn(core, "warning"); + coreErrorSpy = vi.spyOn(core, "error"); }); afterEach(() => { @@ -199,27 +210,27 @@ describe('Github Workflow: Re-Process All Images', () => { rmSync(NOT_IN_PREV_MANIFEST_IMAGE_DIR_PATH, {recursive: true, force: true}); }); - it('failure when moving not in manifest if base out directory is not empty', async () => { + it("failure when moving not in manifest if base out directory is not empty", async () => { mkdirSync(NOT_IN_BASE_MANIFEST_IMAGE_DIR_PATH, {recursive: true}); copyFileSync(getImageOriginalDirPath(IMAGE_V12_1), path.join(NOT_IN_BASE_MANIFEST_IMAGE_DIR_PATH, IMAGE_V12_1)); await expect(async () => { // @ts-expect-error mocked as needed await reProcessAllImages(github, core, context, false, true); - }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining('is not empty')})); + }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining("is not empty")})); }); - it('failure when moving not in manifest if prev out directory is not empty', async () => { + it("failure when moving not in manifest if prev out directory is not empty", async () => { mkdirSync(NOT_IN_PREV_MANIFEST_IMAGE_DIR_PATH, {recursive: true}); copyFileSync(getImageOriginalDirPath(IMAGE_V12_1), path.join(NOT_IN_PREV_MANIFEST_IMAGE_DIR_PATH, IMAGE_V12_1)); await expect(async () => { // @ts-expect-error mocked as needed await reProcessAllImages(github, core, context, false, true); - }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining('is not empty')})); + }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining("is not empty")})); }); - it('failure when image not in subdirectory', async () => { + it("failure when image not in subdirectory", async () => { // this is renaming the image to the same as the test dir name for simplicity in code exclusion const outPath = path.join(common.PREV_IMAGES_DIR, IMAGES_TEST_DIR); @@ -239,7 +250,7 @@ describe('Github Workflow: Re-Process All Images', () => { rmSync(outPath, {force: true}); }); - it('removes image not in manifest', async () => { + it("removes image not in manifest", async () => { const imagePath = useImage(IMAGE_V12_1, BASE_IMAGES_TEST_DIR_PATH); // @ts-expect-error mocked as needed @@ -250,10 +261,10 @@ describe('Github Workflow: Re-Process All Images', () => { expect(writeManifestSpy).toHaveBeenCalledTimes(2); expectWriteNoChange(1, common.PREV_INDEX_MANIFEST_FILENAME); expectWriteNoChange(2, common.BASE_INDEX_MANIFEST_FILENAME); - expect(coreWarningSpy).toHaveBeenCalledWith(expect.stringContaining(`Not found in base manifest:`)); + expect(coreWarningSpy).toHaveBeenCalledWith(expect.stringContaining("Not found in base manifest:")); }); - it('removes multiple images not in manifest', async () => { + it("removes multiple images not in manifest", async () => { const image1Path = useImage(IMAGE_V13_1, BASE_IMAGES_TEST_DIR_PATH); const image2Path = useImage(IMAGE_V12_1, BASE_IMAGES_TEST_DIR_PATH); const image3Path = useImage(IMAGE_V12_1, PREV_IMAGES_TEST_DIR_PATH); @@ -269,12 +280,12 @@ describe('Github Workflow: Re-Process All Images', () => { expectWriteNoChange(1, common.PREV_INDEX_MANIFEST_FILENAME); expectWriteNoChange(2, common.BASE_INDEX_MANIFEST_FILENAME); // prev first, then alphabetical - expect(coreWarningSpy).toHaveBeenNthCalledWith(1, expect.stringContaining(`Not found in base manifest:`)); - expect(coreWarningSpy).toHaveBeenNthCalledWith(2, expect.stringContaining(`Not found in base manifest:`)); - expect(coreWarningSpy).toHaveBeenNthCalledWith(3, expect.stringContaining(`Not found in base manifest:`)); + expect(coreWarningSpy).toHaveBeenNthCalledWith(1, expect.stringContaining("Not found in base manifest:")); + expect(coreWarningSpy).toHaveBeenNthCalledWith(2, expect.stringContaining("Not found in base manifest:")); + expect(coreWarningSpy).toHaveBeenNthCalledWith(3, expect.stringContaining("Not found in base manifest:")); }); - it('moves image not in manifest', async () => { + it("moves image not in manifest", async () => { const oldPath = useImage(IMAGE_V12_1, BASE_IMAGES_TEST_DIR_PATH); // @ts-expect-error mocked as needed @@ -290,7 +301,7 @@ describe('Github Workflow: Re-Process All Images', () => { expectWriteNoChange(3, common.BASE_INDEX_MANIFEST_FILENAME); }); - it('moves multiple images not in manifest', async () => { + it("moves multiple images not in manifest", async () => { const oldPath1 = useImage(IMAGE_V13_1, BASE_IMAGES_TEST_DIR_PATH); const oldPath2 = useImage(IMAGE_V12_1, BASE_IMAGES_TEST_DIR_PATH); const oldPath3 = useImage(IMAGE_V12_1, PREV_IMAGES_TEST_DIR_PATH); @@ -315,7 +326,7 @@ describe('Github Workflow: Re-Process All Images', () => { expectWriteNoChange(4, common.BASE_INDEX_MANIFEST_FILENAME); }); - it('removes invalid not in manifest even if remove disabled', async () => { + it("removes invalid not in manifest even if remove disabled", async () => { const oldPath = useImage(IMAGE_INVALID, BASE_IMAGES_TEST_DIR_PATH); // @ts-expect-error mocked as needed @@ -326,12 +337,12 @@ describe('Github Workflow: Re-Process All Images', () => { expect(writeManifestSpy).toHaveBeenCalledTimes(2); expect(writeManifestSpy).toHaveBeenNthCalledWith(1, common.PREV_INDEX_MANIFEST_FILENAME, []); expect(writeManifestSpy).toHaveBeenNthCalledWith(2, common.BASE_INDEX_MANIFEST_FILENAME, []); - expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining(`Removing`)); - expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining(`Not a valid OTA file`)); - expect(coreWarningSpy).toHaveBeenCalledWith(expect.stringContaining(`Not found in base manifest`)); + expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Removing")); + expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Not a valid OTA file")); + expect(coreWarningSpy).toHaveBeenCalledWith(expect.stringContaining("Not found in base manifest")); }); - it('removes invalid in manifest', async () => { + it("removes invalid in manifest", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_INVALID_METAS]); const oldPath = useImage(IMAGE_INVALID, BASE_IMAGES_TEST_DIR_PATH); @@ -343,11 +354,11 @@ describe('Github Workflow: Re-Process All Images', () => { expect(writeManifestSpy).toHaveBeenCalledTimes(2); expect(writeManifestSpy).toHaveBeenNthCalledWith(1, common.PREV_INDEX_MANIFEST_FILENAME, []); expect(writeManifestSpy).toHaveBeenNthCalledWith(2, common.BASE_INDEX_MANIFEST_FILENAME, []); - expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining(`Removing`)); - expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining(`Not a valid OTA file`)); + expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Removing")); + expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Not a valid OTA file")); }); - it('keeps image and rewrites manifest', async () => { + it("keeps image and rewrites manifest", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [withOldMetas(IMAGE_V14_1_METAS)]); const imagePath = useImage(IMAGE_V14_1, BASE_IMAGES_TEST_DIR_PATH); @@ -361,11 +372,11 @@ describe('Github Workflow: Re-Process All Images', () => { expect(writeManifestSpy).toHaveBeenNthCalledWith(2, common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); }); - it('keeps image with escaped url and rewrites manifest', async () => { + it("keeps image with escaped url and rewrites manifest", async () => { const oldMetas = withOldMetas(IMAGE_V14_1_METAS); - const fileName = oldMetas.url.split('/').pop()!; - const newName = fileName.replace('.ota', `(%1).ota`); - const baseUrl = oldMetas.url.replace(fileName, ''); + const fileName = oldMetas.url.split("/").pop()!; + const newName = fileName.replace(".ota", "(%1).ota"); + const baseUrl = oldMetas.url.replace(fileName, ""); oldMetas.url = baseUrl + encodeURIComponent(newName); setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [oldMetas]); const imagePath = useImage(IMAGE_V14_1, BASE_IMAGES_TEST_DIR_PATH); @@ -385,11 +396,12 @@ describe('Github Workflow: Re-Process All Images', () => { // @ts-expect-error override {fileName: newName, url: `${baseUrl}${encodeURIComponent(newName)}`}, ); + // biome-ignore lint/performance/noDelete: delete outManifestMetas.originalUrl; expect(writeManifestSpy).toHaveBeenNthCalledWith(2, common.BASE_INDEX_MANIFEST_FILENAME, [outManifestMetas]); }); - it('ignores when same images referenced multiple times in manifest', async () => { + it("ignores when same images referenced multiple times in manifest", async () => { const oldMetas1 = withOldMetas(IMAGE_V14_1_METAS); const oldMetas2 = withOldMetas(IMAGE_V14_1_METAS); setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [oldMetas1, oldMetas2]); @@ -408,9 +420,9 @@ describe('Github Workflow: Re-Process All Images', () => { ); }); - it('keeps same images referenced multiple times in manifest with different extra metas', async () => { - const oldMetas1 = withExtraMetas(withOldMetas(IMAGE_V14_1_METAS), {modelId: 'test1'}); - const oldMetas2 = withExtraMetas(withOldMetas(IMAGE_V14_1_METAS), {modelId: 'test2'}); + it("keeps same images referenced multiple times in manifest with different extra metas", async () => { + const oldMetas1 = withExtraMetas(withOldMetas(IMAGE_V14_1_METAS), {modelId: "test1"}); + const oldMetas2 = withExtraMetas(withOldMetas(IMAGE_V14_1_METAS), {modelId: "test2"}); setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [oldMetas1, oldMetas2]); const image1Path = useImage(IMAGE_V14_1, BASE_IMAGES_TEST_DIR_PATH); @@ -422,28 +434,30 @@ describe('Github Workflow: Re-Process All Images', () => { expect(writeManifestSpy).toHaveBeenCalledTimes(2); expect(writeManifestSpy).toHaveBeenNthCalledWith(1, common.PREV_INDEX_MANIFEST_FILENAME, []); expect(writeManifestSpy).toHaveBeenNthCalledWith(2, common.BASE_INDEX_MANIFEST_FILENAME, [ - withExtraMetas(IMAGE_V14_1_METAS, {modelId: 'test1'}), - withExtraMetas(IMAGE_V14_1_METAS, {modelId: 'test2'}), + withExtraMetas(IMAGE_V14_1_METAS, {modelId: "test1"}), + withExtraMetas(IMAGE_V14_1_METAS, {modelId: "test2"}), ]); expect(coreWarningSpy).toHaveBeenCalledWith( expect.stringContaining(`found multiple times in ${common.BASE_INDEX_MANIFEST_FILENAME} manifest`), ); }); - describe('downloads', () => { - let fetchSpy: jest.SpyInstance; - let setTimeoutSpy: jest.SpyInstance; + describe("downloads", () => { + let fetchSpy: MockInstance; + let setTimeoutSpy: MockInstance; let fetchReturnedStatus: {ok: boolean; status: number; body?: object} = {ok: true, status: 200, body: {}}; - const get3rdPartyDir = jest.fn().mockReturnValue(IMAGES_TEST_DIR); + const get3rdPartyDir = vi.fn().mockReturnValue(IMAGES_TEST_DIR); const adaptUrl = (originalUrl: string, manifestName: string): string => { if (manifestName === common.BASE_INDEX_MANIFEST_FILENAME) { return originalUrl.replace(`/${common.PREV_IMAGES_DIR}/`, `/${common.BASE_IMAGES_DIR}/`); - } else if (manifestName === common.PREV_INDEX_MANIFEST_FILENAME) { - return originalUrl.replace(`/${common.BASE_IMAGES_DIR}/`, `/${common.PREV_IMAGES_DIR}/`); - } else { - throw new Error(`Not supported: ${manifestName}`); } + + if (manifestName === common.PREV_INDEX_MANIFEST_FILENAME) { + return originalUrl.replace(`/${common.BASE_IMAGES_DIR}/`, `/${common.PREV_IMAGES_DIR}/`); + } + + throw new Error(`Not supported: ${manifestName}`); }; afterAll(() => { @@ -452,9 +466,12 @@ describe('Github Workflow: Re-Process All Images', () => { }); beforeEach(() => { - process.env.NODE_EXTRA_CA_CERTS = 'cacerts.pem'; + process.env.NODE_EXTRA_CA_CERTS = "cacerts.pem"; + + get3rdPartyDir.mockClear(); + fetchReturnedStatus = {ok: true, status: 200, body: {}}; - fetchSpy = jest.spyOn(global, 'fetch').mockImplementation( + fetchSpy = vi.spyOn(global, "fetch").mockImplementation( // @ts-expect-error mocked as needed (input) => { return { @@ -462,11 +479,11 @@ describe('Github Workflow: Re-Process All Images', () => { status: fetchReturnedStatus.status, body: fetchReturnedStatus.body, // @ts-expect-error Buffer <> ArrayBuffer (props not used) - arrayBuffer: (): ArrayBuffer => readFileSync(getImageOriginalDirPath((input as string).split('/').pop()!)), + arrayBuffer: (): ArrayBuffer => readFileSync(getImageOriginalDirPath((input as string).split("/").pop()!)), }; }, ); - setTimeoutSpy = jest.spyOn(global, 'setTimeout').mockImplementation( + setTimeoutSpy = vi.spyOn(global, "setTimeout").mockImplementation( // @ts-expect-error mock (fn) => { fn(); @@ -474,18 +491,18 @@ describe('Github Workflow: Re-Process All Images', () => { ); }); - it('failure without CA Certificates ENV', async () => { - process.env.NODE_EXTRA_CA_CERTS = ''; + it("failure without CA Certificates ENV", async () => { + process.env.NODE_EXTRA_CA_CERTS = ""; await expect(async () => { // @ts-expect-error mocked as needed await reProcessAllImages(github, core, context, true, false, get3rdPartyDir); }).rejects.toThrow( - expect.objectContaining({message: expect.stringContaining(`Download 3rd Parties requires \`NODE_EXTRA_CA_CERTS=cacerts.pem\``)}), + expect.objectContaining({message: expect.stringContaining("Download 3rd Parties requires `NODE_EXTRA_CA_CERTS=cacerts.pem`")}), ); }); - it('failure with malformed metas', async () => { + it("failure with malformed metas", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [ // @ts-expect-error old metas { @@ -493,9 +510,9 @@ describe('Github Workflow: Re-Process All Images', () => { fileSize: 307682, manufacturerCode: 4417, imageType: 54179, - modelId: 'TS011F', - sha512: '01939ca4fc790432d2c233e19b2440c1e0248d2ce85c9299e0b88928cb2341de675350ac7b78187a25f06a2768f93db0a17c4ba950b60c82c072e0c0833cfcfb', - url: '', // not undefined to pass setManifest + modelId: "TS011F", + sha512: "01939ca4fc790432d2c233e19b2440c1e0248d2ce85c9299e0b88928cb2341de675350ac7b78187a25f06a2768f93db0a17c4ba950b60c82c072e0c0833cfcfb", + url: "", // not undefined to pass setManifest }, ]); @@ -509,10 +526,10 @@ describe('Github Workflow: Re-Process All Images', () => { expectWriteNoChange(2, common.BASE_INDEX_MANIFEST_FILENAME); expectWriteNoChange(3, common.PREV_INDEX_MANIFEST_FILENAME); expectWriteNoChange(4, common.BASE_INDEX_MANIFEST_FILENAME); - expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining(`Ignoring malformed`)); + expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Ignoring malformed")); }); - it('failure from fetch ok', async () => { + it("failure from fetch ok", async () => { setManifest( common.BASE_INDEX_MANIFEST_FILENAME, // @ts-expect-error old metas @@ -535,7 +552,7 @@ describe('Github Workflow: Re-Process All Images', () => { ); }); - it('ignores urls from this repo', async () => { + it("ignores urls from this repo", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); // prevent trigger removal because of missing file useImage(IMAGE_V14_1, BASE_IMAGES_TEST_DIR_PATH); @@ -552,7 +569,7 @@ describe('Github Workflow: Re-Process All Images', () => { expectWriteNoChange(4, common.BASE_INDEX_MANIFEST_FILENAME); }); - it('ignores urls with no out dir specified', async () => { + it("ignores urls with no out dir specified", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [ // @ts-expect-error old metas { @@ -560,9 +577,9 @@ describe('Github Workflow: Re-Process All Images', () => { fileSize: 307682, manufacturerCode: 4417, imageType: 54179, - modelId: 'TS011F', - sha512: '01939ca4fc790432d2c233e19b2440c1e0248d2ce85c9299e0b88928cb2341de675350ac7b78187a25f06a2768f93db0a17c4ba950b60c82c072e0c0833cfcfb', - url: 'https://www.elektroimportoren.no/docs/lib/4512772-Firmware-35.ota', + modelId: "TS011F", + sha512: "01939ca4fc790432d2c233e19b2440c1e0248d2ce85c9299e0b88928cb2341de675350ac7b78187a25f06a2768f93db0a17c4ba950b60c82c072e0c0833cfcfb", + url: "https://www.elektroimportoren.no/docs/lib/4512772-Firmware-35.ota", }, ]); @@ -576,10 +593,10 @@ describe('Github Workflow: Re-Process All Images', () => { expectWriteNoChange(2, common.BASE_INDEX_MANIFEST_FILENAME); expectWriteNoChange(3, common.PREV_INDEX_MANIFEST_FILENAME); expectWriteNoChange(4, common.BASE_INDEX_MANIFEST_FILENAME); - expect(coreWarningSpy).toHaveBeenCalledWith(expect.stringContaining(`no out dir specified`)); + expect(coreWarningSpy).toHaveBeenCalledWith(expect.stringContaining("no out dir specified")); }); - it('ignores invalid OTA file', async () => { + it("ignores invalid OTA file", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [ Object.assign({}, withOldMetas(IMAGE_INVALID_METAS), { url: `https://images.tuyaeu.com/smart/firmware/upgrade/20220907/${IMAGES_TEST_DIR}/${IMAGE_INVALID}`, @@ -596,11 +613,11 @@ describe('Github Workflow: Re-Process All Images', () => { expectWriteNoChange(2, common.BASE_INDEX_MANIFEST_FILENAME); expectWriteNoChange(3, common.PREV_INDEX_MANIFEST_FILENAME); expectWriteNoChange(4, common.BASE_INDEX_MANIFEST_FILENAME); - expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining(`Ignoring`)); - expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining(`Not a valid OTA file`)); + expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Ignoring")); + expect(coreErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Not a valid OTA file")); }); - it('ignores identical image', async () => { + it("ignores identical image", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [ IMAGE_V14_1_METAS, Object.assign({}, withOldMetas(IMAGE_V14_1_METAS), { @@ -618,10 +635,10 @@ describe('Github Workflow: Re-Process All Images', () => { expect(addImageToPrevSpy).toHaveBeenCalledTimes(0); expect(writeManifestSpy).toHaveBeenNthCalledWith(1, common.PREV_INDEX_MANIFEST_FILENAME, []); expect(writeManifestSpy).toHaveBeenNthCalledWith(2, common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); - expect(coreWarningSpy).toHaveBeenCalledWith(expect.stringContaining(`Conflict with image at index \`0\``)); + expect(coreWarningSpy).toHaveBeenCalledWith(expect.stringContaining("Conflict with image at index `0`")); }); - it('success without mocked get3rdPartyDir', async () => { + it("success without mocked get3rdPartyDir", async () => { // NOTE: this is using a name (ZLinky_router_v13.ota) and out dir (Hue) that is unlikely to ever be in conflict with actual Hue images setManifest( common.BASE_INDEX_MANIFEST_FILENAME, @@ -641,14 +658,14 @@ describe('Github Workflow: Re-Process All Images', () => { withExtraMetas(OLD_META_3RD_PARTY_1_REAL_METAS, { originalUrl: OLD_META_3RD_PARTY_1_METAS.url, // @ts-expect-error override - url: adaptUrl(OLD_META_3RD_PARTY_1_REAL_METAS.url, common.BASE_INDEX_MANIFEST_FILENAME).replace(IMAGES_TEST_DIR, 'Hue'), + url: adaptUrl(OLD_META_3RD_PARTY_1_REAL_METAS.url, common.BASE_INDEX_MANIFEST_FILENAME).replace(IMAGES_TEST_DIR, "Hue"), }), ]); - rmSync(path.join(common.BASE_IMAGES_DIR, 'Hue', OLD_META_3RD_PARTY_1_REAL_IMAGE)); + rmSync(path.join(common.BASE_IMAGES_DIR, "Hue", OLD_META_3RD_PARTY_1_REAL_IMAGE)); }); - it('success with add different metas and ignored', async () => { + it("success with add different metas and ignored", async () => { setManifest( common.BASE_INDEX_MANIFEST_FILENAME, // @ts-expect-error old metas @@ -683,7 +700,7 @@ describe('Github Workflow: Re-Process All Images', () => { expect(coreWarningSpy).toHaveBeenCalledWith(expect.stringContaining(`Removing ignored '${OLD_META_3RD_PARTY_IGNORED_METAS.url}'`)); }); - it('success with add+move same and ignored', async () => { + it("success with add+move same and ignored", async () => { setManifest( common.BASE_INDEX_MANIFEST_FILENAME, // @ts-expect-error old metas @@ -715,7 +732,7 @@ describe('Github Workflow: Re-Process All Images', () => { expect(coreWarningSpy).toHaveBeenCalledWith(expect.stringContaining(`Removing ignored '${OLD_META_3RD_PARTY_IGNORED_METAS.url}'`)); }); - it('success with add to prev', async () => { + it("success with add to prev", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [ IMAGE_V14_1_METAS, // @ts-expect-error old metas @@ -746,16 +763,16 @@ describe('Github Workflow: Re-Process All Images', () => { expect(writeManifestSpy).toHaveBeenNthCalledWith(4, common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); }); - it('success with escaped', async () => { + it("success with escaped", async () => { const oldMetas = structuredClone(OLD_META_3RD_PARTY_1_METAS); - const fileName = oldMetas.url.split('/').pop()!; - const newName = fileName.replace('.ota', `(%1).ota`); - const baseUrl = oldMetas.url.replace(fileName, ''); + const fileName = oldMetas.url.split("/").pop()!; + const newName = fileName.replace(".ota", "(%1).ota"); + const baseUrl = oldMetas.url.replace(fileName, ""); oldMetas.url = baseUrl + encodeURIComponent(newName); // @ts-expect-error old metas setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [oldMetas]); // link back to existing image from fetch - fetchSpy = jest.spyOn(global, 'fetch').mockImplementationOnce( + fetchSpy = vi.spyOn(global, "fetch").mockImplementationOnce( // @ts-expect-error mocked as needed () => { return { diff --git a/tests/ghw_update_manifests.test.ts b/tests/ghw_update_manifests.test.ts index 3c0389e..b51ce4e 100644 --- a/tests/ghw_update_manifests.test.ts +++ b/tests/ghw_update_manifests.test.ts @@ -1,35 +1,37 @@ -import type CoreApi from '@actions/core'; -import type {Context} from '@actions/github/lib/context'; -import type {Octokit} from '@octokit/rest'; +import type CoreApi from "@actions/core"; +import type {Context} from "@actions/github/lib/context"; +import type {Octokit} from "@octokit/rest"; -import type {RepoImageMeta} from '../src/types'; +import type {RepoImageMeta} from "../src/types"; -import {rmSync} from 'fs'; +import {rmSync} from "node:fs"; -import * as common from '../src/common'; -import {updateManifests} from '../src/ghw_update_manifests'; +import {type MockInstance, afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import * as common from "../src/common"; +import {updateManifests} from "../src/ghw_update_manifests"; import { BASE_IMAGES_TEST_DIR_PATH, - getAdjustedContent, IMAGE_V13_1, IMAGE_V14_1, IMAGE_V14_1_METAS, PREV_IMAGES_TEST_DIR_PATH, + getAdjustedContent, useImage, withExtraMetas, -} from './data.test'; +} from "./data.test"; const github = { rest: { pulls: { - get: jest.fn, Parameters, unknown>(), + get: vi.fn<(...args: Parameters) => ReturnType>(), }, repos: { - compareCommitsWithBasehead: jest.fn< - ReturnType, - Parameters, - unknown - >(), + compareCommitsWithBasehead: + vi.fn< + ( + ...args: Parameters + ) => ReturnType + >(), }, }, }; @@ -39,40 +41,42 @@ const core: Partial = { warning: console.warn, error: console.error, notice: console.log, - startGroup: jest.fn(), - endGroup: jest.fn(), + startGroup: vi.fn(), + endGroup: vi.fn(), }; const context: Partial = { - eventName: 'push', + eventName: "push", payload: { head_commit: { - message: 'push from pr (#213)', + message: "push from pr (#213)", }, }, repo: { - owner: 'Koenkk', - repo: 'zigbee-OTA', + owner: "Koenkk", + repo: "zigbee-OTA", }, }; -describe('Github Workflow: Update manifests', () => { +describe("Github Workflow: Update manifests", () => { let baseManifest: RepoImageMeta[]; let prevManifest: RepoImageMeta[]; - let readManifestSpy: jest.SpyInstance; - let writeManifestSpy: jest.SpyInstance; - let addImageToBaseSpy: jest.SpyInstance; - let addImageToPrevSpy: jest.SpyInstance; + let readManifestSpy: MockInstance; + let writeManifestSpy: MockInstance; + let addImageToBaseSpy: MockInstance; + let addImageToPrevSpy: MockInstance; let filePaths: ReturnType[] = []; let prBody: string | undefined; const getManifest = (fileName: string): RepoImageMeta[] => { if (fileName === common.BASE_INDEX_MANIFEST_FILENAME) { return baseManifest; - } else if (fileName === common.PREV_INDEX_MANIFEST_FILENAME) { - return prevManifest; - } else { - throw new Error(`${fileName} not supported`); } + + if (fileName === common.PREV_INDEX_MANIFEST_FILENAME) { + return prevManifest; + } + + throw new Error(`${fileName} not supported`); }; const setManifest = (fileName: string, content: RepoImageMeta[]): void => { @@ -92,7 +96,7 @@ describe('Github Workflow: Update manifests', () => { prevManifest = []; }; - const expectNoChanges = (noReadManifest: boolean = false): void => { + const expectNoChanges = (noReadManifest = false): void => { if (noReadManifest) { expect(readManifestSpy).toHaveBeenCalledTimes(0); } else { @@ -119,10 +123,10 @@ describe('Github Workflow: Update manifests', () => { resetManifests(); filePaths = []; - readManifestSpy = jest.spyOn(common, 'readManifest').mockImplementation(getManifest); - writeManifestSpy = jest.spyOn(common, 'writeManifest').mockImplementation(setManifest); - addImageToBaseSpy = jest.spyOn(common, 'addImageToBase'); - addImageToPrevSpy = jest.spyOn(common, 'addImageToPrev'); + readManifestSpy = vi.spyOn(common, "readManifest").mockImplementation(getManifest); + writeManifestSpy = vi.spyOn(common, "writeManifest").mockImplementation(setManifest); + addImageToBaseSpy = vi.spyOn(common, "addImageToBase"); + addImageToPrevSpy = vi.spyOn(common, "addImageToPrev"); github.rest.pulls.get.mockImplementation( // @ts-expect-error mock () => ({data: {body: prBody}}), @@ -139,29 +143,29 @@ describe('Github Workflow: Update manifests', () => { rmSync(common.PR_ARTIFACT_DIR, {recursive: true, force: true}); }); - it('hard failure from outside push context', async () => { + it("hard failure from outside push context", async () => { filePaths = [useImage(IMAGE_V14_1)]; await expect(async () => { // @ts-expect-error mock await updateManifests(github, core, {payload: {}}); - }).rejects.toThrow(`Not a push`); + }).rejects.toThrow("Not a push"); expectNoChanges(true); }); - it('failure with file outside of images directory', async () => { + it("failure with file outside of images directory", async () => { filePaths = [useImage(IMAGE_V13_1, PREV_IMAGES_TEST_DIR_PATH), useImage(IMAGE_V14_1)]; await expect(async () => { // @ts-expect-error mock await updateManifests(github, core, context); - }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining(`Cannot run with files outside`)})); + }).rejects.toThrow(expect.objectContaining({message: expect.stringContaining("Cannot run with files outside")})); expectNoChanges(true); }); - it('success into base', async () => { + it("success into base", async () => { filePaths = [useImage(IMAGE_V14_1)]; // @ts-expect-error mock @@ -175,7 +179,7 @@ describe('Github Workflow: Update manifests', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); }); - it('success with extra metas', async () => { + it("success with extra metas", async () => { filePaths = [useImage(IMAGE_V14_1)]; prBody = `Text before start tag \`\`\`json {"manufacturerName": ["lixee"]} \`\`\` Text after end tag`; @@ -188,18 +192,18 @@ describe('Github Workflow: Update manifests', () => { expect(addImageToPrevSpy).toHaveBeenCalledTimes(0); expect(writeManifestSpy).toHaveBeenCalledTimes(2); expect(writeManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME, [ - withExtraMetas(IMAGE_V14_1_METAS, {manufacturerName: ['lixee']}), + withExtraMetas(IMAGE_V14_1_METAS, {manufacturerName: ["lixee"]}), ]); }); - it('fails to get PR for extra metas', async () => { + it("fails to get PR for extra metas", async () => { filePaths = [useImage(IMAGE_V14_1)]; - github.rest.pulls.get.mockRejectedValueOnce('403'); + github.rest.pulls.get.mockRejectedValueOnce("403"); await expect(async () => { // @ts-expect-error mock await updateManifests(github, core, context); - }).rejects.toThrow(expect.objectContaining({message: `Failed to get PR#213 for extra metas: 403`})); + }).rejects.toThrow(expect.objectContaining({message: "Failed to get PR#213 for extra metas: 403"})); expectNoChanges(false); }); diff --git a/tests/jest.config.ts b/tests/jest.config.ts deleted file mode 100644 index e96ba28..0000000 --- a/tests/jest.config.ts +++ /dev/null @@ -1,222 +0,0 @@ -/** - * For a detailed explanation regarding each configuration property, visit: - * https://jestjs.io/docs/configuration - */ - -// import type {Config} from 'jest'; - -import {createDefaultEsmPreset, JestConfigWithTsJest} from 'ts-jest'; - -const defaultEsmPreset = createDefaultEsmPreset(); - -const config: JestConfigWithTsJest = { - // All imported modules in your tests should be mocked automatically - // automock: false, - - // Stop running tests after `n` failures - // bail: 0, - - // The directory where Jest should store its cached dependency information - cacheDirectory: '.jest-tmp', - - // Automatically clear mock calls, instances, contexts and results before every test - clearMocks: true, - - // Indicates whether the coverage information should be collected while executing the test - collectCoverage: false, - - // An array of glob patterns indicating a set of files for which coverage information should be collected - collectCoverageFrom: [ - 'src/ghw_check_ota_pr.ts', - 'src/ghw_get_changed_ota_files.ts', - 'src/ghw_process_ota_files.ts', - 'src/process_firmware_image.ts', - 'src/ghw_reprocess_all_images.ts', - ], - - // The directory where Jest should output its coverage files - coverageDirectory: 'coverage', - - // An array of regexp pattern strings used to skip coverage collection - // coveragePathIgnorePatterns: [ - // "\\\\node_modules\\\\" - // ], - - // Indicates which provider should be used to instrument code for coverage - coverageProvider: 'babel', - - // A list of reporter names that Jest uses when writing coverage reports - coverageReporters: [ - // "json", - // "text", - 'lcov', - // "clover" - ], - - // An object that configures minimum threshold enforcement for coverage results - coverageThreshold: { - global: { - branches: 100, - functions: 100, - lines: 100, - statements: 100, - }, - }, - - // A path to a custom dependency extractor - // dependencyExtractor: undefined, - - // Make calling deprecated APIs throw helpful error messages - // errorOnDeprecated: false, - - // The default configuration for fake timers - // fakeTimers: { - // "enableGlobally": false - // }, - - // Force coverage collection from ignored files using an array of glob patterns - // forceCoverageMatch: [], - - // A path to a module which exports an async function that is triggered once before all test suites - // globalSetup: undefined, - - // A path to a module which exports an async function that is triggered once after all test suites - // globalTeardown: undefined, - - // A set of global variables that need to be available in all test environments - // globals: {}, - - // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. - maxWorkers: '50%', - - // An array of directory names to be searched recursively up from the requiring module's location - // moduleDirectories: [ - // "node_modules" - // ], - - // An array of file extensions your modules use - moduleFileExtensions: [ - // commonly used first - 'ts', - 'json', - 'js', - 'mjs', - 'cjs', - 'jsx', - 'tsx', - 'node', - ], - - // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module - // moduleNameMapper: {}, - - // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader - // modulePathIgnorePatterns: [], - - // Activates notifications for test results - // notify: false, - - // An enum that specifies notification mode. Requires { notify: true } - // notifyMode: "failure-change", - - // A preset that is used as a base for Jest's configuration - // preset: undefined, - - // Run tests from one or more projects - // projects: undefined, - - // Use this configuration option to add custom reporters to Jest - // reporters: undefined, - - // Automatically reset mock state before every test - // resetMocks: false, - - // Reset the module registry before running each individual test - // resetModules: false, - - // A path to a custom resolver - // resolver: undefined, - - // Automatically restore mock state and implementation before every test - // restoreMocks: false, - - // The root directory that Jest should scan for tests and modules within - rootDir: '..', - - // A list of paths to directories that Jest should use to search for files in - // roots: [ - // "" - // ], - - // Allows you to use a custom runner instead of Jest's default test runner - // runner: "jest-runner", - - // The paths to modules that run some code to configure or set up the testing environment before each test - // setupFiles: [], - - // A list of paths to modules that run some code to configure or set up the testing framework before each test - // setupFilesAfterEnv: [], - - // The number of seconds after which a test is considered as slow and reported as such in the results. - // slowTestThreshold: 5, - - // A list of paths to snapshot serializer modules Jest should use for snapshot testing - // snapshotSerializers: [], - - // The test environment that will be used for testing - // testEnvironment: "jest-environment-node", - - // Options that will be passed to the testEnvironment - // testEnvironmentOptions: {}, - - // Adds a location field to test results - // testLocationInResults: false, - - // The glob patterns Jest uses to detect test files - // testMatch: [ - // "**/__tests__/**/*.[jt]s?(x)", - // "**/?(*.)+(spec|test).[tj]s?(x)" - // ], - - // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped - // testPathIgnorePatterns: [ - // "\\\\node_modules\\\\" - // ], - - // The regexp pattern or array of patterns that Jest uses to detect test files - // testRegex: [], - - // This option allows the use of a custom results processor - // testResultsProcessor: undefined, - - // This option allows use of a custom test runner - // testRunner: "jest-circus/runner", - - // A map from regular expressions to paths to transformers - // transform: undefined, - - // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation - // transformIgnorePatterns: [ - // "\\\\node_modules\\\\", - // "\\.pnp\\.[^\\\\]+$" - // ], - - // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them - // unmockedModulePathPatterns: undefined, - - // Indicates whether each individual test should be reported during the run - // verbose: undefined, - - // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode - // watchPathIgnorePatterns: [], - - // Whether to use watchman for file crawling - // watchman: true, - - ...defaultEsmPreset, - moduleNameMapper: { - '^(\\.{1,2}/.*)\\.js$': '$1', - }, -}; - -export default config; diff --git a/tests/process_firmware_image.test.ts b/tests/process_firmware_image.test.ts index 875f7ec..36b331f 100644 --- a/tests/process_firmware_image.test.ts +++ b/tests/process_firmware_image.test.ts @@ -1,13 +1,13 @@ -import type {RepoImageMeta} from '../src/types'; +import type {RepoImageMeta} from "../src/types"; -import {existsSync, mkdirSync, readFileSync, rmSync} from 'fs'; +import {existsSync, mkdirSync, readFileSync, rmSync} from "node:fs"; -import * as common from '../src/common'; -import {processFirmwareImage, ProcessFirmwareImageStatus} from '../src/process_firmware_image'; +import {type MockInstance, afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import * as common from "../src/common"; +import {ProcessFirmwareImageStatus, processFirmwareImage} from "../src/process_firmware_image"; import { BASE_IMAGES_TEST_DIR_PATH, - getAdjustedContent, - getImageOriginalDirPath, + IMAGES_TEST_DIR, IMAGE_INVALID, IMAGE_TAR, IMAGE_TAR_METAS, @@ -17,33 +17,36 @@ import { IMAGE_V13_1_METAS, IMAGE_V14_1, IMAGE_V14_1_METAS, - IMAGES_TEST_DIR, PREV_IMAGES_TEST_DIR_PATH, + getAdjustedContent, + getImageOriginalDirPath, useImage, withExtraMetas, -} from './data.test'; +} from "./data.test"; -describe('Process Firmware Image', () => { +describe("Process Firmware Image", () => { let baseManifest: RepoImageMeta[]; let prevManifest: RepoImageMeta[]; - let consoleErrorSpy: jest.SpyInstance; - let consoleLogSpy: jest.SpyInstance; - let readManifestSpy: jest.SpyInstance; - let writeManifestSpy: jest.SpyInstance; - let addImageToBaseSpy: jest.SpyInstance; - let addImageToPrevSpy: jest.SpyInstance; - let fetchSpy: jest.SpyInstance; - let setTimeoutSpy: jest.SpyInstance; + let consoleErrorSpy: MockInstance; + let consoleLogSpy: MockInstance; + let readManifestSpy: MockInstance; + let writeManifestSpy: MockInstance; + let addImageToBaseSpy: MockInstance; + let addImageToPrevSpy: MockInstance; + let fetchSpy: MockInstance; + let setTimeoutSpy: MockInstance; let fetchReturnedStatus: {ok: boolean; status: number; body?: object} = {ok: true, status: 200, body: {}}; const getManifest = (fileName: string): RepoImageMeta[] => { if (fileName === common.BASE_INDEX_MANIFEST_FILENAME) { return baseManifest; - } else if (fileName === common.PREV_INDEX_MANIFEST_FILENAME) { - return prevManifest; - } else { - throw new Error(`${fileName} not supported`); } + + if (fileName === common.PREV_INDEX_MANIFEST_FILENAME) { + return prevManifest; + } + + throw new Error(`${fileName} not supported`); }; const setManifest = (fileName: string, content: RepoImageMeta[]): void => { @@ -71,7 +74,7 @@ describe('Process Firmware Image', () => { return newMeta; }; - const expectNoChanges = (noReadManifest: boolean = false): void => { + const expectNoChanges = (noReadManifest = false): void => { if (noReadManifest) { expect(readManifestSpy).toHaveBeenCalledTimes(0); } else { @@ -84,7 +87,7 @@ describe('Process Firmware Image', () => { expect(writeManifestSpy).toHaveBeenCalledTimes(0); }; - const expectWriteNoChanges = (inBase: boolean = true, inPrev: boolean = true): void => { + const expectWriteNoChanges = (inBase = true, inPrev = true): void => { if (inBase) { expect(writeManifestSpy).toHaveBeenNthCalledWith( 1, @@ -115,19 +118,20 @@ describe('Process Firmware Image', () => { setTimeoutSpy.mockRestore(); rmSync(BASE_IMAGES_TEST_DIR_PATH, {recursive: true, force: true}); rmSync(PREV_IMAGES_TEST_DIR_PATH, {recursive: true, force: true}); + rmSync(IMAGES_TEST_DIR, {recursive: true, force: true}); }); beforeEach(() => { resetManifests(); fetchReturnedStatus = {ok: true, status: 200, body: {}}; - consoleErrorSpy = jest.spyOn(console, 'error'); - consoleLogSpy = jest.spyOn(console, 'log'); - readManifestSpy = jest.spyOn(common, 'readManifest').mockImplementation(getManifest); - writeManifestSpy = jest.spyOn(common, 'writeManifest').mockImplementation(setManifest); - addImageToBaseSpy = jest.spyOn(common, 'addImageToBase'); - addImageToPrevSpy = jest.spyOn(common, 'addImageToPrev'); - fetchSpy = jest.spyOn(global, 'fetch').mockImplementation( + consoleErrorSpy = vi.spyOn(console, "error"); + consoleLogSpy = vi.spyOn(console, "log"); + readManifestSpy = vi.spyOn(common, "readManifest").mockImplementation(getManifest); + writeManifestSpy = vi.spyOn(common, "writeManifest").mockImplementation(setManifest); + addImageToBaseSpy = vi.spyOn(common, "addImageToBase"); + addImageToPrevSpy = vi.spyOn(common, "addImageToPrev"); + fetchSpy = vi.spyOn(global, "fetch").mockImplementation( // @ts-expect-error mocked as needed (input) => { return { @@ -139,7 +143,7 @@ describe('Process Firmware Image', () => { }; }, ); - setTimeoutSpy = jest.spyOn(global, 'setTimeout').mockImplementation( + setTimeoutSpy = vi.spyOn(global, "setTimeout").mockImplementation( // @ts-expect-error mock (fn) => { fn(); @@ -152,72 +156,72 @@ describe('Process Firmware Image', () => { rmSync(PREV_IMAGES_TEST_DIR_PATH, {recursive: true, force: true}); }); - it('failure with fetch ok', async () => { + it("failure with fetch ok", async () => { fetchReturnedStatus.ok = false; fetchReturnedStatus.status = 429; const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V14_1, IMAGE_V14_1); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.REQUEST_FAILED); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.RequestFailed); expect(consoleErrorSpy).toHaveBeenCalledWith( expect.stringContaining(`Invalid response from ${IMAGE_V14_1} status=${fetchReturnedStatus.status}.`), ); expectNoChanges(false); }); - it('failure with fetch body', async () => { + it("failure with fetch body", async () => { fetchReturnedStatus.body = undefined; const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V14_1, IMAGE_V14_1); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.REQUEST_FAILED); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.RequestFailed); expect(consoleErrorSpy).toHaveBeenCalledWith( expect.stringContaining(`Invalid response from ${IMAGE_V14_1} status=${fetchReturnedStatus.status}.`), ); expectNoChanges(false); }); - it('failure with invalid OTA file', async () => { + it("failure with invalid OTA file", async () => { const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_INVALID, IMAGE_INVALID); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.ERROR); - expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining(`Not a valid OTA fil`)); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Error); + expect(consoleErrorSpy).toHaveBeenCalledWith(expect.stringContaining("Not a valid OTA fil")); expectNoChanges(false); }); - it('failure with identical OTA file', async () => { + it("failure with identical OTA file", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V14_1, IMAGE_V14_1); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining(`Base manifest already has version`)); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); + expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining("Base manifest already has version")); expect(writeManifestSpy).toHaveBeenNthCalledWith(1, common.PREV_INDEX_MANIFEST_FILENAME, getManifest(common.PREV_INDEX_MANIFEST_FILENAME)); expect(writeManifestSpy).toHaveBeenNthCalledWith(2, common.BASE_INDEX_MANIFEST_FILENAME, getManifest(common.BASE_INDEX_MANIFEST_FILENAME)); expectWriteNoChanges(); }); - it('failure with older OTA file that has identical in prev', async () => { + it("failure with older OTA file that has identical in prev", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); setManifest(common.PREV_INDEX_MANIFEST_FILENAME, [IMAGE_V13_1_METAS]); const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V13_1, IMAGE_V13_1); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining(`an equal or better match is already present in prev manifest`)); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); + expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining("an equal or better match is already present in prev manifest")); expectWriteNoChanges(); }); - it('failure with older OTA file that has newer in prev', async () => { + it("failure with older OTA file that has newer in prev", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [IMAGE_V14_1_METAS]); setManifest(common.PREV_INDEX_MANIFEST_FILENAME, [IMAGE_V13_1_METAS]); const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V12_1, IMAGE_V12_1); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); - expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining(`an equal or better match is already present in prev manifest`)); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); + expect(consoleLogSpy).toHaveBeenCalledWith(expect.stringContaining("an equal or better match is already present in prev manifest")); expectWriteNoChanges(); }); - it('success into base', async () => { + it("success into base", async () => { const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V14_1, IMAGE_V14_1); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); expect(readManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME); expect(readManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME); expect(addImageToBaseSpy).toHaveBeenCalledTimes(1); @@ -226,12 +230,12 @@ describe('Process Firmware Image', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V14_1, IMAGE_V14_1_METAS)]); }); - it('success into prev', async () => { + it("success into prev", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V14_1, IMAGE_V14_1_METAS)]); const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V13_1, IMAGE_V13_1); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); expect(readManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME); expect(readManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME); expect(addImageToBaseSpy).toHaveBeenCalledTimes(0); @@ -241,13 +245,13 @@ describe('Process Firmware Image', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V13_1, IMAGE_V13_1_METAS)]); }); - it('success with newer than current without existing prev', async () => { + it("success with newer than current without existing prev", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V13_1, IMAGE_V13_1_METAS)]); useImage(IMAGE_V13_1, BASE_IMAGES_TEST_DIR_PATH); const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V14_1, IMAGE_V14_1); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); expect(readManifestSpy).toHaveBeenCalledTimes(2); expect(addImageToBaseSpy).toHaveBeenCalledTimes(1); expect(addImageToPrevSpy).toHaveBeenCalledTimes(0); @@ -256,7 +260,7 @@ describe('Process Firmware Image', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V13_1, IMAGE_V13_1_METAS)]); }); - it('success with newer than current with existing prev', async () => { + it("success with newer than current with existing prev", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V13_1, IMAGE_V13_1_METAS)]); setManifest(common.PREV_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V12_1, IMAGE_V12_1_METAS)]); useImage(IMAGE_V13_1, BASE_IMAGES_TEST_DIR_PATH); @@ -264,7 +268,7 @@ describe('Process Firmware Image', () => { const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V14_1, IMAGE_V14_1); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); expect(readManifestSpy).toHaveBeenCalledTimes(2); expect(addImageToBaseSpy).toHaveBeenCalledTimes(1); expect(addImageToPrevSpy).toHaveBeenCalledTimes(0); @@ -273,7 +277,7 @@ describe('Process Firmware Image', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V13_1, IMAGE_V13_1_METAS)]); }); - it('success with older that is newer than prev', async () => { + it("success with older that is newer than prev", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V14_1, IMAGE_V14_1_METAS)]); setManifest(common.PREV_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V12_1, IMAGE_V12_1_METAS)]); useImage(IMAGE_V14_1, BASE_IMAGES_TEST_DIR_PATH); @@ -281,7 +285,7 @@ describe('Process Firmware Image', () => { const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V13_1, IMAGE_V13_1); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); expect(readManifestSpy).toHaveBeenCalledTimes(2); expect(addImageToBaseSpy).toHaveBeenCalledTimes(0); expect(addImageToPrevSpy).toHaveBeenCalledTimes(1); @@ -290,13 +294,13 @@ describe('Process Firmware Image', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V13_1, IMAGE_V13_1_METAS)]); }); - it('success with newer with missing file', async () => { + it("success with newer with missing file", async () => { setManifest(common.BASE_INDEX_MANIFEST_FILENAME, [withOriginalUrl(IMAGE_V13_1, IMAGE_V13_1_METAS)]); // useImage(IMAGE_V13_1, BASE_IMAGES_TEST_DIR_PATH); const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V14_1, IMAGE_V14_1); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); expect(readManifestSpy).toHaveBeenCalledTimes(2); expect(addImageToBaseSpy).toHaveBeenCalledTimes(1); expect(addImageToPrevSpy).toHaveBeenCalledTimes(0); @@ -305,34 +309,34 @@ describe('Process Firmware Image', () => { expect(writeManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME, []); }); - it('success with extra metas', async () => { - const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V14_1, IMAGE_V14_1, {manufacturerName: ['lixee']}); + it("success with extra metas", async () => { + const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V14_1, IMAGE_V14_1, {manufacturerName: ["lixee"]}); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); expect(readManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME); expect(readManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME); expect(addImageToBaseSpy).toHaveBeenCalledTimes(1); expect(addImageToPrevSpy).toHaveBeenCalledTimes(0); expect(writeManifestSpy).toHaveBeenCalledTimes(2); expect(writeManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME, [ - withOriginalUrl(IMAGE_V14_1, withExtraMetas(IMAGE_V14_1_METAS, {manufacturerName: ['lixee']})), + withOriginalUrl(IMAGE_V14_1, withExtraMetas(IMAGE_V14_1_METAS, {manufacturerName: ["lixee"]})), ]); }); - it('success with all extra metas', async () => { + it("success with all extra metas", async () => { const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_V14_1, IMAGE_V14_1, { originalUrl: `https://example.com/${IMAGE_V14_1}`, force: false, hardwareVersionMax: 2, hardwareVersionMin: 1, - manufacturerName: ['lixee'], + manufacturerName: ["lixee"], maxFileVersion: 5, minFileVersion: 3, - modelId: 'bogus', - releaseNotes: 'bugfixes', + modelId: "bogus", + releaseNotes: "bugfixes", }); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); expect(readManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME); expect(readManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME); expect(addImageToBaseSpy).toHaveBeenCalledTimes(1); @@ -345,24 +349,24 @@ describe('Process Firmware Image', () => { force: false, hardwareVersionMax: 2, hardwareVersionMin: 1, - manufacturerName: ['lixee'], + manufacturerName: ["lixee"], maxFileVersion: 5, minFileVersion: 3, - modelId: 'bogus', - releaseNotes: 'bugfixes', + modelId: "bogus", + releaseNotes: "bugfixes", }), ), ]); }); - it('success with tar', async () => { + it("success with tar", async () => { if (!existsSync(common.TMP_DIR)) { mkdirSync(common.TMP_DIR, {recursive: true}); } - const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_TAR, IMAGE_TAR, {}, true, (f) => f.endsWith('.ota')); + const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_TAR, IMAGE_TAR, {}, true, (f) => f.endsWith(".ota")); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.SUCCESS); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.Success); expect(readManifestSpy).toHaveBeenCalledWith(common.BASE_INDEX_MANIFEST_FILENAME); expect(readManifestSpy).toHaveBeenCalledWith(common.PREV_INDEX_MANIFEST_FILENAME); expect(addImageToBaseSpy).toHaveBeenCalledTimes(1); @@ -373,28 +377,28 @@ describe('Process Firmware Image', () => { rmSync(common.TMP_DIR, {recursive: true, force: true}); }); - it('failure with invalid tar', async () => { + it("failure with invalid tar", async () => { if (!existsSync(common.TMP_DIR)) { mkdirSync(common.TMP_DIR, {recursive: true}); } - const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_INVALID, IMAGE_INVALID, {}, true, (f) => f.endsWith('.ota')); + const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_INVALID, IMAGE_INVALID, {}, true, (f) => f.endsWith(".ota")); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.TAR_NO_IMAGE); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.TarNoImage); expectNoChanges(true); rmSync(common.TMP_DIR, {recursive: true, force: true}); }); - it('failure with extract tar (missing dir)', async () => { + it("failure with extract tar (missing dir)", async () => { // if (!existsSync(common.TMP_DIR)) { // mkdirSync(common.TMP_DIR, {recursive: true}); // } - const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_TAR, IMAGE_TAR, {}, true, (f) => f.endsWith('.ota')); + const status = await processFirmwareImage(IMAGES_TEST_DIR, IMAGE_TAR, IMAGE_TAR, {}, true, (f) => f.endsWith(".ota")); - expect(status).toStrictEqual(ProcessFirmwareImageStatus.TAR_NO_IMAGE); - expect(consoleErrorSpy).toHaveBeenCalledWith(expect.objectContaining({syscall: 'chdir', code: 'ENOENT'})); + expect(status).toStrictEqual(ProcessFirmwareImageStatus.TarNoImage); + expect(consoleErrorSpy).toHaveBeenCalledWith(expect.objectContaining({syscall: "chdir", code: "ENOENT"})); expectNoChanges(false); rmSync(common.TMP_DIR, {recursive: true, force: true}); diff --git a/tests/tsconfig.json b/tests/tsconfig.json index c0ec8c5..cb13697 100644 --- a/tests/tsconfig.json +++ b/tests/tsconfig.json @@ -1,10 +1,9 @@ { "extends": "../tsconfig", - "include": ["./**/*", "jest.config.ts"], + "include": ["./**/*", "vitest.config.mts"], "compilerOptions": { - "types": ["jest"], "rootDir": "..", "noEmit": true }, - "references": [{"path": ".."}] + "references": [{ "path": ".." }] } diff --git a/tests/vitest.config.mts b/tests/vitest.config.mts new file mode 100644 index 0000000..c0febdd --- /dev/null +++ b/tests/vitest.config.mts @@ -0,0 +1,32 @@ +import {defineConfig} from "vitest/config"; + +export default defineConfig({ + test: { + onConsoleLog() { + return true; + }, + coverage: { + enabled: false, + provider: "v8", + include: [ + "src/ghw_check_ota_pr.ts", + "src/ghw_get_changed_ota_files.ts", + "src/ghw_process_ota_files.ts", + "src/process_firmware_image.ts", + "src/ghw_reprocess_all_images.ts", + ], + extension: [".ts"], + // exclude: [], + clean: true, + cleanOnRerun: true, + reportsDirectory: "coverage", + reporter: ["text", "html"], + reportOnFailure: false, + thresholds: { + 100: true, + }, + }, + clearMocks: true, + fileParallelism: false, + }, +}); diff --git a/tsconfig.json b/tsconfig.json index 2c7e760..7c18c23 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,8 +14,5 @@ "composite": true, "checkJs": true }, - "include": ["./src/**/*"], - "ts-node": { - "esm": true - } + "include": ["./src/**/*"] }