diff --git a/jest.config.ts b/jest.config.ts deleted file mode 100644 index 8f7591bd..00000000 --- a/jest.config.ts +++ /dev/null @@ -1,73 +0,0 @@ -import type { Config } from 'jest' - -const config: Config = { - projects: [ - // Server-side tests (actions, API routes, utils) - { - displayName: 'server', - preset: 'ts-jest', - testEnvironment: 'node', - // Don't crawl the standalone build output — its package.json shares the - // app's name and triggers a Haste module naming collision warning. - modulePathIgnorePatterns: ['/.next/'], - moduleNameMapper: { - '^@/(.*)$': '/src/$1', - }, - testMatch: [ - '/src/**/__tests__/**/*.test.ts', - '/src/**/__tests__/**/*.spec.ts', - ], - // jose v6, @fleet/ai-forms, bip-kit ship ESM or TS entry — transform through ts-jest - // ai-kit is ESM-only ("type": "module", no require condition), like - // every other entry here. Jest runs CJS, so it must be transformed - // rather than required. - transformIgnorePatterns: ['node_modules/(?!(jose|@fleet/ai-forms|bip-kit|ai-kit))'], - transform: { - '^.+\\.tsx?$': 'ts-jest', - '^.+\\.js$': 'ts-jest', - }, - }, - // Component tests (React, jsdom) - { - displayName: 'components', - preset: 'ts-jest', - testEnvironment: 'jsdom', - modulePathIgnorePatterns: ['/.next/'], - moduleNameMapper: { - '^@/(.*)$': '/src/$1', - }, - testMatch: [ - '/src/**/__tests__/**/*.test.tsx', - '/src/**/__tests__/**/*.spec.tsx', - ], - setupFilesAfterEnv: ['/jest.setup.components.ts'], - // ai-kit is ESM-only ("type": "module", no require condition), like - // every other entry here. Jest runs CJS, so it must be transformed - // rather than required. - transformIgnorePatterns: ['node_modules/(?!(jose|@fleet/ai-forms|bip-kit|ai-kit))'], - transform: { - '^.+\\.tsx?$': ['ts-jest', { tsconfig: { jsx: 'react-jsx' } }], - '^.+\\.js$': ['ts-jest', { tsconfig: { allowJs: true, jsx: 'react-jsx' } }], - }, - }, - ], - collectCoverageFrom: [ - 'src/lib/**/*.ts', - 'src/app/api/**/*.ts', - 'src/components/**/*.tsx', - '!src/**/*.d.ts', - '!src/**/types.ts', - '!src/lib/db.ts', - '!src/lib/logger.ts', - ], - coverageThreshold: { - global: { - branches: 20, - functions: 10, - lines: 20, - statements: 20, - }, - }, -} - -export default config diff --git a/package-lock.json b/package-lock.json index 3d3c91c8..9b6fdf54 100644 --- a/package-lock.json +++ b/package-lock.json @@ -32,23 +32,22 @@ "@testing-library/jest-dom": "^7.0.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.6", - "@types/jest": "^30.0.0", "@types/node": "^20.14.10", "@types/papaparse": "^5.5.2", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.4", "autoprefixer": "^10.5.4", "eslint": "^8.57.0", "eslint-config-next": "^14.2.5", - "jest": "^29.7.0", - "jest-environment-jsdom": "^30.4.1", + "jsdom": "^25.0.1", "postcss": "^8.5.26", "prettier": "3.9.6", "prisma": "^5.17.0", - "ts-jest": "^29.4.12", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", - "typescript": "^5.5.3" + "typescript": "^5.5.3", + "vitest": "^4.1.11" }, "engines": { "node": ">=20" @@ -293,9 +292,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", "dev": true, "license": "MIT", "engines": { @@ -357,221 +356,14 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz", - "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -580,14 +372,14 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.28.6.tgz", - "integrity": "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==", + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" + "@babel/helper-plugin-utils": "^7.29.7" }, "engines": { "node": ">=6.9.0" @@ -651,13 +443,6 @@ "node": ">=6.9.0" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "license": "MIT" - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -831,969 +616,688 @@ "tslib": "^2.4.0" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + "node": ">=18" } }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "node_modules/@esbuild/android-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=18" } }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "node_modules/@esbuild/android-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18" } }, - "node_modules/@fleet/ai-forms": { - "version": "0.1.0", - "resolved": "git+ssh://git@github.com/bitbaum/ai-forms.git#68087895ab9d46d73d03b91ebf5e648b969ebd76", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "peerDependencies": { - "react": ">=18" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - } + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@esbuild/darwin-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=10.10.0" + "node": ">=18" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "node": ">=18" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "BSD-3-Clause" + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "node_modules/@esbuild/linux-arm": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", + "cpu": [ + "arm" + ], "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" + "node": ">=18" } }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" + "node": ">=18" } }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", + "cpu": [ + "loong64" + ], "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", + "cpu": [ + "mips64el" + ], "dev": true, "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "node_modules/@esbuild/linux-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=8" + "node": ">=18" } }, - "node_modules/@jest/console": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", - "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/@jest/core": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", - "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "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": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "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.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, + "optional": true, + "os": [ + "openharmony" + ], "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 - } + "node": ">=18" } }, - "node_modules/@jest/diff-sequences": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", - "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/@jest/environment-jsdom-abstract/-/environment-jsdom-abstract-30.4.1.tgz", - "integrity": "sha512-dSlKrqug3siYNHVnjwIldShY12wAH3spwRltO/+8VOjg0X+xEq7vOs3DbBs4LRKsu7OH+NUb9kuZUNBF9Ho3TA==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/environment": "30.4.1", - "@jest/fake-timers": "30.4.1", - "@jest/types": "30.4.1", - "@types/jsdom": "^21.1.7", - "@types/node": "*", - "jest-mock": "30.4.1", - "jest-util": "30.4.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "canvas": "^3.0.0", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/environment": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.4.1.tgz", - "integrity": "sha512-AK9yNRqgKxiabqMoe4oW+3/TSSeV8vkdC7BGaxZdU0AFXfOpofTLqdru2GXKZghP3sdgwE9XXpnVwfZ8JnFV4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "30.4.1", - "@jest/types": "30.4.1", - "@types/node": "*", - "jest-mock": "30.4.1" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/fake-timers": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.4.1.tgz", - "integrity": "sha512-iW5umdmfPeWzehrVhugFQZqCchSCud5S1l2YT0O9ZhjRR0ExclANDZkiSBwzqtnlOn0J1JXvO+HZ6rkuyOVOgQ==", + "node_modules/@esbuild/win32-x64": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "30.4.1", - "@sinonjs/fake-timers": "^15.4.0", - "@types/node": "*", - "jest-message-util": "30.4.1", - "jest-mock": "30.4.1", - "jest-util": "30.4.1" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=18" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/pattern": { - "version": "30.4.0", - "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.4.0.tgz", - "integrity": "sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "jest-regex-util": "30.4.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/schemas": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz", - "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.34.0" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@jest/types": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.4.1.tgz", - "integrity": "sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==", + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/pattern": "30.4.0", - "@jest/schemas": "30.4.1", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@sinclair/typebox": { - "version": "0.34.52", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.52.tgz", - "integrity": "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/@sinonjs/fake-timers": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.4.0.tgz", - "integrity": "sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" - } - }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://opencollective.com/eslint" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/ci-info": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", - "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "license": "MIT", "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-message-util": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.4.1.tgz", - "integrity": "sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==", - "dev": true, + "node_modules/@fleet/ai-forms": { + "version": "0.1.0", + "resolved": "git+ssh://git@github.com/bitbaum/ai-forms.git#68087895ab9d46d73d03b91ebf5e648b969ebd76", "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.4.1", - "@types/stack-utils": "^2.0.3", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "jest-util": "30.4.1", - "picomatch": "^4.0.3", - "pretty-format": "30.4.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" + "peerDependencies": { + "react": ">=18" }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependenciesMeta": { + "react": { + "optional": true + } } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-mock": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.4.1.tgz", - "integrity": "sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@jest/types": "30.4.1", - "@types/node": "*", - "jest-util": "30.4.1" + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=10.10.0" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-regex-util": { - "version": "30.4.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.4.0.tgz", - "integrity": "sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/jest-util": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.4.1.tgz", - "integrity": "sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==", + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@jest/types": "30.4.1", - "@types/node": "*", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.3" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=12" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/picomatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", - "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "dev": true, "license": "MIT", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@jest/environment-jsdom-abstract/node_modules/pretty-format": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz", - "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "30.4.1", - "ansi-styles": "^5.2.0", - "react-is-18": "npm:react-is@^18.3.1", - "react-is-19": "npm:react-is@^19.2.5" + "ansi-regex": "^6.0.1" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "expect": "^29.7.0", - "jest-snapshot": "^29.7.0" + "node": ">=12" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@jest/expect-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", - "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", - "dev": true, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jest/fake-timers": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", - "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", - "dev": true, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, - "node_modules/@jest/get-type": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.1.0.tgz", - "integrity": "sha512-eMbZE2hUnx1WV0pmURZY9XoXPkUYjpc55mb0CrhtdWLtzMQPFvu/rZkTLZFTsdaVQa+Tr4eWAteqcUzoawq/uA==", - "dev": true, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "license": "MIT", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=6.0.0" } }, - "node_modules/@jest/globals": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", - "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", - "dev": true, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", "license": "MIT", + "peer": true, "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/types": "^29.6.3", - "jest-mock": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, - "node_modules/@jest/pattern": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", - "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", - "dev": true, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { - "@types/node": "*", - "jest-regex-util": "30.0.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@jest/pattern/node_modules/jest-regex-util": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", - "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", "dev": true, "license": "MIT", - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" } }, - "node_modules/@jest/reporters": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", - "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", - "dev": true, - "license": "MIT", - "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.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "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 - } - } - }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.27.8" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/source-map": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", - "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.18", - "callsites": "^3.0.0", - "graceful-fs": "^4.2.9" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", - "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", - "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/test-result": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", - "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "babel-plugin-istanbul": "^6.1.1", - "chalk": "^4.0.0", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "micromatch": "^4.0.4", - "pirates": "^4.0.4", - "slash": "^3.0.0", - "write-file-atomic": "^4.0.2" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jest/types": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", - "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" - } - }, - "node_modules/@next/env": { - "version": "14.2.35", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", - "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", - "license": "MIT" - }, - "node_modules/@next/eslint-plugin-next": { - "version": "14.2.35", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.35.tgz", - "integrity": "sha512-Jw9A3ICz2183qSsqwi7fgq4SBPiNfmOLmTPXKvlnzstUwyvBrtySiY+8RXJweNAs9KThb1+bYhZh9XWcNOr2zQ==", + "node_modules/@next/env": { + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.35.tgz", + "integrity": "sha512-DuhvCtj4t9Gwrx80dmz2F4t/zKQ4ktN8WrMwOuVzkJfBilwAwGr6v16M5eI8yCuZ63H9TTuEU09Iu2HqkzFPVQ==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.2.35", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.35.tgz", + "integrity": "sha512-Jw9A3ICz2183qSsqwi7fgq4SBPiNfmOLmTPXKvlnzstUwyvBrtySiY+8RXJweNAs9KThb1+bYhZh9XWcNOr2zQ==", "dev": true, "license": "MIT", "dependencies": { @@ -2197,6 +1701,13 @@ "@prisma/debug": "5.22.0" } }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.27", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", + "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/plugin-commonjs": { "version": "28.0.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.1.tgz", @@ -3189,33 +2700,13 @@ "webpack": ">=5.0.0" } }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", "dev": true, "license": "MIT" }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -3478,414 +2969,128 @@ "integrity": "sha512-9xlo6R2qDs5uixm0bcIqCeMCE6HiQsIyel9KQySStiyqNl2tnj2mP3DX1Nf56MD6KMenNNlBBsy3LJ7gUEQPXQ==", "license": "MIT" }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "license": "MIT" }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", - "dev": true, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "peer": true }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true, "license": "MIT" }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "dev": true, + "node_modules/@types/node": { + "version": "20.19.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", + "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", "license": "MIT", "dependencies": { - "@types/istanbul-lib-coverage": "*" + "undici-types": "~6.21.0" } }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "node_modules/@types/papaparse": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.5.2.tgz", + "integrity": "sha512-gFnFp/JMzLHCwRf7tQHrNnfhN4eYBVYYI897CGX4MY1tzY9l2aLkVyx2IlKZ/SAqDbB3I1AOZW5gTMGGsqWliA==", "dev": true, "license": "MIT", "dependencies": { - "@types/istanbul-lib-report": "*" + "@types/node": "*" } }, - "node_modules/@types/jest": { - "version": "30.0.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", - "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.27", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", + "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", "dev": true, "license": "MIT", "dependencies": { - "expect": "^30.0.0", - "pretty-format": "^30.0.0" + "@types/prop-types": "*", + "csstype": "^3.2.2" } }, - "node_modules/@types/jest/node_modules/@jest/expect-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.2.0.tgz", - "integrity": "sha512-1JnRfhqpD8HGpOmQp180Fo9Zt69zNtC+9lR+kT7NVL05tNXIi+QC8Csz7lfidMoVLPD3FnOtcmp0CEFnxExGEA==", + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/get-type": "30.1.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "peerDependencies": { + "@types/react": "^18.0.0" } }, - "node_modules/@types/jest/node_modules/@jest/schemas": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", - "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.1.tgz", + "integrity": "sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==", "dev": true, "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.34.0" + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/type-utils": "8.53.1", + "@typescript-eslint/utils": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.4.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.53.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@types/jest/node_modules/@jest/types": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.2.0.tgz", - "integrity": "sha512-H9xg1/sfVvyfU7o3zMfBEjQ1gcsdeTMgqHoYdN79tuLqfTtuu7WckRA1R5whDwOzxaZAeMKTYWqP+WCAi0CHsg==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/pattern": "30.0.1", - "@jest/schemas": "30.0.5", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" - }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@types/jest/node_modules/@sinclair/typebox": { - "version": "0.34.48", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.48.tgz", - "integrity": "sha512-kKJTNuK3AQOrgjjotVxMrCn1sUJwM76wMszfq1kdU4uYVJjvEWuFQ6HgvLt4Xz3fSmZlTOxJ/Ie13KnIcWQXFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/jest/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@types/jest/node_modules/ci-info": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", - "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@types/jest/node_modules/expect": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.2.0.tgz", - "integrity": "sha512-u/feCi0GPsI+988gU2FLcsHyAHTU0MX1Wg68NhAnN7z/+C5wqG+CY8J53N9ioe8RXgaoz0nBR/TYMf3AycUuPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/expect-utils": "30.2.0", - "@jest/get-type": "30.1.0", - "jest-matcher-utils": "30.2.0", - "jest-message-util": "30.2.0", - "jest-mock": "30.2.0", - "jest-util": "30.2.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@types/jest/node_modules/jest-diff": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.2.0.tgz", - "integrity": "sha512-dQHFo3Pt4/NLlG5z4PxZ/3yZTZ1C7s9hveiOj+GCN+uT109NC2QgsoVZsVOAvbJ3RgKkvyLGXZV9+piDpWbm6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/diff-sequences": "30.0.1", - "@jest/get-type": "30.1.0", - "chalk": "^4.1.2", - "pretty-format": "30.2.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@types/jest/node_modules/jest-matcher-utils": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.2.0.tgz", - "integrity": "sha512-dQ94Nq4dbzmUWkQ0ANAWS9tBRfqCrn0bV9AMYdOi/MHW726xn7eQmMeRTpX2ViC00bpNaWXq+7o4lIQ3AX13Hg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/get-type": "30.1.0", - "chalk": "^4.1.2", - "jest-diff": "30.2.0", - "pretty-format": "30.2.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@types/jest/node_modules/jest-message-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.2.0.tgz", - "integrity": "sha512-y4DKFLZ2y6DxTWD4cDe07RglV88ZiNEdlRfGtqahfbIjfsw1nMCPx49Uev4IA/hWn3sDKyAnSPwoYSsAEdcimw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.2.0", - "@types/stack-utils": "^2.0.3", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.2.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@types/jest/node_modules/jest-mock": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.2.0.tgz", - "integrity": "sha512-JNNNl2rj4b5ICpmAcq+WbLH83XswjPbjH4T7yvGzfAGCPh1rw+xVNbtk+FnRslvt9lkCcdn9i1oAoKUuFsOxRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "jest-util": "30.2.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@types/jest/node_modules/jest-util": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.2.0.tgz", - "integrity": "sha512-QKNsM0o3Xe6ISQU869e+DhG+4CK/48aHYdJZGlFQVTjnbvgpcKyxpzk29fGiO7i/J8VENZ+d2iGnSsvmuHywlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "30.2.0", - "@types/node": "*", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@types/jest/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@types/jest/node_modules/pretty-format": { - "version": "30.2.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.2.0.tgz", - "integrity": "sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@types/jsdom": { - "version": "21.1.7", - "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", - "integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/tough-cookie": "*", - "parse5": "^7.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "license": "MIT", - "peer": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "20.19.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", - "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/papaparse": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.5.2.tgz", - "integrity": "sha512-gFnFp/JMzLHCwRf7tQHrNnfhN4eYBVYYI897CGX4MY1tzY9l2aLkVyx2IlKZ/SAqDbB3I1AOZW5gTMGGsqWliA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.3.27", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", - "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", - "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/tough-cookie": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", - "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/yargs": { - "version": "17.0.35", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", - "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.53.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.1.tgz", - "integrity": "sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.53.1", - "@typescript-eslint/type-utils": "8.53.1", - "@typescript-eslint/utils": "8.53.1", - "@typescript-eslint/visitor-keys": "8.53.1", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.53.1", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { @@ -4394,46 +3599,190 @@ "win32" ] }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "node_modules/@vitejs/plugin-react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", + "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + "@babel/core": "^7.28.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.27", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "license": "MIT", - "peer": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "node_modules/@vitest/expect": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.11.tgz", + "integrity": "sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==", + "dev": true, "license": "MIT", - "peer": true + "dependencies": { + "@standard-schema/spec": "^1.1.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", + "chai": "^6.2.2", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "node_modules/@vitest/mocker": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.11.tgz", + "integrity": "sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@vitest/spy": "4.1.11", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/mocker/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.11.tgz", + "integrity": "sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.11.tgz", + "integrity": "sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "4.1.11", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.11.tgz", + "integrity": "sha512-pN7ikn1ON7h8ee4gIAp4AzyK+zBtJPzVbqOgu5LCEh4VaJVbPQcgYQYJIMGQPXVeJJq1fnfazis7a5pFNPahog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.11", + "@vitest/utils": "4.1.11", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.11.tgz", + "integrity": "sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.11.tgz", + "integrity": "sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.1.11", + "convert-source-map": "^2.0.0", + "tinyrainbow": "^3.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } @@ -4724,35 +4073,6 @@ "license": "MIT", "peer": true }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -4981,6 +4301,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/ast-types-flow": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", @@ -5007,6 +4337,13 @@ "node": ">= 0.4" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/autoprefixer": { "version": "10.5.4", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.4.tgz", @@ -5080,132 +4417,6 @@ "node": ">= 0.4" } }, - "node_modules/babel-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", - "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/transform": "^29.7.0", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.6.3", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "slash": "^3.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", - "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^5.0.4", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", - "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.12.3", - "@babel/parser": "^7.14.7", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", - "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", - "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/babel-preset-jest": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", - "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -5311,34 +4522,12 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/bs-logger": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", - "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-json-stable-stringify": "2.x" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/busboy": { "version": "1.6.0", @@ -5411,16 +4600,6 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -5450,6 +4629,16 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -5467,16 +4656,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -5523,137 +4702,54 @@ "node": ">=6.0" } }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", - "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", - "dev": true, - "license": "MIT" - }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=12" + "node": ">=7.0.0" } }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", - "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, "license": "MIT" }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "delayed-stream": "~1.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.8" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -5682,28 +4778,6 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "license": "MIT" }, - "node_modules/create-jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", - "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "prompts": "^2.0.1" - }, - "bin": { - "create-jest": "bin/create-jest.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -5902,21 +4976,6 @@ "dev": true, "license": "MIT" }, - "node_modules/dedent": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.1.tgz", - "integrity": "sha512-9JmrhGZpOlEgOLdQgSm0zxFaYoQon408V1v49aqTWuXENVlnCuY9JBZcXZiCsZQWDjTm5Qf/nIvAy77mXDAjEg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -5924,16 +4983,6 @@ "dev": true, "license": "MIT" }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -5970,6 +5019,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -5981,16 +5040,6 @@ "node": ">=6" } }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -6007,16 +5056,6 @@ "node": ">=0.3.1" } }, - "node_modules/diff-sequences": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", - "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -6084,19 +5123,6 @@ "integrity": "sha512-958V+Kbhtgz+SxXeEVKBjrlKRBIDAYvUJfwhjxMZ5S6ut9jAl7l9ZKBkBrvjyjZE36PabLUo2L8kEeV5O4vgJg==", "license": "ISC" }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -6131,16 +5157,6 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, "node_modules/es-abstract": { "version": "1.24.1", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz", @@ -6324,6 +5340,48 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -6784,20 +5842,6 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/esquery": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", @@ -6857,61 +5901,14 @@ "node": ">=0.8.x" } }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", - "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", "dev": true, - "license": "MIT", - "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" - }, + "license": "Apache-2.0", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=12.0.0" } }, "node_modules/fast-deep-equal": { @@ -6988,16 +5985,6 @@ "reusify": "^1.0.4" } }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" - } - }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -7094,6 +6081,23 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "5.3.4", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", @@ -7131,892 +6135,26 @@ }, "node_modules/function-bind": { "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-tsconfig": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", - "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "10.3.10", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", - "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.5", - "minimatch": "^9.0.1", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", - "path-scurry": "^1.10.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "license": "BSD-2-Clause", - "peer": true - }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "license": "ISC" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/handlebars": { - "version": "4.7.9", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", - "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "wordwrap": "^1.0.0" - }, - "bin": { - "handlebars": "bin/handlebars" - }, - "engines": { - "node": ">=0.4.7" - }, - "optionalDependencies": { - "uglify-js": "^3.1.4" - } - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-encoding": "^3.1.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/http-proxy-agent/node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-in-the-middle": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-3.3.3.tgz", - "integrity": "sha512-AiohS3H80sXO6owEltjGX+glb7qXaDhBoJb9XcQVH4UI207xu/bDLUcadVKp7Qe576reg9yr/PXZjV5qx8gfbA==", - "license": "Apache-2.0", - "dependencies": { - "cjs-module-lexer": "^2.2.0", - "es-module-lexer": "^2.2.0", - "module-details-from-path": "^1.0.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/import-in-the-middle/node_modules/cjs-module-lexer": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.1.tgz", - "integrity": "sha512-Ca8swihM+/4yKecYHY52kgJd300hi2lADU/a1RxNTRe+RJ9jvqQlESpbz9DnG9mowez8qwXHB8qYdIUw9e+F5Q==", - "license": "MIT" - }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "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.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bun-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", - "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.7.1" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "license": "MIT", - "engines": { - "node": ">=0.12.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "license": "MIT", "dependencies": { + "call-bind": "^1.0.8", "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -8025,43 +6163,52 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "license": "MIT", - "dependencies": { - "@types/estree": "*" + "engines": { + "node": ">=6.9.0" } }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -8070,27 +6217,30 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dev": true, "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -8099,91 +6249,112 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "resolve-pkg-maps": "^1.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">= 0.4" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "dev": true, - "license": "MIT", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10.13.0" } }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause", + "peer": true + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", + "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", "dev": true, "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.16" + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" }, "engines": { - "node": ">= 0.4" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -8192,16 +6363,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, "engines": { "node": ">= 0.4" }, @@ -8209,995 +6376,769 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, "license": "MIT" }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" + "es-define-property": "^1.0.0" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" + "dunder-proto": "^1.0.0" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "has-symbols": "^1.0.3" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/iterator.prototype": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", - "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", - "dev": true, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "get-proto": "^1.0.0", - "has-symbols": "^1.1.0", - "set-function-name": "^2.0.2" + "function-bind": "^1.1.2" }, "engines": { "node": ">= 0.4" } }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", "dev": true, - "license": "BlueOak-1.0.0", + "license": "MIT", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "whatwg-encoding": "^3.1.1" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "node": ">=18" } }, - "node_modules/jest": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", - "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "^29.7.0", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.7.0" - }, - "bin": { - "jest": "bin/jest.js" + "agent-base": "^7.1.0", + "debug": "^4.3.4" }, "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 - } + "node": ">= 14" } }, - "node_modules/jest-changed-files": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", - "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", "dev": true, "license": "MIT", - "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 14" } }, - "node_modules/jest-circus": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", - "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", - "dev": true, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.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.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 6" } }, - "node_modules/jest-cli": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", - "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/core": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "create-jest": "^29.7.0", - "exit": "^0.1.2", - "import-local": "^3.0.2", - "jest-config": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "yargs": "^17.3.1" - }, - "bin": { - "jest": "bin/jest.js" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "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 - } + "node": ">=0.10.0" } }, - "node_modules/jest-config": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", - "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-jest": "^29.7.0", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "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.4", - "parse-json": "^5.2.0", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, "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 - } + "node": ">= 4" } }, - "node_modules/jest-config/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" }, "engines": { - "node": "*" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-diff": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", - "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", - "dev": true, - "license": "MIT", + "node_modules/import-in-the-middle": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-3.3.3.tgz", + "integrity": "sha512-AiohS3H80sXO6owEltjGX+glb7qXaDhBoJb9XcQVH4UI207xu/bDLUcadVKp7Qe576reg9yr/PXZjV5qx8gfbA==", + "license": "Apache-2.0", "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "cjs-module-lexer": "^2.2.0", + "es-module-lexer": "^2.2.0", + "module-details-from-path": "^1.0.4" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=18" } }, - "node_modules/jest-docblock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", - "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "node_modules/import-in-the-middle/node_modules/cjs-module-lexer": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.2.1.tgz", + "integrity": "sha512-Ca8swihM+/4yKecYHY52kgJd300hi2lADU/a1RxNTRe+RJ9jvqQlESpbz9DnG9mowez8qwXHB8qYdIUw9e+F5Q==", + "license": "MIT" + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", - "dependencies": { - "detect-newline": "^3.0.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.8.19" } }, - "node_modules/jest-each": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", - "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "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.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/jest-environment-jsdom": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-30.4.1.tgz", - "integrity": "sha512-o3nfaN4zej7qgk2X0j8Jhq/S9nAVKs2xK3QeQxeHVvpkEPxaA1yxDGydR+iVI7zPy7Cp62Aq2h3Ja46QvfWHGA==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "30.4.1", - "@jest/environment-jsdom-abstract": "30.4.1", - "jsdom": "^26.1.0" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "canvas": "^3.0.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } + "node": ">= 0.4" } }, - "node_modules/jest-environment-jsdom/node_modules/@jest/environment": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.4.1.tgz", - "integrity": "sha512-AK9yNRqgKxiabqMoe4oW+3/TSSeV8vkdC7BGaxZdU0AFXfOpofTLqdru2GXKZghP3sdgwE9XXpnVwfZ8JnFV4w==", + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "license": "MIT", "dependencies": { - "@jest/fake-timers": "30.4.1", - "@jest/types": "30.4.1", - "@types/node": "*", - "jest-mock": "30.4.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-jsdom/node_modules/@jest/fake-timers": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.4.1.tgz", - "integrity": "sha512-iW5umdmfPeWzehrVhugFQZqCchSCud5S1l2YT0O9ZhjRR0ExclANDZkiSBwzqtnlOn0J1JXvO+HZ6rkuyOVOgQ==", + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.4.1", - "@sinonjs/fake-timers": "^15.4.0", - "@types/node": "*", - "jest-message-util": "30.4.1", - "jest-mock": "30.4.1", - "jest-util": "30.4.1" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-jsdom/node_modules/@jest/pattern": { - "version": "30.4.0", - "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.4.0.tgz", - "integrity": "sha512-RAWn3+f9u8BsHijKJ71uHcFp6vmyEt6VvoWXkl6hKF3qVIuWNmudVjg12DlBPGup/frIl5UcUlH5HfEuvHpEXg==", + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "jest-regex-util": "30.4.0" + "has-bigints": "^1.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-jsdom/node_modules/@jest/schemas": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.4.1.tgz", - "integrity": "sha512-i6b4qw5qnP8c5FEeBJg/uZQ4ddrkN6Ca8qISJh0pr7a5hfn3h3v5x60BEbOC7OYAGZNMs1LfFLwnW2CuK8F57Q==", - "dev": true, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "license": "MIT", "dependencies": { - "@sinclair/typebox": "^0.34.0" + "binary-extensions": "^2.0.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=8" } }, - "node_modules/jest-environment-jsdom/node_modules/@jest/types": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.4.1.tgz", - "integrity": "sha512-f1x/vJXIfjOlEmejYpbkbgw1gOqpPECwMvMEtBqe47j7H2Hg8h8w3o3ikhSXq3MI15kg+oQ0exWO0uCtTNJLoQ==", + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, "license": "MIT", "dependencies": { - "@jest/pattern": "30.4.0", - "@jest/schemas": "30.4.1", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-jsdom/node_modules/@sinclair/typebox": { - "version": "0.34.52", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.52.tgz", - "integrity": "sha512-XiMQh7qqVlxZzcVD+kkGMNGMzcTrDMLWI7S4x7z1MkCkbDPrekpZXEUK0eZqZFMuHQg2a2DZOcDIh9o5v3Gonw==", - "dev": true, - "license": "MIT" - }, - "node_modules/jest-environment-jsdom/node_modules/@sinonjs/fake-timers": { - "version": "15.4.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-15.4.0.tgz", - "integrity": "sha512-DsG+8/LscQIQg68J6Ef3dv10u6nVyetYn923s3/sus5eaGfTo1of5WMZSLf0UJc9KDuKPilPH0UDJCjvNbDNCA==", + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@sinonjs/commons": "^3.0.1" + "semver": "^7.7.1" } }, - "node_modules/jest-environment-jsdom/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-jsdom/node_modules/ci-info": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", - "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-jsdom/node_modules/jest-message-util": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.4.1.tgz", - "integrity": "sha512-kwCKIvq0MCW1HzLoGola9Te6JUdzgV0loyKJ3Qghrkz9i5/RRIHsL95BMQc2HBBhlBKC4j22K9p11TGHH8RBpQ==", + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.4.1", - "@types/stack-utils": "^2.0.3", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "jest-util": "30.4.1", - "picomatch": "^4.0.3", - "pretty-format": "30.4.1", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-jsdom/node_modules/jest-mock": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.4.1.tgz", - "integrity": "sha512-/i8SVb8/NSB7RfNi8gfqu8gxLV23KaL5EpAttyb9iz8qWRIqXRLflycz/32wXsYkOnaUlx8NAKnJYtpsmXUmfw==", + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.4.1", - "@types/node": "*", - "jest-util": "30.4.1" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-jsdom/node_modules/jest-regex-util": { - "version": "30.4.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.4.0.tgz", - "integrity": "sha512-mWlvLviKIgIQ8VCuM1xRdD0TWp3zlzionlmDBjuXVBs+VkmXq6FgW9T4Emr7oGz/Rk6feDCGyiugolcQEyp3mg==", - "dev": true, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "license": "MIT", "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-environment-jsdom/node_modules/jest-util": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.4.1.tgz", - "integrity": "sha512-vjQb1sACEiv13DKJMDToJpzVW0joCsIQrmbg0fi7CyOOt+g9jTuQl2A216pWRBYhOVt53XbL/2LbMKg1BECWOw==", + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "30.4.1", - "@types/node": "*", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.3" + "call-bound": "^1.0.3" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-jsdom/node_modules/picomatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", - "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "node": ">=8" } }, - "node_modules/jest-environment-jsdom/node_modules/pretty-format": { - "version": "30.4.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.4.1.tgz", - "integrity": "sha512-K6KiKMHTL4jjX4u3Kir2EW07nRfcqVTXIImx50wbjHQTcZPgg+gjVeNTIT3l3L1Rd4UefxfogquC9J37SoFyyw==", + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/schemas": "30.4.1", - "ansi-styles": "^5.2.0", - "react-is-18": "npm:react-is@^18.3.1", - "react-is-19": "npm:react-is@^19.2.5" + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-environment-node": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", - "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", - "dev": true, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-get-type": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", - "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true, "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-haste-map": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", - "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/graceful-fs": "^4.1.3", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.6.3", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "micromatch": "^4.0.4", - "walker": "^1.0.8" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-leak-detector": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", - "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", - "dev": true, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "license": "MIT", - "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.12.0" } }, - "node_modules/jest-matcher-utils": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", - "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-mock": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", - "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", "dev": true, + "license": "MIT" + }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "@types/estree": "*" } }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, - "peerDependencies": { - "jest-resolve": "*" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-regex-util": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", - "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true, "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", - "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" + "node": ">= 0.4" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-resolve-dependencies": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", - "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "license": "MIT", "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" + "call-bound": "^1.0.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "license": "MIT", "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": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "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" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "license": "MIT", - "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": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "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" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runtime/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { - "node": "*" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "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.5.3" + "which-typed-array": "^1.1.16" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-validate": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", - "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "leven": "^3.1.0", - "pretty-format": "^29.7.0" + "call-bound": "^1.0.3" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-watcher": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", - "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "license": "MIT", "dependencies": { - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "jest-util": "^29.7.0", - "string-length": "^4.0.1" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", "dev": true, "license": "MIT", "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "dependencies": { - "has-flag": "^4.0.0" + "@isaacs/cliui": "^8.0.2" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/jiti": { @@ -9238,30 +7179,31 @@ } }, "node_modules/jsdom": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", - "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", "dev": true, "license": "MIT", "dependencies": { - "cssstyle": "^4.2.1", + "cssstyle": "^4.1.0", "data-urls": "^5.0.0", - "decimal.js": "^10.5.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.6", + "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.16", - "parse5": "^7.2.1", - "rrweb-cssom": "^0.8.0", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^5.1.1", + "tough-cookie": "^5.0.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.1.1", + "whatwg-url": "^14.0.0", "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, @@ -9269,7 +7211,7 @@ "node": ">=18" }, "peerDependencies": { - "canvas": "^3.0.0" + "canvas": "^2.11.2" }, "peerDependenciesMeta": { "canvas": { @@ -9301,6 +7243,13 @@ "node": ">= 14" } }, + "node_modules/jsdom/node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "license": "MIT" + }, "node_modules/jsdom/node_modules/tr46": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", @@ -9357,13 +7306,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -9416,16 +7358,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/language-subtag-registry": { "version": "0.3.23", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", @@ -9446,16 +7378,6 @@ "node": ">=0.10" } }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -9517,13 +7439,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -9581,22 +7496,6 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -9604,16 +7503,6 @@ "dev": true, "license": "ISC" }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" - } - }, "node_modules/marked": { "version": "14.1.4", "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.4.tgz", @@ -9640,7 +7529,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/merge2": { "version": "1.4.1", @@ -9683,14 +7573,27 @@ "node": ">= 0.6" } }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, "engines": { - "node": ">=6" + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, "node_modules/min-indent": { @@ -9803,7 +7706,8 @@ "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/next": { "version": "14.2.35", @@ -9903,13 +7807,6 @@ } } }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true, - "license": "MIT" - }, "node_modules/node-releases": { "version": "2.0.53", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", @@ -9928,19 +7825,6 @@ "node": ">=0.10.0" } }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/nwsapi": { "version": "2.2.24", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.24.tgz", @@ -10079,6 +7963,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -10089,22 +7987,6 @@ "wrappy": "1" } }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -10171,16 +8053,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/papaparse": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.7.0.tgz", @@ -10195,28 +8067,9 @@ "license": "MIT", "dependencies": { "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + }, + "engines": { + "node": ">=6" } }, "node_modules/parse5": { @@ -10291,6 +8144,13 @@ "dev": true, "license": "ISC" }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -10327,75 +8187,6 @@ "node": ">= 6" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/playwright": { "version": "1.62.1", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", @@ -10634,34 +8425,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/prisma": { "version": "5.22.0", "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.22.0.tgz", @@ -10691,20 +8454,6 @@ "node": ">=0.4.0" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -10740,23 +8489,6 @@ "node": ">=6" } }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -10802,28 +8534,15 @@ "react": "^18.3.1" } }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, - "node_modules/react-is-18": { - "name": "react-is", - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, - "node_modules/react-is-19": { - "name": "react-is", - "version": "19.2.8", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.8.tgz", - "integrity": "sha512-s5un28nYxKJw5gvUHyW5PCC28CvBqLu9r3cWgzHT4Vo/5fqqkFcdRYsGcKf50WMPpjjFZS5d76fn3YCo2njKwQ==", + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, "node_modules/read-cache": { "version": "1.0.0", @@ -10904,16 +8623,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", @@ -10957,29 +8666,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -11000,16 +8686,6 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/resolve.exports": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", - "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/reusify": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", @@ -11441,6 +9117,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", @@ -11454,23 +9137,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "dev": true, - "license": "MIT" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -11489,24 +9155,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/stable-hash": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", @@ -11514,28 +9162,12 @@ "dev": true, "license": "MIT" }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, "node_modules/stacktrace-parser": { "version": "0.1.11", @@ -11558,6 +9190,13 @@ "node": ">=8" } }, + "node_modules/std-env": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", + "dev": true, + "license": "MIT" + }, "node_modules/stop-iteration-iterator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", @@ -11580,20 +9219,6 @@ "node": ">=10.0.0" } }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -11804,26 +9429,6 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/strip-indent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", @@ -12107,43 +9712,6 @@ "source-map": "^0.6.0" } }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -12172,6 +9740,23 @@ "node": ">=0.8" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -12217,6 +9802,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tinyrainbow": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz", + "integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tldts": { "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", @@ -12235,14 +9830,7 @@ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", "dev": true, - "license": "MIT" - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true, - "license": "BSD-3-Clause" + "license": "MIT" }, "node_modules/to-regex-range": { "version": "5.0.1", @@ -12294,72 +9882,6 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "license": "Apache-2.0" }, - "node_modules/ts-jest": { - "version": "29.4.12", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.12.tgz", - "integrity": "sha512-Ov6ClY53Fflh6BGAnY2DlTq1hYDrTycz2PVTXBWFW2CU+9zrEqAp9fWdGXl42EXO5RLSFAcAZ2JFKbP+zBTFfw==", - "dev": true, - "license": "MIT", - "dependencies": { - "bs-logger": "^0.2.6", - "fast-json-stable-stringify": "^2.1.0", - "handlebars": "^4.7.9", - "json5": "^2.2.3", - "lodash.memoize": "^4.1.2", - "make-error": "^1.3.6", - "semver": "^7.8.5", - "type-fest": "^4.41.0", - "yargs-parser": "^21.1.1" - }, - "bin": { - "ts-jest": "cli.js" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.0.0-beta.0 <8", - "@jest/transform": "^29.0.0 || ^30.0.0", - "@jest/types": "^29.0.0 || ^30.0.0", - "babel-jest": "^29.0.0 || ^30.0.0", - "jest": "^29.0.0 || ^30.0.0", - "jest-util": "^29.0.0 || ^30.0.0", - "typescript": ">=4.3 <7" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "@jest/transform": { - "optional": true - }, - "@jest/types": { - "optional": true - }, - "babel-jest": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "jest-util": { - "optional": true - } - } - }, - "node_modules/ts-jest/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ts-node": { "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", @@ -12455,16 +9977,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", @@ -12570,20 +10082,6 @@ "node": ">=14.17" } }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "dev": true, - "license": "BSD-2-Clause", - "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/unbox-primitive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", @@ -12697,19 +10195,213 @@ "dev": true, "license": "MIT" }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "node_modules/vite": { + "version": "7.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.6.tgz", + "integrity": "sha512-4XP60spRGjSZFf1qYH+dJIkK2znL3zQfl9KkOV9MkkRR/3Dls0dxaBsQPTloEc5BLXWPL9vsOxopxyKoMmDueg==", "dev": true, - "license": "ISC", + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0 || ^0.28.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "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 + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.11.tgz", + "integrity": "sha512-fhACrNXUidIbGSBr5FlbuBkO7VWC1ZyLl0DO4CU2DrQoAPxX84Ysxs+HeGQpii5lZWV1Q4gBZTTu49mF+A6Edw==", + "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" + "@vitest/expect": "4.1.11", + "@vitest/mocker": "4.1.11", + "@vitest/pretty-format": "4.1.11", + "@vitest/runner": "4.1.11", + "@vitest/snapshot": "4.1.11", + "@vitest/spy": "4.1.11", + "@vitest/utils": "4.1.11", + "es-module-lexer": "^2.0.0", + "expect-type": "^1.3.0", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^4.0.0-rc.1", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.1.0", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.1.11", + "@vitest/browser-preview": "4.1.11", + "@vitest/browser-webdriverio": "4.1.11", + "@vitest/coverage-istanbul": "4.1.11", + "@vitest/coverage-v8": "4.1.11", + "@vitest/ui": "4.1.11", + "happy-dom": "*", + "jsdom": "*", + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "vite": { + "optional": false + } + } + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10.12.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/w3c-xmlserializer": { @@ -12725,16 +10417,6 @@ "node": ">=18" } }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" - } - }, "node_modules/watchpack": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", @@ -12974,6 +10656,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", @@ -12984,13 +10683,6 @@ "node": ">=0.10.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true, - "license": "MIT" - }, "node_modules/wrap-ansi": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", @@ -13099,27 +10791,6 @@ "dev": true, "license": "ISC" }, - "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/write-file-atomic/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, "node_modules/ws": { "version": "8.21.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz", @@ -13159,73 +10830,12 @@ "dev": true, "license": "MIT" }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "license": "ISC" }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index e446085b..91212710 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "lint": "next lint", "typecheck": "tsc --noEmit", "verify": "npm run format:check && npm run lint && npm run typecheck && npm run test", - "test": "jest", + "test": "vitest run", "test:e2e": "playwright test", "prisma:generate": "prisma generate", "prisma:migrate": "prisma migrate deploy", @@ -53,22 +53,21 @@ "@testing-library/jest-dom": "^7.0.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.6", - "@types/jest": "^30.0.0", "@types/node": "^20.14.10", "@types/papaparse": "^5.5.2", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.4", "autoprefixer": "^10.5.4", "eslint": "^8.57.0", "eslint-config-next": "^14.2.5", - "jest": "^29.7.0", - "jest-environment-jsdom": "^30.4.1", + "jsdom": "^25.0.1", "postcss": "^8.5.26", "prettier": "3.9.6", "prisma": "^5.17.0", - "ts-jest": "^29.4.12", "ts-node": "^10.9.2", "tsconfig-paths": "^4.2.0", - "typescript": "^5.5.3" + "typescript": "^5.5.3", + "vitest": "^4.1.11" } } diff --git a/src/app/(admin)/transfer-requests/__tests__/TransferActions.test.tsx b/src/app/(admin)/transfer-requests/__tests__/TransferActions.test.tsx index 4f344c80..c2892e09 100644 --- a/src/app/(admin)/transfer-requests/__tests__/TransferActions.test.tsx +++ b/src/app/(admin)/transfer-requests/__tests__/TransferActions.test.tsx @@ -1,22 +1,22 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, waitFor, act } from '@testing-library/react' import { TransferActions } from '../TransferActions' // --- Mocks --- -const mockApprove = jest.fn() -const mockDeny = jest.fn() -jest.mock('@/lib/actions/transfers', () => ({ +const mockApprove = vi.hoisted(() => vi.fn()) +const mockDeny = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/actions/transfers', () => ({ approveTransferRequest: (...args: unknown[]) => mockApprove(...args), denyTransferRequest: (...args: unknown[]) => mockDeny(...args), })) -const mockRefresh = jest.fn() -jest.mock('next/navigation', () => ({ +const mockRefresh = vi.hoisted(() => vi.fn()) +vi.mock('next/navigation', () => ({ useRouter: () => ({ refresh: mockRefresh }), })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ TRANSFER_ACTION_LABELS: { notesPlaceholder: 'Notiz (optional)', approve: 'Genehmigen', @@ -41,7 +41,7 @@ function mockError(message = 'Fehler aufgetreten') { // --- Tests --- describe('TransferActions', () => { - afterEach(() => jest.clearAllMocks()) + afterEach(() => vi.clearAllMocks()) // ── Rendering ─────────────────────────────────────────────────────────── diff --git a/src/app/api/__tests__/staff-chores.test.ts b/src/app/api/__tests__/staff-chores.test.ts index 9f5355bb..02155b12 100644 --- a/src/app/api/__tests__/staff-chores.test.ts +++ b/src/app/api/__tests__/staff-chores.test.ts @@ -1,24 +1,24 @@ import { NextRequest } from 'next/server' import { POST } from '@/app/api/chores/route' -const mockRequireStaffAuth = jest.fn() -jest.mock('@/lib/auth', () => ({ +const mockRequireStaffAuth = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth', () => ({ requireStaffAuth: () => mockRequireStaffAuth(), })) -const mockUnitFindUnique = jest.fn() -const mockTaskCreate = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockUnitFindUnique = vi.hoisted(() => vi.fn()) +const mockTaskCreate = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { housingUnit: { findUnique: (...args: unknown[]) => mockUnitFindUnique(...args) }, householdTask: { create: (...args: unknown[]) => mockTaskCreate(...args) }, }, })) -const mockLogAudit = jest.fn().mockResolvedValue(undefined) -jest.mock('@/lib/audit', () => ({ logAudit: (...args: unknown[]) => mockLogAudit(...args) })) -jest.mock('@/lib/logger', () => ({ - logger: { errorWithCause: jest.fn(), error: jest.fn(), info: jest.fn() }, +const mockLogAudit = vi.hoisted(() => vi.fn().mockResolvedValue(undefined)) +vi.mock('@/lib/audit', () => ({ logAudit: (...args: unknown[]) => mockLogAudit(...args) })) +vi.mock('@/lib/logger', () => ({ + logger: { errorWithCause: vi.fn(), error: vi.fn(), info: vi.fn() }, })) /** @@ -43,7 +43,7 @@ const VALID = { } beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() mockRequireStaffAuth.mockResolvedValue({ id: 'staff-1', name: 'M. Keller', role: 'ADMIN' }) mockUnitFindUnique.mockResolvedValue({ id: 'unit-1', code: 'DEMO-U05' }) mockTaskCreate.mockImplementation((args: { data: unknown }) => diff --git a/src/app/api/ai/chat/__tests__/chat.test.ts b/src/app/api/ai/chat/__tests__/chat.test.ts index e25f3ea0..9105c8f0 100644 --- a/src/app/api/ai/chat/__tests__/chat.test.ts +++ b/src/app/api/ai/chat/__tests__/chat.test.ts @@ -4,18 +4,18 @@ * Covers: auth guard, API key guard, schema validation, and SSE streaming. */ -const mockGetCurrentUser = jest.fn() -jest.mock('@/lib/auth', () => ({ +const mockGetCurrentUser = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth', () => ({ getCurrentUser: (...args: unknown[]) => mockGetCurrentUser(...args), })) -const mockHasAIProvider = jest.fn() -jest.mock('@/lib/ai/provider', () => ({ +const mockHasAIProvider = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/ai/provider', () => ({ hasAIProvider: (...args: unknown[]) => mockHasAIProvider(...args), })) -const mockRunStaffChat = jest.fn() -jest.mock('@/lib/ai/staff-chat', () => ({ +const mockRunStaffChat = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/ai/staff-chat', () => ({ runStaffChat: (...args: unknown[]) => mockRunStaffChat(...args), })) @@ -56,7 +56,7 @@ async function readStream(res: Response): Promise { describe('POST /api/ai/chat', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() mockHasAIProvider.mockReturnValue(false) }) diff --git a/src/app/api/auth/__tests__/account-routes.test.ts b/src/app/api/auth/__tests__/account-routes.test.ts index 824b0b73..f6db2546 100644 --- a/src/app/api/auth/__tests__/account-routes.test.ts +++ b/src/app/api/auth/__tests__/account-routes.test.ts @@ -7,12 +7,12 @@ import { NextRequest } from 'next/server' // --- Mocks --- -const mockRegisterAccount = jest.fn() -const mockLoginWithEmail = jest.fn() -const mockRequestPasswordReset = jest.fn() -const mockResetPassword = jest.fn() -const mockVerifyEmailToken = jest.fn() -jest.mock('@/lib/auth/account', () => ({ +const mockRegisterAccount = vi.hoisted(() => vi.fn()) +const mockLoginWithEmail = vi.hoisted(() => vi.fn()) +const mockRequestPasswordReset = vi.hoisted(() => vi.fn()) +const mockResetPassword = vi.hoisted(() => vi.fn()) +const mockVerifyEmailToken = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth/account', () => ({ registerAccount: (...args: unknown[]) => mockRegisterAccount(...args), loginWithEmail: (...args: unknown[]) => mockLoginWithEmail(...args), requestPasswordReset: (...args: unknown[]) => mockRequestPasswordReset(...args), @@ -20,35 +20,35 @@ jest.mock('@/lib/auth/account', () => ({ verifyEmailToken: (...args: unknown[]) => mockVerifyEmailToken(...args), })) -const mockSetSessionCookie = jest.fn() -const mockLoginByCode = jest.fn() -jest.mock('@/lib/auth', () => ({ +const mockSetSessionCookie = vi.hoisted(() => vi.fn()) +const mockLoginByCode = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth', () => ({ setSessionCookie: (...args: unknown[]) => mockSetSessionCookie(...args), loginByCode: (...args: unknown[]) => mockLoginByCode(...args), })) -const mockSetResidentCookie = jest.fn() -jest.mock('@/lib/portal-auth', () => ({ +const mockSetResidentCookie = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/portal-auth', () => ({ setResidentCookie: (...args: unknown[]) => mockSetResidentCookie(...args), })) -const mockConsumeRateLimit = jest.fn() -const mockCheckRateLimit = jest.fn() -jest.mock('@/lib/auth/rate-limit', () => ({ +const mockConsumeRateLimit = vi.hoisted(() => vi.fn()) +const mockCheckRateLimit = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth/rate-limit', () => ({ consumeRateLimit: (...args: unknown[]) => mockConsumeRateLimit(...args), checkRateLimit: (...args: unknown[]) => mockCheckRateLimit(...args), - recordLoginAttempt: jest.fn(), - clearLoginAttempts: jest.fn(), + recordLoginAttempt: vi.fn(), + clearLoginAttempts: vi.fn(), getClientIp: () => '10.0.0.1', })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) @@ -69,7 +69,7 @@ function jsonRequest(path: string, body: Record): NextRequest { } beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() mockConsumeRateLimit.mockReturnValue({ allowed: true }) mockCheckRateLimit.mockReturnValue({ allowed: true }) }) diff --git a/src/app/api/auth/__tests__/auth-routes.test.ts b/src/app/api/auth/__tests__/auth-routes.test.ts index 91315991..83aed2d4 100644 --- a/src/app/api/auth/__tests__/auth-routes.test.ts +++ b/src/app/api/auth/__tests__/auth-routes.test.ts @@ -10,26 +10,26 @@ import { ERROR_MESSAGES } from '@/lib/constants/error-messages' // --- Mocks --- -const mockClearSessionCookie = jest.fn() -const mockGetCurrentUser = jest.fn() -jest.mock('@/lib/auth', () => ({ +const mockClearSessionCookie = vi.hoisted(() => vi.fn()) +const mockGetCurrentUser = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth', () => ({ clearSessionCookie: (...args: unknown[]) => mockClearSessionCookie(...args), getCurrentUser: (...args: unknown[]) => mockGetCurrentUser(...args), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) -const mockUserFindUnique = jest.fn() -const mockUserCreate = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockUserFindUnique = vi.hoisted(() => vi.fn()) +const mockUserCreate = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { user: { findUnique: (...args: unknown[]) => mockUserFindUnique(...args), @@ -67,7 +67,7 @@ const ADMIN_USER = { describe('POST /api/auth/logout', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('calls clearSessionCookie(true) and returns success', async () => { @@ -105,7 +105,7 @@ describe('POST /api/auth/logout', () => { describe('GET /api/auth/session', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns current user when authenticated', async () => { @@ -162,7 +162,7 @@ describe('GET /api/auth/session', () => { describe('POST /api/auth/register (admin-only staff provisioning)', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() // Default: authenticated admin mockGetCurrentUser.mockResolvedValue(ADMIN_USER) }) diff --git a/src/app/api/auth/__tests__/demo.test.ts b/src/app/api/auth/__tests__/demo.test.ts index b394e414..ff50e048 100644 --- a/src/app/api/auth/__tests__/demo.test.ts +++ b/src/app/api/auth/__tests__/demo.test.ts @@ -12,16 +12,16 @@ import { NextRequest } from 'next/server' // --- Mocks --- -const mockLoginByCode = jest.fn() -const mockSetSessionCookie = jest.fn() -jest.mock('@/lib/auth', () => ({ +const mockLoginByCode = vi.hoisted(() => vi.fn()) +const mockSetSessionCookie = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth', () => ({ loginByCode: (...args: unknown[]) => mockLoginByCode(...args), setSessionCookie: (...args: unknown[]) => mockSetSessionCookie(...args), })) -const mockCheckRateLimit = jest.fn() -const mockRecordLoginAttempt = jest.fn() -jest.mock('@/lib/auth/rate-limit', () => ({ +const mockCheckRateLimit = vi.hoisted(() => vi.fn()) +const mockRecordLoginAttempt = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth/rate-limit', () => ({ getClientIp: (request: { headers: { get(name: string): string | null } }) => request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || request.headers.get('x-real-ip') || @@ -30,27 +30,27 @@ jest.mock('@/lib/auth/rate-limit', () => ({ recordLoginAttempt: (...args: unknown[]) => mockRecordLoginAttempt(...args), })) -const mockSetResidentCookie = jest.fn() -jest.mock('@/lib/portal-auth', () => ({ +const mockSetResidentCookie = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/portal-auth', () => ({ setResidentCookie: (...args: unknown[]) => mockSetResidentCookie(...args), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) // A door is offered only when its ACCOUNT exists, so the endpoint reads the // database. Config presence proves nothing now that codes are derived: it // would offer five buttons on an instance where the seed never ran. -const mockUserFindMany = jest.fn() -const mockResidentFindUnique = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockUserFindMany = vi.hoisted(() => vi.fn()) +const mockResidentFindUnique = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { user: { findMany: (...args: unknown[]) => mockUserFindMany(...args) }, resident: { findUnique: (...args: unknown[]) => mockResidentFindUnique(...args) }, @@ -86,7 +86,7 @@ describe('POST /api/auth/demo', () => { const originalEnv = { ...process.env } beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() process.env.DEMO_ACCESS_ENABLED = 'true' process.env.DEMO_STAFF_CODE = STAFF_CODE process.env.DEMO_RESIDENT_CODE = RESIDENT_CODE diff --git a/src/app/api/auth/__tests__/invite.test.ts b/src/app/api/auth/__tests__/invite.test.ts index a9f4d93b..63030ae6 100644 --- a/src/app/api/auth/__tests__/invite.test.ts +++ b/src/app/api/auth/__tests__/invite.test.ts @@ -10,14 +10,14 @@ import { ERROR_MESSAGES } from '@/lib/constants/error-messages' // --- Mocks --- -const mockGetCurrentUser = jest.fn() -jest.mock('@/lib/auth', () => ({ +const mockGetCurrentUser = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth', () => ({ getCurrentUser: (...args: unknown[]) => mockGetCurrentUser(...args), })) -const mockCheckRateLimit = jest.fn() -const mockRecordLoginAttempt = jest.fn() -jest.mock('@/lib/auth/rate-limit', () => ({ +const mockCheckRateLimit = vi.hoisted(() => vi.fn()) +const mockRecordLoginAttempt = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth/rate-limit', () => ({ getClientIp: (request: { headers: { get(name: string): string | null } }) => request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || request.headers.get('x-real-ip') || @@ -26,14 +26,14 @@ jest.mock('@/lib/auth/rate-limit', () => ({ recordLoginAttempt: (...args: unknown[]) => mockRecordLoginAttempt(...args), })) -jest.mock('@/lib/auth/code-generation', () => ({ - generateStaffCode: jest.fn(() => 'AOZ-GEN001'), +vi.mock('@/lib/auth/code-generation', () => ({ + generateStaffCode: vi.fn(() => 'AOZ-GEN001'), })) -const mockUserFindUnique = jest.fn() -const mockUserCreate = jest.fn() -const mockAccountFindUnique = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockUserFindUnique = vi.hoisted(() => vi.fn()) +const mockUserCreate = vi.hoisted(() => vi.fn()) +const mockAccountFindUnique = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { user: { findUnique: (...args: unknown[]) => mockUserFindUnique(...args), @@ -46,13 +46,13 @@ jest.mock('@/lib/db', () => ({ }, })) -const mockSendEmail = jest.fn() -jest.mock('@/lib/email/service', () => ({ +const mockSendEmail = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/email/service', () => ({ sendEmail: (...args: unknown[]) => mockSendEmail(...args), })) -jest.mock('@/lib/email/templates', () => ({ - staffInviteEmail: jest.fn(() => ({ +vi.mock('@/lib/email/templates', () => ({ + staffInviteEmail: vi.fn(() => ({ subject: 'Ihr AOZ Housing Zugangscode', html: '

Your code

', })), @@ -90,7 +90,7 @@ const ADMIN_USER = { describe('POST /api/auth/invite', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() mockCheckRateLimit.mockReturnValue({ allowed: true }) mockGetCurrentUser.mockResolvedValue(ADMIN_USER) mockUserFindUnique.mockResolvedValue(null) // code not taken diff --git a/src/app/api/auth/__tests__/login.test.ts b/src/app/api/auth/__tests__/login.test.ts index a152b23a..934d2744 100644 --- a/src/app/api/auth/__tests__/login.test.ts +++ b/src/app/api/auth/__tests__/login.test.ts @@ -9,17 +9,17 @@ import { NextRequest } from 'next/server' // --- Mocks --- -const mockLoginByCode = jest.fn() -const mockSetSessionCookie = jest.fn() -jest.mock('@/lib/auth', () => ({ +const mockLoginByCode = vi.hoisted(() => vi.fn()) +const mockSetSessionCookie = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth', () => ({ loginByCode: (...args: unknown[]) => mockLoginByCode(...args), setSessionCookie: (...args: unknown[]) => mockSetSessionCookie(...args), })) -const mockCheckRateLimit = jest.fn() -const mockRecordLoginAttempt = jest.fn() -const mockClearLoginAttempts = jest.fn() -jest.mock('@/lib/auth/rate-limit', () => ({ +const mockCheckRateLimit = vi.hoisted(() => vi.fn()) +const mockRecordLoginAttempt = vi.hoisted(() => vi.fn()) +const mockClearLoginAttempts = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth/rate-limit', () => ({ getClientIp: (request: { headers: { get(name: string): string | null } }) => request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() || request.headers.get('x-real-ip') || @@ -29,19 +29,19 @@ jest.mock('@/lib/auth/rate-limit', () => ({ clearLoginAttempts: (...args: unknown[]) => mockClearLoginAttempts(...args), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) -const mockCookieSet = jest.fn() -jest.mock('next/headers', () => ({ - cookies: jest.fn().mockResolvedValue({ +const mockCookieSet = vi.hoisted(() => vi.fn()) +vi.mock('next/headers', () => ({ + cookies: vi.fn().mockResolvedValue({ set: (...args: unknown[]) => mockCookieSet(...args), }), })) @@ -78,7 +78,7 @@ const STAFF_USER = { describe('POST /api/auth/login', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() // Default: rate limit allows mockCheckRateLimit.mockReturnValue({ allowed: true }) }) diff --git a/src/app/api/auth/__tests__/provisioning-least-privilege.test.ts b/src/app/api/auth/__tests__/provisioning-least-privilege.test.ts index a1590006..9135af20 100644 --- a/src/app/api/auth/__tests__/provisioning-least-privilege.test.ts +++ b/src/app/api/auth/__tests__/provisioning-least-privilege.test.ts @@ -18,18 +18,18 @@ import { NextRequest } from 'next/server' import { ERROR_MESSAGES } from '@/lib/constants/error-messages' -const mockGetCurrentUser = jest.fn() -jest.mock('@/lib/auth', () => ({ +const mockGetCurrentUser = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth', () => ({ getCurrentUser: (...args: unknown[]) => mockGetCurrentUser(...args), })) -jest.mock('@/lib/auth/code-generation', () => ({ - generateStaffCode: jest.fn(() => 'AOZ-GEN001'), +vi.mock('@/lib/auth/code-generation', () => ({ + generateStaffCode: vi.fn(() => 'AOZ-GEN001'), })) -const mockUserFindUnique = jest.fn() -const mockUserCreate = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockUserFindUnique = vi.hoisted(() => vi.fn()) +const mockUserCreate = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { user: { findUnique: (...args: unknown[]) => mockUserFindUnique(...args), @@ -38,8 +38,8 @@ jest.mock('@/lib/db', () => ({ }, })) -jest.mock('@/lib/logger', () => ({ - logger: { info: jest.fn(), warn: jest.fn(), error: jest.fn(), errorWithCause: jest.fn() }, +vi.mock('@/lib/logger', () => ({ + logger: { info: vi.fn(), warn: vi.fn(), error: vi.fn(), errorWithCause: vi.fn() }, })) import { POST } from '../register/route' @@ -53,7 +53,7 @@ function post(body: Record): NextRequest { } beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() mockUserFindUnique.mockResolvedValue(null) mockUserCreate.mockResolvedValue({ id: 'u1', diff --git a/src/app/api/cron/__tests__/notifications.test.ts b/src/app/api/cron/__tests__/notifications.test.ts index 07e6d0c2..b210098e 100644 --- a/src/app/api/cron/__tests__/notifications.test.ts +++ b/src/app/api/cron/__tests__/notifications.test.ts @@ -5,13 +5,13 @@ // --- Mocks --- -const mockIncidentFindMany = jest.fn() -const mockPlacementFindMany = jest.fn() +const mockIncidentFindMany = vi.hoisted(() => vi.fn()) +const mockPlacementFindMany = vi.hoisted(() => vi.fn()) // $queryRaw is used for pg_try_advisory_lock + pg_advisory_unlock. // Default mock: lock acquired so the route proceeds normally; tests can // override per case. -const mockQueryRaw = jest.fn().mockResolvedValue([{ ok: true }]) -jest.mock('@/lib/db', () => ({ +const mockQueryRaw = vi.hoisted(() => vi.fn().mockResolvedValue([{ ok: true }])) +vi.mock('@/lib/db', () => ({ prisma: { incident: { findMany: (...args: unknown[]) => mockIncidentFindMany(...args), @@ -23,26 +23,26 @@ jest.mock('@/lib/db', () => ({ }, })) -const mockNotifyStaff = jest.fn() -jest.mock('@/lib/email', () => ({ +const mockNotifyStaff = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/email', () => ({ notifyStaff: (...args: unknown[]) => mockNotifyStaff(...args), - incidentFollowUpReminder: jest.fn().mockReturnValue({ + incidentFollowUpReminder: vi.fn().mockReturnValue({ subject: '[AOZ Housing] 1 überfällige Nachverfolgungen', html: '

test incidents

', }), - checkInReminder: jest.fn().mockReturnValue({ + checkInReminder: vi.fn().mockReturnValue({ subject: '[AOZ Housing] 1 Check-ins überfällig', html: '

test check-ins

', }), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) @@ -65,7 +65,7 @@ function createCronRequest(authHeader?: string): Request { const originalEnv = process.env.CRON_SECRET beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() process.env.CRON_SECRET = CRON_SECRET mockIncidentFindMany.mockResolvedValue([]) mockPlacementFindMany.mockResolvedValue([]) diff --git a/src/app/api/cron/__tests__/reset-demo.test.ts b/src/app/api/cron/__tests__/reset-demo.test.ts index 10a050b9..9bee2d0f 100644 --- a/src/app/api/cron/__tests__/reset-demo.test.ts +++ b/src/app/api/cron/__tests__/reset-demo.test.ts @@ -8,30 +8,30 @@ // $queryRaw serves pg_try_advisory_lock + pg_advisory_unlock. Default: // lock acquired so the route proceeds; tests override per case. -const mockQueryRaw = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockQueryRaw = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { $queryRaw: (...args: unknown[]) => mockQueryRaw(...args), }, })) -const mockResetDemoData = jest.fn() -jest.mock('@/lib/demo/reset', () => ({ +const mockResetDemoData = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/demo/reset', () => ({ resetDemoData: (...args: unknown[]) => mockResetDemoData(...args), })) -const mockResetDemoWorld = jest.fn() -jest.mock('@/lib/demo/scoped-reset', () => ({ +const mockResetDemoWorld = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/demo/scoped-reset', () => ({ resetDemoWorld: (...args: unknown[]) => mockResetDemoWorld(...args), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) @@ -79,7 +79,7 @@ describe('POST /api/cron/reset-demo', () => { const originalEnv = { ...process.env } beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() process.env.CRON_SECRET = CRON_SECRET process.env.DEMO_ACCESS_ENABLED = 'true' delete process.env.DEMO_RESET_SCOPE diff --git a/src/app/api/export/__tests__/export-routes.test.ts b/src/app/api/export/__tests__/export-routes.test.ts index 67abae8d..f17c0276 100644 --- a/src/app/api/export/__tests__/export-routes.test.ts +++ b/src/app/api/export/__tests__/export-routes.test.ts @@ -6,8 +6,8 @@ // --- Mocks --- -const mockGetCurrentUser = jest.fn() -jest.mock('@/lib/auth', () => ({ +const mockGetCurrentUser = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth', () => ({ getCurrentUser: (...args: unknown[]) => mockGetCurrentUser(...args), authorizeStaff: async () => { const user = await mockGetCurrentUser() @@ -16,8 +16,8 @@ jest.mock('@/lib/auth', () => ({ }, })) -const mockResidentFindMany = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockResidentFindMany = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { resident: { findMany: (...args: unknown[]) => mockResidentFindMany(...args), @@ -30,7 +30,7 @@ import { GET } from '../../export/residents/route' describe('GET /api/export/residents', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) it('returns 401 when not authenticated', async () => { diff --git a/src/app/api/import/__tests__/import-routes.test.ts b/src/app/api/import/__tests__/import-routes.test.ts index 71ff2d21..5db3eaa8 100644 --- a/src/app/api/import/__tests__/import-routes.test.ts +++ b/src/app/api/import/__tests__/import-routes.test.ts @@ -6,8 +6,8 @@ // --- Mocks --- -const mockGetCurrentUser = jest.fn() -jest.mock('@/lib/auth', () => ({ +const mockGetCurrentUser = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/auth', () => ({ getCurrentUser: (...args: unknown[]) => mockGetCurrentUser(...args), authorizeStaff: async () => { const user = await mockGetCurrentUser() @@ -18,10 +18,10 @@ jest.mock('@/lib/auth', () => ({ // Route now uses createMany + a transaction; pre-checks existing codes via // findMany, and writes AuditLog entries via auditLog.createMany. -const mockResidentFindMany = jest.fn().mockResolvedValue([]) -const mockResidentCreateMany = jest.fn().mockResolvedValue({ count: 0 }) -const mockAuditLogCreateMany = jest.fn().mockResolvedValue({ count: 0 }) -const mockTx = { +const mockResidentFindMany = vi.hoisted(() => vi.fn().mockResolvedValue([])) +const mockResidentCreateMany = vi.hoisted(() => vi.fn().mockResolvedValue({ count: 0 })) +const mockAuditLogCreateMany = vi.hoisted(() => vi.fn().mockResolvedValue({ count: 0 })) +const mockTx = vi.hoisted(() => ({ resident: { findMany: mockResidentFindMany, createMany: mockResidentCreateMany, @@ -29,27 +29,29 @@ const mockTx = { auditLog: { createMany: mockAuditLogCreateMany, }, -} -const mockTransaction = jest.fn(async (cb: (tx: typeof mockTx) => Promise) => cb(mockTx)) -jest.mock('@/lib/db', () => ({ +})) +const mockTransaction = vi.hoisted(() => + vi.fn(async (cb: (tx: typeof mockTx) => Promise) => cb(mockTx)), +) +vi.mock('@/lib/db', () => ({ prisma: { $transaction: (...args: unknown[]) => mockTransaction(...(args as [(tx: typeof mockTx) => Promise])), }, })) -const mockLogAudit = jest.fn() -jest.mock('@/lib/audit', () => ({ +const mockLogAudit = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/audit', () => ({ logAudit: (...args: unknown[]) => mockLogAudit(...args), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) @@ -90,7 +92,7 @@ const STAFF_USER = { describe('POST /api/import/residents', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) it('returns 401 when not authenticated', async () => { diff --git a/src/app/api/portal/__tests__/chores.test.ts b/src/app/api/portal/__tests__/chores.test.ts index cd60b12b..b1009ef2 100644 --- a/src/app/api/portal/__tests__/chores.test.ts +++ b/src/app/api/portal/__tests__/chores.test.ts @@ -16,27 +16,27 @@ import { ERROR_MESSAGES } from '@/lib/constants/error-messages' // --- Mocks --- -const mockGetPortalAuth = jest.fn() -jest.mock('@/lib/portal-auth', () => ({ +const mockGetPortalAuth = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/portal-auth', () => ({ getPortalAuth: () => mockGetPortalAuth(), })) -const mockFindMany = jest.fn() -const mockFindFirst = jest.fn() -const mockCreate = jest.fn() -const mockUpdate = jest.fn() -const mockGroupBy = jest.fn() -const mockCompletionFindMany = jest.fn() -const mockIncidentCreate = jest.fn() -const mockFlagCreate = jest.fn() -const mockRequestCreate = jest.fn() -const mockTransaction = jest.fn() -const mockCompletionCreate = jest.fn() -const mockFlagUpdateMany = jest.fn() -const mockRequestUpdateMany = jest.fn() -const mockTaskUpdate = jest.fn() - -jest.mock('@/lib/db', () => ({ +const mockFindMany = vi.hoisted(() => vi.fn()) +const mockFindFirst = vi.hoisted(() => vi.fn()) +const mockCreate = vi.hoisted(() => vi.fn()) +const mockUpdate = vi.hoisted(() => vi.fn()) +const mockGroupBy = vi.hoisted(() => vi.fn()) +const mockCompletionFindMany = vi.hoisted(() => vi.fn()) +const mockIncidentCreate = vi.hoisted(() => vi.fn()) +const mockFlagCreate = vi.hoisted(() => vi.fn()) +const mockRequestCreate = vi.hoisted(() => vi.fn()) +const mockTransaction = vi.hoisted(() => vi.fn()) +const mockCompletionCreate = vi.hoisted(() => vi.fn()) +const mockFlagUpdateMany = vi.hoisted(() => vi.fn()) +const mockRequestUpdateMany = vi.hoisted(() => vi.fn()) +const mockTaskUpdate = vi.fn() + +vi.mock('@/lib/db', () => ({ prisma: { householdTask: { findMany: (...args: unknown[]) => mockFindMany(...args), @@ -68,35 +68,40 @@ jest.mock('@/lib/db', () => ({ }, })) -const mockLogAudit = jest.fn().mockResolvedValue(undefined) -jest.mock('@/lib/audit', () => ({ +const mockLogAudit = vi.hoisted(() => vi.fn().mockResolvedValue(undefined)) +vi.mock('@/lib/audit', () => ({ logAudit: (...args: unknown[]) => mockLogAudit(...args), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) -const mockValidateFormData = jest.fn() -const MockValidationError = class ValidationError extends Error { - fieldErrors: Record - constructor(message: string, fieldErrors: Record = {}) { - super(message) - this.fieldErrors = fieldErrors - } -} +const mockValidateFormData = vi.hoisted(() => vi.fn()) +const MockValidationError = vi.hoisted( + () => + class ValidationError extends Error { + fieldErrors: Record + constructor(message: string, fieldErrors: Record = {}) { + super(message) + this.fieldErrors = fieldErrors + } + }, +) // Use the REAL schemas and stub only the form-data helper. A hand-copied // schema here would go on passing while the route silently dropped every field // the real schema later gained — which is exactly how two portal fields were // lost once already. The mock must never become a second definition. -jest.mock('@/lib/validation/schemas', () => ({ - ...jest.requireActual('@/lib/validation/schemas'), +// async: vitest's importActual is async, unlike jest's requireActual, +// so the factory has to await it. +vi.mock('@/lib/validation/schemas', async () => ({ + ...(await vi.importActual>('@/lib/validation/schemas')), validateFormData: (...args: unknown[]) => mockValidateFormData(...args), ValidationError: MockValidationError, })) @@ -164,7 +169,7 @@ const SAMPLE_TASK = { describe('GET /api/portal/chores', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns 401 when not authenticated', async () => { @@ -336,7 +341,7 @@ describe('GET /api/portal/chores', () => { describe('POST /api/portal/chores', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns 401 when not authenticated', async () => { @@ -510,7 +515,7 @@ describe('POST /api/portal/chores', () => { describe('GET /api/portal/chores/[id]', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns 401 when not authenticated', async () => { @@ -616,7 +621,7 @@ describe('GET /api/portal/chores/[id]', () => { describe('POST /api/portal/chores/[id]/complete', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns 401 when not authenticated', async () => { @@ -665,16 +670,16 @@ describe('POST /api/portal/chores/[id]/complete', () => { mockTransaction.mockImplementation(async (fn: (tx: unknown) => Promise) => { const tx = { taskCompletion: { - create: jest.fn().mockResolvedValue(completionResult), + create: vi.fn().mockResolvedValue(completionResult), }, householdTask: { - update: jest.fn().mockResolvedValue({}), + update: vi.fn().mockResolvedValue({}), }, taskAttentionFlag: { - updateMany: jest.fn().mockResolvedValue({ count: 0 }), + updateMany: vi.fn().mockResolvedValue({ count: 0 }), }, taskRequest: { - updateMany: jest.fn().mockResolvedValue({ count: 0 }), + updateMany: vi.fn().mockResolvedValue({ count: 0 }), }, } return fn(tx) @@ -690,10 +695,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { // Verify the transaction callback updates the task const txFn = mockTransaction.mock.calls[0][0] const mockTx = { - taskCompletion: { create: jest.fn().mockResolvedValue(completionResult) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue(completionResult) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, } await txFn(mockTx) @@ -709,10 +714,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { mockFindFirst.mockResolvedValue({ ...SAMPLE_TASK }) mockTransaction.mockImplementation(async (fn: (tx: unknown) => Promise) => fn({ - taskCompletion: { create: jest.fn().mockResolvedValue({ id: 'comp-1' }) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue({ id: 'comp-1' }) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, }), ) @@ -724,10 +729,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { await completeChore(req, makeParams('task-1')) const mockTx = { - taskCompletion: { create: jest.fn().mockResolvedValue({ id: 'comp-1' }) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue({ id: 'comp-1' }) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, } await mockTransaction.mock.calls[0][0](mockTx) @@ -743,10 +748,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { mockFindFirst.mockResolvedValue({ ...SAMPLE_TASK }) mockTransaction.mockImplementation(async (fn: (tx: unknown) => Promise) => fn({ - taskCompletion: { create: jest.fn().mockResolvedValue({ id: 'comp-1' }) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue({ id: 'comp-1' }) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, }), ) @@ -757,10 +762,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { expect(res.status).toBe(200) const mockTx = { - taskCompletion: { create: jest.fn().mockResolvedValue({ id: 'comp-1' }) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue({ id: 'comp-1' }) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, } await mockTransaction.mock.calls[0][0](mockTx) @@ -778,10 +783,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { const completionResult = { id: 'comp-2' } mockTransaction.mockImplementation(async (fn: (tx: unknown) => Promise) => { const tx = { - taskCompletion: { create: jest.fn().mockResolvedValue(completionResult) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue(completionResult) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, } return fn(tx) }) @@ -794,10 +799,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { // Verify ONE_TIME sets isCompleted + completedAt const txFn = mockTransaction.mock.calls[0][0] const mockTx = { - taskCompletion: { create: jest.fn().mockResolvedValue(completionResult) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue(completionResult) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, } await txFn(mockTx) @@ -818,10 +823,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { const completionResult = { id: 'comp-3' } mockTransaction.mockImplementation(async (fn: (tx: unknown) => Promise) => { const tx = { - taskCompletion: { create: jest.fn().mockResolvedValue(completionResult) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 2 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue(completionResult) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 2 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, } return fn(tx) }) @@ -832,10 +837,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { // Verify flags are resolved const txFn = mockTransaction.mock.calls[0][0] const mockTx = { - taskCompletion: { create: jest.fn().mockResolvedValue(completionResult) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 2 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue(completionResult) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 2 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, } await txFn(mockTx) @@ -856,10 +861,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { const completionResult = { id: 'comp-4' } mockTransaction.mockImplementation(async (fn: (tx: unknown) => Promise) => { const tx = { - taskCompletion: { create: jest.fn().mockResolvedValue(completionResult) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 1 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue(completionResult) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 1 }) }, } return fn(tx) }) @@ -869,10 +874,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { const txFn = mockTransaction.mock.calls[0][0] const mockTx = { - taskCompletion: { create: jest.fn().mockResolvedValue(completionResult) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 1 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue(completionResult) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 1 }) }, } await txFn(mockTx) @@ -895,10 +900,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { const completionResult = { id: 'comp-5' } mockTransaction.mockImplementation(async (fn: (tx: unknown) => Promise) => { const tx = { - taskCompletion: { create: jest.fn().mockResolvedValue(completionResult) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue(completionResult) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, } return fn(tx) }) @@ -912,10 +917,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { // Verify the notes/duration are passed through the transaction const txFn = mockTransaction.mock.calls[0][0] const mockTx = { - taskCompletion: { create: jest.fn().mockResolvedValue(completionResult) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue(completionResult) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, } await txFn(mockTx) @@ -936,10 +941,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { const completionResult = { id: 'comp-6' } mockTransaction.mockImplementation(async (fn: (tx: unknown) => Promise) => { const tx = { - taskCompletion: { create: jest.fn().mockResolvedValue(completionResult) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue(completionResult) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, } return fn(tx) }) @@ -961,10 +966,10 @@ describe('POST /api/portal/chores/[id]/complete', () => { mockTransaction.mockImplementation(async (fn: (tx: unknown) => Promise) => { const tx = { - taskCompletion: { create: jest.fn().mockResolvedValue({ id: 'comp-audit' }) }, - householdTask: { update: jest.fn().mockResolvedValue({}) }, - taskAttentionFlag: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, - taskRequest: { updateMany: jest.fn().mockResolvedValue({ count: 0 }) }, + taskCompletion: { create: vi.fn().mockResolvedValue({ id: 'comp-audit' }) }, + householdTask: { update: vi.fn().mockResolvedValue({}) }, + taskAttentionFlag: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, + taskRequest: { updateMany: vi.fn().mockResolvedValue({ count: 0 }) }, } return fn(tx) }) @@ -1014,7 +1019,7 @@ describe('POST /api/portal/chores/[id]/complete', () => { describe('POST /api/portal/chores/[id]/complaint', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns 401 when not authenticated', async () => { @@ -1217,7 +1222,7 @@ describe('POST /api/portal/chores/[id]/complaint', () => { describe('POST /api/portal/chores/[id]/attention', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns 401 when not authenticated', async () => { @@ -1363,7 +1368,7 @@ describe('POST /api/portal/chores/[id]/attention', () => { describe('POST /api/portal/chores/[id]/request', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns 401 when not authenticated', async () => { diff --git a/src/app/api/portal/__tests__/expenses.test.ts b/src/app/api/portal/__tests__/expenses.test.ts index ae1000c2..44f49ad6 100644 --- a/src/app/api/portal/__tests__/expenses.test.ts +++ b/src/app/api/portal/__tests__/expenses.test.ts @@ -12,18 +12,18 @@ import { ERROR_MESSAGES } from '@/lib/constants/error-messages' // --- Mocks --- -const mockGetPortalAuth = jest.fn() -const mockGetActiveUnitMembers = jest.fn() -jest.mock('@/lib/portal-auth', () => ({ +const mockGetPortalAuth = vi.hoisted(() => vi.fn()) +const mockGetActiveUnitMembers = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/portal-auth', () => ({ getPortalAuth: () => mockGetPortalAuth(), getActiveUnitMembers: (...args: unknown[]) => mockGetActiveUnitMembers(...args), })) -const mockExpenseCreate = jest.fn() -const mockExpenseFindUnique = jest.fn() -const mockExpenseDelete = jest.fn() -const mockSettlementCreate = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockExpenseCreate = vi.hoisted(() => vi.fn()) +const mockExpenseFindUnique = vi.hoisted(() => vi.fn()) +const mockExpenseDelete = vi.hoisted(() => vi.fn()) +const mockSettlementCreate = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { expense: { create: (...args: unknown[]) => mockExpenseCreate(...args), @@ -36,18 +36,18 @@ jest.mock('@/lib/db', () => ({ }, })) -const mockLogAudit = jest.fn().mockResolvedValue(undefined) -jest.mock('@/lib/audit', () => ({ +const mockLogAudit = vi.hoisted(() => vi.fn().mockResolvedValue(undefined)) +vi.mock('@/lib/audit', () => ({ logAudit: (...args: unknown[]) => mockLogAudit(...args), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) @@ -82,7 +82,7 @@ function jsonRequest(url: string, method: string, body: unknown): NextRequest { const VALID_EXPENSE = { description: 'Wocheneinkauf', category: 'GROCERIES', amountRappen: 4000 } beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() mockGetPortalAuth.mockResolvedValue(AUTH) mockGetActiveUnitMembers.mockResolvedValue(MEMBERS) mockExpenseCreate.mockImplementation((args: { data: unknown }) => diff --git a/src/app/api/portal/__tests__/portal-auth.test.ts b/src/app/api/portal/__tests__/portal-auth.test.ts index e4682e24..24b86992 100644 --- a/src/app/api/portal/__tests__/portal-auth.test.ts +++ b/src/app/api/portal/__tests__/portal-auth.test.ts @@ -6,8 +6,8 @@ // --- Mocks --- // Mock redirect to capture calls (next/navigation redirect throws by design) -const mockRedirect = jest.fn() -jest.mock('next/navigation', () => ({ +const mockRedirect = vi.hoisted(() => vi.fn()) +vi.mock('next/navigation', () => ({ redirect: (...args: unknown[]) => { mockRedirect(...args) throw new Error('NEXT_REDIRECT') @@ -15,9 +15,9 @@ jest.mock('next/navigation', () => ({ })) // Mock cookies -const mockCookieDelete = jest.fn() -jest.mock('next/headers', () => ({ - cookies: jest.fn().mockResolvedValue({ +const mockCookieDelete = vi.hoisted(() => vi.fn()) +vi.mock('next/headers', () => ({ + cookies: vi.fn().mockResolvedValue({ delete: (...args: unknown[]) => mockCookieDelete(...args), }), })) @@ -29,7 +29,7 @@ import { POST as logoutPOST } from '../logout/route' describe('POST /api/portal/logout', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('deletes the resident_code cookie', async () => { diff --git a/src/app/api/portal/__tests__/preferences.test.ts b/src/app/api/portal/__tests__/preferences.test.ts index de5408f2..ae15dd7b 100644 --- a/src/app/api/portal/__tests__/preferences.test.ts +++ b/src/app/api/portal/__tests__/preferences.test.ts @@ -9,16 +9,16 @@ import { ERROR_MESSAGES } from '@/lib/constants/error-messages' // --- Mocks --- -const mockCookieGet = jest.fn() -jest.mock('next/headers', () => ({ - cookies: jest.fn().mockResolvedValue({ +const mockCookieGet = vi.hoisted(() => vi.fn()) +vi.mock('next/headers', () => ({ + cookies: vi.fn().mockResolvedValue({ get: (name: string) => mockCookieGet(name), }), })) -const mockFindUnique = jest.fn() -const mockUpdate = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockFindUnique = vi.hoisted(() => vi.fn()) +const mockUpdate = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { resident: { findUnique: (...args: unknown[]) => mockFindUnique(...args), @@ -27,17 +27,17 @@ jest.mock('@/lib/db', () => ({ }, })) -jest.mock('@/lib/audit', () => ({ - logAudit: jest.fn().mockResolvedValue(undefined), +vi.mock('@/lib/audit', () => ({ + logAudit: vi.fn().mockResolvedValue(undefined), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) @@ -78,7 +78,7 @@ function createPreferencesRequest(data: Record): NextRequest { describe('POST /api/portal/preferences', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns 401 when no resident_code cookie', async () => { diff --git a/src/app/api/portal/__tests__/profile.test.ts b/src/app/api/portal/__tests__/profile.test.ts index ca9400e2..587ad2bb 100644 --- a/src/app/api/portal/__tests__/profile.test.ts +++ b/src/app/api/portal/__tests__/profile.test.ts @@ -15,29 +15,29 @@ import { PHOTO_LIMITS } from '@/lib/config/profile' // --- Mocks --- -const mockGetPortalAuth = jest.fn() -const mockGetPortalResident = jest.fn() -jest.mock('@/lib/portal-auth', () => ({ +const mockGetPortalAuth = vi.hoisted(() => vi.fn()) +const mockGetPortalResident = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/portal-auth', () => ({ getPortalAuth: () => mockGetPortalAuth(), getPortalResident: () => mockGetPortalResident(), })) // The photo route asks whether the viewer is staff before it asks anything // else. Default: nobody is, so the resident-facing cases are unaffected. -const mockGetCurrentUser = jest.fn().mockResolvedValue(null) -jest.mock('@/lib/auth', () => ({ +const mockGetCurrentUser = vi.hoisted(() => vi.fn().mockResolvedValue(null)) +vi.mock('@/lib/auth', () => ({ getCurrentUser: () => mockGetCurrentUser(), })) -const mockResidentUpdate = jest.fn() +const mockResidentUpdate = vi.hoisted(() => vi.fn()) // Every photo request now loads the subject's visibility setting first. -const mockResidentFindUnique = jest.fn() -const mockPhotoUpsert = jest.fn() -const mockPhotoDeleteMany = jest.fn() -const mockPhotoFindUnique = jest.fn() -const mockPlacementFindFirst = jest.fn() -const mockUnitUpdate = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockResidentFindUnique = vi.hoisted(() => vi.fn()) +const mockPhotoUpsert = vi.hoisted(() => vi.fn()) +const mockPhotoDeleteMany = vi.hoisted(() => vi.fn()) +const mockPhotoFindUnique = vi.hoisted(() => vi.fn()) +const mockPlacementFindFirst = vi.hoisted(() => vi.fn()) +const mockUnitUpdate = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { resident: { update: (...args: unknown[]) => mockResidentUpdate(...args), @@ -53,18 +53,18 @@ jest.mock('@/lib/db', () => ({ }, })) -const mockLogAudit = jest.fn().mockResolvedValue(undefined) -jest.mock('@/lib/audit', () => ({ +const mockLogAudit = vi.hoisted(() => vi.fn().mockResolvedValue(undefined)) +vi.mock('@/lib/audit', () => ({ logAudit: (...args: unknown[]) => mockLogAudit(...args), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) @@ -98,7 +98,7 @@ function photoRequest(file: File | null): NextRequest { } beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() mockGetPortalResident.mockResolvedValue(RESIDENT) mockGetPortalAuth.mockResolvedValue(AUTH) mockGetCurrentUser.mockResolvedValue(null) diff --git a/src/app/api/portal/__tests__/report.test.ts b/src/app/api/portal/__tests__/report.test.ts index 9456e559..88cb759a 100644 --- a/src/app/api/portal/__tests__/report.test.ts +++ b/src/app/api/portal/__tests__/report.test.ts @@ -10,18 +10,18 @@ import { ERROR_MESSAGES } from '@/lib/constants/error-messages' // --- Mocks --- -const mockCookieGet = jest.fn() -jest.mock('next/headers', () => ({ - cookies: jest.fn().mockResolvedValue({ +const mockCookieGet = vi.hoisted(() => vi.fn()) +vi.mock('next/headers', () => ({ + cookies: vi.fn().mockResolvedValue({ get: (name: string) => mockCookieGet(name), }), })) -const mockFindUnique = jest.fn() -const mockIncidentCreate = jest.fn() -const mockMaintenanceCreate = jest.fn() -const mockPlacementFindFirst = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockFindUnique = vi.hoisted(() => vi.fn()) +const mockIncidentCreate = vi.hoisted(() => vi.fn()) +const mockMaintenanceCreate = vi.hoisted(() => vi.fn()) +const mockPlacementFindFirst = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { resident: { findUnique: (...args: unknown[]) => mockFindUnique(...args), @@ -38,31 +38,35 @@ jest.mock('@/lib/db', () => ({ }, })) -const mockLogAudit = jest.fn().mockResolvedValue(undefined) -jest.mock('@/lib/audit', () => ({ +const mockLogAudit = vi.hoisted(() => vi.fn().mockResolvedValue(undefined)) +vi.mock('@/lib/audit', () => ({ logAudit: (...args: unknown[]) => mockLogAudit(...args), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) -const mockNotifyStaff = jest.fn().mockResolvedValue(true) -const mockNewIncidentNotification = jest.fn().mockReturnValue({ - subject: '[AOZ Housing] Neuer Vorfall', - html: '

test

', -}) -const mockNewMaintenanceNotification = jest.fn().mockReturnValue({ - subject: '[AOZ Housing] Neue Wartungsanfrage', - html: '

test

', -}) -jest.mock('@/lib/email', () => ({ +const mockNotifyStaff = vi.hoisted(() => vi.fn().mockResolvedValue(true)) +const mockNewIncidentNotification = vi.hoisted(() => + vi.fn().mockReturnValue({ + subject: '[AOZ Housing] Neuer Vorfall', + html: '

test

', + }), +) +const mockNewMaintenanceNotification = vi.hoisted(() => + vi.fn().mockReturnValue({ + subject: '[AOZ Housing] Neue Wartungsanfrage', + html: '

test

', + }), +) +vi.mock('@/lib/email', () => ({ notifyStaff: (...args: unknown[]) => mockNotifyStaff(...args), newIncidentNotification: (...args: unknown[]) => mockNewIncidentNotification(...args), newMaintenanceRequestNotification: (...args: unknown[]) => @@ -70,22 +74,25 @@ jest.mock('@/lib/email', () => ({ })) // Mock validation — the route uses validateFormData + ValidationError -const mockValidateFormData = jest.fn() -const MockValidationError = class ValidationError extends Error { - fieldErrors: Record - constructor(message: string, fieldErrors: Record = {}) { - super(message) - this.fieldErrors = fieldErrors - } -} -jest.mock('@/lib/validation/schemas', () => ({ +const mockValidateFormData = vi.hoisted(() => vi.fn()) +const MockValidationError = vi.hoisted( + () => + class ValidationError extends Error { + fieldErrors: Record + constructor(message: string, fieldErrors: Record = {}) { + super(message) + this.fieldErrors = fieldErrors + } + }, +) +vi.mock('@/lib/validation/schemas', () => ({ portalReportSchema: {}, validateFormData: (...args: unknown[]) => mockValidateFormData(...args), ValidationError: MockValidationError, })) // Mock PORTAL_LABELS with the locations the route looks up -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ PORTAL_LABELS: { report: { locations: [ @@ -138,7 +145,7 @@ const RESIDENT_NO_PLACEMENT = { describe('POST /api/portal/report', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns 401 when no resident_code cookie', async () => { diff --git a/src/app/api/portal/__tests__/satisfaction.test.ts b/src/app/api/portal/__tests__/satisfaction.test.ts index 38acd6d7..8ead95fc 100644 --- a/src/app/api/portal/__tests__/satisfaction.test.ts +++ b/src/app/api/portal/__tests__/satisfaction.test.ts @@ -10,26 +10,26 @@ import { ERROR_MESSAGES } from '@/lib/constants/error-messages' // --- Mocks --- -const mockCookieGet = jest.fn() -jest.mock('next/headers', () => ({ - cookies: jest.fn().mockResolvedValue({ +const mockCookieGet = vi.hoisted(() => vi.fn()) +vi.mock('next/headers', () => ({ + cookies: vi.fn().mockResolvedValue({ get: (name: string) => mockCookieGet(name), }), })) // Transaction mock objects — these are used inside the $transaction callback -const mockTxSatisfactionCheckInCreate = jest.fn() -const mockTxPlacementUpdate = jest.fn() -const mockTxIncidentCreate = jest.fn() +const mockTxSatisfactionCheckInCreate = vi.fn() +const mockTxPlacementUpdate = vi.fn() +const mockTxIncidentCreate = vi.fn() const tx = { satisfactionCheckIn: { create: (...args: unknown[]) => mockTxSatisfactionCheckInCreate(...args) }, placement: { update: (...args: unknown[]) => mockTxPlacementUpdate(...args) }, incident: { create: (...args: unknown[]) => mockTxIncidentCreate(...args) }, } -const mockFindUnique = jest.fn() -const mockTransaction = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockFindUnique = vi.hoisted(() => vi.fn()) +const mockTransaction = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { resident: { findUnique: (...args: unknown[]) => mockFindUnique(...args), @@ -38,26 +38,26 @@ jest.mock('@/lib/db', () => ({ }, })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) -const mockSafeParse = jest.fn() -jest.mock('@/lib/validation/schemas', () => ({ +const mockSafeParse = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/validation/schemas', () => ({ portalSatisfactionSchema: { safeParse: (...args: unknown[]) => mockSafeParse(...args), }, })) -jest.mock('@/lib/email', () => ({ - notifyStaff: jest.fn().mockResolvedValue(true), - lowSatisfactionAlert: jest.fn().mockReturnValue({ subject: 'test', html: '

test

' }), +vi.mock('@/lib/email', () => ({ + notifyStaff: vi.fn().mockResolvedValue(true), + lowSatisfactionAlert: vi.fn().mockReturnValue({ subject: 'test', html: '

test

' }), })) // --- Import after mocks --- @@ -101,7 +101,7 @@ const RESIDENT_NO_PLACEMENT = { describe('POST /api/portal/satisfaction', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() // Default: transaction passes the callback through with our mock tx mockTransaction.mockImplementation(async (cb: (tx: unknown) => unknown) => { return cb(tx) @@ -296,7 +296,7 @@ describe('POST /api/portal/satisfaction', () => { describe('GET /api/portal/satisfaction', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns 401 when no resident_code cookie', async () => { diff --git a/src/app/api/portal/__tests__/transfer.test.ts b/src/app/api/portal/__tests__/transfer.test.ts index 2eb35fbf..958ce614 100644 --- a/src/app/api/portal/__tests__/transfer.test.ts +++ b/src/app/api/portal/__tests__/transfer.test.ts @@ -10,17 +10,17 @@ import { ERROR_MESSAGES } from '@/lib/constants/error-messages' // --- Mocks --- -const mockCookieGet = jest.fn() -jest.mock('next/headers', () => ({ - cookies: jest.fn().mockResolvedValue({ +const mockCookieGet = vi.hoisted(() => vi.fn()) +vi.mock('next/headers', () => ({ + cookies: vi.fn().mockResolvedValue({ get: (name: string) => mockCookieGet(name), }), })) -const mockFindUnique = jest.fn() -const mockTransferCreate = jest.fn() -const mockHousingUnitFindUnique = jest.fn() -jest.mock('@/lib/db', () => ({ +const mockFindUnique = vi.hoisted(() => vi.fn()) +const mockTransferCreate = vi.hoisted(() => vi.fn()) +const mockHousingUnitFindUnique = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/db', () => ({ prisma: { resident: { findUnique: (...args: unknown[]) => mockFindUnique(...args), @@ -34,26 +34,24 @@ jest.mock('@/lib/db', () => ({ }, })) -const mockLogAudit = jest.fn().mockResolvedValue(undefined) -jest.mock('@/lib/audit', () => ({ +const mockLogAudit = vi.hoisted(() => vi.fn().mockResolvedValue(undefined)) +vi.mock('@/lib/audit', () => ({ logAudit: (...args: unknown[]) => mockLogAudit(...args), })) -jest.mock('@/lib/logger', () => ({ +vi.mock('@/lib/logger', () => ({ logger: { - debug: jest.fn(), - info: jest.fn(), - warn: jest.fn(), - error: jest.fn(), - errorWithCause: jest.fn(), + debug: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + errorWithCause: vi.fn(), }, })) -jest.mock('@/lib/email', () => ({ - notifyStaff: jest.fn(), - newTransferRequestNotification: jest - .fn() - .mockReturnValue({ subject: 'test', html: '

test

' }), +vi.mock('@/lib/email', () => ({ + notifyStaff: vi.fn(), + newTransferRequestNotification: vi.fn().mockReturnValue({ subject: 'test', html: '

test

' }), })) // --- Import after mocks --- @@ -99,7 +97,7 @@ const VALID_REASON = 'Ich möchte in eine ruhigere Unterkunft wechseln' describe('POST /api/portal/transfer', () => { beforeEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) test('returns 401 when no resident_code cookie', async () => { diff --git a/src/components/__tests__/PlacementConfirm.test.tsx b/src/components/__tests__/PlacementConfirm.test.tsx index 51a78e91..db0b3432 100644 --- a/src/components/__tests__/PlacementConfirm.test.tsx +++ b/src/components/__tests__/PlacementConfirm.test.tsx @@ -1,10 +1,10 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, waitFor } from '@testing-library/react' import { PlacementConfirm } from '../PlacementConfirm' // --- Mocks --- -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ MATCHING_LABELS: { blocked: 'Blockiert', place: 'Platzieren', @@ -34,7 +34,7 @@ const BASE_PROPS = { unitCode: 'A01', fitScore: 80, hasConflicts: false, - action: jest.fn().mockResolvedValue(undefined), + action: vi.fn().mockResolvedValue(undefined), formData: { residentId: 'res-1', spotId: 'spot-1' }, } @@ -53,7 +53,7 @@ function openModal() { // --- Tests --- describe('PlacementConfirm', () => { - afterEach(() => jest.clearAllMocks()) + afterEach(() => vi.clearAllMocks()) // ── Trigger button labels ───────────────────────────────────────────────── @@ -171,7 +171,7 @@ describe('PlacementConfirm', () => { }) it('does NOT call action when cancel is clicked', () => { - const action = jest.fn() + const action = vi.fn() renderConfirm({ action }) openModal() fireEvent.click(screen.getByRole('button', { name: 'Abbrechen' })) @@ -181,7 +181,7 @@ describe('PlacementConfirm', () => { // ── Confirm calls action with formData ──────────────────────────────────── it('calls action with FormData containing all formData entries', async () => { - const action = jest.fn().mockResolvedValue(undefined) + const action = vi.fn().mockResolvedValue(undefined) renderConfirm({ action, formData: { residentId: 'r-99', spotId: 'sp-7' } }) openModal() fireEvent.click(screen.getByRole('button', { name: 'Jetzt platzieren' })) @@ -193,7 +193,7 @@ describe('PlacementConfirm', () => { }) it('closes the modal after confirm resolves', async () => { - const action = jest.fn().mockResolvedValue(undefined) + const action = vi.fn().mockResolvedValue(undefined) renderConfirm({ action }) openModal() fireEvent.click(screen.getByRole('button', { name: 'Jetzt platzieren' })) diff --git a/src/components/admin/__tests__/AdminUrlFeedback.test.tsx b/src/components/admin/__tests__/AdminUrlFeedback.test.tsx index 3f1d0073..77a23f09 100644 --- a/src/components/admin/__tests__/AdminUrlFeedback.test.tsx +++ b/src/components/admin/__tests__/AdminUrlFeedback.test.tsx @@ -1,31 +1,32 @@ -import '@testing-library/jest-dom' +import type { Mock } from 'vitest' +import '@testing-library/jest-dom/vitest' import { render, waitFor } from '@testing-library/react' import { useSearchParams, useRouter, usePathname } from 'next/navigation' import { AdminUrlFeedback } from '../AdminUrlFeedback' import { showToast } from '@/components/ui/Toast' import { RESIDENT_DETAIL_LABELS } from '@/lib/constants/labels/ui' -jest.mock('next/navigation', () => ({ - useSearchParams: jest.fn(), - useRouter: jest.fn(), - usePathname: jest.fn(), +vi.mock('next/navigation', () => ({ + useSearchParams: vi.fn(), + useRouter: vi.fn(), + usePathname: vi.fn(), })) -jest.mock('@/components/ui/Toast', () => ({ - showToast: jest.fn(), +vi.mock('@/components/ui/Toast', () => ({ + showToast: vi.fn(), })) -const mockReplace = jest.fn() +const mockReplace = vi.fn() beforeEach(() => { - jest.clearAllMocks() - ;(useRouter as jest.Mock).mockReturnValue({ replace: mockReplace }) + vi.clearAllMocks() + ;(useRouter as Mock).mockReturnValue({ replace: mockReplace }) }) describe('AdminUrlFeedback', () => { it('shows placement toast on resident detail URL', async () => { - ;(usePathname as jest.Mock).mockReturnValue('/residents/abc123') - ;(useSearchParams as jest.Mock).mockReturnValue(new URLSearchParams('placed=true')) + ;(usePathname as Mock).mockReturnValue('/residents/abc123') + ;(useSearchParams as Mock).mockReturnValue(new URLSearchParams('placed=true')) render() diff --git a/src/components/ai/__tests__/AIChatInterface.test.tsx b/src/components/ai/__tests__/AIChatInterface.test.tsx index d7c6bcbe..98779b0b 100644 --- a/src/components/ai/__tests__/AIChatInterface.test.tsx +++ b/src/components/ai/__tests__/AIChatInterface.test.tsx @@ -3,7 +3,7 @@ import { render, screen, fireEvent, waitFor, act } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { AIChatInterface } from '../AIChatInterface' -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ UI_LABELS: { aiChatPlaceholder: 'Frage stellen…', aiChatSend: 'Senden', @@ -16,22 +16,23 @@ jest.mock('@/lib/constants/labels', () => ({ AI_SUGGESTED_QUESTIONS: ['Frage 1', 'Frage 2'], })) -jest.mock('lucide-react', () => ({ +vi.mock('lucide-react', async () => ({ + ...(await vi.importActual>('lucide-react')), Send: () => , Bot: () => , User: () => , Loader2: () => , })) -const mockFetch = jest.fn() +const mockFetch = vi.fn() beforeAll(() => { global.fetch = mockFetch - Element.prototype.scrollIntoView = jest.fn() + Element.prototype.scrollIntoView = vi.fn() }) afterEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) function makeMockReader(chunks: string[]) { @@ -39,7 +40,7 @@ function makeMockReader(chunks: string[]) { // Buffer extends Uint8Array so TextDecoder.decode(buffer) works correctly. let i = 0 return { - read: jest.fn().mockImplementation(async () => { + read: vi.fn().mockImplementation(async () => { if (i < chunks.length) { return { done: false as const, value: Buffer.from(chunks[i++]) } } @@ -208,7 +209,7 @@ describe('AIChatInterface — streaming', () => { }) mockFetch.mockResolvedValueOnce({ ok: true, - body: { getReader: () => ({ read: jest.fn().mockReturnValue(pending) }) }, + body: { getReader: () => ({ read: vi.fn().mockReturnValue(pending) }) }, }) render() await userEvent.type(screen.getByPlaceholderText('Frage stellen…'), 'Hi') @@ -270,7 +271,7 @@ describe('AIChatInterface — streaming', () => { }) mockFetch.mockResolvedValueOnce({ ok: true, - body: { getReader: () => ({ read: jest.fn().mockReturnValue(pending) }) }, + body: { getReader: () => ({ read: vi.fn().mockReturnValue(pending) }) }, }) render() await userEvent.type(screen.getByPlaceholderText('Frage stellen…'), 'Hi') diff --git a/src/components/dashboard/__tests__/ActionDashboard.test.tsx b/src/components/dashboard/__tests__/ActionDashboard.test.tsx index c676487d..3db0012c 100644 --- a/src/components/dashboard/__tests__/ActionDashboard.test.tsx +++ b/src/components/dashboard/__tests__/ActionDashboard.test.tsx @@ -1,17 +1,17 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { ActionDashboard } from '../ActionDashboard' // --- Mocks --- -jest.mock('../PrimaryActionHero', () => ({ +vi.mock('../PrimaryActionHero', () => ({ HeroAction: ({ action }: { action: { type: string } }) => (
), CriticalAlertBanner: ({ incidents }: { incidents: Array<{ id: string }> }) => (
), - determinePrimaryAction: jest.fn(() => ({ + determinePrimaryAction: vi.fn(() => ({ type: 'ALL_GOOD', label: 'OK', href: '/', @@ -19,7 +19,7 @@ jest.mock('../PrimaryActionHero', () => ({ })), })) -jest.mock('../QuickStatsRow', () => ({ +vi.mock('../QuickStatsRow', () => ({ QuickStat: ({ label, value }: { label: string; value: number }) => (
{label}: {value} @@ -27,7 +27,7 @@ jest.mock('../QuickStatsRow', () => ({ ), })) -jest.mock('../ActionTilesGrid', () => ({ +vi.mock('../ActionTilesGrid', () => ({ ActionTile: ({ title, count }: { title: string; count: number }) => (
{title} ({count}) @@ -35,14 +35,15 @@ jest.mock('../ActionTilesGrid', () => ({ ), })) -jest.mock('../AllClearState', () => ({ +vi.mock('../AllClearState', () => ({ AllClearState: () =>
, QuickActionsBar: ({ unplacedCount, freeBeds }: { unplacedCount: number; freeBeds: number }) => (
), })) -jest.mock('@/lib/config/thresholds', () => ({ +vi.mock('@/lib/config/thresholds', async () => ({ + ...(await vi.importActual>('@/lib/config/thresholds')), DISPLAY_LIMITS: { dashboardItems: 3 }, })) diff --git a/src/components/dashboard/__tests__/ActionTilesGrid.test.tsx b/src/components/dashboard/__tests__/ActionTilesGrid.test.tsx index e3401aa8..d0f75f1c 100644 --- a/src/components/dashboard/__tests__/ActionTilesGrid.test.tsx +++ b/src/components/dashboard/__tests__/ActionTilesGrid.test.tsx @@ -1,8 +1,8 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { ActionTile } from '../ActionTilesGrid' -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -19,11 +19,12 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/config/thresholds', () => ({ +vi.mock('@/lib/config/thresholds', async () => ({ + ...(await vi.importActual>('@/lib/config/thresholds')), DISPLAY_LIMITS: { dashboardItems: 3 }, })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ DASHBOARD_LABELS: { showAllPrefix: 'Alle', showAllSuffix: 'anzeigen', diff --git a/src/components/dashboard/__tests__/AllClearState.test.tsx b/src/components/dashboard/__tests__/AllClearState.test.tsx index bf827e58..5354f133 100644 --- a/src/components/dashboard/__tests__/AllClearState.test.tsx +++ b/src/components/dashboard/__tests__/AllClearState.test.tsx @@ -1,8 +1,8 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { AllClearState, QuickActionsBar } from '../AllClearState' -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -19,7 +19,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ DASHBOARD_LABELS: { allClearTitle: 'Alles unter Kontrolle!', allClearConflictFreeSuffix: 'Tage ohne Konflikte.', diff --git a/src/components/dashboard/__tests__/ConflictCard.test.tsx b/src/components/dashboard/__tests__/ConflictCard.test.tsx index c230ab2e..df33b559 100644 --- a/src/components/dashboard/__tests__/ConflictCard.test.tsx +++ b/src/components/dashboard/__tests__/ConflictCard.test.tsx @@ -1,10 +1,10 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { ConflictCard } from '../ConflictCard' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -21,7 +21,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants/labels/dashboard', () => ({ +vi.mock('@/lib/constants/labels/dashboard', () => ({ ALGORITHM_ACCURACY_LABELS: { conflictCardTitle: 'Konflikte', conflictCardActiveSuffix: 'aktiv (30 Tage)', @@ -37,7 +37,8 @@ jest.mock('@/lib/constants/labels/dashboard', () => ({ }, })) -jest.mock('@/lib/config/thresholds', () => ({ +vi.mock('@/lib/config/thresholds', async () => ({ + ...(await vi.importActual>('@/lib/config/thresholds')), DISPLAY_LIMITS: { dashboardItems: 3 }, })) diff --git a/src/components/dashboard/__tests__/DashboardMetrics.test.tsx b/src/components/dashboard/__tests__/DashboardMetrics.test.tsx index 1ad607b1..a6e0efc5 100644 --- a/src/components/dashboard/__tests__/DashboardMetrics.test.tsx +++ b/src/components/dashboard/__tests__/DashboardMetrics.test.tsx @@ -1,10 +1,10 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { DashboardMetrics } from '../DashboardMetrics' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -21,7 +21,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants/labels/dashboard', () => ({ +vi.mock('@/lib/constants/labels/dashboard', () => ({ ALGORITHM_ACCURACY_LABELS: { statResidents: 'Bewohner', statWaitingForPlacement: (n: number) => `${n} warten auf Platzierung`, diff --git a/src/components/dashboard/__tests__/MaintenanceCard.test.tsx b/src/components/dashboard/__tests__/MaintenanceCard.test.tsx index f1088ed0..93ff7538 100644 --- a/src/components/dashboard/__tests__/MaintenanceCard.test.tsx +++ b/src/components/dashboard/__tests__/MaintenanceCard.test.tsx @@ -1,10 +1,10 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { MaintenanceCard } from '../MaintenanceCard' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -21,7 +21,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ MAINTENANCE_CARD_LABELS: { title: 'Wartung & Service', openSuffix: 'offen', diff --git a/src/components/dashboard/__tests__/OccupancyCard.test.tsx b/src/components/dashboard/__tests__/OccupancyCard.test.tsx index d2db9b0a..9f7dc7d0 100644 --- a/src/components/dashboard/__tests__/OccupancyCard.test.tsx +++ b/src/components/dashboard/__tests__/OccupancyCard.test.tsx @@ -1,10 +1,10 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { OccupancyCard } from '../OccupancyCard' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -21,7 +21,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ DASHBOARD_LABELS: { sectionOccupancy: 'Belegung', sectionHousing: 'Unterkünfte', @@ -37,7 +37,8 @@ jest.mock('@/lib/constants/labels', () => ({ }, })) -jest.mock('@/lib/config/thresholds', () => ({ +vi.mock('@/lib/config/thresholds', async () => ({ + ...(await vi.importActual>('@/lib/config/thresholds')), getOccupancyLevel: (percent: number) => { if (percent >= 90) return 'critical' if (percent >= 70) return 'warning' diff --git a/src/components/dashboard/__tests__/PrimaryActionHero.test.tsx b/src/components/dashboard/__tests__/PrimaryActionHero.test.tsx index fd922ce9..e74fb82f 100644 --- a/src/components/dashboard/__tests__/PrimaryActionHero.test.tsx +++ b/src/components/dashboard/__tests__/PrimaryActionHero.test.tsx @@ -1,11 +1,11 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent } from '@testing-library/react' import { determinePrimaryAction, HeroAction, CriticalAlertBanner } from '../PrimaryActionHero' import type { PrimaryActionType } from '../PrimaryActionHero' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -22,11 +22,11 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/config/checkin-intervals', () => ({ +vi.mock('@/lib/config/checkin-intervals', () => ({ VERY_OVERDUE_THRESHOLD_DAYS: 14, })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ DASHBOARD_LABELS: { heroCriticalIncidentsSuffix: 'kritische Vorfälle', heroActionNow: 'Sofort bearbeiten', diff --git a/src/components/dashboard/__tests__/QuickStatsRow.test.tsx b/src/components/dashboard/__tests__/QuickStatsRow.test.tsx index 9ebd3a2f..4b7d8d20 100644 --- a/src/components/dashboard/__tests__/QuickStatsRow.test.tsx +++ b/src/components/dashboard/__tests__/QuickStatsRow.test.tsx @@ -1,8 +1,8 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { QuickStat } from '../QuickStatsRow' -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, diff --git a/src/components/dashboard/__tests__/SystemHealth.test.tsx b/src/components/dashboard/__tests__/SystemHealth.test.tsx index 70456dfb..179d956f 100644 --- a/src/components/dashboard/__tests__/SystemHealth.test.tsx +++ b/src/components/dashboard/__tests__/SystemHealth.test.tsx @@ -1,10 +1,10 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { SystemHealth } from '../SystemHealth' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -21,7 +21,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ SYSTEM_HEALTH_LABELS: { title: 'Systemstatus', conflictsThirtyDays: 'Konflikte (30 Tage)', diff --git a/src/components/dashboard/__tests__/TaskSection.test.tsx b/src/components/dashboard/__tests__/TaskSection.test.tsx index 32e8d2bf..d1873a54 100644 --- a/src/components/dashboard/__tests__/TaskSection.test.tsx +++ b/src/components/dashboard/__tests__/TaskSection.test.tsx @@ -1,10 +1,10 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { TaskSection } from '../TaskSection' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -21,7 +21,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ DASHBOARD_LABELS: { sectionTasks: 'Aufgaben', allClearAllDone: 'Alles erledigt!', diff --git a/src/components/forms/__tests__/DynamicFormField.test.tsx b/src/components/forms/__tests__/DynamicFormField.test.tsx index 50c0391b..2205b936 100644 --- a/src/components/forms/__tests__/DynamicFormField.test.tsx +++ b/src/components/forms/__tests__/DynamicFormField.test.tsx @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { DynamicFormField } from '../DynamicFormField' import type { diff --git a/src/components/forms/__tests__/DynamicFormFieldInputs.test.tsx b/src/components/forms/__tests__/DynamicFormFieldInputs.test.tsx index eab37f39..e88c4af3 100644 --- a/src/components/forms/__tests__/DynamicFormFieldInputs.test.tsx +++ b/src/components/forms/__tests__/DynamicFormFieldInputs.test.tsx @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { TextField as ControlledTextField, @@ -37,7 +37,7 @@ const MultiField = (props: ChangeOptional>) // --- Mocks --- -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ UI_LABELS: { selectPlaceholder: 'Bitte wählen' }, AI_FORM_LABELS: { aiMarker: 'KI', aiMarkerTitle: 'Von der KI ausgefüllt — bitte prüfen' }, FORM_VALIDATION_UX_LABELS: { diff --git a/src/components/forms/__tests__/FormFields.test.tsx b/src/components/forms/__tests__/FormFields.test.tsx index 451d8eef..1d9da3d9 100644 --- a/src/components/forms/__tests__/FormFields.test.tsx +++ b/src/components/forms/__tests__/FormFields.test.tsx @@ -1,14 +1,14 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, act } from '@testing-library/react' // ============================================================================= // Shared mocks // ============================================================================= -const mockRouterReplace = jest.fn() -const mockShowToast = jest.fn() +const mockRouterReplace = vi.hoisted(() => vi.fn()) +const mockShowToast = vi.hoisted(() => vi.fn()) -jest.mock('next/navigation', () => ({ +vi.mock('next/navigation', () => ({ useRouter: () => ({ replace: mockRouterReplace }), usePathname: () => '/residents', useSearchParams: () => mockSearchParams, @@ -16,12 +16,12 @@ jest.mock('next/navigation', () => ({ let mockSearchParams = new URLSearchParams() -jest.mock('@/components/ui/Toast', () => ({ +vi.mock('@/components/ui/Toast', () => ({ showToast: (...args: unknown[]) => mockShowToast(...args), })) // DynamicFormField stub: renders a div showing factor id + disabled flag -jest.mock('../DynamicFormField', () => ({ +vi.mock('../DynamicFormField', () => ({ DynamicFormField: ({ factor, disabled, @@ -42,7 +42,7 @@ jest.mock('../DynamicFormField', () => ({ // Config mocks for DynamicFormSection (props-based, no module mock needed) // Config mocks for HousingFormFields / ResidentFormFields -jest.mock('@/lib/config/housing-factors', () => ({ +vi.mock('@/lib/config/housing-factors', () => ({ HOUSING_FORM_SECTIONS: [ { id: 'basic', label: 'Grunddaten', order: 1 }, { id: 'facilities', label: 'Ausstattung', order: 2 }, @@ -67,9 +67,15 @@ jest.mock('@/lib/config/housing-factors', () => ({ }, })) -const codeFactor = { id: 'code', type: 'text', label: 'Code', formSection: 'basic', formOrder: 1 } +const codeFactor = vi.hoisted(() => ({ + id: 'code', + type: 'text', + label: 'Code', + formSection: 'basic', + formOrder: 1, +})) -jest.mock('@/lib/config/resident-factors', () => ({ +vi.mock('@/lib/config/resident-factors', () => ({ RESIDENT_FORM_SECTIONS: [{ id: 'basic', label: 'Stammdaten', order: 1 }], // The AI field registry and the form's starting values are both derived from // RESIDENT_FACTORS, so the mock has to provide it too. @@ -81,7 +87,7 @@ jest.mock('@/lib/config/resident-factors', () => ({ isEssentialFactor: () => true, })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ RESIDENT_FORM_LABELS: { medDocTitle: 'Medizinische Dokumentation', medDocDesc: 'Berechtigung für besondere Unterbringungsbedürfnisse', @@ -105,7 +111,7 @@ jest.mock('@/lib/constants', () => ({ }, })) -jest.mock('@/lib/config/placement-spots', () => ({ +vi.mock('@/lib/config/placement-spots', () => ({ MEDICAL_DOC_TYPE_LABELS: { PRIVATE_ROOM: 'Einzelzimmer', STUDIO: 'Studio', diff --git a/src/components/forms/__tests__/FormValidationUX.test.tsx b/src/components/forms/__tests__/FormValidationUX.test.tsx index e2b71989..0df3804b 100644 --- a/src/components/forms/__tests__/FormValidationUX.test.tsx +++ b/src/components/forms/__tests__/FormValidationUX.test.tsx @@ -2,7 +2,7 @@ import React from 'react' import { render, act } from '@testing-library/react' import { FormValidationUX } from '../FormValidationUX' -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ FORM_VALIDATION_UX_LABELS: { requiredFields: 'Bitte prüfen Sie die markierten Pflichtfelder.', fieldRequired: 'Dieses Feld ist erforderlich', @@ -30,7 +30,7 @@ function setupDOM() { afterEach(() => { document.body.innerHTML = '' - jest.restoreAllMocks() + vi.restoreAllMocks() }) describe('FormValidationUX', () => { @@ -189,7 +189,7 @@ describe('FormValidationUX', () => { expect(summary.classList.contains('hidden')).toBe(false) // Make form valid - jest.spyOn(form, 'checkValidity').mockReturnValue(true) + vi.spyOn(form, 'checkValidity').mockReturnValue(true) act(() => { input.value = 'filled' @@ -207,7 +207,7 @@ describe('FormValidationUX', () => { input.dispatchEvent(new Event('invalid', { bubbles: false, cancelable: true })) }) - jest.spyOn(form, 'checkValidity').mockReturnValue(false) + vi.spyOn(form, 'checkValidity').mockReturnValue(false) act(() => { input.value = 'partial' @@ -235,7 +235,7 @@ describe('FormValidationUX', () => { it('removes input listener so events have no effect after unmount', () => { const { form, input } = setupDOM() - const spy = jest.spyOn(form, 'checkValidity').mockReturnValue(true) + const spy = vi.spyOn(form, 'checkValidity').mockReturnValue(true) const { unmount } = render() unmount() diff --git a/src/components/housing/__tests__/ApartmentProfileCard.test.tsx b/src/components/housing/__tests__/ApartmentProfileCard.test.tsx index 78b7ce82..fa866ed2 100644 --- a/src/components/housing/__tests__/ApartmentProfileCard.test.tsx +++ b/src/components/housing/__tests__/ApartmentProfileCard.test.tsx @@ -1,11 +1,11 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { ApartmentProfileCard } from '../ApartmentProfileCard' import type { ResidentHouseholdProfile } from '@/lib/types' // --- Mocks --- -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ SLEEP_SCHEDULE_LABELS: { EARLY_BIRD: 'Frühaufsteher', NIGHT_OWL: 'Nachtmensch', @@ -41,12 +41,12 @@ jest.mock('@/lib/constants', () => ({ getLabel: (labels: Record, key: string) => labels[key] ?? key, })) -jest.mock('@/lib/utils', () => ({ +vi.mock('@/lib/utils', () => ({ getScoreColorClass: (score: number) => score >= 80 ? 'score-excellent' : score >= 60 ? 'score-good' : 'score-medium', })) -jest.mock('@/lib/config/resident-factors', () => ({ +vi.mock('@/lib/config/resident-factors', () => ({ RESIDENT_FACTORS: { cleanlinessPractice: { type: 'scale', lowLabel: 'Niedrig', highLabel: 'Hoch' }, noiseTolerance: { type: 'scale', lowLabel: 'Leise', highLabel: 'Laut' }, diff --git a/src/components/housing/__tests__/BedGrid.test.tsx b/src/components/housing/__tests__/BedGrid.test.tsx index b0b8af12..9bd12a66 100644 --- a/src/components/housing/__tests__/BedGrid.test.tsx +++ b/src/components/housing/__tests__/BedGrid.test.tsx @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent } from '@testing-library/react' import { BedGrid, BedGridSummary } from '../BedGrid' import type { HousingSpot } from '../types' @@ -7,13 +7,20 @@ import type { HousingSpot } from '../types' // MOCKS // ============================================================================= -jest.mock('next/link', () => { - return function MockLink({ children, href }: { children: React.ReactNode; href: string }) { +vi.mock('next/link', () => { + const MockLink = function MockLink({ + children, + href, + }: { + children: React.ReactNode + href: string + }) { return {children} } + return { default: MockLink } }) -jest.mock('@/lib/config/placement-spots', () => ({ +vi.mock('@/lib/config/placement-spots', () => ({ SPOT_TYPE_ICONS: { BED: 'bed-icon', PRIVATE_ROOM: 'room-icon', @@ -22,7 +29,7 @@ jest.mock('@/lib/config/placement-spots', () => ({ }, })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ AGE_RANGE_LABELS: { YOUNG_ADULT: '18-25', ADULT: '26-40', @@ -187,7 +194,7 @@ describe('BedGrid', () => { describe('click handling', () => { it('calls onBedClick when clicking an available spot', () => { - const onBedClick = jest.fn() + const onBedClick = vi.fn() const spot = makeSpot() render() @@ -196,7 +203,7 @@ describe('BedGrid', () => { }) it('does not call onBedClick for unavailable spots', () => { - const onBedClick = jest.fn() + const onBedClick = vi.fn() const spots = [makeUnavailableSpot()] render() @@ -205,7 +212,7 @@ describe('BedGrid', () => { }) it('calls onOccupiedBedClick when clicking an occupied spot', () => { - const onOccupiedBedClick = jest.fn() + const onOccupiedBedClick = vi.fn() const spot = makeOccupiedSpot() render() @@ -227,7 +234,7 @@ describe('BedGrid', () => { it('makes available spots have button role when onBedClick provided', () => { const spots = [makeSpot()] - render() + render() expect(screen.getByRole('button')).toBeInTheDocument() }) @@ -240,7 +247,7 @@ describe('BedGrid', () => { }) it('supports keyboard activation with Enter key', () => { - const onBedClick = jest.fn() + const onBedClick = vi.fn() const spot = makeSpot() render() @@ -250,7 +257,7 @@ describe('BedGrid', () => { }) it('supports keyboard activation with Space key', () => { - const onBedClick = jest.fn() + const onBedClick = vi.fn() const spot = makeSpot() render() diff --git a/src/components/housing/__tests__/CompatibilityDetailPopover.test.tsx b/src/components/housing/__tests__/CompatibilityDetailPopover.test.tsx index edb165c4..9c09762c 100644 --- a/src/components/housing/__tests__/CompatibilityDetailPopover.test.tsx +++ b/src/components/housing/__tests__/CompatibilityDetailPopover.test.tsx @@ -1,11 +1,11 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent } from '@testing-library/react' import { CompatibilityDetailPopover } from '../CompatibilityDetailPopover' import type { CompatibilityScore } from '../CompatibilityDetailPopover' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -22,13 +22,13 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/utils', () => ({ +vi.mock('@/lib/utils', () => ({ getScoreColorClass: (score: number) => score >= 80 ? 'score-excellent' : score >= 60 ? 'score-good' : 'score-medium', getScoreLabel: (score: number) => (score >= 80 ? 'Sehr gut' : score >= 60 ? 'Gut' : 'Mittel'), })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ COMPATIBILITY_DIMENSION_LABELS: { lifestyle: { label: 'Lebensstil', description: 'Schlaf, Lärm, Sauberkeit' }, social: { label: 'Sozial', description: 'Sprache, Umgang' }, @@ -49,7 +49,8 @@ jest.mock('@/lib/constants', () => ({ }, })) -jest.mock('@/lib/config/thresholds', () => ({ +vi.mock('@/lib/config/thresholds', async () => ({ + ...(await vi.importActual>('@/lib/config/thresholds')), SCORE_BG_COLORS: { excellent: 'bg-score-excellent', good: 'bg-score-good', @@ -90,7 +91,7 @@ function makeScore(overrides: Partial = {}): CompatibilitySc } function renderPopover(score: CompatibilityScore | null = makeScore()) { - const onClose = jest.fn() + const onClose = vi.fn() render( { resident2={R2} score={makeScore({ lifestyleScore: 70 })} position={POSITION} - onClose={jest.fn()} + onClose={vi.fn()} />, ) // The bar div has style width: 70% diff --git a/src/components/housing/__tests__/CompatibilityMatrixInteractive.test.tsx b/src/components/housing/__tests__/CompatibilityMatrixInteractive.test.tsx index 85987f54..961461dc 100644 --- a/src/components/housing/__tests__/CompatibilityMatrixInteractive.test.tsx +++ b/src/components/housing/__tests__/CompatibilityMatrixInteractive.test.tsx @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import React from 'react' import { render, screen, fireEvent } from '@testing-library/react' import { CompatibilityMatrixInteractive } from '../CompatibilityMatrixInteractive' @@ -7,7 +7,7 @@ import type { ResidentBasic } from '@/lib/types' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -24,12 +24,12 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/utils', () => ({ +vi.mock('@/lib/utils', () => ({ getScoreBgClass: (score: number) => score >= 80 ? 'bg-score-excellent/15' : score >= 60 ? 'bg-score-good/15' : 'bg-score-medium/15', })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ COMPATIBILITY_MATRIX_LABELS: { clickHint: 'Auf eine Zelle klicken für Kompatibilitätsdetails', swipeHint: 'Wischen zum Scrollen', @@ -43,7 +43,7 @@ jest.mock('@/lib/constants', () => ({ })) // Stub the popover — forwardRef so popoverRef.current attaches for outside-click tests -jest.mock('../CompatibilityDetailPopover', () => ({ +vi.mock('../CompatibilityDetailPopover', () => ({ CompatibilityDetailPopover: React.forwardRef(function PopoverStub( { resident1, diff --git a/src/components/housing/__tests__/HousingCardActions.test.tsx b/src/components/housing/__tests__/HousingCardActions.test.tsx index 41abebef..2e851515 100644 --- a/src/components/housing/__tests__/HousingCardActions.test.tsx +++ b/src/components/housing/__tests__/HousingCardActions.test.tsx @@ -1,23 +1,23 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, waitFor } from '@testing-library/react' import { HousingCardActions } from '../HousingCardActions' // --- Mocks --- -const mockPush = jest.fn() -const mockRefresh = jest.fn() -jest.mock('next/navigation', () => ({ +const mockPush = vi.hoisted(() => vi.fn()) +const mockRefresh = vi.hoisted(() => vi.fn()) +vi.mock('next/navigation', () => ({ useRouter: () => ({ push: mockPush, refresh: mockRefresh }), })) -const mockArchive = jest.fn() -const mockRestore = jest.fn() -jest.mock('@/lib/actions', () => ({ +const mockArchive = vi.hoisted(() => vi.fn()) +const mockRestore = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/actions', () => ({ archiveHousingUnit: (...args: unknown[]) => mockArchive(...args), restoreHousingUnit: (...args: unknown[]) => mockRestore(...args), })) -jest.mock('@/lib/config/crud-actions', () => ({ +vi.mock('@/lib/config/crud-actions', () => ({ CRUD_ACTIONS: { edit: { label: 'Bearbeiten' }, duplicate: { label: 'Duplizieren' }, @@ -31,7 +31,7 @@ jest.mock('@/lib/config/crud-actions', () => ({ }, })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ UI_LABELS: { actions: 'Aktionen' }, })) @@ -45,10 +45,10 @@ function openMenu() { describe('HousingCardActions', () => { beforeAll(() => { - jest.spyOn(window, 'alert').mockImplementation(() => {}) + vi.spyOn(window, 'alert').mockImplementation(() => {}) }) - afterAll(() => jest.restoreAllMocks()) - afterEach(() => jest.clearAllMocks()) + afterAll(() => vi.restoreAllMocks()) + afterEach(() => vi.clearAllMocks()) // ── Trigger renders ────────────────────────────────────────────────────── diff --git a/src/components/housing/__tests__/HousingClientComponents.test.tsx b/src/components/housing/__tests__/HousingClientComponents.test.tsx index 3a9d1eda..cc72a85d 100644 --- a/src/components/housing/__tests__/HousingClientComponents.test.tsx +++ b/src/components/housing/__tests__/HousingClientComponents.test.tsx @@ -1,49 +1,52 @@ -import '@testing-library/jest-dom' +import type { Mock } from 'vitest' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, act } from '@testing-library/react' // ============================================================================= // Mocks shared across suites // ============================================================================= -const mockRouter = { push: jest.fn(), refresh: jest.fn() } -jest.mock('next/navigation', () => ({ +const mockRouter = vi.hoisted(() => ({ push: vi.fn(), refresh: vi.fn() })) +vi.mock('next/navigation', () => ({ useRouter: () => mockRouter, })) // --- DangerZone mock (captures props for assertion) --- -const MockDangerZone = jest.fn( - ({ - entityType, - entityId, - entityCode, - redirectPath, - ariaId, - }: { - entityType: string - entityId: string - entityCode: string - redirectPath: string - ariaId: string - }) => ( -
+const MockDangerZone = vi.hoisted(() => + vi.fn( + ({ + entityType, + entityId, + entityCode, + redirectPath, + ariaId, + }: { + entityType: string + entityId: string + entityCode: string + redirectPath: string + ariaId: string + }) => ( +
+ ), ), ) -jest.mock('@/components/ui/DangerZone', () => ({ +vi.mock('@/components/ui/DangerZone', () => ({ DangerZone: MockDangerZone, })) // --- Label mocks for HousingDangerZone --- -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ HOUSING_DANGER_ZONE_LABELS: { title: 'Housing Danger Zone', description: 'Housing delete description', @@ -83,7 +86,7 @@ jest.mock('@/lib/constants/labels', () => ({ }, })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ DANGER_ZONE_LABELS: { title: 'Resident Danger Zone', description: 'Resident delete description', @@ -108,9 +111,9 @@ jest.mock('@/lib/constants', () => ({ }, })) -jest.mock('@/lib/actions', () => ({ - hardDeleteHousingUnitProtected: jest.fn(), - hardDeleteResidentProtected: jest.fn(), +vi.mock('@/lib/actions', () => ({ + hardDeleteHousingUnitProtected: vi.fn(), + hardDeleteResidentProtected: vi.fn(), })) // --- RoomVisualizationWithPlacement mocks --- @@ -128,31 +131,33 @@ const STUB_SPOT: HousingSpot = { placements: [], } -const MockPlacementPanel = jest.fn( - ({ - isOpen, - onClose, - onPlaceResident, - }: { - isOpen: boolean - onClose: () => void - onPlaceResident: (residentId: string, spotId: string) => Promise - spot: HousingSpot | null - compatibleResidents: unknown[] - housingUnitId: string - }) => ( -
- - -
+const MockPlacementPanel = vi.hoisted(() => + vi.fn( + ({ + isOpen, + onClose, + onPlaceResident, + }: { + isOpen: boolean + onClose: () => void + onPlaceResident: (residentId: string, spotId: string) => Promise + spot: HousingSpot | null + compatibleResidents: unknown[] + housingUnitId: string + }) => ( +
+ + +
+ ), ), ) -jest.mock('../PlacementPanel', () => ({ +vi.mock('../PlacementPanel', () => ({ PlacementPanel: MockPlacementPanel, })) -jest.mock('../RoomVisualization', () => ({ +vi.mock('../RoomVisualization', () => ({ RoomVisualization: ({ spots, onAvailableBedClick, @@ -176,8 +181,8 @@ jest.mock('../RoomVisualization', () => ({ ), })) -jest.mock('@/lib/actions/placements', () => ({ - createPlacement: jest.fn().mockResolvedValue({ success: true }), +vi.mock('@/lib/actions/placements', () => ({ + createPlacement: vi.fn().mockResolvedValue({ success: true }), })) // ============================================================================= @@ -296,7 +301,7 @@ describe('RoomVisualizationWithPlacement', () => { mockRouter.push.mockClear() mockRouter.refresh.mockClear() MockPlacementPanel.mockClear() - ;(createPlacement as jest.Mock).mockResolvedValue({ success: true }) + ;(createPlacement as Mock).mockResolvedValue({ success: true }) }) it('renders RoomVisualization with spots', () => { diff --git a/src/components/housing/__tests__/HousingDangerZone.test.tsx b/src/components/housing/__tests__/HousingDangerZone.test.tsx index 75c58f2c..2d45beb8 100644 --- a/src/components/housing/__tests__/HousingDangerZone.test.tsx +++ b/src/components/housing/__tests__/HousingDangerZone.test.tsx @@ -1,11 +1,11 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' -jest.mock('next/navigation', () => ({ - useRouter: () => ({ push: jest.fn(), refresh: jest.fn() }), +vi.mock('next/navigation', () => ({ + useRouter: () => ({ push: vi.fn(), refresh: vi.fn() }), })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ HOUSING_DANGER_ZONE_LABELS: { title: 'Housing Danger Zone', description: 'Nur für Test-Unterkünfte.', @@ -23,8 +23,8 @@ jest.mock('@/lib/constants/labels', () => ({ HOUSING_BLOCKER_LABELS: { placements: 'Platzierungen', incidents: 'Vorfälle' }, })) -jest.mock('@/lib/actions', () => ({ - hardDeleteHousingUnitProtected: jest.fn().mockResolvedValue({ success: false }), +vi.mock('@/lib/actions', () => ({ + hardDeleteHousingUnitProtected: vi.fn().mockResolvedValue({ success: false }), })) import { HousingDangerZone } from '../HousingDangerZone' diff --git a/src/components/housing/__tests__/HousingList.test.tsx b/src/components/housing/__tests__/HousingList.test.tsx index 273812af..9e7dcd70 100644 --- a/src/components/housing/__tests__/HousingList.test.tsx +++ b/src/components/housing/__tests__/HousingList.test.tsx @@ -1,10 +1,10 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { HousingList, HousingListItem } from '../HousingList' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -21,13 +21,13 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/components/housing/HousingCardActions', () => ({ +vi.mock('@/components/housing/HousingCardActions', () => ({ HousingCardActions: ({ housingId, status }: { housingId: string; status: string }) => (
), })) -jest.mock('@/lib/utils', () => ({ +vi.mock('@/lib/utils', () => ({ getOccupancyColorClass: (percent: number) => percent >= 90 ? 'bg-status-error' : percent >= 70 ? 'bg-status-warning' : 'bg-status-success', })) @@ -35,7 +35,7 @@ jest.mock('@/lib/utils', () => ({ /* * The label constants are NOT mocked, deliberately. * - * They used to be — the same object hand-copied into two `jest.mock` factories, + * They used to be — the same object hand-copied into two `vi.mock` factories, * one for the barrel and one for `labels`. Both copies had already drifted * (neither carried `buildingGroup` or `ungroupedBuilding`), and the drift was * invisible because a test that asserts on its own fixture always agrees with @@ -45,7 +45,7 @@ jest.mock('@/lib/utils', () => ({ * truth for exactly the values the component exists to render. */ -jest.mock('@/lib/constants/labels/housing', () => ({ +vi.mock('@/lib/constants/labels/housing', () => ({ HOUSING_STATUS_LABELS: { AVAILABLE: 'Verfügbar', FULL: 'Voll belegt', diff --git a/src/components/housing/__tests__/PlacementPanel.test.tsx b/src/components/housing/__tests__/PlacementPanel.test.tsx index 05aca88a..56a2d5ea 100644 --- a/src/components/housing/__tests__/PlacementPanel.test.tsx +++ b/src/components/housing/__tests__/PlacementPanel.test.tsx @@ -1,11 +1,11 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, waitFor } from '@testing-library/react' import { PlacementPanel } from '../PlacementPanel' import type { CompatibleResident, HousingSpot } from '../types' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -22,7 +22,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ AGE_RANGE_LABELS: { ADULT: '26-40', YOUNG_ADULT: '18-25' }, LANGUAGE_LABELS: { DE: 'Deutsch', EN: 'Englisch', AR: 'Arabisch' }, PLACEMENT_PANEL_LABELS: { @@ -45,11 +45,12 @@ jest.mock('@/lib/constants', () => ({ getLabel: (map: Record, key: string) => map[key] ?? key, })) -jest.mock('@/lib/utils/formatting', () => ({ +vi.mock('@/lib/utils/formatting', () => ({ getScoreColorClass: () => 'text-score-good', })) -jest.mock('@/lib/config/thresholds', () => ({ +vi.mock('@/lib/config/thresholds', async () => ({ + ...(await vi.importActual>('@/lib/config/thresholds')), DISPLAY_LIMITS: { languagePreview: 2 }, })) @@ -91,10 +92,10 @@ interface PanelOverrides { const BASE_PROPS: PanelOverrides = { isOpen: true, - onClose: jest.fn(), + onClose: vi.fn(), spot: SPOT, compatibleResidents: [], - onPlaceResident: jest.fn().mockResolvedValue(undefined), + onPlaceResident: vi.fn().mockResolvedValue(undefined), housingUnitId: 'unit-1', } @@ -106,7 +107,7 @@ function renderPanel(overrides: PanelOverrides = {}) { // --- Tests --- describe('PlacementPanel', () => { - afterEach(() => jest.clearAllMocks()) + afterEach(() => vi.clearAllMocks()) // ── Closed / null spot ──────────────────────────────────────────────────── @@ -143,14 +144,14 @@ describe('PlacementPanel', () => { }) it('calls onClose when the close button is clicked', () => { - const onClose = jest.fn() + const onClose = vi.fn() renderPanel({ onClose }) fireEvent.click(screen.getByRole('button', { name: 'Schliessen' })) expect(onClose).toHaveBeenCalledTimes(1) }) it('calls onClose when the backdrop is clicked', () => { - const onClose = jest.fn() + const onClose = vi.fn() const { container } = renderPanel({ onClose }) // Backdrop is the fixed overlay div before the panel const backdrop = container.querySelector('.scrim')! @@ -225,7 +226,7 @@ describe('PlacementPanel', () => { // ── Place action ────────────────────────────────────────────────────────── it('calls onPlaceResident with residentId and spotId when place is clicked', async () => { - const onPlaceResident = jest.fn().mockResolvedValue(undefined) + const onPlaceResident = vi.fn().mockResolvedValue(undefined) renderPanel({ compatibleResidents: [makeResident()], onPlaceResident, @@ -235,8 +236,8 @@ describe('PlacementPanel', () => { }) it('calls onClose after successful placement', async () => { - const onClose = jest.fn() - const onPlaceResident = jest.fn().mockResolvedValue(undefined) + const onClose = vi.fn() + const onPlaceResident = vi.fn().mockResolvedValue(undefined) renderPanel({ compatibleResidents: [makeResident()], onPlaceResident, onClose }) fireEvent.click(screen.getByRole('button', { name: 'Platzieren' })) await waitFor(() => expect(onClose).toHaveBeenCalled()) diff --git a/src/components/housing/__tests__/ProblemDetectionCard.test.tsx b/src/components/housing/__tests__/ProblemDetectionCard.test.tsx index a7dee704..5edffc59 100644 --- a/src/components/housing/__tests__/ProblemDetectionCard.test.tsx +++ b/src/components/housing/__tests__/ProblemDetectionCard.test.tsx @@ -1,11 +1,11 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { ProblemDetectionCard } from '../ProblemDetectionCard' import type { ResidentSummary } from '@/lib/types' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -22,7 +22,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ AGE_RANGE_LABELS: { YOUNG_ADULT: '18-25', ADULT: '26-40', MIDDLE_AGED: '41-60', SENIOR: '60+' }, LANGUAGE_LABELS: { de: 'Deutsch', en: 'Englisch', ar: 'Arabisch' }, PROBLEM_DETECTION_LABELS: { @@ -52,12 +52,13 @@ jest.mock('@/lib/constants', () => ({ getLabel: (labels: Record, key: string) => labels[key] ?? key, })) -jest.mock('@/lib/utils', () => ({ +vi.mock('@/lib/utils', () => ({ getScoreColorClass: (score: number) => score >= 80 ? 'score-excellent' : score >= 60 ? 'score-good' : 'score-medium', })) -jest.mock('@/lib/config/thresholds', () => ({ +vi.mock('@/lib/config/thresholds', async () => ({ + ...(await vi.importActual>('@/lib/config/thresholds')), DISPLAY_LIMITS: { languagePreview: 2 }, })) diff --git a/src/components/housing/__tests__/ResidentBedPopover.test.tsx b/src/components/housing/__tests__/ResidentBedPopover.test.tsx index 2682e27b..ce8a965e 100644 --- a/src/components/housing/__tests__/ResidentBedPopover.test.tsx +++ b/src/components/housing/__tests__/ResidentBedPopover.test.tsx @@ -1,11 +1,11 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent } from '@testing-library/react' import { ResidentBedPopover, getActivePlacement } from '../ResidentBedPopover' import type { HousingSpot, HousingPlacement } from '../types' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -24,7 +24,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ AGE_RANGE_LABELS: { YOUNG_ADULT: '18-25', ADULT: '26-40', MIDDLE_AGED: '41-60', SENIOR: '60+' }, LANGUAGE_LABELS: { de: 'Deutsch', en: 'Englisch', ar: 'Arabisch' }, BED_GRID_LABELS: { @@ -36,7 +36,8 @@ jest.mock('@/lib/constants', () => ({ getLabel: (labels: Record, key: string) => labels[key] ?? key, })) -jest.mock('@/lib/config/thresholds', () => ({ +vi.mock('@/lib/config/thresholds', async () => ({ + ...(await vi.importActual>('@/lib/config/thresholds')), DISPLAY_LIMITS: { languagePreview: 2 }, })) @@ -78,7 +79,7 @@ function makeSpot(overrides: Partial & { id: string }): HousingSpot const POSITION = { x: 200, y: 150 } -function renderPopover(spot: HousingSpot, onClose = jest.fn()) { +function renderPopover(spot: HousingSpot, onClose = vi.fn()) { render() return { onClose } } @@ -116,7 +117,7 @@ describe('ResidentBedPopover', () => { it('renders nothing when spot has no active placement', () => { const spot = makeSpot({ id: 's1', placements: [] }) const { container } = render( - , + , ) expect(container).toBeEmptyDOMElement() }) @@ -124,7 +125,7 @@ describe('ResidentBedPopover', () => { it('renders nothing when only ENDED placement exists', () => { const spot = makeSpot({ id: 's1', placements: [makePlacement('r1', 'ENDED')] }) const { container } = render( - , + , ) expect(container).toBeEmptyDOMElement() }) @@ -247,7 +248,7 @@ describe('ResidentBedPopover', () => { it('applies position styles from props', () => { const spot = makeSpot({ id: 's1', placements: [makePlacement('r1')] }) const { container } = render( - , + , ) const popover = container.firstChild as HTMLElement // left = max(8, 300 - 128) = 172 diff --git a/src/components/housing/__tests__/RoomVisualization.test.tsx b/src/components/housing/__tests__/RoomVisualization.test.tsx index 8544809f..6785ca3d 100644 --- a/src/components/housing/__tests__/RoomVisualization.test.tsx +++ b/src/components/housing/__tests__/RoomVisualization.test.tsx @@ -1,11 +1,11 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent } from '@testing-library/react' import { RoomVisualization } from '../RoomVisualization' import type { HousingSpot, HousingPlacement } from '../types' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -22,7 +22,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/config/placement-spots', () => ({ +vi.mock('@/lib/config/placement-spots', () => ({ SPOT_TYPE_ICONS: { BED: '🛏️', PRIVATE_ROOM: '🚪', STUDIO: '🏠', ROOM: '🚿' }, SPOT_STATUS_LABELS: { AVAILABLE: 'Verfügbar', @@ -32,7 +32,7 @@ jest.mock('@/lib/config/placement-spots', () => ({ }, })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ HOUSING_SPOTS_LABELS: { emptyRoomView: 'Keine Plätze definiert für diese Unterkunft', addSpotsBtn: 'Plätze hinzufügen', @@ -45,7 +45,7 @@ jest.mock('@/lib/constants/labels', () => ({ }, })) -jest.mock('../BedGrid', () => ({ +vi.mock('../BedGrid', () => ({ BedGrid: ({ spots, onBedClick, @@ -286,12 +286,12 @@ describe('RoomVisualization', () => { it('shows "Platzieren" button on available top-level spot when onPlaceResident given', () => { const spot = makeSpot({ id: 's1', type: 'PRIVATE_ROOM', status: 'AVAILABLE' }) - render() + render() expect(screen.getByRole('button', { name: 'Platzieren' })).toBeInTheDocument() }) it('calls onPlaceResident with spot id when "Platzieren" clicked', () => { - const onPlace = jest.fn() + const onPlace = vi.fn() const spot = makeSpot({ id: 'spot-99', type: 'PRIVATE_ROOM', status: 'AVAILABLE' }) render() fireEvent.click(screen.getByRole('button', { name: 'Platzieren' })) @@ -307,7 +307,7 @@ describe('RoomVisualization', () => { // ── BedGrid click → onAvailableBedClick ─────────────────────────────────── it('passes onAvailableBedClick through BedGrid stub when provided', () => { - const onBedClick = jest.fn() + const onBedClick = vi.fn() const room = makeSpot({ id: 'r1', type: 'ROOM' }) const bed = makeSpot({ id: 'b1', type: 'BED', parentSpotId: 'r1', code: 'B1' }) render( @@ -322,7 +322,7 @@ describe('RoomVisualization', () => { }) it('calls onPlaceResident via BedGrid when onAvailableBedClick not provided', () => { - const onPlace = jest.fn() + const onPlace = vi.fn() const room = makeSpot({ id: 'r1', type: 'ROOM' }) const bed = makeSpot({ id: 'b1', type: 'BED', parentSpotId: 'r1', code: 'B1' }) render( diff --git a/src/components/housing/__tests__/RoomVisualizationWithPlacement.test.tsx b/src/components/housing/__tests__/RoomVisualizationWithPlacement.test.tsx index 1490500c..555f80e1 100644 --- a/src/components/housing/__tests__/RoomVisualizationWithPlacement.test.tsx +++ b/src/components/housing/__tests__/RoomVisualizationWithPlacement.test.tsx @@ -1,19 +1,19 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, act } from '@testing-library/react' // --- Mocks --- -const mockRouterRefresh = jest.fn() -jest.mock('next/navigation', () => ({ +const mockRouterRefresh = vi.hoisted(() => vi.fn()) +vi.mock('next/navigation', () => ({ useRouter: () => ({ refresh: mockRouterRefresh }), })) -const mockCreatePlacement = jest.fn() -jest.mock('@/lib/actions/placements', () => ({ +const mockCreatePlacement = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/actions/placements', () => ({ createPlacement: (...args: unknown[]) => mockCreatePlacement(...args), })) -jest.mock('@/components/housing/RoomVisualization', () => ({ +vi.mock('@/components/housing/RoomVisualization', () => ({ RoomVisualization: ({ spots, housingUnitId, @@ -33,7 +33,7 @@ jest.mock('@/components/housing/RoomVisualization', () => ({ ), })) -jest.mock('@/components/housing/PlacementPanel', () => ({ +vi.mock('@/components/housing/PlacementPanel', () => ({ PlacementPanel: ({ isOpen, onClose, diff --git a/src/components/layout/__tests__/AdminSidebar.test.tsx b/src/components/layout/__tests__/AdminSidebar.test.tsx index f9d4104d..b60793a1 100644 --- a/src/components/layout/__tests__/AdminSidebar.test.tsx +++ b/src/components/layout/__tests__/AdminSidebar.test.tsx @@ -12,7 +12,7 @@ import { render, screen } from '@testing-library/react' import { AdminSidebar } from '@/components/layout/AdminSidebar' import { visibleMegaMenuGroups } from '@/lib/config/navigation' -jest.mock('next/navigation', () => ({ +vi.mock('next/navigation', () => ({ usePathname: () => mockPathname, })) diff --git a/src/components/layout/__tests__/MobileNavAndUserMenu.test.tsx b/src/components/layout/__tests__/MobileNavAndUserMenu.test.tsx index 0ce9c70f..c042e171 100644 --- a/src/components/layout/__tests__/MobileNavAndUserMenu.test.tsx +++ b/src/components/layout/__tests__/MobileNavAndUserMenu.test.tsx @@ -1,19 +1,19 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, act } from '@testing-library/react' // --- Navigation mock --- -jest.mock('next/navigation', () => ({ +vi.mock('next/navigation', () => ({ usePathname: () => mockPathname, useRouter: () => mockRouter, })) let mockPathname = '/' -const mockRouter = { push: jest.fn(), refresh: jest.fn() } +const mockRouter = vi.hoisted(() => ({ push: vi.fn(), refresh: vi.fn() })) // --- next/link mock --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, // Spread the rest: this mock used to forward only the four props it named, // so any attribute the component set — aria-current among them — vanished @@ -39,7 +39,7 @@ jest.mock('next/link', () => ({ // --- Config/constants mocks --- -jest.mock('@/lib/config/navigation', () => ({ +vi.mock('@/lib/config/navigation', () => ({ // The drawer consumes the SAME grouped nav as the desktop megamenu — one // top-level link, one group (whose /new shortcut must be filtered out). MEGAMENU_GROUPS: [ @@ -62,7 +62,7 @@ jest.mock('@/lib/config/navigation', () => ({ }, })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ APP_LABELS: { tagline: 'Kompatibles Wohnen' }, UI_LABELS: { menuOpen: 'Menü öffnen', @@ -76,7 +76,7 @@ jest.mock('@/lib/constants/labels', () => ({ ROLE_LABELS: { ADMIN: 'Administrator' }, })) -jest.mock('@/components/ui/Logo', () => ({ +vi.mock('@/components/ui/Logo', () => ({ Logo: ({ size }: { size?: string }) =>
, })) @@ -259,7 +259,7 @@ describe('UserMenu', () => { beforeEach(() => { mockRouter.push.mockClear() mockRouter.refresh.mockClear() - global.fetch = jest.fn().mockResolvedValue({ ok: true }) + global.fetch = vi.fn().mockResolvedValue({ ok: true }) }) it('renders toggle button with aria-label', () => { @@ -364,7 +364,7 @@ describe('UserMenu', () => { // FairnessSummary // ============================================================================= -jest.mock('@/lib/config/household-tasks', () => ({ +vi.mock('@/lib/config/household-tasks', () => ({ CHORE_LABELS: { balance: { title: 'Aufgaben-Saldo', diff --git a/src/components/matching/__tests__/MatchCard.test.tsx b/src/components/matching/__tests__/MatchCard.test.tsx index 8e4e616a..5c82ef79 100644 --- a/src/components/matching/__tests__/MatchCard.test.tsx +++ b/src/components/matching/__tests__/MatchCard.test.tsx @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { MatchCard } from '../MatchCard' import type { MatchResult } from '@/lib/matching/types' @@ -8,8 +8,8 @@ import type { Resident } from '@prisma/client' // MOCKS // ============================================================================= -jest.mock('next/link', () => { - return function MockLink({ +vi.mock('next/link', () => { + const MockLink = function MockLink({ children, href, className, @@ -24,13 +24,14 @@ jest.mock('next/link', () => { ) } + return { default: MockLink } }) -jest.mock('@/lib/actions/matching', () => ({ - placeResident: jest.fn(), +vi.mock('@/lib/actions/matching', () => ({ + placeResident: vi.fn(), })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ SLEEP_SCHEDULE_LABELS: { EARLY_BIRD: 'Fruehaufsteher', STANDARD: 'Normal', @@ -83,7 +84,7 @@ jest.mock('@/lib/constants', () => ({ getLabel: (labels: Record, key: string) => labels[key] || key, })) -jest.mock('@/lib/utils', () => ({ +vi.mock('@/lib/utils', () => ({ getScoreColorClass: (score: number) => { if (score >= 80) return 'text-score-excellent-text' if (score >= 60) return 'text-score-good-text' @@ -93,11 +94,11 @@ jest.mock('@/lib/utils', () => ({ }, })) -jest.mock('../HeadToHeadComparison', () => ({ +vi.mock('../HeadToHeadComparison', () => ({ HeadToHeadComparison: () =>
HeadToHead Mock
, })) -jest.mock('../SpotSelection', () => ({ +vi.mock('../SpotSelection', () => ({ SpotSelection: () =>
SpotSelection Mock
, })) diff --git a/src/components/portal/__tests__/ChoreActions.test.tsx b/src/components/portal/__tests__/ChoreActions.test.tsx index 6ad3d6b2..8cab3dda 100644 --- a/src/components/portal/__tests__/ChoreActions.test.tsx +++ b/src/components/portal/__tests__/ChoreActions.test.tsx @@ -1,10 +1,11 @@ -import '@testing-library/jest-dom' +import type { Mock } from 'vitest' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, waitFor } from '@testing-library/react' import { ChoreActions } from '../ChoreActions' // --- Mocks --- -jest.mock('@/lib/config/household-tasks', () => ({ +vi.mock('@/lib/config/household-tasks', () => ({ CHORE_LABELS: { actions: { complete: 'Erledigt!', @@ -56,13 +57,13 @@ jest.mock('@/lib/config/household-tasks', () => ({ }, })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ UI_LABELS: { close: 'Schliessen' }, })) -const mockPush = jest.fn() -const mockRefresh = jest.fn() -jest.mock('next/navigation', () => ({ +const mockPush = vi.hoisted(() => vi.fn()) +const mockRefresh = vi.hoisted(() => vi.fn()) +vi.mock('next/navigation', () => ({ useRouter: () => ({ push: mockPush, refresh: mockRefresh }), })) @@ -75,25 +76,25 @@ const ROOMMATES = [ ] function mockFetchSuccess() { - global.fetch = jest.fn().mockResolvedValue({ ok: true } as Response) + global.fetch = vi.fn().mockResolvedValue({ ok: true } as Response) } function mockFetchApiError(message = 'Ungültige Anfrage') { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ ok: false, json: async () => ({ error: message }), } as unknown as Response) } function mockFetchNetworkError() { - global.fetch = jest.fn().mockRejectedValue(new Error('Network error')) + global.fetch = vi.fn().mockRejectedValue(new Error('Network error')) } // --- Tests --- describe('ChoreActions', () => { afterEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) // ── Initial state ─────────────────────────────────────────────────────── @@ -162,7 +163,7 @@ describe('ChoreActions', () => { fireEvent.submit(screen.getByRole('button', { name: 'Erledigt!' }).closest('form')!) await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const [url, options] = (global.fetch as jest.Mock).mock.calls[0] + const [url, options] = (global.fetch as Mock).mock.calls[0] expect(url).toBe(`/api/portal/chores/${TASK_ID}/complete`) expect(options.method).toBe('POST') }) @@ -193,7 +194,7 @@ describe('ChoreActions', () => { fireEvent.submit(screen.getByRole('button', { name: 'Erledigt!' }).closest('form')!) await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const body = JSON.parse((global.fetch as jest.Mock).mock.calls[0][1].body) + const body = JSON.parse((global.fetch as Mock).mock.calls[0][1].body) expect(body.notes).toBe('Sehr gründlich geputzt') }) @@ -207,7 +208,7 @@ describe('ChoreActions', () => { fireEvent.submit(screen.getByRole('button', { name: 'Anfrage senden' }).closest('form')!) await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const [url] = (global.fetch as jest.Mock).mock.calls[0] + const [url] = (global.fetch as Mock).mock.calls[0] expect(url).toBe(`/api/portal/chores/${TASK_ID}/request`) }) @@ -220,7 +221,7 @@ describe('ChoreActions', () => { fireEvent.submit(screen.getByRole('button', { name: 'Anfrage senden' }).closest('form')!) await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const body = JSON.parse((global.fetch as jest.Mock).mock.calls[0][1].body) + const body = JSON.parse((global.fetch as Mock).mock.calls[0][1].body) expect(body.requestedResidentId).toBe('res-2') }) @@ -246,7 +247,7 @@ describe('ChoreActions', () => { fireEvent.submit(screen.getByRole('button', { name: 'Markieren' }).closest('form')!) await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const [url] = (global.fetch as jest.Mock).mock.calls[0] + const [url] = (global.fetch as Mock).mock.calls[0] expect(url).toBe(`/api/portal/chores/${TASK_ID}/attention`) }) @@ -277,7 +278,7 @@ describe('ChoreActions', () => { ) await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const [url, options] = (global.fetch as jest.Mock).mock.calls[0] + const [url, options] = (global.fetch as Mock).mock.calls[0] expect(url).toBe(`/api/portal/chores/${TASK_ID}/complaint`) const body = JSON.parse(options.body) expect(body.description).toBe('Niemand putzt das Bad') diff --git a/src/components/portal/__tests__/ChoreCard.test.tsx b/src/components/portal/__tests__/ChoreCard.test.tsx index 90331d41..81ea2051 100644 --- a/src/components/portal/__tests__/ChoreCard.test.tsx +++ b/src/components/portal/__tests__/ChoreCard.test.tsx @@ -1,10 +1,10 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent } from '@testing-library/react' import { ChoreCard } from '../ChoreCard' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -23,7 +23,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/config/household-tasks', () => ({ +vi.mock('@/lib/config/household-tasks', () => ({ TASK_CATEGORY_ICONS: { CLEANING: '🧹', OTHER: '📋' }, TASK_STATUS_COLORS: { IDLE: 'bg-gray-100 text-gray-700', @@ -52,11 +52,11 @@ jest.mock('@/lib/config/household-tasks', () => ({ }, })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ UI_LABELS: { details: 'Details' }, })) -jest.mock('@/lib/utils', () => ({ +vi.mock('@/lib/utils', () => ({ formatDate: (date: string) => `formatted:${date}`, })) @@ -78,7 +78,7 @@ const BASE_TASK = { requests: [] as Array<{ id: string }>, } -function renderCard(taskOverrides = {}, isCompleting = false, onQuickComplete = jest.fn()) { +function renderCard(taskOverrides = {}, isCompleting = false, onQuickComplete = vi.fn()) { const task = { ...BASE_TASK, ...taskOverrides } return render( , @@ -174,7 +174,7 @@ describe('ChoreCard', () => { }) it('calls onQuickComplete with task id when button clicked', () => { - const onQuickComplete = jest.fn() + const onQuickComplete = vi.fn() renderCard({ isCompleted: false, currentStatus: 'IDLE' }, false, onQuickComplete) fireEvent.click(screen.getByRole('button')) expect(onQuickComplete).toHaveBeenCalledWith('task-1') diff --git a/src/components/portal/__tests__/ChoreList.test.tsx b/src/components/portal/__tests__/ChoreList.test.tsx index 03f75480..eef97375 100644 --- a/src/components/portal/__tests__/ChoreList.test.tsx +++ b/src/components/portal/__tests__/ChoreList.test.tsx @@ -1,10 +1,11 @@ -import '@testing-library/jest-dom' +import type { Mock } from 'vitest' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, waitFor, act } from '@testing-library/react' import { ChoreList } from '../ChoreList' // --- Mocks --- -jest.mock('../ChoreCard', () => ({ +vi.mock('../ChoreCard', () => ({ ChoreCard: ({ task, onQuickComplete, @@ -23,18 +24,18 @@ jest.mock('../ChoreCard', () => ({ ), })) -jest.mock('../ChoreBalanceSummary', () => ({ +vi.mock('../ChoreBalanceSummary', () => ({ ChoreBalanceSummary: ({ balances }: { balances: Array<{ code: string }> }) => (
{balances.map((b) => b.code).join(',')}
), })) -const mockRefresh = jest.fn() -jest.mock('next/navigation', () => ({ - useRouter: () => ({ refresh: mockRefresh, push: jest.fn(), replace: jest.fn() }), +const mockRefresh = vi.hoisted(() => vi.fn()) +vi.mock('next/navigation', () => ({ + useRouter: () => ({ refresh: mockRefresh, push: vi.fn(), replace: vi.fn() }), })) -jest.mock('@/lib/config/household-tasks', () => ({ +vi.mock('@/lib/config/household-tasks', () => ({ TASK_CATEGORY_LABELS: { CLEANING: 'Reinigung', COOKING: 'Kochen' }, TASK_CATEGORY_ICONS: { CLEANING: '🧹', COOKING: '🍳' }, CHORE_LABELS: { @@ -81,12 +82,12 @@ function makeTask(overrides: { describe('ChoreList', () => { beforeEach(() => { - global.fetch = jest.fn() + global.fetch = vi.fn() mockRefresh.mockClear() }) afterEach(() => { - jest.resetAllMocks() + vi.resetAllMocks() }) // ── Empty state ─────────────────────────────────────────────────────────── @@ -209,7 +210,7 @@ describe('ChoreList', () => { // ── Quick complete (fetch flow) ─────────────────────────────────────────── it('calls fetch with POST when quick-complete triggered', async () => { - ;(global.fetch as jest.Mock).mockResolvedValueOnce({ ok: false }) + ;(global.fetch as Mock).mockResolvedValueOnce({ ok: false }) const tasks = [makeTask({ id: 'task-99', title: 'My task' })] render() await act(async () => { @@ -222,7 +223,7 @@ describe('ChoreList', () => { it('shows completing state while fetch is in progress', async () => { let resolveRequest!: (value: unknown) => void - ;(global.fetch as jest.Mock).mockReturnValueOnce( + ;(global.fetch as Mock).mockReturnValueOnce( new Promise((res) => { resolveRequest = res }), @@ -238,7 +239,7 @@ describe('ChoreList', () => { }) it('does not refresh when fetch returns non-ok response', async () => { - ;(global.fetch as jest.Mock).mockResolvedValueOnce({ ok: false }) + ;(global.fetch as Mock).mockResolvedValueOnce({ ok: false }) const tasks = [makeTask({ id: 'task-99', title: 'My task' })] render() await act(async () => { @@ -248,7 +249,7 @@ describe('ChoreList', () => { }) it('refreshes router when fetch returns ok', async () => { - ;(global.fetch as jest.Mock).mockResolvedValueOnce({ ok: true }) + ;(global.fetch as Mock).mockResolvedValueOnce({ ok: true }) const tasks = [makeTask({ id: 'task-99', title: 'My task' })] render() await act(async () => { diff --git a/src/components/portal/__tests__/CreateChoreForm.test.tsx b/src/components/portal/__tests__/CreateChoreForm.test.tsx index 3e3ec244..2b7c1215 100644 --- a/src/components/portal/__tests__/CreateChoreForm.test.tsx +++ b/src/components/portal/__tests__/CreateChoreForm.test.tsx @@ -1,10 +1,11 @@ -import '@testing-library/jest-dom' +import type { Mock } from 'vitest' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, waitFor, act } from '@testing-library/react' import { CreateChoreForm } from '../CreateChoreForm' // --- Mocks --- -jest.mock('@/lib/config/household-tasks', () => ({ +vi.mock('@/lib/config/household-tasks', () => ({ TASK_CATEGORY_LABELS: { CLEANING: 'Reinigung', TRASH: 'Abfall', @@ -67,37 +68,37 @@ jest.mock('@/lib/config/household-tasks', () => ({ }, })) -const mockPush = jest.fn() -const mockRefresh = jest.fn() -jest.mock('next/navigation', () => ({ +const mockPush = vi.hoisted(() => vi.fn()) +const mockRefresh = vi.hoisted(() => vi.fn()) +vi.mock('next/navigation', () => ({ useRouter: () => ({ push: mockPush, refresh: mockRefresh }), })) // --- Helpers --- function mockFetchSuccess(id?: string) { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ ok: true, json: async () => ({ data: id ? { id } : {} }), } as unknown as Response) } function mockFetchApiError(message = 'Ungültig') { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ ok: false, json: async () => ({ error: message }), } as unknown as Response) } function mockFetchNetworkError() { - global.fetch = jest.fn().mockRejectedValue(new Error('Network error')) + global.fetch = vi.fn().mockRejectedValue(new Error('Network error')) } // --- Tests --- describe('CreateChoreForm', () => { afterEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) // ── Rendering ─────────────────────────────────────────────────────────── @@ -190,7 +191,7 @@ describe('CreateChoreForm', () => { fireEvent.submit(screen.getByRole('button', { name: 'Aufgabe erstellen' }).closest('form')!) await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const [url, options] = (global.fetch as jest.Mock).mock.calls[0] + const [url, options] = (global.fetch as Mock).mock.calls[0] expect(url).toBe('/api/portal/chores') expect(options.method).toBe('POST') expect(options.body).toBeInstanceOf(FormData) @@ -240,7 +241,7 @@ describe('CreateChoreForm', () => { it('shows pending label while submitting', async () => { let resolve: (v: unknown) => void - global.fetch = jest.fn().mockReturnValue( + global.fetch = vi.fn().mockReturnValue( new Promise((r) => { resolve = r }), diff --git a/src/components/portal/__tests__/PortalNav.test.tsx b/src/components/portal/__tests__/PortalNav.test.tsx index 97f80fcb..90a7067e 100644 --- a/src/components/portal/__tests__/PortalNav.test.tsx +++ b/src/components/portal/__tests__/PortalNav.test.tsx @@ -1,16 +1,16 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent } from '@testing-library/react' import { PortalNav } from '../PortalNav' import { PORTAL_LABELS } from '@/lib/constants/labels' let mockPathname = '/portal' -jest.mock('next/navigation', () => ({ +vi.mock('next/navigation', () => ({ usePathname: () => mockPathname, - useRouter: () => ({ refresh: jest.fn() }), + useRouter: () => ({ refresh: vi.fn() }), })) -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -28,7 +28,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants/labels', () => jest.requireActual('@/lib/constants/labels')) +vi.mock('@/lib/constants/labels', async () => await vi.importActual('@/lib/constants/labels')) function renderNav(hasStaffAccess?: boolean) { return render() diff --git a/src/components/portal/__tests__/PortalSidebar.test.tsx b/src/components/portal/__tests__/PortalSidebar.test.tsx index 1dce4554..85d7569b 100644 --- a/src/components/portal/__tests__/PortalSidebar.test.tsx +++ b/src/components/portal/__tests__/PortalSidebar.test.tsx @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { de } from '@/lib/i18n/dictionaries/de' import type { MessageKey } from '@/lib/i18n/dictionaries/de' import { render, screen } from '@testing-library/react' @@ -8,11 +8,11 @@ import { PORTAL_LABELS } from '@/lib/constants/labels' let mockPathname = '/portal' -jest.mock('next/navigation', () => ({ +vi.mock('next/navigation', () => ({ usePathname: () => mockPathname, })) -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, diff --git a/src/components/portal/__tests__/PortalTabBar.test.tsx b/src/components/portal/__tests__/PortalTabBar.test.tsx index 86d169e4..d3fcca25 100644 --- a/src/components/portal/__tests__/PortalTabBar.test.tsx +++ b/src/components/portal/__tests__/PortalTabBar.test.tsx @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { de } from '@/lib/i18n/dictionaries/de' import type { MessageKey } from '@/lib/i18n/dictionaries/de' import { render, screen, fireEvent, within } from '@testing-library/react' @@ -8,12 +8,12 @@ import { PORTAL_LABELS } from '@/lib/constants/labels' let mockPathname = '/portal' -jest.mock('next/navigation', () => ({ +vi.mock('next/navigation', () => ({ usePathname: () => mockPathname, - useRouter: () => ({ refresh: jest.fn() }), + useRouter: () => ({ refresh: vi.fn() }), })) -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -31,7 +31,7 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/lib/constants/labels', () => jest.requireActual('@/lib/constants/labels')) +vi.mock('@/lib/constants/labels', async () => await vi.importActual('@/lib/constants/labels')) function renderBar() { return render() diff --git a/src/components/portal/__tests__/SatisfactionRating.test.tsx b/src/components/portal/__tests__/SatisfactionRating.test.tsx index bc7f2100..26661b9e 100644 --- a/src/components/portal/__tests__/SatisfactionRating.test.tsx +++ b/src/components/portal/__tests__/SatisfactionRating.test.tsx @@ -1,4 +1,5 @@ -import '@testing-library/jest-dom' +import type { Mock } from 'vitest' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, waitFor } from '@testing-library/react' import { SatisfactionRating } from '../SatisfactionRating' import { de } from '@/lib/i18n/dictionaries/de' @@ -8,8 +9,10 @@ import { de } from '@/lib/i18n/dictionaries/de' // The scale itself comes from the real module. Restating the faces here made // this a second definition that could agree with itself while disagreeing with // what ships — a mock that drifts from its subject tests nothing. -jest.mock('@/lib/constants', () => ({ - ...jest.requireActual('@/lib/constants'), +// async: vitest's importActual is async, unlike jest's requireActual, +// so the factory has to await it. +vi.mock('@/lib/constants', async () => ({ + ...(await vi.importActual>('@/lib/constants')), SATISFACTION_SURVEY_LABELS: { saveFailed: 'Speichern fehlgeschlagen. Bitte erneut versuchen.', day: 'Tag', @@ -28,15 +31,15 @@ jest.mock('@/lib/constants', () => ({ // --- Helpers --- function mockFetchSuccess() { - global.fetch = jest.fn().mockResolvedValue({ ok: true } as Response) + global.fetch = vi.fn().mockResolvedValue({ ok: true } as Response) } function mockFetchFailure() { - global.fetch = jest.fn().mockResolvedValue({ ok: false } as Response) + global.fetch = vi.fn().mockResolvedValue({ ok: false } as Response) } function mockFetchNetworkError() { - global.fetch = jest.fn().mockRejectedValue(new Error('Network error')) + global.fetch = vi.fn().mockRejectedValue(new Error('Network error')) } /** Date that is 8 days in the past — triggers the prompt form. */ @@ -48,7 +51,7 @@ const RECENT_DATE = new Date(Date.now() - 2 * 24 * 60 * 60 * 1000) describe('SatisfactionRating', () => { afterEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) // ── Prompt mode (no check-in or >= 7 days) ───────────────────────────── @@ -226,7 +229,7 @@ describe('SatisfactionRating', () => { await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const [url, options] = (global.fetch as jest.Mock).mock.calls[0] + const [url, options] = (global.fetch as Mock).mock.calls[0] expect(url).toBe('/api/portal/satisfaction') expect(options.method).toBe('POST') const body = JSON.parse(options.body) @@ -246,7 +249,7 @@ describe('SatisfactionRating', () => { await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const body = JSON.parse((global.fetch as jest.Mock).mock.calls[0][1].body) + const body = JSON.parse((global.fetch as Mock).mock.calls[0][1].body) expect(body.rating).toBe(2) expect(body.concerns).toBe('Es ist sehr laut') }) @@ -263,7 +266,7 @@ describe('SatisfactionRating', () => { await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const body = JSON.parse((global.fetch as jest.Mock).mock.calls[0][1].body) + const body = JSON.parse((global.fetch as Mock).mock.calls[0][1].body) expect(body.rating).toBe(1) expect(body.concerns).toBeUndefined() }) diff --git a/src/components/portal/__tests__/TransferRequestForm.test.tsx b/src/components/portal/__tests__/TransferRequestForm.test.tsx index 4b6ce5ad..bf0af995 100644 --- a/src/components/portal/__tests__/TransferRequestForm.test.tsx +++ b/src/components/portal/__tests__/TransferRequestForm.test.tsx @@ -1,4 +1,5 @@ -import '@testing-library/jest-dom' +import type { Mock } from 'vitest' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, waitFor } from '@testing-library/react' import { TransferRequestForm } from '../TransferRequestForm' @@ -22,7 +23,7 @@ const TRANSFER_COPY: Record = { 'error.generic': 'Ein Fehler ist aufgetreten. Bitte erneut versuchen.', } -jest.mock('@/lib/i18n/LocaleProvider', () => ({ +vi.mock('@/lib/i18n/LocaleProvider', () => ({ useT: () => (key: string) => TRANSFER_COPY[key] ?? key, })) @@ -38,28 +39,28 @@ const AVAILABLE_UNITS = [ ] function mockFetchSuccess() { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ ok: true, json: async () => ({ success: true }), } as Response) } function mockFetchApiError(message = 'Anfrage ungültig') { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ ok: false, json: async () => ({ success: false, error: message }), } as Response) } function mockFetchNetworkError() { - global.fetch = jest.fn().mockRejectedValue(new Error('Network error')) + global.fetch = vi.fn().mockRejectedValue(new Error('Network error')) } // --- Tests --- describe('TransferRequestForm', () => { afterEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) it('renders the form with reason textarea and submit button', () => { @@ -197,7 +198,7 @@ describe('TransferRequestForm', () => { await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const [url, options] = (global.fetch as jest.Mock).mock.calls[0] + const [url, options] = (global.fetch as Mock).mock.calls[0] expect(url).toBe('/api/portal/transfer') expect(options.method).toBe('POST') const body = JSON.parse(options.body) @@ -217,9 +218,9 @@ describe('TransferRequestForm', () => { }) fireEvent.submit(screen.getByRole('button', { name: 'Anfrage senden' }).closest('form')!) - await waitFor(() => expect(global.fetch as jest.Mock).toHaveBeenCalledTimes(1)) + await waitFor(() => expect(global.fetch as Mock).toHaveBeenCalledTimes(1)) - const body = JSON.parse((global.fetch as jest.Mock).mock.calls[0][1].body) + const body = JSON.parse((global.fetch as Mock).mock.calls[0][1].body) expect(body.targetUnitId).toBe('unit-2') }) }) diff --git a/src/components/residents/__tests__/CSVImport.test.tsx b/src/components/residents/__tests__/CSVImport.test.tsx index 0b42a450..74242a52 100644 --- a/src/components/residents/__tests__/CSVImport.test.tsx +++ b/src/components/residents/__tests__/CSVImport.test.tsx @@ -1,10 +1,11 @@ -import '@testing-library/jest-dom' +import type { Mock } from 'vitest' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, waitFor, act } from '@testing-library/react' import { CSVImport } from '../CSVImport' // --- Mocks --- -jest.mock('@/lib/constants/labels/export', () => ({ +vi.mock('@/lib/constants/labels/export', () => ({ EXPORT_LABELS: { selectFile: 'CSV-Datei wählen', downloadTemplate: 'Vorlage herunterladen', @@ -19,7 +20,8 @@ jest.mock('@/lib/constants/labels/export', () => ({ }, })) -jest.mock('@/lib/config/thresholds', () => ({ +vi.mock('@/lib/config/thresholds', async () => ({ + ...(await vi.importActual>('@/lib/config/thresholds')), DISPLAY_LIMITS: { importErrorPreview: 10 }, })) @@ -29,7 +31,7 @@ let capturedParseCall: { config: { complete: (r: { data: unknown[] }) => void; error: () => void } } | null = null -jest.mock('papaparse', () => ({ +vi.mock('papaparse', () => ({ __esModule: true, default: { parse: ( @@ -74,9 +76,9 @@ const PREVIEW_ROWS = [ describe('CSVImport', () => { beforeEach(() => { capturedParseCall = null - global.fetch = jest.fn() + global.fetch = vi.fn() }) - afterEach(() => jest.restoreAllMocks()) + afterEach(() => vi.restoreAllMocks()) // ── Initial render ─────────────────────────────────────────────────────── @@ -173,7 +175,7 @@ describe('CSVImport', () => { // ── Submit + loading state ─────────────────────────────────────────────── it('sends a POST request to /api/import/residents when import button is clicked', async () => { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ json: async () => ({ success: true, created: 2, skipped: 0, errors: [] }), }) @@ -187,14 +189,14 @@ describe('CSVImport', () => { fireEvent.click(screen.getByRole('button', { name: 'Importieren' })) await waitFor(() => expect(global.fetch).toHaveBeenCalledTimes(1)) - const [url, opts] = (global.fetch as jest.Mock).mock.calls[0] + const [url, opts] = (global.fetch as Mock).mock.calls[0] expect(url).toBe('/api/import/residents') expect(opts.method).toBe('POST') expect(opts.body).toBeInstanceOf(FormData) }) it('appends the selected file under the key "file" in the FormData', async () => { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ json: async () => ({ success: true, created: 1, skipped: 0, errors: [] }), }) @@ -209,13 +211,13 @@ describe('CSVImport', () => { fireEvent.click(screen.getByRole('button', { name: 'Importieren' })) await waitFor(() => expect(global.fetch).toHaveBeenCalled()) - const formData: FormData = (global.fetch as jest.Mock).mock.calls[0][1].body + const formData: FormData = (global.fetch as Mock).mock.calls[0][1].body expect(formData.get('file')).toBe(csvFile) }) it('shows the importing label while the request is in flight', async () => { let resolve!: (v: { json: () => Promise }) => void - global.fetch = jest.fn().mockReturnValue( + global.fetch = vi.fn().mockReturnValue( new Promise((r) => { resolve = r as typeof resolve }), @@ -243,7 +245,7 @@ describe('CSVImport', () => { // ── Success result display ─────────────────────────────────────────────── it('shows created and skipped counts on success', async () => { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ json: async () => ({ success: true, created: 5, skipped: 2, errors: [] }), }) @@ -261,7 +263,7 @@ describe('CSVImport', () => { }) it('hides preview table after successful import', async () => { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ json: async () => ({ success: true, created: 1, skipped: 0, errors: [] }), }) @@ -278,7 +280,7 @@ describe('CSVImport', () => { }) it('does not show error list when result has no errors', async () => { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ json: async () => ({ success: true, created: 3, skipped: 0, errors: [] }), }) @@ -297,7 +299,7 @@ describe('CSVImport', () => { // ── Error display in result ────────────────────────────────────────────── it('shows per-row errors returned by the API', async () => { - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ json: async () => ({ success: false, created: 0, @@ -321,7 +323,7 @@ describe('CSVImport', () => { it('truncates error list at DISPLAY_LIMITS.importErrorPreview (10) and shows overflow count', async () => { const errors = Array.from({ length: 13 }, (_, i) => ({ row: i + 2, error: `Fehler ${i + 1}` })) - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ json: async () => ({ success: false, created: 0, skipped: 0, errors }), }) @@ -344,7 +346,7 @@ describe('CSVImport', () => { it('does not show overflow notice when errors fit within limit', async () => { const errors = Array.from({ length: 3 }, (_, i) => ({ row: i + 2, error: `Fehler ${i + 1}` })) - global.fetch = jest.fn().mockResolvedValue({ + global.fetch = vi.fn().mockResolvedValue({ json: async () => ({ success: false, created: 0, skipped: 0, errors }), }) @@ -363,7 +365,7 @@ describe('CSVImport', () => { // ── Network/fetch error ────────────────────────────────────────────────── it('shows "Import fehlgeschlagen" when fetch throws', async () => { - global.fetch = jest.fn().mockRejectedValue(new Error('network')) + global.fetch = vi.fn().mockRejectedValue(new Error('network')) const { container } = renderImport() const input = container.querySelector('input[type="file"]') as HTMLElement diff --git a/src/components/residents/__tests__/CareWorkspace.test.tsx b/src/components/residents/__tests__/CareWorkspace.test.tsx index 0c31fc48..602bafdd 100644 --- a/src/components/residents/__tests__/CareWorkspace.test.tsx +++ b/src/components/residents/__tests__/CareWorkspace.test.tsx @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { CareWorkspace } from '../CareWorkspace' import { CARE_ROLES, CARE_ROLE_LABELS, writableCareDomains } from '@/lib/config/care' @@ -17,13 +17,14 @@ import { ASSIGNABLE_STAFF_ROLES, type StaffRole } from '@/lib/auth/role-policy' * `CARE_ROLES.map` back type-checks, lints and looks completely fine. */ -jest.mock('@/lib/actions/care', () => ({ - createAppointment: jest.fn(), - saveCareAttributes: jest.fn(), - setAppointmentStatus: jest.fn(), +vi.mock('@/lib/actions/care', () => ({ + createAppointment: vi.fn(), + saveCareAttributes: vi.fn(), + setAppointmentStatus: vi.fn(), })) -jest.mock('lucide-react', () => ({ +vi.mock('lucide-react', async () => ({ + ...(await vi.importActual>('lucide-react')), ChevronDown: () => , })) diff --git a/src/components/residents/__tests__/EndPlacementForm.test.tsx b/src/components/residents/__tests__/EndPlacementForm.test.tsx index d0a929bb..a91af43b 100644 --- a/src/components/residents/__tests__/EndPlacementForm.test.tsx +++ b/src/components/residents/__tests__/EndPlacementForm.test.tsx @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent } from '@testing-library/react' import { EndPlacementForm } from '../EndPlacementForm' @@ -22,11 +22,11 @@ afterAll(() => { // --- Mocks --- -jest.mock('@/lib/actions', () => ({ - endPlacement: jest.fn(), +vi.mock('@/lib/actions', () => ({ + endPlacement: vi.fn(), })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ END_REASON_LABELS: { NATURAL: 'Regulär', CONFLICT: 'Konflikt', @@ -71,7 +71,8 @@ jest.mock('@/lib/constants', () => ({ }, })) -jest.mock('@/lib/config/thresholds', () => ({ +vi.mock('@/lib/config/thresholds', async () => ({ + ...(await vi.importActual>('@/lib/config/thresholds')), DISPLAY_LIMITS: { descriptionPreview: 50 }, })) @@ -82,8 +83,8 @@ const BASE_PROPS = { residentId: 'resident-xyz', recentIncidents: [], selectedEndReason: '', - onReasonChange: jest.fn(), - onClose: jest.fn(), + onReasonChange: vi.fn(), + onClose: vi.fn(), } function renderForm(overrides = {}) { @@ -94,7 +95,7 @@ function renderForm(overrides = {}) { describe('EndPlacementForm', () => { afterEach(() => { - jest.clearAllMocks() + vi.clearAllMocks() }) // ── Rendering ─────────────────────────────────────────────────────────── @@ -130,14 +131,14 @@ describe('EndPlacementForm', () => { // ── Callbacks ─────────────────────────────────────────────────────────── it('calls onClose when the close button is clicked', () => { - const onClose = jest.fn() + const onClose = vi.fn() renderForm({ onClose }) fireEvent.click(screen.getByRole('button', { name: /Schliessen/ })) expect(onClose).toHaveBeenCalledTimes(1) }) it('calls onReasonChange with the correct key when a radio is clicked', () => { - const onReasonChange = jest.fn() + const onReasonChange = vi.fn() renderForm({ onReasonChange }) fireEvent.click(screen.getByRole('radio', { name: /Auf Wunsch/ })) expect(onReasonChange).toHaveBeenCalledWith('REQUEST') diff --git a/src/components/residents/__tests__/PlacementActions.test.tsx b/src/components/residents/__tests__/PlacementActions.test.tsx index 1e529e78..34127dec 100644 --- a/src/components/residents/__tests__/PlacementActions.test.tsx +++ b/src/components/residents/__tests__/PlacementActions.test.tsx @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent } from '@testing-library/react' import { PlacementActions } from '../PlacementActions' import type { UnitWithSpots } from '@/lib/types' @@ -24,13 +24,13 @@ afterAll(() => { console.error = originalConsoleError }) -jest.mock('@/lib/actions', () => ({ - endPlacement: jest.fn(), - transferPlacement: jest.fn(), +vi.mock('@/lib/actions', () => ({ + endPlacement: vi.fn(), + transferPlacement: vi.fn(), })) -jest.mock('next/link', () => { - return function MockLink({ +vi.mock('next/link', () => { + const MockLink = function MockLink({ children, href, className, @@ -45,14 +45,15 @@ jest.mock('next/link', () => { ) } + return { default: MockLink } }) -jest.mock('@/lib/config/placement-spots', () => ({ +vi.mock('@/lib/config/placement-spots', () => ({ SPOT_TYPE_LABELS: { BED: 'Bett', PRIVATE_ROOM: 'Einzelzimmer' }, SPOT_TYPE_ICONS: { BED: '🛏', PRIVATE_ROOM: '🚪' }, })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ END_REASON_LABELS: { NATURAL_END: 'Natürliches Ende', CONFLICT: 'Konflikt', @@ -119,11 +120,12 @@ jest.mock('@/lib/constants', () => ({ }, })) -jest.mock('@/lib/config/thresholds', () => ({ +vi.mock('@/lib/config/thresholds', async () => ({ + ...(await vi.importActual>('@/lib/config/thresholds')), DISPLAY_LIMITS: { descriptionPreview: 50 }, })) -jest.mock('../TransferRecommendations', () => ({ +vi.mock('../TransferRecommendations', () => ({ TransferUnitSelector: ({ eligibleUnits, onUnitSelect, diff --git a/src/components/residents/__tests__/ResidentCardActions.test.tsx b/src/components/residents/__tests__/ResidentCardActions.test.tsx index c51d7617..c8095097 100644 --- a/src/components/residents/__tests__/ResidentCardActions.test.tsx +++ b/src/components/residents/__tests__/ResidentCardActions.test.tsx @@ -1,23 +1,23 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent, waitFor } from '@testing-library/react' import { ResidentCardActions } from '../ResidentCardActions' // --- Mocks --- -const mockPush = jest.fn() -const mockRefresh = jest.fn() -jest.mock('next/navigation', () => ({ +const mockPush = vi.hoisted(() => vi.fn()) +const mockRefresh = vi.hoisted(() => vi.fn()) +vi.mock('next/navigation', () => ({ useRouter: () => ({ push: mockPush, refresh: mockRefresh }), })) -const mockArchive = jest.fn() -const mockRestore = jest.fn() -jest.mock('@/lib/actions', () => ({ +const mockArchive = vi.hoisted(() => vi.fn()) +const mockRestore = vi.hoisted(() => vi.fn()) +vi.mock('@/lib/actions', () => ({ archiveResident: (...args: unknown[]) => mockArchive(...args), restoreResident: (...args: unknown[]) => mockRestore(...args), })) -jest.mock('@/lib/config/crud-actions', () => ({ +vi.mock('@/lib/config/crud-actions', () => ({ CRUD_ACTIONS: { edit: { label: 'Bearbeiten' }, duplicate: { label: 'Duplizieren' }, @@ -31,7 +31,7 @@ jest.mock('@/lib/config/crud-actions', () => ({ }, })) -jest.mock('@/lib/constants/labels', () => ({ +vi.mock('@/lib/constants/labels', () => ({ UI_LABELS: { actions: 'Aktionen' }, })) @@ -45,10 +45,10 @@ function openMenu() { describe('ResidentCardActions', () => { beforeAll(() => { - jest.spyOn(window, 'alert').mockImplementation(() => {}) + vi.spyOn(window, 'alert').mockImplementation(() => {}) }) - afterAll(() => jest.restoreAllMocks()) - afterEach(() => jest.clearAllMocks()) + afterAll(() => vi.restoreAllMocks()) + afterEach(() => vi.clearAllMocks()) // ── Trigger renders ────────────────────────────────────────────────────── diff --git a/src/components/residents/__tests__/ResidentDangerZone.test.tsx b/src/components/residents/__tests__/ResidentDangerZone.test.tsx index cb5a1f14..eb9c00fd 100644 --- a/src/components/residents/__tests__/ResidentDangerZone.test.tsx +++ b/src/components/residents/__tests__/ResidentDangerZone.test.tsx @@ -1,11 +1,11 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' -jest.mock('next/navigation', () => ({ - useRouter: () => ({ push: jest.fn(), refresh: jest.fn() }), +vi.mock('next/navigation', () => ({ + useRouter: () => ({ push: vi.fn(), refresh: vi.fn() }), })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ DANGER_ZONE_LABELS: { title: 'Danger Zone', description: 'Nur für Test-Bewohner.', @@ -30,8 +30,8 @@ jest.mock('@/lib/constants', () => ({ }, })) -jest.mock('@/lib/actions', () => ({ - hardDeleteResidentProtected: jest.fn().mockResolvedValue({ success: false }), +vi.mock('@/lib/actions', () => ({ + hardDeleteResidentProtected: vi.fn().mockResolvedValue({ success: false }), })) import { ResidentDangerZone } from '../ResidentDangerZone' diff --git a/src/components/residents/__tests__/ResidentsList.test.tsx b/src/components/residents/__tests__/ResidentsList.test.tsx index c44b569f..87b44a03 100644 --- a/src/components/residents/__tests__/ResidentsList.test.tsx +++ b/src/components/residents/__tests__/ResidentsList.test.tsx @@ -1,10 +1,10 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen } from '@testing-library/react' import { ResidentsList, type ResidentListItem } from '../ResidentsList' // --- Mocks --- -jest.mock('next/link', () => ({ +vi.mock('next/link', () => ({ __esModule: true, default: ({ href, @@ -21,13 +21,13 @@ jest.mock('next/link', () => ({ ), })) -jest.mock('@/components/residents/ResidentCardActions', () => ({ +vi.mock('@/components/residents/ResidentCardActions', () => ({ ResidentCardActions: ({ residentId }: { residentId: string }) => (
), })) -jest.mock('@/lib/constants', () => ({ +vi.mock('@/lib/constants', () => ({ AGE_RANGE_LABELS: { ADULT: '26-40', YOUNG_ADULT: '18-25' }, GENDER_LABELS_SHORT: { MALE: 'M', FEMALE: 'W', PREFER_NOT_SAY: '-' }, RESIDENT_STATUS_LABELS: { ACTIVE: 'Aktiv', PLACED: 'Platziert', EXITED: 'Archiviert' }, @@ -45,7 +45,7 @@ jest.mock('@/lib/constants', () => ({ getLabel: (labels: Record, key: string) => labels[key] ?? key, })) -jest.mock('@/lib/utils', () => ({ +vi.mock('@/lib/utils', () => ({ getStatusBadgeClass: (status: string) => `badge-${status.toLowerCase()}`, formatDate: (d: Date | string) => '01.01.2024', })) diff --git a/src/components/residents/__tests__/TransferForm.test.tsx b/src/components/residents/__tests__/TransferForm.test.tsx index 718a2173..076f2abc 100644 --- a/src/components/residents/__tests__/TransferForm.test.tsx +++ b/src/components/residents/__tests__/TransferForm.test.tsx @@ -1,4 +1,4 @@ -import '@testing-library/jest-dom' +import '@testing-library/jest-dom/vitest' import { render, screen, fireEvent } from '@testing-library/react' import { TransferForm } from '../TransferForm' import type { UnitWithSpots } from '@/lib/types' @@ -23,13 +23,13 @@ afterAll(() => { // --- Mocks --- -jest.mock('@/lib/actions', () => ({ - transferPlacement: jest.fn(), +vi.mock('@/lib/actions', () => ({ + transferPlacement: vi.fn(), })) // Stub TransferUnitSelector so tests stay focused on TransferForm behaviour. // Renders a plain