├── .editorconfig ├── .github └── workflows │ ├── checks.yml │ └── release.yml ├── .gitignore ├── .prettierrc ├── LICENSE ├── README.md ├── __test__ ├── tests │ ├── deep │ │ ├── deep.ts │ │ ├── index.ts │ │ └── nested │ │ │ ├── dependency │ │ │ ├── index.ts │ │ │ └── variable.ts │ │ │ ├── index.ts │ │ │ └── nested.ts │ ├── fail0.mock.ts │ ├── fail1.mock.ts │ ├── pass0.mock.ts │ ├── pass1.mock.ts │ └── variable.mock.ts ├── v2.spec.ts └── v3.spec.ts ├── example.svg ├── package-lock.json ├── package.json ├── src ├── cache.ts ├── files.ts ├── index.ts ├── load.ts ├── options.ts ├── pool.ts ├── prune.ts ├── runner.ts ├── setup.ts ├── strategy.ts ├── tests.vite.config.ts ├── util.ts ├── v2.ts ├── v3.ts └── writer.ts ├── tsconfig.json └── vite.config.ts /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.github/workflows/checks.yml: -------------------------------------------------------------------------------- 1 | name: Checks 2 | on: 3 | pull_request: 4 | branches: 5 | - main 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | name: 'Run tests' 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-node@v4.0.3 15 | with: 16 | node-version: "20" 17 | - run: npm ci 18 | - run: npm run test 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - main 6 | workflow_dispatch: 7 | 8 | jobs: 9 | build: 10 | name: 'Build & Release' 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-node@v4.0.3 15 | with: 16 | node-version: "20" 17 | - run: npm ci 18 | - run: npm run build 19 | - uses: JS-DevTools/npm-publish@v3 20 | with: 21 | token: ${{ secrets.NPM_TOKEN }} 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | dist 4 | __test__/.cache* 5 | .DS_Store 6 | __test__/tests/deep/nested/dependency/variables/* 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "always", 3 | "bracketSpacing": true, 4 | "endOfLine": "auto", 5 | "printWidth": 100, 6 | "quoteProps": "as-needed", 7 | "semi": true, 8 | "singleQuote": true, 9 | "tabWidth": 2, 10 | "trailingComma": "all", 11 | "useTabs": false 12 | } 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Nikola Pavlovic 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vite-plugin-vitest-cache [![npm](https://img.shields.io/npm/v/@raegen/vite-plugin-vitest-cache)](https://www.npmjs.com/package/@raegen/vite-plugin-vitest-cache) (vCache) 2 | 3 | ![vitest-cache-example](example.svg) 4 | 5 | 6 | > [!NOTE] 7 | > In vitest terms, the caching covers: transformation, setup, collection, running, environment and preparation of tests. All of those are skipped for cached entries in exchange for a small price of calculating the hashes. 8 | 9 | vCache provides test caching for [Vitest](https://github.com/vitest-dev/vitest). This plugin is useful for: 10 | - running non-trivial, complex, resource-intensive, or otherwise slow tests, as it enables running only the tests that are actually affected by code changes 11 | - monorepos, as it avoids the complications and limitations stemming from complex package dependency trees by ignoring module boundaries and treating everything as sources, calculating hashes from tree shaken code. 12 | 13 | ## How it Works 14 | 15 | It uses the same toolkit used for building your sources to build the test files. Hashes of these files are then used for cache matching. When running the tests, only the test files without a cache-hit (test files affected by the latest code changes for example) are run, the rest are simply restored from cache. 16 | 17 | ## How is this different from vitest `related`/`--changed` 18 | 19 | They are different tools with similar, albeit somewhat different goals/purposes. 20 | - `$ vitest related` (`--changed` is parametrized `related`) determines affected files based on imported paths 21 | - `vCache` determines affected files based on imported code 22 | 23 | ## Installation 24 | 25 | ```sh 26 | npm install --save-dev @raegen/vite-plugin-vitest-cache 27 | ``` 28 | ```sh 29 | yarn add --dev @raegen/vite-plugin-vitest-cache 30 | ``` 31 | 32 | ## Usage 33 | 34 | ```ts 35 | import { defineConfig } from "vitest"; 36 | import vCache from '@raegen/vite-plugin-vitest-cache'; 37 | 38 | export default defineConfig({ 39 | plugins: [vCache()], 40 | }); 41 | ``` 42 | 43 | ### Usage with CI 44 | 45 | The only potential obstacle here, is cache persistence across runs, contexts. Since we use filesystem for cache storage, it's just a matter of configuring the respective CI cache to include the paths used by vCache (See [dir](https://github.com/raegen/vite-plugin-vitest-cache/edit/main/README.md#dir)). 46 | 47 | #### Github Actions 48 | ```yaml 49 | jobs: 50 | test: 51 | runs-on: ubuntu-latest 52 | 53 | steps: 54 | - uses: actions/checkout@v4 55 | 56 | - name: vCache 57 | id: v-cache 58 | uses: actions/cache@v4 59 | with: 60 | path: **/.tests 61 | key: v-cache 62 | 63 | - name: Test 64 | run: ...run tests 65 | ``` 66 | 67 | #### Gitlab CI/CD 68 | ```yaml 69 | job: 70 | script: ...run tests 71 | artifacts: 72 | name: v-cache 73 | paths: 74 | - **/.tests 75 | ``` 76 | 77 | ## Options 78 | 79 | ### dir 80 | 81 | Control where the caches are saved. 82 | 83 | `@default` ".tests" (relative to the project root) 84 | 85 | ```ts 86 | vCache({ dir: ".tests" }); 87 | ``` 88 | 89 | ### states 90 | 91 | Control which result states to cache. Possible values are "pass" and "fail". 92 | 93 | `@default` ["pass"] 94 | 95 | ```ts 96 | vCache({ states: ["pass"] }); 97 | ``` 98 | 99 | ### silent 100 | 101 | Control whether vCache should write any logs to stdout. 102 | 103 | `@default` false 104 | 105 | ```ts 106 | vCache({ silent: true }); 107 | ``` 108 | 109 | ### strategy 110 | 111 | ```ts 112 | interface ExtendedCacheEntry { 113 | data: SerializedRecord; 114 | path: string; 115 | cost: number; 116 | timestamp: number; 117 | size: number; 118 | } 119 | 120 | interface CacheStrategy { 121 | (entries: ExtendedCacheEntry[]): ExtendedCacheEntry[]; 122 | } 123 | ``` 124 | 125 | Cache cleanup strategy. We can't have it grow forever, can we? Strategy is effectively a reducer for cache entries. It is invoked for each existing cache id (test file), with an array of currently stored cache entries (`entries: ExtendedCacheEntry[]`) for that id and should return an array of cache entries to be stored. (all the cache entries not present in the returned array are removed). 126 | 127 | `@default` stores last 3 USED cached entries 128 | 129 | ```ts 130 | vCache({ 131 | strategy: (entries: ExtendedCacheEntry[]) => entries.sort((a, b) => b.timestamp - a.timestamp).slice(0, 3) 132 | }) 133 | ``` 134 | 135 | 136 | ## Note 137 | 138 | > [!CAUTION] 139 | > The purpose of this plugin is not to promote what are ultimately bad test practices. Your unit tests should _NOT_ be non-trivial, complex, resource-intensive, or otherwise slow. If you find yourself in need of such tests, first and foremost evaluate whether unit testing is what you need and look into integration, E2E testing etc. 140 | -------------------------------------------------------------------------------- /__test__/tests/deep/deep.ts: -------------------------------------------------------------------------------- 1 | import { nested } from './nested'; 2 | 3 | export const deep = `deep/${nested}`; 4 | -------------------------------------------------------------------------------- /__test__/tests/deep/index.ts: -------------------------------------------------------------------------------- 1 | export * from './deep' 2 | -------------------------------------------------------------------------------- /__test__/tests/deep/nested/dependency/index.ts: -------------------------------------------------------------------------------- 1 | export * from './variable' 2 | -------------------------------------------------------------------------------- /__test__/tests/deep/nested/dependency/variable.ts: -------------------------------------------------------------------------------- 1 | export const variable = JSON.stringify( 2 | import.meta.glob<{ default: string }>('./variables/*.ts', { 3 | eager: true, 4 | }), 5 | ); 6 | -------------------------------------------------------------------------------- /__test__/tests/deep/nested/index.ts: -------------------------------------------------------------------------------- 1 | export * from './nested'; 2 | -------------------------------------------------------------------------------- /__test__/tests/deep/nested/nested.ts: -------------------------------------------------------------------------------- 1 | import { variable } from './dependency'; 2 | 3 | export const nested = `nested/${variable}` 4 | -------------------------------------------------------------------------------- /__test__/tests/fail0.mock.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | 3 | 4 | describe('fails 0', () => { 5 | it('should fail 0', async () => { 6 | expect(true).toBe(false); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /__test__/tests/fail1.mock.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | 3 | 4 | describe('fails 1', () => { 5 | it('should pass fail', async () => { 6 | expect(true).toBe(true); 7 | }); 8 | it('should fail 1', async () => { 9 | expect(true).toBe(false); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /__test__/tests/pass0.mock.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | 3 | 4 | describe('passes 0', () => { 5 | it('should pass 0', async () => { 6 | expect(true).toBe(true); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /__test__/tests/pass1.mock.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | 3 | 4 | describe('passes 1', () => { 5 | it('should pass 1', async () => { 6 | expect(true).toBe(true); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /__test__/tests/variable.mock.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, it } from 'vitest'; 2 | import { deep } from './deep'; 3 | 4 | 5 | describe('passes 2', () => { 6 | it('should pass 2', async () => { 7 | expect(deep).toBe(deep); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /__test__/v2.spec.ts: -------------------------------------------------------------------------------- 1 | import { beforeEach, describe, expect, it } from 'vitest'; 2 | import { InlineConfig, startVitest } from 'vitest/node'; 3 | import { mkdir, readdir, readFile, rm, stat, writeFile } from 'node:fs/promises'; 4 | import { dirname, resolve } from 'node:path'; 5 | import { File, Suite, Task } from '@vitest/runner'; 6 | 7 | const isPass = (task: Task | Suite | File) => { 8 | if (task.type === 'suite') { 9 | return task.tasks.every(isPass); 10 | } 11 | 12 | return task.result.state === 'pass'; 13 | }; 14 | 15 | const isCached = async (path: string) => { 16 | try { 17 | await stat(resolve(path)); 18 | return readdir(resolve(path)).then((files) => Promise.all(files.map((file) => readFile(resolve(path, file), 'utf-8').then(JSON.parse).then(({ data }) => !!data))).then((r) => r.some(Boolean))); 19 | } catch (e) { 20 | return false; 21 | } 22 | }; 23 | 24 | const writeFileRecursive = async (path: string, data: string) => { 25 | await mkdir(dirname(path), { recursive: true }); 26 | await writeFile(path, data); 27 | }; 28 | 29 | const dir = '__test__/.cache2'; 30 | 31 | const run = async (config?: InlineConfig) => { 32 | const { vCache } = await import('../src/v2'); 33 | return startVitest('test', undefined, { 34 | watch: false, 35 | include: ['__test__/tests/*.mock.ts'], 36 | reporters: [{}], 37 | ...config, 38 | }, { 39 | plugins: [vCache({ 40 | dir, 41 | silent: false, 42 | }) as any], 43 | }).then((vitest) => vitest.close().then(() => vitest)); 44 | } 45 | 46 | describe('v-cache', () => { 47 | beforeEach(async () => { 48 | if (await stat(resolve(dir)).catch(() => null)) { 49 | await rm(resolve(dir), { recursive: true }); 50 | } 51 | }); 52 | 53 | it('should cache passing tests', { 54 | timeout: 10000, 55 | }, async () => { 56 | await run(); 57 | 58 | expect(await isCached(`${dir}/pass0.mock.ts`)).toBe(true); 59 | expect(await isCached(`${dir}/pass1.mock.ts`)).toBe(true); 60 | expect(await isCached(`${dir}/variable.mock.ts`)).toBe(true); 61 | expect(await isCached(`${dir}/fail0.mock.ts`)).toBe(false); 62 | expect(await isCached(`${dir}/fail1.mock.ts`)).toBe(false); 63 | }); 64 | 65 | it('should restore cached tests from cache', async () => { 66 | let files = (await run()).state.getFiles(); 67 | 68 | for (const file of files) { 69 | expect(file.result).not.toHaveProperty('duration', 0); 70 | } 71 | 72 | const reference = Object.fromEntries(files.map((file) => [file.filepath, file])); 73 | 74 | files = (await run()).state.getFiles(); 75 | 76 | for (const file of files) { 77 | if (isPass(file)) { 78 | expect(file.result).toHaveProperty('startTime', reference[file.filepath].result.startTime); 79 | expect(file.result).toHaveProperty('duration', 0); 80 | } else { 81 | expect(file.result).not.toHaveProperty('startTime', reference[file.filepath].result.startTime); 82 | expect(file.result).not.toHaveProperty('duration', 0); 83 | } 84 | } 85 | }); 86 | 87 | it('should rerun only the tests affected by change', async () => { 88 | const reference = Object.fromEntries((await run()).state.getFiles().map((file) => [file.filepath.match(/__test__.*$/)?.[0], file])); 89 | 90 | const timestamp = Date.now(); 91 | await writeFileRecursive(resolve(`__test__/tests/deep/nested/dependency/variables/${timestamp}.ts`), `export default '${timestamp}';`); 92 | 93 | const files = Object.fromEntries((await run()).state.getFiles().flatMap((files) => files).map((file) => [file.filepath.match(/__test__.*$/)?.[0], file])); 94 | 95 | expect(files['__test__/tests/variable.mock.ts'].result).not.toHaveProperty('startTime', reference['__test__/tests/variable.mock.ts'].result.startTime); 96 | expect(files['__test__/tests/variable.mock.ts'].result).not.toHaveProperty('duration', 0); 97 | 98 | expect(files['__test__/tests/pass0.mock.ts'].result).toHaveProperty('startTime', reference['__test__/tests/pass0.mock.ts'].result.startTime); 99 | expect(files['__test__/tests/pass0.mock.ts'].result).toHaveProperty('duration', 0); 100 | 101 | expect(files['__test__/tests/pass1.mock.ts'].result).toHaveProperty('startTime', reference['__test__/tests/pass1.mock.ts'].result.startTime); 102 | expect(files['__test__/tests/pass1.mock.ts'].result).toHaveProperty('duration', 0); 103 | 104 | expect(files['__test__/tests/fail0.mock.ts'].result).not.toHaveProperty('startTime', reference['__test__/tests/fail0.mock.ts'].result.startTime); 105 | expect(files['__test__/tests/fail0.mock.ts'].result).not.toHaveProperty('duration', 0); 106 | 107 | expect(files['__test__/tests/fail1.mock.ts'].result).not.toHaveProperty('startTime', reference['__test__/tests/fail1.mock.ts'].result.startTime); 108 | expect(files['__test__/tests/fail1.mock.ts'].result).not.toHaveProperty('duration', 0); 109 | }); 110 | }); 111 | -------------------------------------------------------------------------------- /__test__/v3.spec.ts: -------------------------------------------------------------------------------- 1 | import { beforeEach, describe, expect, it } from 'vitest'; 2 | import { InlineConfig, startVitest } from 'vitest/node'; 3 | import { vCache } from '../src/v3'; 4 | import { mkdir, readdir, readFile, rm, stat, writeFile } from 'node:fs/promises'; 5 | import { dirname, resolve } from 'node:path'; 6 | import { File, Suite, Task } from '@vitest/runner'; 7 | 8 | const isPass = (task: Task | Suite | File) => { 9 | if (task.type === 'suite') { 10 | return task.tasks.every(isPass); 11 | } 12 | 13 | return task.result.state === 'pass'; 14 | }; 15 | 16 | const isCached = async (path: string) => { 17 | try { 18 | await stat(resolve(path)); 19 | return readdir(resolve(path)).then((files) => Promise.all(files.map((file) => readFile(resolve(path, file), 'utf-8').then(JSON.parse).then(({ data }) => !!data))).then((r) => r.some(Boolean))); 20 | } catch (e) { 21 | return false; 22 | } 23 | }; 24 | 25 | const writeFileRecursive = async (path: string, data: string) => { 26 | await mkdir(dirname(path), { recursive: true }); 27 | await writeFile(path, data); 28 | }; 29 | 30 | const dir = '__test__/.cache3'; 31 | 32 | const run = async (config?: InlineConfig) => startVitest('test', undefined, { 33 | watch: false, 34 | }, { 35 | plugins: [vCache({ 36 | dir, 37 | silent: false, 38 | })], 39 | test: { 40 | include: ['__test__/tests/*.mock.ts'], 41 | reporters: [{}], 42 | ...config, 43 | }, 44 | }).then((vitest) => vitest.close().then(() => vitest)); 45 | 46 | describe('v-cache', () => { 47 | beforeEach(async () => { 48 | if (await stat(resolve(dir)).catch(() => null)) { 49 | await rm(resolve(dir), { recursive: true }); 50 | } 51 | }); 52 | 53 | it('should cache passing tests', { 54 | timeout: 10000, 55 | }, async () => { 56 | await run(); 57 | 58 | expect(await isCached(`${dir}/pass0.mock.ts`)).toBe(true); 59 | expect(await isCached(`${dir}/pass1.mock.ts`)).toBe(true); 60 | expect(await isCached(`${dir}/variable.mock.ts`)).toBe(true); 61 | expect(await isCached(`${dir}/fail0.mock.ts`)).toBe(false); 62 | expect(await isCached(`${dir}/fail1.mock.ts`)).toBe(false); 63 | }); 64 | 65 | it('should restore cached tests from cache', async () => { 66 | let files = (await run()).state.getFiles(); 67 | 68 | for (const file of files) { 69 | expect(file.result).not.toHaveProperty('duration', 0); 70 | } 71 | 72 | const reference = Object.fromEntries(files.map((file) => [file.filepath, file])); 73 | 74 | files = (await run()).state.getFiles(); 75 | 76 | for (const file of files) { 77 | if (isPass(file)) { 78 | expect(file.result).toHaveProperty('startTime', reference[file.filepath].result.startTime); 79 | expect(file.result).toHaveProperty('duration', 0); 80 | } else { 81 | expect(file.result).not.toHaveProperty('startTime', reference[file.filepath].result.startTime); 82 | expect(file.result).not.toHaveProperty('duration', 0); 83 | } 84 | } 85 | }); 86 | 87 | it('should rerun only the tests affected by change', async () => { 88 | const reference = Object.fromEntries((await run()).state.getFiles().map((file) => [file.filepath.match(/__test__.*$/)?.[0], file])); 89 | 90 | const timestamp = Date.now(); 91 | await writeFileRecursive(resolve(`__test__/tests/deep/nested/dependency/variables/${timestamp}.ts`), `export default '${timestamp}';`); 92 | 93 | const files = Object.fromEntries((await run()).state.getFiles().flatMap((files) => files).map((file) => [file.filepath.match(/__test__.*$/)?.[0], file])); 94 | 95 | expect(files['__test__/tests/variable.mock.ts'].result).not.toHaveProperty('startTime', reference['__test__/tests/variable.mock.ts'].result.startTime); 96 | expect(files['__test__/tests/variable.mock.ts'].result).not.toHaveProperty('duration', 0); 97 | 98 | expect(files['__test__/tests/pass0.mock.ts'].result).toHaveProperty('startTime', reference['__test__/tests/pass0.mock.ts'].result.startTime); 99 | expect(files['__test__/tests/pass0.mock.ts'].result).toHaveProperty('duration', 0); 100 | 101 | expect(files['__test__/tests/pass1.mock.ts'].result).toHaveProperty('startTime', reference['__test__/tests/pass1.mock.ts'].result.startTime); 102 | expect(files['__test__/tests/pass1.mock.ts'].result).toHaveProperty('duration', 0); 103 | 104 | expect(files['__test__/tests/fail0.mock.ts'].result).not.toHaveProperty('startTime', reference['__test__/tests/fail0.mock.ts'].result.startTime); 105 | expect(files['__test__/tests/fail0.mock.ts'].result).not.toHaveProperty('duration', 0); 106 | 107 | expect(files['__test__/tests/fail1.mock.ts'].result).not.toHaveProperty('startTime', reference['__test__/tests/fail1.mock.ts'].result.startTime); 108 | expect(files['__test__/tests/fail1.mock.ts'].result).not.toHaveProperty('duration', 0); 109 | }); 110 | }); 111 | -------------------------------------------------------------------------------- /example.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
[vCache] 0.3.0
 6 | [vCache] built hashes in 6.02s
 7 |   src/epsga/SD/siCueitommn/ssoMsnii/ormF/mFro.spec.tsx  (10 tests)
10 |   src/agsep/DS/pnsgimCaa/ystcnaila/prAsgainwnvOeCatvacilmeyi/ttses____/ixend.spec.tsx  (7 tests)
12 |   src/saepg/DS/agmsinapC/itepnCpSamsga/gmpSnCtpaaieu/mgrmpoaFinaC/bLmcoekFeodaarFo/ioselnlitPusefQr/luits.spec.tsx  (8 tests)
14 |   src/pgeas/DS/msgpinCaa/gatppnsaimCSe/atppeSugaimnC/lUFoprwFlmoo/mtTTWcepDAottltearoasFnamhpevraop.spec.tsx  (5 tests)
16 |   src/apegs/DS/aCsmpanig/sCioasmpMniiagn/oismnanwosFiipCaglM/setst/oisulwmilnpfoos-.spec.tsx   (1 test)
18 |   src/pegsa/SD/Cmasipnag/nmmySgCupramaai/ocpontemsn/aeerHd/nxied.spec.tsx  (2 tests)
20 |   src/epasg/DS/asnmCpgai/SeanismgCappt/mSepCptagiuna/pmoFUFlowlor/PUptaxhgNltlotoeweF.spec.tsx  (6 tests)
22 |   src/sgpae/SD/pamaCsign/awlgFpnoiCam/ibSader/esrtuo/twitoSFsepUollgn/litus.spec.tsx  (5 tests)
24 |   src/eagps/DS/nsaigmpCa/igeanstSpCapm/aSgniCumptpea/loFwUolmporF/wcorlyoloUrtFpFmoaF/rtooaFplomFcyorUlwF.spec.tsx  (6 tests)
26 |   src/psage/SD/oemutmsiiCn/scatAylin/sMbemre/secbcteemrdeMAp/tApceMbcdesemre.spec.tsx  (3 tests)
28 |   src/gasep/DS/sCiaamngp/magyrmnCamaiSpu/osnpcmnote/trRleDisagtoa/xenid.spec.tsx  (3 tests)
30 |   src/aesgp/SD/mimsueoitCn/aityAclns/mbreeMs/rdiDceeMbesnmle/leMndcreiDbmees.spec.tsx  (3 tests)
32 |   src/ennoscoptm/waeipApheWsvrPt/WCPmovprpTrPAesehroFsewttvpransoiueo.spec.tsx  (6 tests)
34 |   src/apegs/DS/Caiasmnpg/ppCesmantigSa/nutCapSapmeig/poFlFoomwlrU/_s_s_tet_/u-falol-mwlpioe.spec.tsx  (2 tests)
36 |   src/doainm/lUolFpow/EFtptllUpnyiwAlorpoaov.spec.tsx  (1 test)
38 |   src/apseg/DS/iuoCmeitnsm/aytAlcsni/ebsMrme/gemeMsidnnrPeb/esrednPbMnmige.spec.tsx  (2 tests)
40 |   src/gsape/SD/etnisCuimmo/eenmgstS/rbemseM/bsmrMee.spec.tsx  (2 tests)
42 |   src/apegs/SD/eiCnomutmis/ennmtocosp/BdairnnegetW/endxi.spec.tsx  (2 tests)
44 |   src/iults/siacnmgpa/otleloolrtpSmeTcFpwteaisoengOteplU.spec.tsx  (7 tests)
46 |   src/tnopseconm/PodocagFeevrkerePsFaaieomwbL/tnrIo/rineisGttLeg.spec.tsx  (3 tests) 29533ms
48 |   src/spaeg/SD/eCmiomnistu/netgSsem/esgLstSinemt/StLsenigestm.spec.tsx  (2 tests) 6995ms
50 |   src/ltuis/s_tet__s_/rtoamfaeDt.spec.tsx  (4 tests) 5208ms
52 |   src/gsape/SD/snagpiamC/lCpawoimFgna/Mnai/lwoF/sdeno/aedTlNimDyoee/st_t_e_s_/lisut.spec.tsx  (5 tests) 21713ms
54 |   src/pAp.spec.tsx  (9 tests) 12001ms
56 |   src/pgsae/SD/pnagamCsi/ayCnaraummpgimS/tomsnncpoe/woFl/oensmpotcn/opwolFlU/sulit.spec.tsx  (4 tests)
58 |  Test Files  25 passed (25)
61 |       Tests  108 passed (108)
64 |    Start at  12:42:04
65 |    Duration  10.36s (transform 32ms, setup 129.76s, collect 307.15s, tests 0ms, environment 1.31s, prepare 17.14s)
66 | [vCache] 20/25 files read from cache
68 |
69 |
70 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@raegen/vite-plugin-vitest-cache", 3 | "version": "0.3.6", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@raegen/vite-plugin-vitest-cache", 9 | "version": "0.3.6", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@ungap/structured-clone": "^1.2.0", 13 | "chalk": "^5.3.0", 14 | "fast-glob": "^3.3.2", 15 | "vite": "^6.2.2" 16 | }, 17 | "devDependencies": { 18 | "@types/node": "^20.10.0", 19 | "@types/ungap__structured-clone": "^1.2.0", 20 | "@vitest2/runner": "npm:@vitest/runner@^2.1.9", 21 | "typescript": "^5.4.5", 22 | "vite": "^6.2.2", 23 | "vitest": "^3.0.8", 24 | "vitest2": "npm:vitest@^2.1.9" 25 | }, 26 | "peerDependencies": { 27 | "@vitest/runner": ">=1.1.0", 28 | "vitest": ">=1.1.0" 29 | } 30 | }, 31 | "node_modules/@esbuild/aix-ppc64": { 32 | "version": "0.25.1", 33 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.1.tgz", 34 | "integrity": "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ==", 35 | "cpu": [ 36 | "ppc64" 37 | ], 38 | "dev": true, 39 | "license": "MIT", 40 | "optional": true, 41 | "os": [ 42 | "aix" 43 | ], 44 | "engines": { 45 | "node": ">=18" 46 | } 47 | }, 48 | "node_modules/@esbuild/android-arm": { 49 | "version": "0.25.1", 50 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.1.tgz", 51 | "integrity": "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q==", 52 | "cpu": [ 53 | "arm" 54 | ], 55 | "dev": true, 56 | "license": "MIT", 57 | "optional": true, 58 | "os": [ 59 | "android" 60 | ], 61 | "engines": { 62 | "node": ">=18" 63 | } 64 | }, 65 | "node_modules/@esbuild/android-arm64": { 66 | "version": "0.25.1", 67 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.1.tgz", 68 | "integrity": "sha512-50tM0zCJW5kGqgG7fQ7IHvQOcAn9TKiVRuQ/lN0xR+T2lzEFvAi1ZcS8DiksFcEpf1t/GYOeOfCAgDHFpkiSmA==", 69 | "cpu": [ 70 | "arm64" 71 | ], 72 | "dev": true, 73 | "license": "MIT", 74 | "optional": true, 75 | "os": [ 76 | "android" 77 | ], 78 | "engines": { 79 | "node": ">=18" 80 | } 81 | }, 82 | "node_modules/@esbuild/android-x64": { 83 | "version": "0.25.1", 84 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.1.tgz", 85 | "integrity": "sha512-GCj6WfUtNldqUzYkN/ITtlhwQqGWu9S45vUXs7EIYf+7rCiiqH9bCloatO9VhxsL0Pji+PF4Lz2XXCES+Q8hDw==", 86 | "cpu": [ 87 | "x64" 88 | ], 89 | "dev": true, 90 | "license": "MIT", 91 | "optional": true, 92 | "os": [ 93 | "android" 94 | ], 95 | "engines": { 96 | "node": ">=18" 97 | } 98 | }, 99 | "node_modules/@esbuild/darwin-arm64": { 100 | "version": "0.25.1", 101 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.1.tgz", 102 | "integrity": "sha512-5hEZKPf+nQjYoSr/elb62U19/l1mZDdqidGfmFutVUjjUZrOazAtwK+Kr+3y0C/oeJfLlxo9fXb1w7L+P7E4FQ==", 103 | "cpu": [ 104 | "arm64" 105 | ], 106 | "dev": true, 107 | "license": "MIT", 108 | "optional": true, 109 | "os": [ 110 | "darwin" 111 | ], 112 | "engines": { 113 | "node": ">=18" 114 | } 115 | }, 116 | "node_modules/@esbuild/darwin-x64": { 117 | "version": "0.25.1", 118 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.1.tgz", 119 | "integrity": "sha512-hxVnwL2Dqs3fM1IWq8Iezh0cX7ZGdVhbTfnOy5uURtao5OIVCEyj9xIzemDi7sRvKsuSdtCAhMKarxqtlyVyfA==", 120 | "cpu": [ 121 | "x64" 122 | ], 123 | "dev": true, 124 | "license": "MIT", 125 | "optional": true, 126 | "os": [ 127 | "darwin" 128 | ], 129 | "engines": { 130 | "node": ">=18" 131 | } 132 | }, 133 | "node_modules/@esbuild/freebsd-arm64": { 134 | "version": "0.25.1", 135 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.1.tgz", 136 | "integrity": "sha512-1MrCZs0fZa2g8E+FUo2ipw6jw5qqQiH+tERoS5fAfKnRx6NXH31tXBKI3VpmLijLH6yriMZsxJtaXUyFt/8Y4A==", 137 | "cpu": [ 138 | "arm64" 139 | ], 140 | "dev": true, 141 | "license": "MIT", 142 | "optional": true, 143 | "os": [ 144 | "freebsd" 145 | ], 146 | "engines": { 147 | "node": ">=18" 148 | } 149 | }, 150 | "node_modules/@esbuild/freebsd-x64": { 151 | "version": "0.25.1", 152 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.1.tgz", 153 | "integrity": "sha512-0IZWLiTyz7nm0xuIs0q1Y3QWJC52R8aSXxe40VUxm6BB1RNmkODtW6LHvWRrGiICulcX7ZvyH6h5fqdLu4gkww==", 154 | "cpu": [ 155 | "x64" 156 | ], 157 | "dev": true, 158 | "license": "MIT", 159 | "optional": true, 160 | "os": [ 161 | "freebsd" 162 | ], 163 | "engines": { 164 | "node": ">=18" 165 | } 166 | }, 167 | "node_modules/@esbuild/linux-arm": { 168 | "version": "0.25.1", 169 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.1.tgz", 170 | "integrity": "sha512-NdKOhS4u7JhDKw9G3cY6sWqFcnLITn6SqivVArbzIaf3cemShqfLGHYMx8Xlm/lBit3/5d7kXvriTUGa5YViuQ==", 171 | "cpu": [ 172 | "arm" 173 | ], 174 | "dev": true, 175 | "license": "MIT", 176 | "optional": true, 177 | "os": [ 178 | "linux" 179 | ], 180 | "engines": { 181 | "node": ">=18" 182 | } 183 | }, 184 | "node_modules/@esbuild/linux-arm64": { 185 | "version": "0.25.1", 186 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.1.tgz", 187 | "integrity": "sha512-jaN3dHi0/DDPelk0nLcXRm1q7DNJpjXy7yWaWvbfkPvI+7XNSc/lDOnCLN7gzsyzgu6qSAmgSvP9oXAhP973uQ==", 188 | "cpu": [ 189 | "arm64" 190 | ], 191 | "dev": true, 192 | "license": "MIT", 193 | "optional": true, 194 | "os": [ 195 | "linux" 196 | ], 197 | "engines": { 198 | "node": ">=18" 199 | } 200 | }, 201 | "node_modules/@esbuild/linux-ia32": { 202 | "version": "0.25.1", 203 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.1.tgz", 204 | "integrity": "sha512-OJykPaF4v8JidKNGz8c/q1lBO44sQNUQtq1KktJXdBLn1hPod5rE/Hko5ugKKZd+D2+o1a9MFGUEIUwO2YfgkQ==", 205 | "cpu": [ 206 | "ia32" 207 | ], 208 | "dev": true, 209 | "license": "MIT", 210 | "optional": true, 211 | "os": [ 212 | "linux" 213 | ], 214 | "engines": { 215 | "node": ">=18" 216 | } 217 | }, 218 | "node_modules/@esbuild/linux-loong64": { 219 | "version": "0.25.1", 220 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.1.tgz", 221 | "integrity": "sha512-nGfornQj4dzcq5Vp835oM/o21UMlXzn79KobKlcs3Wz9smwiifknLy4xDCLUU0BWp7b/houtdrgUz7nOGnfIYg==", 222 | "cpu": [ 223 | "loong64" 224 | ], 225 | "dev": true, 226 | "license": "MIT", 227 | "optional": true, 228 | "os": [ 229 | "linux" 230 | ], 231 | "engines": { 232 | "node": ">=18" 233 | } 234 | }, 235 | "node_modules/@esbuild/linux-mips64el": { 236 | "version": "0.25.1", 237 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.1.tgz", 238 | "integrity": "sha512-1osBbPEFYwIE5IVB/0g2X6i1qInZa1aIoj1TdL4AaAb55xIIgbg8Doq6a5BzYWgr+tEcDzYH67XVnTmUzL+nXg==", 239 | "cpu": [ 240 | "mips64el" 241 | ], 242 | "dev": true, 243 | "license": "MIT", 244 | "optional": true, 245 | "os": [ 246 | "linux" 247 | ], 248 | "engines": { 249 | "node": ">=18" 250 | } 251 | }, 252 | "node_modules/@esbuild/linux-ppc64": { 253 | "version": "0.25.1", 254 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.1.tgz", 255 | "integrity": "sha512-/6VBJOwUf3TdTvJZ82qF3tbLuWsscd7/1w+D9LH0W/SqUgM5/JJD0lrJ1fVIfZsqB6RFmLCe0Xz3fmZc3WtyVg==", 256 | "cpu": [ 257 | "ppc64" 258 | ], 259 | "dev": true, 260 | "license": "MIT", 261 | "optional": true, 262 | "os": [ 263 | "linux" 264 | ], 265 | "engines": { 266 | "node": ">=18" 267 | } 268 | }, 269 | "node_modules/@esbuild/linux-riscv64": { 270 | "version": "0.25.1", 271 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.1.tgz", 272 | "integrity": "sha512-nSut/Mx5gnilhcq2yIMLMe3Wl4FK5wx/o0QuuCLMtmJn+WeWYoEGDN1ipcN72g1WHsnIbxGXd4i/MF0gTcuAjQ==", 273 | "cpu": [ 274 | "riscv64" 275 | ], 276 | "dev": true, 277 | "license": "MIT", 278 | "optional": true, 279 | "os": [ 280 | "linux" 281 | ], 282 | "engines": { 283 | "node": ">=18" 284 | } 285 | }, 286 | "node_modules/@esbuild/linux-s390x": { 287 | "version": "0.25.1", 288 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.1.tgz", 289 | "integrity": "sha512-cEECeLlJNfT8kZHqLarDBQso9a27o2Zd2AQ8USAEoGtejOrCYHNtKP8XQhMDJMtthdF4GBmjR2au3x1udADQQQ==", 290 | "cpu": [ 291 | "s390x" 292 | ], 293 | "dev": true, 294 | "license": "MIT", 295 | "optional": true, 296 | "os": [ 297 | "linux" 298 | ], 299 | "engines": { 300 | "node": ">=18" 301 | } 302 | }, 303 | "node_modules/@esbuild/linux-x64": { 304 | "version": "0.25.1", 305 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.1.tgz", 306 | "integrity": "sha512-xbfUhu/gnvSEg+EGovRc+kjBAkrvtk38RlerAzQxvMzlB4fXpCFCeUAYzJvrnhFtdeyVCDANSjJvOvGYoeKzFA==", 307 | "cpu": [ 308 | "x64" 309 | ], 310 | "dev": true, 311 | "license": "MIT", 312 | "optional": true, 313 | "os": [ 314 | "linux" 315 | ], 316 | "engines": { 317 | "node": ">=18" 318 | } 319 | }, 320 | "node_modules/@esbuild/netbsd-arm64": { 321 | "version": "0.25.1", 322 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.1.tgz", 323 | "integrity": "sha512-O96poM2XGhLtpTh+s4+nP7YCCAfb4tJNRVZHfIE7dgmax+yMP2WgMd2OecBuaATHKTHsLWHQeuaxMRnCsH8+5g==", 324 | "cpu": [ 325 | "arm64" 326 | ], 327 | "dev": true, 328 | "license": "MIT", 329 | "optional": true, 330 | "os": [ 331 | "netbsd" 332 | ], 333 | "engines": { 334 | "node": ">=18" 335 | } 336 | }, 337 | "node_modules/@esbuild/netbsd-x64": { 338 | "version": "0.25.1", 339 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.1.tgz", 340 | "integrity": "sha512-X53z6uXip6KFXBQ+Krbx25XHV/NCbzryM6ehOAeAil7X7oa4XIq+394PWGnwaSQ2WRA0KI6PUO6hTO5zeF5ijA==", 341 | "cpu": [ 342 | "x64" 343 | ], 344 | "dev": true, 345 | "license": "MIT", 346 | "optional": true, 347 | "os": [ 348 | "netbsd" 349 | ], 350 | "engines": { 351 | "node": ">=18" 352 | } 353 | }, 354 | "node_modules/@esbuild/openbsd-arm64": { 355 | "version": "0.25.1", 356 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.1.tgz", 357 | "integrity": "sha512-Na9T3szbXezdzM/Kfs3GcRQNjHzM6GzFBeU1/6IV/npKP5ORtp9zbQjvkDJ47s6BCgaAZnnnu/cY1x342+MvZg==", 358 | "cpu": [ 359 | "arm64" 360 | ], 361 | "dev": true, 362 | "license": "MIT", 363 | "optional": true, 364 | "os": [ 365 | "openbsd" 366 | ], 367 | "engines": { 368 | "node": ">=18" 369 | } 370 | }, 371 | "node_modules/@esbuild/openbsd-x64": { 372 | "version": "0.25.1", 373 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.1.tgz", 374 | "integrity": "sha512-T3H78X2h1tszfRSf+txbt5aOp/e7TAz3ptVKu9Oyir3IAOFPGV6O9c2naym5TOriy1l0nNf6a4X5UXRZSGX/dw==", 375 | "cpu": [ 376 | "x64" 377 | ], 378 | "dev": true, 379 | "license": "MIT", 380 | "optional": true, 381 | "os": [ 382 | "openbsd" 383 | ], 384 | "engines": { 385 | "node": ">=18" 386 | } 387 | }, 388 | "node_modules/@esbuild/sunos-x64": { 389 | "version": "0.25.1", 390 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.1.tgz", 391 | "integrity": "sha512-2H3RUvcmULO7dIE5EWJH8eubZAI4xw54H1ilJnRNZdeo8dTADEZ21w6J22XBkXqGJbe0+wnNJtw3UXRoLJnFEg==", 392 | "cpu": [ 393 | "x64" 394 | ], 395 | "dev": true, 396 | "license": "MIT", 397 | "optional": true, 398 | "os": [ 399 | "sunos" 400 | ], 401 | "engines": { 402 | "node": ">=18" 403 | } 404 | }, 405 | "node_modules/@esbuild/win32-arm64": { 406 | "version": "0.25.1", 407 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.1.tgz", 408 | "integrity": "sha512-GE7XvrdOzrb+yVKB9KsRMq+7a2U/K5Cf/8grVFRAGJmfADr/e/ODQ134RK2/eeHqYV5eQRFxb1hY7Nr15fv1NQ==", 409 | "cpu": [ 410 | "arm64" 411 | ], 412 | "dev": true, 413 | "license": "MIT", 414 | "optional": true, 415 | "os": [ 416 | "win32" 417 | ], 418 | "engines": { 419 | "node": ">=18" 420 | } 421 | }, 422 | "node_modules/@esbuild/win32-ia32": { 423 | "version": "0.25.1", 424 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.1.tgz", 425 | "integrity": "sha512-uOxSJCIcavSiT6UnBhBzE8wy3n0hOkJsBOzy7HDAuTDE++1DJMRRVCPGisULScHL+a/ZwdXPpXD3IyFKjA7K8A==", 426 | "cpu": [ 427 | "ia32" 428 | ], 429 | "dev": true, 430 | "license": "MIT", 431 | "optional": true, 432 | "os": [ 433 | "win32" 434 | ], 435 | "engines": { 436 | "node": ">=18" 437 | } 438 | }, 439 | "node_modules/@esbuild/win32-x64": { 440 | "version": "0.25.1", 441 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.1.tgz", 442 | "integrity": "sha512-Y1EQdcfwMSeQN/ujR5VayLOJ1BHaK+ssyk0AEzPjC+t1lITgsnccPqFjb6V+LsTp/9Iov4ysfjxLaGJ9RPtkVg==", 443 | "cpu": [ 444 | "x64" 445 | ], 446 | "dev": true, 447 | "license": "MIT", 448 | "optional": true, 449 | "os": [ 450 | "win32" 451 | ], 452 | "engines": { 453 | "node": ">=18" 454 | } 455 | }, 456 | "node_modules/@jridgewell/sourcemap-codec": { 457 | "version": "1.5.0", 458 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 459 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 460 | "dev": true, 461 | "license": "MIT" 462 | }, 463 | "node_modules/@nodelib/fs.scandir": { 464 | "version": "2.1.5", 465 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 466 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 467 | "dependencies": { 468 | "@nodelib/fs.stat": "2.0.5", 469 | "run-parallel": "^1.1.9" 470 | }, 471 | "engines": { 472 | "node": ">= 8" 473 | } 474 | }, 475 | "node_modules/@nodelib/fs.stat": { 476 | "version": "2.0.5", 477 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 478 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 479 | "engines": { 480 | "node": ">= 8" 481 | } 482 | }, 483 | "node_modules/@nodelib/fs.walk": { 484 | "version": "1.2.8", 485 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 486 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 487 | "dependencies": { 488 | "@nodelib/fs.scandir": "2.1.5", 489 | "fastq": "^1.6.0" 490 | }, 491 | "engines": { 492 | "node": ">= 8" 493 | } 494 | }, 495 | "node_modules/@rollup/rollup-android-arm-eabi": { 496 | "version": "4.35.0", 497 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.35.0.tgz", 498 | "integrity": "sha512-uYQ2WfPaqz5QtVgMxfN6NpLD+no0MYHDBywl7itPYd3K5TjjSghNKmX8ic9S8NU8w81NVhJv/XojcHptRly7qQ==", 499 | "cpu": [ 500 | "arm" 501 | ], 502 | "dev": true, 503 | "license": "MIT", 504 | "optional": true, 505 | "os": [ 506 | "android" 507 | ] 508 | }, 509 | "node_modules/@rollup/rollup-android-arm64": { 510 | "version": "4.35.0", 511 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.35.0.tgz", 512 | "integrity": "sha512-FtKddj9XZudurLhdJnBl9fl6BwCJ3ky8riCXjEw3/UIbjmIY58ppWwPEvU3fNu+W7FUsAsB1CdH+7EQE6CXAPA==", 513 | "cpu": [ 514 | "arm64" 515 | ], 516 | "dev": true, 517 | "license": "MIT", 518 | "optional": true, 519 | "os": [ 520 | "android" 521 | ] 522 | }, 523 | "node_modules/@rollup/rollup-darwin-arm64": { 524 | "version": "4.35.0", 525 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.35.0.tgz", 526 | "integrity": "sha512-Uk+GjOJR6CY844/q6r5DR/6lkPFOw0hjfOIzVx22THJXMxktXG6CbejseJFznU8vHcEBLpiXKY3/6xc+cBm65Q==", 527 | "cpu": [ 528 | "arm64" 529 | ], 530 | "dev": true, 531 | "license": "MIT", 532 | "optional": true, 533 | "os": [ 534 | "darwin" 535 | ] 536 | }, 537 | "node_modules/@rollup/rollup-darwin-x64": { 538 | "version": "4.35.0", 539 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.35.0.tgz", 540 | "integrity": "sha512-3IrHjfAS6Vkp+5bISNQnPogRAW5GAV1n+bNCrDwXmfMHbPl5EhTmWtfmwlJxFRUCBZ+tZ/OxDyU08aF6NI/N5Q==", 541 | "cpu": [ 542 | "x64" 543 | ], 544 | "dev": true, 545 | "license": "MIT", 546 | "optional": true, 547 | "os": [ 548 | "darwin" 549 | ] 550 | }, 551 | "node_modules/@rollup/rollup-freebsd-arm64": { 552 | "version": "4.35.0", 553 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.35.0.tgz", 554 | "integrity": "sha512-sxjoD/6F9cDLSELuLNnY0fOrM9WA0KrM0vWm57XhrIMf5FGiN8D0l7fn+bpUeBSU7dCgPV2oX4zHAsAXyHFGcQ==", 555 | "cpu": [ 556 | "arm64" 557 | ], 558 | "dev": true, 559 | "license": "MIT", 560 | "optional": true, 561 | "os": [ 562 | "freebsd" 563 | ] 564 | }, 565 | "node_modules/@rollup/rollup-freebsd-x64": { 566 | "version": "4.35.0", 567 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.35.0.tgz", 568 | "integrity": "sha512-2mpHCeRuD1u/2kruUiHSsnjWtHjqVbzhBkNVQ1aVD63CcexKVcQGwJ2g5VphOd84GvxfSvnnlEyBtQCE5hxVVw==", 569 | "cpu": [ 570 | "x64" 571 | ], 572 | "dev": true, 573 | "license": "MIT", 574 | "optional": true, 575 | "os": [ 576 | "freebsd" 577 | ] 578 | }, 579 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 580 | "version": "4.35.0", 581 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.35.0.tgz", 582 | "integrity": "sha512-mrA0v3QMy6ZSvEuLs0dMxcO2LnaCONs1Z73GUDBHWbY8tFFocM6yl7YyMu7rz4zS81NDSqhrUuolyZXGi8TEqg==", 583 | "cpu": [ 584 | "arm" 585 | ], 586 | "dev": true, 587 | "license": "MIT", 588 | "optional": true, 589 | "os": [ 590 | "linux" 591 | ] 592 | }, 593 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 594 | "version": "4.35.0", 595 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.35.0.tgz", 596 | "integrity": "sha512-DnYhhzcvTAKNexIql8pFajr0PiDGrIsBYPRvCKlA5ixSS3uwo/CWNZxB09jhIapEIg945KOzcYEAGGSmTSpk7A==", 597 | "cpu": [ 598 | "arm" 599 | ], 600 | "dev": true, 601 | "license": "MIT", 602 | "optional": true, 603 | "os": [ 604 | "linux" 605 | ] 606 | }, 607 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 608 | "version": "4.35.0", 609 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.35.0.tgz", 610 | "integrity": "sha512-uagpnH2M2g2b5iLsCTZ35CL1FgyuzzJQ8L9VtlJ+FckBXroTwNOaD0z0/UF+k5K3aNQjbm8LIVpxykUOQt1m/A==", 611 | "cpu": [ 612 | "arm64" 613 | ], 614 | "dev": true, 615 | "license": "MIT", 616 | "optional": true, 617 | "os": [ 618 | "linux" 619 | ] 620 | }, 621 | "node_modules/@rollup/rollup-linux-arm64-musl": { 622 | "version": "4.35.0", 623 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.35.0.tgz", 624 | "integrity": "sha512-XQxVOCd6VJeHQA/7YcqyV0/88N6ysSVzRjJ9I9UA/xXpEsjvAgDTgH3wQYz5bmr7SPtVK2TsP2fQ2N9L4ukoUg==", 625 | "cpu": [ 626 | "arm64" 627 | ], 628 | "dev": true, 629 | "license": "MIT", 630 | "optional": true, 631 | "os": [ 632 | "linux" 633 | ] 634 | }, 635 | "node_modules/@rollup/rollup-linux-loongarch64-gnu": { 636 | "version": "4.35.0", 637 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.35.0.tgz", 638 | "integrity": "sha512-5pMT5PzfgwcXEwOaSrqVsz/LvjDZt+vQ8RT/70yhPU06PTuq8WaHhfT1LW+cdD7mW6i/J5/XIkX/1tCAkh1W6g==", 639 | "cpu": [ 640 | "loong64" 641 | ], 642 | "dev": true, 643 | "license": "MIT", 644 | "optional": true, 645 | "os": [ 646 | "linux" 647 | ] 648 | }, 649 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 650 | "version": "4.35.0", 651 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.35.0.tgz", 652 | "integrity": "sha512-c+zkcvbhbXF98f4CtEIP1EBA/lCic5xB0lToneZYvMeKu5Kamq3O8gqrxiYYLzlZH6E3Aq+TSW86E4ay8iD8EA==", 653 | "cpu": [ 654 | "ppc64" 655 | ], 656 | "dev": true, 657 | "license": "MIT", 658 | "optional": true, 659 | "os": [ 660 | "linux" 661 | ] 662 | }, 663 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 664 | "version": "4.35.0", 665 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.35.0.tgz", 666 | "integrity": "sha512-s91fuAHdOwH/Tad2tzTtPX7UZyytHIRR6V4+2IGlV0Cej5rkG0R61SX4l4y9sh0JBibMiploZx3oHKPnQBKe4g==", 667 | "cpu": [ 668 | "riscv64" 669 | ], 670 | "dev": true, 671 | "license": "MIT", 672 | "optional": true, 673 | "os": [ 674 | "linux" 675 | ] 676 | }, 677 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 678 | "version": "4.35.0", 679 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.35.0.tgz", 680 | "integrity": "sha512-hQRkPQPLYJZYGP+Hj4fR9dDBMIM7zrzJDWFEMPdTnTy95Ljnv0/4w/ixFw3pTBMEuuEuoqtBINYND4M7ujcuQw==", 681 | "cpu": [ 682 | "s390x" 683 | ], 684 | "dev": true, 685 | "license": "MIT", 686 | "optional": true, 687 | "os": [ 688 | "linux" 689 | ] 690 | }, 691 | "node_modules/@rollup/rollup-linux-x64-gnu": { 692 | "version": "4.35.0", 693 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.35.0.tgz", 694 | "integrity": "sha512-Pim1T8rXOri+0HmV4CdKSGrqcBWX0d1HoPnQ0uw0bdp1aP5SdQVNBy8LjYncvnLgu3fnnCt17xjWGd4cqh8/hA==", 695 | "cpu": [ 696 | "x64" 697 | ], 698 | "dev": true, 699 | "license": "MIT", 700 | "optional": true, 701 | "os": [ 702 | "linux" 703 | ] 704 | }, 705 | "node_modules/@rollup/rollup-linux-x64-musl": { 706 | "version": "4.35.0", 707 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.35.0.tgz", 708 | "integrity": "sha512-QysqXzYiDvQWfUiTm8XmJNO2zm9yC9P/2Gkrwg2dH9cxotQzunBHYr6jk4SujCTqnfGxduOmQcI7c2ryuW8XVg==", 709 | "cpu": [ 710 | "x64" 711 | ], 712 | "dev": true, 713 | "license": "MIT", 714 | "optional": true, 715 | "os": [ 716 | "linux" 717 | ] 718 | }, 719 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 720 | "version": "4.35.0", 721 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.35.0.tgz", 722 | "integrity": "sha512-OUOlGqPkVJCdJETKOCEf1mw848ZyJ5w50/rZ/3IBQVdLfR5jk/6Sr5m3iO2tdPgwo0x7VcncYuOvMhBWZq8ayg==", 723 | "cpu": [ 724 | "arm64" 725 | ], 726 | "dev": true, 727 | "license": "MIT", 728 | "optional": true, 729 | "os": [ 730 | "win32" 731 | ] 732 | }, 733 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 734 | "version": "4.35.0", 735 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.35.0.tgz", 736 | "integrity": "sha512-2/lsgejMrtwQe44glq7AFFHLfJBPafpsTa6JvP2NGef/ifOa4KBoglVf7AKN7EV9o32evBPRqfg96fEHzWo5kw==", 737 | "cpu": [ 738 | "ia32" 739 | ], 740 | "dev": true, 741 | "license": "MIT", 742 | "optional": true, 743 | "os": [ 744 | "win32" 745 | ] 746 | }, 747 | "node_modules/@rollup/rollup-win32-x64-msvc": { 748 | "version": "4.35.0", 749 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.35.0.tgz", 750 | "integrity": "sha512-PIQeY5XDkrOysbQblSW7v3l1MDZzkTEzAfTPkj5VAu3FW8fS4ynyLg2sINp0fp3SjZ8xkRYpLqoKcYqAkhU1dw==", 751 | "cpu": [ 752 | "x64" 753 | ], 754 | "dev": true, 755 | "license": "MIT", 756 | "optional": true, 757 | "os": [ 758 | "win32" 759 | ] 760 | }, 761 | "node_modules/@types/estree": { 762 | "version": "1.0.6", 763 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 764 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 765 | "dev": true, 766 | "license": "MIT" 767 | }, 768 | "node_modules/@types/node": { 769 | "version": "20.14.15", 770 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.15.tgz", 771 | "integrity": "sha512-Fz1xDMCF/B00/tYSVMlmK7hVeLh7jE5f3B7X1/hmV0MJBwE27KlS7EvD/Yp+z1lm8mVhwV5w+n8jOZG8AfTlKw==", 772 | "dev": true, 773 | "dependencies": { 774 | "undici-types": "~5.26.4" 775 | } 776 | }, 777 | "node_modules/@types/ungap__structured-clone": { 778 | "version": "1.2.0", 779 | "resolved": "https://registry.npmjs.org/@types/ungap__structured-clone/-/ungap__structured-clone-1.2.0.tgz", 780 | "integrity": "sha512-ZoaihZNLeZSxESbk9PUAPZOlSpcKx81I1+4emtULDVmBLkYutTcMlCj2K9VNlf9EWODxdO6gkAqEaLorXwZQVA==", 781 | "dev": true 782 | }, 783 | "node_modules/@ungap/structured-clone": { 784 | "version": "1.2.0", 785 | "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", 786 | "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==" 787 | }, 788 | "node_modules/@vitest/expect": { 789 | "version": "3.0.8", 790 | "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.8.tgz", 791 | "integrity": "sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==", 792 | "dev": true, 793 | "license": "MIT", 794 | "dependencies": { 795 | "@vitest/spy": "3.0.8", 796 | "@vitest/utils": "3.0.8", 797 | "chai": "^5.2.0", 798 | "tinyrainbow": "^2.0.0" 799 | }, 800 | "funding": { 801 | "url": "https://opencollective.com/vitest" 802 | } 803 | }, 804 | "node_modules/@vitest/mocker": { 805 | "version": "3.0.8", 806 | "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.8.tgz", 807 | "integrity": "sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==", 808 | "dev": true, 809 | "license": "MIT", 810 | "dependencies": { 811 | "@vitest/spy": "3.0.8", 812 | "estree-walker": "^3.0.3", 813 | "magic-string": "^0.30.17" 814 | }, 815 | "funding": { 816 | "url": "https://opencollective.com/vitest" 817 | }, 818 | "peerDependencies": { 819 | "msw": "^2.4.9", 820 | "vite": "^5.0.0 || ^6.0.0" 821 | }, 822 | "peerDependenciesMeta": { 823 | "msw": { 824 | "optional": true 825 | }, 826 | "vite": { 827 | "optional": true 828 | } 829 | } 830 | }, 831 | "node_modules/@vitest/pretty-format": { 832 | "version": "3.0.8", 833 | "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.8.tgz", 834 | "integrity": "sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==", 835 | "license": "MIT", 836 | "dependencies": { 837 | "tinyrainbow": "^2.0.0" 838 | }, 839 | "funding": { 840 | "url": "https://opencollective.com/vitest" 841 | } 842 | }, 843 | "node_modules/@vitest/runner": { 844 | "version": "3.0.8", 845 | "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.8.tgz", 846 | "integrity": "sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==", 847 | "license": "MIT", 848 | "dependencies": { 849 | "@vitest/utils": "3.0.8", 850 | "pathe": "^2.0.3" 851 | }, 852 | "funding": { 853 | "url": "https://opencollective.com/vitest" 854 | } 855 | }, 856 | "node_modules/@vitest/snapshot": { 857 | "version": "3.0.8", 858 | "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.8.tgz", 859 | "integrity": "sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==", 860 | "dev": true, 861 | "license": "MIT", 862 | "dependencies": { 863 | "@vitest/pretty-format": "3.0.8", 864 | "magic-string": "^0.30.17", 865 | "pathe": "^2.0.3" 866 | }, 867 | "funding": { 868 | "url": "https://opencollective.com/vitest" 869 | } 870 | }, 871 | "node_modules/@vitest/spy": { 872 | "version": "3.0.8", 873 | "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.8.tgz", 874 | "integrity": "sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==", 875 | "dev": true, 876 | "license": "MIT", 877 | "dependencies": { 878 | "tinyspy": "^3.0.2" 879 | }, 880 | "funding": { 881 | "url": "https://opencollective.com/vitest" 882 | } 883 | }, 884 | "node_modules/@vitest/utils": { 885 | "version": "3.0.8", 886 | "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.8.tgz", 887 | "integrity": "sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==", 888 | "license": "MIT", 889 | "dependencies": { 890 | "@vitest/pretty-format": "3.0.8", 891 | "loupe": "^3.1.3", 892 | "tinyrainbow": "^2.0.0" 893 | }, 894 | "funding": { 895 | "url": "https://opencollective.com/vitest" 896 | } 897 | }, 898 | "node_modules/@vitest2/runner": { 899 | "name": "@vitest/runner", 900 | "version": "2.1.9", 901 | "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", 902 | "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", 903 | "dev": true, 904 | "dependencies": { 905 | "@vitest/utils": "2.1.9", 906 | "pathe": "^1.1.2" 907 | }, 908 | "funding": { 909 | "url": "https://opencollective.com/vitest" 910 | } 911 | }, 912 | "node_modules/@vitest2/runner/node_modules/@vitest/pretty-format": { 913 | "version": "2.1.9", 914 | "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", 915 | "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", 916 | "dev": true, 917 | "dependencies": { 918 | "tinyrainbow": "^1.2.0" 919 | }, 920 | "funding": { 921 | "url": "https://opencollective.com/vitest" 922 | } 923 | }, 924 | "node_modules/@vitest2/runner/node_modules/@vitest/utils": { 925 | "version": "2.1.9", 926 | "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", 927 | "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", 928 | "dev": true, 929 | "dependencies": { 930 | "@vitest/pretty-format": "2.1.9", 931 | "loupe": "^3.1.2", 932 | "tinyrainbow": "^1.2.0" 933 | }, 934 | "funding": { 935 | "url": "https://opencollective.com/vitest" 936 | } 937 | }, 938 | "node_modules/@vitest2/runner/node_modules/pathe": { 939 | "version": "1.1.2", 940 | "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", 941 | "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", 942 | "dev": true 943 | }, 944 | "node_modules/@vitest2/runner/node_modules/tinyrainbow": { 945 | "version": "1.2.0", 946 | "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", 947 | "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", 948 | "dev": true, 949 | "engines": { 950 | "node": ">=14.0.0" 951 | } 952 | }, 953 | "node_modules/assertion-error": { 954 | "version": "2.0.1", 955 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", 956 | "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", 957 | "dev": true, 958 | "license": "MIT", 959 | "engines": { 960 | "node": ">=12" 961 | } 962 | }, 963 | "node_modules/braces": { 964 | "version": "3.0.3", 965 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 966 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 967 | "dependencies": { 968 | "fill-range": "^7.1.1" 969 | }, 970 | "engines": { 971 | "node": ">=8" 972 | } 973 | }, 974 | "node_modules/cac": { 975 | "version": "6.7.14", 976 | "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", 977 | "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", 978 | "dev": true, 979 | "license": "MIT", 980 | "engines": { 981 | "node": ">=8" 982 | } 983 | }, 984 | "node_modules/chai": { 985 | "version": "5.2.0", 986 | "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", 987 | "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", 988 | "dev": true, 989 | "license": "MIT", 990 | "dependencies": { 991 | "assertion-error": "^2.0.1", 992 | "check-error": "^2.1.1", 993 | "deep-eql": "^5.0.1", 994 | "loupe": "^3.1.0", 995 | "pathval": "^2.0.0" 996 | }, 997 | "engines": { 998 | "node": ">=12" 999 | } 1000 | }, 1001 | "node_modules/chalk": { 1002 | "version": "5.3.0", 1003 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", 1004 | "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", 1005 | "engines": { 1006 | "node": "^12.17.0 || ^14.13 || >=16.0.0" 1007 | }, 1008 | "funding": { 1009 | "url": "https://github.com/chalk/chalk?sponsor=1" 1010 | } 1011 | }, 1012 | "node_modules/check-error": { 1013 | "version": "2.1.1", 1014 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", 1015 | "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", 1016 | "dev": true, 1017 | "license": "MIT", 1018 | "engines": { 1019 | "node": ">= 16" 1020 | } 1021 | }, 1022 | "node_modules/debug": { 1023 | "version": "4.4.0", 1024 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", 1025 | "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", 1026 | "dev": true, 1027 | "license": "MIT", 1028 | "dependencies": { 1029 | "ms": "^2.1.3" 1030 | }, 1031 | "engines": { 1032 | "node": ">=6.0" 1033 | }, 1034 | "peerDependenciesMeta": { 1035 | "supports-color": { 1036 | "optional": true 1037 | } 1038 | } 1039 | }, 1040 | "node_modules/deep-eql": { 1041 | "version": "5.0.2", 1042 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", 1043 | "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", 1044 | "dev": true, 1045 | "license": "MIT", 1046 | "engines": { 1047 | "node": ">=6" 1048 | } 1049 | }, 1050 | "node_modules/es-module-lexer": { 1051 | "version": "1.6.0", 1052 | "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", 1053 | "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", 1054 | "dev": true, 1055 | "license": "MIT" 1056 | }, 1057 | "node_modules/esbuild": { 1058 | "version": "0.25.1", 1059 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.1.tgz", 1060 | "integrity": "sha512-BGO5LtrGC7vxnqucAe/rmvKdJllfGaYWdyABvyMoXQlfYMb2bbRuReWR5tEGE//4LcNJj9XrkovTqNYRFZHAMQ==", 1061 | "dev": true, 1062 | "hasInstallScript": true, 1063 | "license": "MIT", 1064 | "bin": { 1065 | "esbuild": "bin/esbuild" 1066 | }, 1067 | "engines": { 1068 | "node": ">=18" 1069 | }, 1070 | "optionalDependencies": { 1071 | "@esbuild/aix-ppc64": "0.25.1", 1072 | "@esbuild/android-arm": "0.25.1", 1073 | "@esbuild/android-arm64": "0.25.1", 1074 | "@esbuild/android-x64": "0.25.1", 1075 | "@esbuild/darwin-arm64": "0.25.1", 1076 | "@esbuild/darwin-x64": "0.25.1", 1077 | "@esbuild/freebsd-arm64": "0.25.1", 1078 | "@esbuild/freebsd-x64": "0.25.1", 1079 | "@esbuild/linux-arm": "0.25.1", 1080 | "@esbuild/linux-arm64": "0.25.1", 1081 | "@esbuild/linux-ia32": "0.25.1", 1082 | "@esbuild/linux-loong64": "0.25.1", 1083 | "@esbuild/linux-mips64el": "0.25.1", 1084 | "@esbuild/linux-ppc64": "0.25.1", 1085 | "@esbuild/linux-riscv64": "0.25.1", 1086 | "@esbuild/linux-s390x": "0.25.1", 1087 | "@esbuild/linux-x64": "0.25.1", 1088 | "@esbuild/netbsd-arm64": "0.25.1", 1089 | "@esbuild/netbsd-x64": "0.25.1", 1090 | "@esbuild/openbsd-arm64": "0.25.1", 1091 | "@esbuild/openbsd-x64": "0.25.1", 1092 | "@esbuild/sunos-x64": "0.25.1", 1093 | "@esbuild/win32-arm64": "0.25.1", 1094 | "@esbuild/win32-ia32": "0.25.1", 1095 | "@esbuild/win32-x64": "0.25.1" 1096 | } 1097 | }, 1098 | "node_modules/estree-walker": { 1099 | "version": "3.0.3", 1100 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", 1101 | "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", 1102 | "dev": true, 1103 | "license": "MIT", 1104 | "dependencies": { 1105 | "@types/estree": "^1.0.0" 1106 | } 1107 | }, 1108 | "node_modules/expect-type": { 1109 | "version": "1.2.0", 1110 | "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.0.tgz", 1111 | "integrity": "sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==", 1112 | "dev": true, 1113 | "license": "Apache-2.0", 1114 | "engines": { 1115 | "node": ">=12.0.0" 1116 | } 1117 | }, 1118 | "node_modules/fast-glob": { 1119 | "version": "3.3.2", 1120 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", 1121 | "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", 1122 | "dependencies": { 1123 | "@nodelib/fs.stat": "^2.0.2", 1124 | "@nodelib/fs.walk": "^1.2.3", 1125 | "glob-parent": "^5.1.2", 1126 | "merge2": "^1.3.0", 1127 | "micromatch": "^4.0.4" 1128 | }, 1129 | "engines": { 1130 | "node": ">=8.6.0" 1131 | } 1132 | }, 1133 | "node_modules/fastq": { 1134 | "version": "1.17.1", 1135 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", 1136 | "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", 1137 | "dependencies": { 1138 | "reusify": "^1.0.4" 1139 | } 1140 | }, 1141 | "node_modules/fill-range": { 1142 | "version": "7.1.1", 1143 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 1144 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1145 | "dependencies": { 1146 | "to-regex-range": "^5.0.1" 1147 | }, 1148 | "engines": { 1149 | "node": ">=8" 1150 | } 1151 | }, 1152 | "node_modules/fsevents": { 1153 | "version": "2.3.3", 1154 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1155 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1156 | "dev": true, 1157 | "hasInstallScript": true, 1158 | "license": "MIT", 1159 | "optional": true, 1160 | "os": [ 1161 | "darwin" 1162 | ], 1163 | "engines": { 1164 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1165 | } 1166 | }, 1167 | "node_modules/glob-parent": { 1168 | "version": "5.1.2", 1169 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1170 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1171 | "dependencies": { 1172 | "is-glob": "^4.0.1" 1173 | }, 1174 | "engines": { 1175 | "node": ">= 6" 1176 | } 1177 | }, 1178 | "node_modules/is-extglob": { 1179 | "version": "2.1.1", 1180 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1181 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1182 | "engines": { 1183 | "node": ">=0.10.0" 1184 | } 1185 | }, 1186 | "node_modules/is-glob": { 1187 | "version": "4.0.3", 1188 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1189 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1190 | "dependencies": { 1191 | "is-extglob": "^2.1.1" 1192 | }, 1193 | "engines": { 1194 | "node": ">=0.10.0" 1195 | } 1196 | }, 1197 | "node_modules/is-number": { 1198 | "version": "7.0.0", 1199 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1200 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1201 | "engines": { 1202 | "node": ">=0.12.0" 1203 | } 1204 | }, 1205 | "node_modules/loupe": { 1206 | "version": "3.1.3", 1207 | "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", 1208 | "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", 1209 | "license": "MIT" 1210 | }, 1211 | "node_modules/magic-string": { 1212 | "version": "0.30.17", 1213 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", 1214 | "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", 1215 | "dev": true, 1216 | "license": "MIT", 1217 | "dependencies": { 1218 | "@jridgewell/sourcemap-codec": "^1.5.0" 1219 | } 1220 | }, 1221 | "node_modules/merge2": { 1222 | "version": "1.4.1", 1223 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1224 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1225 | "engines": { 1226 | "node": ">= 8" 1227 | } 1228 | }, 1229 | "node_modules/micromatch": { 1230 | "version": "4.0.7", 1231 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", 1232 | "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", 1233 | "dependencies": { 1234 | "braces": "^3.0.3", 1235 | "picomatch": "^2.3.1" 1236 | }, 1237 | "engines": { 1238 | "node": ">=8.6" 1239 | } 1240 | }, 1241 | "node_modules/ms": { 1242 | "version": "2.1.3", 1243 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1244 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1245 | "dev": true, 1246 | "license": "MIT" 1247 | }, 1248 | "node_modules/nanoid": { 1249 | "version": "3.3.9", 1250 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.9.tgz", 1251 | "integrity": "sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==", 1252 | "dev": true, 1253 | "funding": [ 1254 | { 1255 | "type": "github", 1256 | "url": "https://github.com/sponsors/ai" 1257 | } 1258 | ], 1259 | "license": "MIT", 1260 | "bin": { 1261 | "nanoid": "bin/nanoid.cjs" 1262 | }, 1263 | "engines": { 1264 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1265 | } 1266 | }, 1267 | "node_modules/pathe": { 1268 | "version": "2.0.3", 1269 | "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", 1270 | "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", 1271 | "license": "MIT" 1272 | }, 1273 | "node_modules/pathval": { 1274 | "version": "2.0.0", 1275 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", 1276 | "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", 1277 | "dev": true, 1278 | "license": "MIT", 1279 | "engines": { 1280 | "node": ">= 14.16" 1281 | } 1282 | }, 1283 | "node_modules/picocolors": { 1284 | "version": "1.1.1", 1285 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1286 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1287 | "dev": true, 1288 | "license": "ISC" 1289 | }, 1290 | "node_modules/picomatch": { 1291 | "version": "2.3.1", 1292 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1293 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1294 | "engines": { 1295 | "node": ">=8.6" 1296 | }, 1297 | "funding": { 1298 | "url": "https://github.com/sponsors/jonschlinkert" 1299 | } 1300 | }, 1301 | "node_modules/postcss": { 1302 | "version": "8.5.3", 1303 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", 1304 | "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", 1305 | "dev": true, 1306 | "funding": [ 1307 | { 1308 | "type": "opencollective", 1309 | "url": "https://opencollective.com/postcss/" 1310 | }, 1311 | { 1312 | "type": "tidelift", 1313 | "url": "https://tidelift.com/funding/github/npm/postcss" 1314 | }, 1315 | { 1316 | "type": "github", 1317 | "url": "https://github.com/sponsors/ai" 1318 | } 1319 | ], 1320 | "license": "MIT", 1321 | "dependencies": { 1322 | "nanoid": "^3.3.8", 1323 | "picocolors": "^1.1.1", 1324 | "source-map-js": "^1.2.1" 1325 | }, 1326 | "engines": { 1327 | "node": "^10 || ^12 || >=14" 1328 | } 1329 | }, 1330 | "node_modules/queue-microtask": { 1331 | "version": "1.2.3", 1332 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1333 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1334 | "funding": [ 1335 | { 1336 | "type": "github", 1337 | "url": "https://github.com/sponsors/feross" 1338 | }, 1339 | { 1340 | "type": "patreon", 1341 | "url": "https://www.patreon.com/feross" 1342 | }, 1343 | { 1344 | "type": "consulting", 1345 | "url": "https://feross.org/support" 1346 | } 1347 | ] 1348 | }, 1349 | "node_modules/reusify": { 1350 | "version": "1.0.4", 1351 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1352 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1353 | "engines": { 1354 | "iojs": ">=1.0.0", 1355 | "node": ">=0.10.0" 1356 | } 1357 | }, 1358 | "node_modules/rollup": { 1359 | "version": "4.35.0", 1360 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.35.0.tgz", 1361 | "integrity": "sha512-kg6oI4g+vc41vePJyO6dHt/yl0Rz3Thv0kJeVQ3D1kS3E5XSuKbPc29G4IpT/Kv1KQwgHVcN+HtyS+HYLNSvQg==", 1362 | "dev": true, 1363 | "license": "MIT", 1364 | "dependencies": { 1365 | "@types/estree": "1.0.6" 1366 | }, 1367 | "bin": { 1368 | "rollup": "dist/bin/rollup" 1369 | }, 1370 | "engines": { 1371 | "node": ">=18.0.0", 1372 | "npm": ">=8.0.0" 1373 | }, 1374 | "optionalDependencies": { 1375 | "@rollup/rollup-android-arm-eabi": "4.35.0", 1376 | "@rollup/rollup-android-arm64": "4.35.0", 1377 | "@rollup/rollup-darwin-arm64": "4.35.0", 1378 | "@rollup/rollup-darwin-x64": "4.35.0", 1379 | "@rollup/rollup-freebsd-arm64": "4.35.0", 1380 | "@rollup/rollup-freebsd-x64": "4.35.0", 1381 | "@rollup/rollup-linux-arm-gnueabihf": "4.35.0", 1382 | "@rollup/rollup-linux-arm-musleabihf": "4.35.0", 1383 | "@rollup/rollup-linux-arm64-gnu": "4.35.0", 1384 | "@rollup/rollup-linux-arm64-musl": "4.35.0", 1385 | "@rollup/rollup-linux-loongarch64-gnu": "4.35.0", 1386 | "@rollup/rollup-linux-powerpc64le-gnu": "4.35.0", 1387 | "@rollup/rollup-linux-riscv64-gnu": "4.35.0", 1388 | "@rollup/rollup-linux-s390x-gnu": "4.35.0", 1389 | "@rollup/rollup-linux-x64-gnu": "4.35.0", 1390 | "@rollup/rollup-linux-x64-musl": "4.35.0", 1391 | "@rollup/rollup-win32-arm64-msvc": "4.35.0", 1392 | "@rollup/rollup-win32-ia32-msvc": "4.35.0", 1393 | "@rollup/rollup-win32-x64-msvc": "4.35.0", 1394 | "fsevents": "~2.3.2" 1395 | } 1396 | }, 1397 | "node_modules/run-parallel": { 1398 | "version": "1.2.0", 1399 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1400 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1401 | "funding": [ 1402 | { 1403 | "type": "github", 1404 | "url": "https://github.com/sponsors/feross" 1405 | }, 1406 | { 1407 | "type": "patreon", 1408 | "url": "https://www.patreon.com/feross" 1409 | }, 1410 | { 1411 | "type": "consulting", 1412 | "url": "https://feross.org/support" 1413 | } 1414 | ], 1415 | "dependencies": { 1416 | "queue-microtask": "^1.2.2" 1417 | } 1418 | }, 1419 | "node_modules/siginfo": { 1420 | "version": "2.0.0", 1421 | "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", 1422 | "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", 1423 | "dev": true 1424 | }, 1425 | "node_modules/source-map-js": { 1426 | "version": "1.2.1", 1427 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 1428 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 1429 | "dev": true, 1430 | "license": "BSD-3-Clause", 1431 | "engines": { 1432 | "node": ">=0.10.0" 1433 | } 1434 | }, 1435 | "node_modules/stackback": { 1436 | "version": "0.0.2", 1437 | "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", 1438 | "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", 1439 | "dev": true 1440 | }, 1441 | "node_modules/std-env": { 1442 | "version": "3.8.1", 1443 | "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.1.tgz", 1444 | "integrity": "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==", 1445 | "dev": true, 1446 | "license": "MIT" 1447 | }, 1448 | "node_modules/tinybench": { 1449 | "version": "2.9.0", 1450 | "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", 1451 | "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", 1452 | "dev": true 1453 | }, 1454 | "node_modules/tinyexec": { 1455 | "version": "0.3.2", 1456 | "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", 1457 | "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", 1458 | "dev": true, 1459 | "license": "MIT" 1460 | }, 1461 | "node_modules/tinypool": { 1462 | "version": "1.0.2", 1463 | "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", 1464 | "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", 1465 | "dev": true, 1466 | "license": "MIT", 1467 | "engines": { 1468 | "node": "^18.0.0 || >=20.0.0" 1469 | } 1470 | }, 1471 | "node_modules/tinyrainbow": { 1472 | "version": "2.0.0", 1473 | "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", 1474 | "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", 1475 | "license": "MIT", 1476 | "engines": { 1477 | "node": ">=14.0.0" 1478 | } 1479 | }, 1480 | "node_modules/tinyspy": { 1481 | "version": "3.0.2", 1482 | "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", 1483 | "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", 1484 | "dev": true, 1485 | "license": "MIT", 1486 | "engines": { 1487 | "node": ">=14.0.0" 1488 | } 1489 | }, 1490 | "node_modules/to-regex-range": { 1491 | "version": "5.0.1", 1492 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1493 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1494 | "dependencies": { 1495 | "is-number": "^7.0.0" 1496 | }, 1497 | "engines": { 1498 | "node": ">=8.0" 1499 | } 1500 | }, 1501 | "node_modules/typescript": { 1502 | "version": "5.5.4", 1503 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", 1504 | "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", 1505 | "dev": true, 1506 | "bin": { 1507 | "tsc": "bin/tsc", 1508 | "tsserver": "bin/tsserver" 1509 | }, 1510 | "engines": { 1511 | "node": ">=14.17" 1512 | } 1513 | }, 1514 | "node_modules/undici-types": { 1515 | "version": "5.26.5", 1516 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", 1517 | "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", 1518 | "dev": true 1519 | }, 1520 | "node_modules/vite": { 1521 | "version": "6.2.2", 1522 | "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.2.tgz", 1523 | "integrity": "sha512-yW7PeMM+LkDzc7CgJuRLMW2Jz0FxMOsVJ8Lv3gpgW9WLcb9cTW+121UEr1hvmfR7w3SegR5ItvYyzVz1vxNJgQ==", 1524 | "dev": true, 1525 | "dependencies": { 1526 | "esbuild": "^0.25.0", 1527 | "postcss": "^8.5.3", 1528 | "rollup": "^4.30.1" 1529 | }, 1530 | "bin": { 1531 | "vite": "bin/vite.js" 1532 | }, 1533 | "engines": { 1534 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 1535 | }, 1536 | "funding": { 1537 | "url": "https://github.com/vitejs/vite?sponsor=1" 1538 | }, 1539 | "optionalDependencies": { 1540 | "fsevents": "~2.3.3" 1541 | }, 1542 | "peerDependencies": { 1543 | "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 1544 | "jiti": ">=1.21.0", 1545 | "less": "*", 1546 | "lightningcss": "^1.21.0", 1547 | "sass": "*", 1548 | "sass-embedded": "*", 1549 | "stylus": "*", 1550 | "sugarss": "*", 1551 | "terser": "^5.16.0", 1552 | "tsx": "^4.8.1", 1553 | "yaml": "^2.4.2" 1554 | }, 1555 | "peerDependenciesMeta": { 1556 | "@types/node": { 1557 | "optional": true 1558 | }, 1559 | "jiti": { 1560 | "optional": true 1561 | }, 1562 | "less": { 1563 | "optional": true 1564 | }, 1565 | "lightningcss": { 1566 | "optional": true 1567 | }, 1568 | "sass": { 1569 | "optional": true 1570 | }, 1571 | "sass-embedded": { 1572 | "optional": true 1573 | }, 1574 | "stylus": { 1575 | "optional": true 1576 | }, 1577 | "sugarss": { 1578 | "optional": true 1579 | }, 1580 | "terser": { 1581 | "optional": true 1582 | }, 1583 | "tsx": { 1584 | "optional": true 1585 | }, 1586 | "yaml": { 1587 | "optional": true 1588 | } 1589 | } 1590 | }, 1591 | "node_modules/vite-node": { 1592 | "version": "3.0.8", 1593 | "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.8.tgz", 1594 | "integrity": "sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==", 1595 | "dev": true, 1596 | "license": "MIT", 1597 | "dependencies": { 1598 | "cac": "^6.7.14", 1599 | "debug": "^4.4.0", 1600 | "es-module-lexer": "^1.6.0", 1601 | "pathe": "^2.0.3", 1602 | "vite": "^5.0.0 || ^6.0.0" 1603 | }, 1604 | "bin": { 1605 | "vite-node": "vite-node.mjs" 1606 | }, 1607 | "engines": { 1608 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 1609 | }, 1610 | "funding": { 1611 | "url": "https://opencollective.com/vitest" 1612 | } 1613 | }, 1614 | "node_modules/vitest": { 1615 | "version": "3.0.8", 1616 | "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.8.tgz", 1617 | "integrity": "sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==", 1618 | "dev": true, 1619 | "license": "MIT", 1620 | "dependencies": { 1621 | "@vitest/expect": "3.0.8", 1622 | "@vitest/mocker": "3.0.8", 1623 | "@vitest/pretty-format": "^3.0.8", 1624 | "@vitest/runner": "3.0.8", 1625 | "@vitest/snapshot": "3.0.8", 1626 | "@vitest/spy": "3.0.8", 1627 | "@vitest/utils": "3.0.8", 1628 | "chai": "^5.2.0", 1629 | "debug": "^4.4.0", 1630 | "expect-type": "^1.1.0", 1631 | "magic-string": "^0.30.17", 1632 | "pathe": "^2.0.3", 1633 | "std-env": "^3.8.0", 1634 | "tinybench": "^2.9.0", 1635 | "tinyexec": "^0.3.2", 1636 | "tinypool": "^1.0.2", 1637 | "tinyrainbow": "^2.0.0", 1638 | "vite": "^5.0.0 || ^6.0.0", 1639 | "vite-node": "3.0.8", 1640 | "why-is-node-running": "^2.3.0" 1641 | }, 1642 | "bin": { 1643 | "vitest": "vitest.mjs" 1644 | }, 1645 | "engines": { 1646 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 1647 | }, 1648 | "funding": { 1649 | "url": "https://opencollective.com/vitest" 1650 | }, 1651 | "peerDependencies": { 1652 | "@edge-runtime/vm": "*", 1653 | "@types/debug": "^4.1.12", 1654 | "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 1655 | "@vitest/browser": "3.0.8", 1656 | "@vitest/ui": "3.0.8", 1657 | "happy-dom": "*", 1658 | "jsdom": "*" 1659 | }, 1660 | "peerDependenciesMeta": { 1661 | "@edge-runtime/vm": { 1662 | "optional": true 1663 | }, 1664 | "@types/debug": { 1665 | "optional": true 1666 | }, 1667 | "@types/node": { 1668 | "optional": true 1669 | }, 1670 | "@vitest/browser": { 1671 | "optional": true 1672 | }, 1673 | "@vitest/ui": { 1674 | "optional": true 1675 | }, 1676 | "happy-dom": { 1677 | "optional": true 1678 | }, 1679 | "jsdom": { 1680 | "optional": true 1681 | } 1682 | } 1683 | }, 1684 | "node_modules/vitest2": { 1685 | "name": "vitest", 1686 | "version": "2.1.9", 1687 | "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", 1688 | "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", 1689 | "dev": true, 1690 | "dependencies": { 1691 | "@vitest/expect": "2.1.9", 1692 | "@vitest/mocker": "2.1.9", 1693 | "@vitest/pretty-format": "^2.1.9", 1694 | "@vitest/runner": "2.1.9", 1695 | "@vitest/snapshot": "2.1.9", 1696 | "@vitest/spy": "2.1.9", 1697 | "@vitest/utils": "2.1.9", 1698 | "chai": "^5.1.2", 1699 | "debug": "^4.3.7", 1700 | "expect-type": "^1.1.0", 1701 | "magic-string": "^0.30.12", 1702 | "pathe": "^1.1.2", 1703 | "std-env": "^3.8.0", 1704 | "tinybench": "^2.9.0", 1705 | "tinyexec": "^0.3.1", 1706 | "tinypool": "^1.0.1", 1707 | "tinyrainbow": "^1.2.0", 1708 | "vite": "^5.0.0", 1709 | "vite-node": "2.1.9", 1710 | "why-is-node-running": "^2.3.0" 1711 | }, 1712 | "bin": { 1713 | "vitest": "vitest.mjs" 1714 | }, 1715 | "engines": { 1716 | "node": "^18.0.0 || >=20.0.0" 1717 | }, 1718 | "funding": { 1719 | "url": "https://opencollective.com/vitest" 1720 | }, 1721 | "peerDependencies": { 1722 | "@edge-runtime/vm": "*", 1723 | "@types/node": "^18.0.0 || >=20.0.0", 1724 | "@vitest/browser": "2.1.9", 1725 | "@vitest/ui": "2.1.9", 1726 | "happy-dom": "*", 1727 | "jsdom": "*" 1728 | }, 1729 | "peerDependenciesMeta": { 1730 | "@edge-runtime/vm": { 1731 | "optional": true 1732 | }, 1733 | "@types/node": { 1734 | "optional": true 1735 | }, 1736 | "@vitest/browser": { 1737 | "optional": true 1738 | }, 1739 | "@vitest/ui": { 1740 | "optional": true 1741 | }, 1742 | "happy-dom": { 1743 | "optional": true 1744 | }, 1745 | "jsdom": { 1746 | "optional": true 1747 | } 1748 | } 1749 | }, 1750 | "node_modules/vitest2/node_modules/@esbuild/aix-ppc64": { 1751 | "version": "0.21.5", 1752 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", 1753 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", 1754 | "cpu": [ 1755 | "ppc64" 1756 | ], 1757 | "dev": true, 1758 | "optional": true, 1759 | "os": [ 1760 | "aix" 1761 | ], 1762 | "engines": { 1763 | "node": ">=12" 1764 | } 1765 | }, 1766 | "node_modules/vitest2/node_modules/@esbuild/android-arm": { 1767 | "version": "0.21.5", 1768 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", 1769 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", 1770 | "cpu": [ 1771 | "arm" 1772 | ], 1773 | "dev": true, 1774 | "optional": true, 1775 | "os": [ 1776 | "android" 1777 | ], 1778 | "engines": { 1779 | "node": ">=12" 1780 | } 1781 | }, 1782 | "node_modules/vitest2/node_modules/@esbuild/android-arm64": { 1783 | "version": "0.21.5", 1784 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", 1785 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", 1786 | "cpu": [ 1787 | "arm64" 1788 | ], 1789 | "dev": true, 1790 | "optional": true, 1791 | "os": [ 1792 | "android" 1793 | ], 1794 | "engines": { 1795 | "node": ">=12" 1796 | } 1797 | }, 1798 | "node_modules/vitest2/node_modules/@esbuild/android-x64": { 1799 | "version": "0.21.5", 1800 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", 1801 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", 1802 | "cpu": [ 1803 | "x64" 1804 | ], 1805 | "dev": true, 1806 | "optional": true, 1807 | "os": [ 1808 | "android" 1809 | ], 1810 | "engines": { 1811 | "node": ">=12" 1812 | } 1813 | }, 1814 | "node_modules/vitest2/node_modules/@esbuild/darwin-arm64": { 1815 | "version": "0.21.5", 1816 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", 1817 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", 1818 | "cpu": [ 1819 | "arm64" 1820 | ], 1821 | "dev": true, 1822 | "optional": true, 1823 | "os": [ 1824 | "darwin" 1825 | ], 1826 | "engines": { 1827 | "node": ">=12" 1828 | } 1829 | }, 1830 | "node_modules/vitest2/node_modules/@esbuild/darwin-x64": { 1831 | "version": "0.21.5", 1832 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", 1833 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", 1834 | "cpu": [ 1835 | "x64" 1836 | ], 1837 | "dev": true, 1838 | "optional": true, 1839 | "os": [ 1840 | "darwin" 1841 | ], 1842 | "engines": { 1843 | "node": ">=12" 1844 | } 1845 | }, 1846 | "node_modules/vitest2/node_modules/@esbuild/freebsd-arm64": { 1847 | "version": "0.21.5", 1848 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", 1849 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", 1850 | "cpu": [ 1851 | "arm64" 1852 | ], 1853 | "dev": true, 1854 | "optional": true, 1855 | "os": [ 1856 | "freebsd" 1857 | ], 1858 | "engines": { 1859 | "node": ">=12" 1860 | } 1861 | }, 1862 | "node_modules/vitest2/node_modules/@esbuild/freebsd-x64": { 1863 | "version": "0.21.5", 1864 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", 1865 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", 1866 | "cpu": [ 1867 | "x64" 1868 | ], 1869 | "dev": true, 1870 | "optional": true, 1871 | "os": [ 1872 | "freebsd" 1873 | ], 1874 | "engines": { 1875 | "node": ">=12" 1876 | } 1877 | }, 1878 | "node_modules/vitest2/node_modules/@esbuild/linux-arm": { 1879 | "version": "0.21.5", 1880 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", 1881 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", 1882 | "cpu": [ 1883 | "arm" 1884 | ], 1885 | "dev": true, 1886 | "optional": true, 1887 | "os": [ 1888 | "linux" 1889 | ], 1890 | "engines": { 1891 | "node": ">=12" 1892 | } 1893 | }, 1894 | "node_modules/vitest2/node_modules/@esbuild/linux-arm64": { 1895 | "version": "0.21.5", 1896 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", 1897 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", 1898 | "cpu": [ 1899 | "arm64" 1900 | ], 1901 | "dev": true, 1902 | "optional": true, 1903 | "os": [ 1904 | "linux" 1905 | ], 1906 | "engines": { 1907 | "node": ">=12" 1908 | } 1909 | }, 1910 | "node_modules/vitest2/node_modules/@esbuild/linux-ia32": { 1911 | "version": "0.21.5", 1912 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", 1913 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", 1914 | "cpu": [ 1915 | "ia32" 1916 | ], 1917 | "dev": true, 1918 | "optional": true, 1919 | "os": [ 1920 | "linux" 1921 | ], 1922 | "engines": { 1923 | "node": ">=12" 1924 | } 1925 | }, 1926 | "node_modules/vitest2/node_modules/@esbuild/linux-loong64": { 1927 | "version": "0.21.5", 1928 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", 1929 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", 1930 | "cpu": [ 1931 | "loong64" 1932 | ], 1933 | "dev": true, 1934 | "optional": true, 1935 | "os": [ 1936 | "linux" 1937 | ], 1938 | "engines": { 1939 | "node": ">=12" 1940 | } 1941 | }, 1942 | "node_modules/vitest2/node_modules/@esbuild/linux-mips64el": { 1943 | "version": "0.21.5", 1944 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", 1945 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", 1946 | "cpu": [ 1947 | "mips64el" 1948 | ], 1949 | "dev": true, 1950 | "optional": true, 1951 | "os": [ 1952 | "linux" 1953 | ], 1954 | "engines": { 1955 | "node": ">=12" 1956 | } 1957 | }, 1958 | "node_modules/vitest2/node_modules/@esbuild/linux-ppc64": { 1959 | "version": "0.21.5", 1960 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", 1961 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", 1962 | "cpu": [ 1963 | "ppc64" 1964 | ], 1965 | "dev": true, 1966 | "optional": true, 1967 | "os": [ 1968 | "linux" 1969 | ], 1970 | "engines": { 1971 | "node": ">=12" 1972 | } 1973 | }, 1974 | "node_modules/vitest2/node_modules/@esbuild/linux-riscv64": { 1975 | "version": "0.21.5", 1976 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", 1977 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", 1978 | "cpu": [ 1979 | "riscv64" 1980 | ], 1981 | "dev": true, 1982 | "optional": true, 1983 | "os": [ 1984 | "linux" 1985 | ], 1986 | "engines": { 1987 | "node": ">=12" 1988 | } 1989 | }, 1990 | "node_modules/vitest2/node_modules/@esbuild/linux-s390x": { 1991 | "version": "0.21.5", 1992 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", 1993 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", 1994 | "cpu": [ 1995 | "s390x" 1996 | ], 1997 | "dev": true, 1998 | "optional": true, 1999 | "os": [ 2000 | "linux" 2001 | ], 2002 | "engines": { 2003 | "node": ">=12" 2004 | } 2005 | }, 2006 | "node_modules/vitest2/node_modules/@esbuild/linux-x64": { 2007 | "version": "0.21.5", 2008 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", 2009 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", 2010 | "cpu": [ 2011 | "x64" 2012 | ], 2013 | "dev": true, 2014 | "optional": true, 2015 | "os": [ 2016 | "linux" 2017 | ], 2018 | "engines": { 2019 | "node": ">=12" 2020 | } 2021 | }, 2022 | "node_modules/vitest2/node_modules/@esbuild/netbsd-x64": { 2023 | "version": "0.21.5", 2024 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", 2025 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", 2026 | "cpu": [ 2027 | "x64" 2028 | ], 2029 | "dev": true, 2030 | "optional": true, 2031 | "os": [ 2032 | "netbsd" 2033 | ], 2034 | "engines": { 2035 | "node": ">=12" 2036 | } 2037 | }, 2038 | "node_modules/vitest2/node_modules/@esbuild/openbsd-x64": { 2039 | "version": "0.21.5", 2040 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", 2041 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", 2042 | "cpu": [ 2043 | "x64" 2044 | ], 2045 | "dev": true, 2046 | "optional": true, 2047 | "os": [ 2048 | "openbsd" 2049 | ], 2050 | "engines": { 2051 | "node": ">=12" 2052 | } 2053 | }, 2054 | "node_modules/vitest2/node_modules/@esbuild/sunos-x64": { 2055 | "version": "0.21.5", 2056 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", 2057 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", 2058 | "cpu": [ 2059 | "x64" 2060 | ], 2061 | "dev": true, 2062 | "optional": true, 2063 | "os": [ 2064 | "sunos" 2065 | ], 2066 | "engines": { 2067 | "node": ">=12" 2068 | } 2069 | }, 2070 | "node_modules/vitest2/node_modules/@esbuild/win32-arm64": { 2071 | "version": "0.21.5", 2072 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", 2073 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", 2074 | "cpu": [ 2075 | "arm64" 2076 | ], 2077 | "dev": true, 2078 | "optional": true, 2079 | "os": [ 2080 | "win32" 2081 | ], 2082 | "engines": { 2083 | "node": ">=12" 2084 | } 2085 | }, 2086 | "node_modules/vitest2/node_modules/@esbuild/win32-ia32": { 2087 | "version": "0.21.5", 2088 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", 2089 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", 2090 | "cpu": [ 2091 | "ia32" 2092 | ], 2093 | "dev": true, 2094 | "optional": true, 2095 | "os": [ 2096 | "win32" 2097 | ], 2098 | "engines": { 2099 | "node": ">=12" 2100 | } 2101 | }, 2102 | "node_modules/vitest2/node_modules/@esbuild/win32-x64": { 2103 | "version": "0.21.5", 2104 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", 2105 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", 2106 | "cpu": [ 2107 | "x64" 2108 | ], 2109 | "dev": true, 2110 | "optional": true, 2111 | "os": [ 2112 | "win32" 2113 | ], 2114 | "engines": { 2115 | "node": ">=12" 2116 | } 2117 | }, 2118 | "node_modules/vitest2/node_modules/@vitest/expect": { 2119 | "version": "2.1.9", 2120 | "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", 2121 | "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", 2122 | "dev": true, 2123 | "dependencies": { 2124 | "@vitest/spy": "2.1.9", 2125 | "@vitest/utils": "2.1.9", 2126 | "chai": "^5.1.2", 2127 | "tinyrainbow": "^1.2.0" 2128 | }, 2129 | "funding": { 2130 | "url": "https://opencollective.com/vitest" 2131 | } 2132 | }, 2133 | "node_modules/vitest2/node_modules/@vitest/mocker": { 2134 | "version": "2.1.9", 2135 | "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", 2136 | "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", 2137 | "dev": true, 2138 | "dependencies": { 2139 | "@vitest/spy": "2.1.9", 2140 | "estree-walker": "^3.0.3", 2141 | "magic-string": "^0.30.12" 2142 | }, 2143 | "funding": { 2144 | "url": "https://opencollective.com/vitest" 2145 | }, 2146 | "peerDependencies": { 2147 | "msw": "^2.4.9", 2148 | "vite": "^5.0.0" 2149 | }, 2150 | "peerDependenciesMeta": { 2151 | "msw": { 2152 | "optional": true 2153 | }, 2154 | "vite": { 2155 | "optional": true 2156 | } 2157 | } 2158 | }, 2159 | "node_modules/vitest2/node_modules/@vitest/pretty-format": { 2160 | "version": "2.1.9", 2161 | "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", 2162 | "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", 2163 | "dev": true, 2164 | "dependencies": { 2165 | "tinyrainbow": "^1.2.0" 2166 | }, 2167 | "funding": { 2168 | "url": "https://opencollective.com/vitest" 2169 | } 2170 | }, 2171 | "node_modules/vitest2/node_modules/@vitest/runner": { 2172 | "version": "2.1.9", 2173 | "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", 2174 | "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", 2175 | "dev": true, 2176 | "dependencies": { 2177 | "@vitest/utils": "2.1.9", 2178 | "pathe": "^1.1.2" 2179 | }, 2180 | "funding": { 2181 | "url": "https://opencollective.com/vitest" 2182 | } 2183 | }, 2184 | "node_modules/vitest2/node_modules/@vitest/snapshot": { 2185 | "version": "2.1.9", 2186 | "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", 2187 | "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", 2188 | "dev": true, 2189 | "dependencies": { 2190 | "@vitest/pretty-format": "2.1.9", 2191 | "magic-string": "^0.30.12", 2192 | "pathe": "^1.1.2" 2193 | }, 2194 | "funding": { 2195 | "url": "https://opencollective.com/vitest" 2196 | } 2197 | }, 2198 | "node_modules/vitest2/node_modules/@vitest/spy": { 2199 | "version": "2.1.9", 2200 | "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", 2201 | "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", 2202 | "dev": true, 2203 | "dependencies": { 2204 | "tinyspy": "^3.0.2" 2205 | }, 2206 | "funding": { 2207 | "url": "https://opencollective.com/vitest" 2208 | } 2209 | }, 2210 | "node_modules/vitest2/node_modules/@vitest/utils": { 2211 | "version": "2.1.9", 2212 | "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", 2213 | "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", 2214 | "dev": true, 2215 | "dependencies": { 2216 | "@vitest/pretty-format": "2.1.9", 2217 | "loupe": "^3.1.2", 2218 | "tinyrainbow": "^1.2.0" 2219 | }, 2220 | "funding": { 2221 | "url": "https://opencollective.com/vitest" 2222 | } 2223 | }, 2224 | "node_modules/vitest2/node_modules/esbuild": { 2225 | "version": "0.21.5", 2226 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", 2227 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 2228 | "dev": true, 2229 | "hasInstallScript": true, 2230 | "bin": { 2231 | "esbuild": "bin/esbuild" 2232 | }, 2233 | "engines": { 2234 | "node": ">=12" 2235 | }, 2236 | "optionalDependencies": { 2237 | "@esbuild/aix-ppc64": "0.21.5", 2238 | "@esbuild/android-arm": "0.21.5", 2239 | "@esbuild/android-arm64": "0.21.5", 2240 | "@esbuild/android-x64": "0.21.5", 2241 | "@esbuild/darwin-arm64": "0.21.5", 2242 | "@esbuild/darwin-x64": "0.21.5", 2243 | "@esbuild/freebsd-arm64": "0.21.5", 2244 | "@esbuild/freebsd-x64": "0.21.5", 2245 | "@esbuild/linux-arm": "0.21.5", 2246 | "@esbuild/linux-arm64": "0.21.5", 2247 | "@esbuild/linux-ia32": "0.21.5", 2248 | "@esbuild/linux-loong64": "0.21.5", 2249 | "@esbuild/linux-mips64el": "0.21.5", 2250 | "@esbuild/linux-ppc64": "0.21.5", 2251 | "@esbuild/linux-riscv64": "0.21.5", 2252 | "@esbuild/linux-s390x": "0.21.5", 2253 | "@esbuild/linux-x64": "0.21.5", 2254 | "@esbuild/netbsd-x64": "0.21.5", 2255 | "@esbuild/openbsd-x64": "0.21.5", 2256 | "@esbuild/sunos-x64": "0.21.5", 2257 | "@esbuild/win32-arm64": "0.21.5", 2258 | "@esbuild/win32-ia32": "0.21.5", 2259 | "@esbuild/win32-x64": "0.21.5" 2260 | } 2261 | }, 2262 | "node_modules/vitest2/node_modules/pathe": { 2263 | "version": "1.1.2", 2264 | "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", 2265 | "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", 2266 | "dev": true 2267 | }, 2268 | "node_modules/vitest2/node_modules/tinyrainbow": { 2269 | "version": "1.2.0", 2270 | "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", 2271 | "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", 2272 | "dev": true, 2273 | "engines": { 2274 | "node": ">=14.0.0" 2275 | } 2276 | }, 2277 | "node_modules/vitest2/node_modules/vite": { 2278 | "version": "5.4.14", 2279 | "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.14.tgz", 2280 | "integrity": "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==", 2281 | "dev": true, 2282 | "dependencies": { 2283 | "esbuild": "^0.21.3", 2284 | "postcss": "^8.4.43", 2285 | "rollup": "^4.20.0" 2286 | }, 2287 | "bin": { 2288 | "vite": "bin/vite.js" 2289 | }, 2290 | "engines": { 2291 | "node": "^18.0.0 || >=20.0.0" 2292 | }, 2293 | "funding": { 2294 | "url": "https://github.com/vitejs/vite?sponsor=1" 2295 | }, 2296 | "optionalDependencies": { 2297 | "fsevents": "~2.3.3" 2298 | }, 2299 | "peerDependencies": { 2300 | "@types/node": "^18.0.0 || >=20.0.0", 2301 | "less": "*", 2302 | "lightningcss": "^1.21.0", 2303 | "sass": "*", 2304 | "sass-embedded": "*", 2305 | "stylus": "*", 2306 | "sugarss": "*", 2307 | "terser": "^5.4.0" 2308 | }, 2309 | "peerDependenciesMeta": { 2310 | "@types/node": { 2311 | "optional": true 2312 | }, 2313 | "less": { 2314 | "optional": true 2315 | }, 2316 | "lightningcss": { 2317 | "optional": true 2318 | }, 2319 | "sass": { 2320 | "optional": true 2321 | }, 2322 | "sass-embedded": { 2323 | "optional": true 2324 | }, 2325 | "stylus": { 2326 | "optional": true 2327 | }, 2328 | "sugarss": { 2329 | "optional": true 2330 | }, 2331 | "terser": { 2332 | "optional": true 2333 | } 2334 | } 2335 | }, 2336 | "node_modules/vitest2/node_modules/vite-node": { 2337 | "version": "2.1.9", 2338 | "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", 2339 | "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", 2340 | "dev": true, 2341 | "dependencies": { 2342 | "cac": "^6.7.14", 2343 | "debug": "^4.3.7", 2344 | "es-module-lexer": "^1.5.4", 2345 | "pathe": "^1.1.2", 2346 | "vite": "^5.0.0" 2347 | }, 2348 | "bin": { 2349 | "vite-node": "vite-node.mjs" 2350 | }, 2351 | "engines": { 2352 | "node": "^18.0.0 || >=20.0.0" 2353 | }, 2354 | "funding": { 2355 | "url": "https://opencollective.com/vitest" 2356 | } 2357 | }, 2358 | "node_modules/why-is-node-running": { 2359 | "version": "2.3.0", 2360 | "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", 2361 | "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", 2362 | "dev": true, 2363 | "dependencies": { 2364 | "siginfo": "^2.0.0", 2365 | "stackback": "0.0.2" 2366 | }, 2367 | "bin": { 2368 | "why-is-node-running": "cli.js" 2369 | }, 2370 | "engines": { 2371 | "node": ">=8" 2372 | } 2373 | } 2374 | } 2375 | } 2376 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@raegen/vite-plugin-vitest-cache", 3 | "version": "0.3.7", 4 | "description": "Run Vitest with test result caching.", 5 | "repository": { 6 | "type": "git", 7 | "url": "git+https://github.com/raegen/vitest-cache.git" 8 | }, 9 | "files": [ 10 | "dist" 11 | ], 12 | "author": "raegen", 13 | "license": "MIT", 14 | "scripts": { 15 | "build": "tsc", 16 | "test": "vitest" 17 | }, 18 | "bugs": { 19 | "url": "https://github.com/raegen/vitest-cache/issues" 20 | }, 21 | "homepage": "https://github.com/raegen/vitest-cache#readme", 22 | "private": false, 23 | "keywords": [ 24 | "vCache", 25 | "vite", 26 | "vitest", 27 | "vite-plugin", 28 | "cache" 29 | ], 30 | "type": "module", 31 | "module": "./dist/index.js", 32 | "exports": "./dist/index.js", 33 | "types": "./dist/index.d.ts", 34 | "dependencies": { 35 | "chalk": "^5.3.0", 36 | "fast-glob": "^3.3.2", 37 | "@ungap/structured-clone": "^1.2.0", 38 | "vite": "^6.2.2" 39 | }, 40 | "peerDependencies": { 41 | "@vitest/runner": ">=1.1.0", 42 | "vitest": ">=1.1.0" 43 | }, 44 | "devDependencies": { 45 | "@types/node": "^20.10.0", 46 | "typescript": "^5.4.5", 47 | "vite": "^6.2.2", 48 | "vitest2": "npm:vitest@^2.1.9", 49 | "@vitest2/runner": "npm:@vitest/runner@^2.1.9", 50 | "vitest": "^3.0.8", 51 | "@types/ungap__structured-clone": "^1.2.0" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/cache.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs/promises'; 2 | import { deserialize, serialize, SerializedRecord } from '@ungap/structured-clone'; 3 | 4 | export interface CacheEntry { 5 | data: SerializedRecord; 6 | path: string; 7 | cost: number; 8 | timestamp: number; 9 | } 10 | 11 | export class TaskCache { 12 | constructor(readonly store: { [key: string]: CacheEntry }) { 13 | } 14 | 15 | cost(key: string) { 16 | const cache = this.store[key]; 17 | if (!cache) { 18 | return null; 19 | } 20 | return Math.round(cache.cost); 21 | } 22 | 23 | restore(key: string) { 24 | const cache = this.store[key]; 25 | 26 | if (!cache) { 27 | return null; 28 | } 29 | 30 | return cache.data ? deserialize(cache.data) : null; 31 | } 32 | 33 | has(key: string) { 34 | return !!this.store[key]?.data; 35 | } 36 | 37 | async save(key: string, data: T) { 38 | const cache = this.store[key]; 39 | 40 | if (!cache) { 41 | return null; 42 | } 43 | 44 | return fs.writeFile(cache.path, JSON.stringify({ 45 | ...cache, 46 | data: serialize(data), 47 | }), { 48 | encoding: 'utf-8', 49 | }); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/files.ts: -------------------------------------------------------------------------------- 1 | import { createVitest, ResolvedConfig } from 'vitest/node'; 2 | 3 | const convertToUserConfig = ({ shard, cache, ...config }: ResolvedConfig) => ({ 4 | ...config, 5 | shard: shard ? `${shard.index}/${shard.count}` : undefined, 6 | }); 7 | 8 | declare module 'vitest/node' { 9 | export interface Vitest { 10 | getTestFilepaths(): Promise; 11 | } 12 | } 13 | 14 | export const getFiles = async (config: ResolvedConfig): Promise => createVitest('test', convertToUserConfig(config)).then((vitest) => vitest.getTestFilepaths().finally(() => vitest.close())); 15 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import type { InlineConfig } from 'vitest/node'; 2 | import * as vi from 'vitest/node'; 3 | import type { CacheOptions } from './options.js'; 4 | import { vCache as v2 } from './v2.js'; 5 | import { vCache as v3 } from './v3.js'; 6 | 7 | declare module 'vite' { 8 | export interface UserConfig { 9 | test?: InlineConfig; 10 | } 11 | } 12 | 13 | export const vCache = vi.version ? v3 : v2; 14 | 15 | export type { 16 | CacheOptions, 17 | }; 18 | 19 | export default vi.version ? v3 : v2; 20 | -------------------------------------------------------------------------------- /src/load.ts: -------------------------------------------------------------------------------- 1 | import { OutputAsset, RollupOutput } from 'rollup'; 2 | import { build } from 'vite'; 3 | import { here } from './util.js'; 4 | import type { CacheEntry } from './cache.js'; 5 | 6 | const mapOutput = (output: RollupOutput['output']): { 7 | [k: string]: CacheEntry; 8 | } => 9 | Object.fromEntries( 10 | output 11 | .filter( 12 | (entry): entry is OutputAsset => entry.type === 'asset', 13 | ) 14 | .map( 15 | ({ 16 | name, 17 | source, 18 | }) => [name, JSON.parse(`${source}`)], 19 | ), 20 | ); 21 | 22 | export const load = (files: string[], dir: string) => build({ 23 | configFile: here('./tests.vite.config'), 24 | build: { 25 | outDir: dir, 26 | rollupOptions: { 27 | input: files, 28 | }, 29 | }, 30 | }).then(({ output }: RollupOutput) => mapOutput(output)) 31 | -------------------------------------------------------------------------------- /src/options.ts: -------------------------------------------------------------------------------- 1 | import type { TaskState } from 'vitest'; 2 | import type { CacheStrategy } from './strategy.js'; 3 | 4 | export interface CacheOptions { 5 | /* location for the caches, relative to the project root */ 6 | dir?: string; // default: '.tests' 7 | /* default: ['pass'] - which task states (test outcomes) should be cached */ 8 | states?: TaskState[]; // default: ['pass'] by default only passing tests are cached, failing tests are always rerun 9 | silent?: boolean; // default: false - if true, vCache will not write anything to stdout 10 | strategy?: CacheStrategy; 11 | } 12 | -------------------------------------------------------------------------------- /src/pool.ts: -------------------------------------------------------------------------------- 1 | import { createMethodsRPC, createVitest, ProcessPool, TestModule, Vitest } from 'vitest/node'; 2 | import { getTasks } from '@vitest/runner/utils'; 3 | import { createMeasurement, flagCache, format, formatDim, version } from './util.js'; 4 | import { load } from './load.js'; 5 | import { TaskCache } from './cache.js'; 6 | import { File, Task } from '@vitest/runner'; 7 | import { prune } from './prune.js'; 8 | 9 | interface TestModuleWithTask extends TestModule { 10 | task?: File; 11 | } 12 | 13 | const createCtx = async (vitest: Vitest) => { 14 | const { config } = vitest; 15 | const { silent } = config.vCache; 16 | 17 | const options = config.poolOptions?.vCache as any; 18 | 19 | if (!silent) { 20 | console.log(format('[vCache]'), formatDim(version)); 21 | } 22 | const building = createMeasurement('built hashes in', silent); 23 | 24 | const files = (await vitest.getRelevantTestSpecifications()).map(({ moduleId }) => moduleId); 25 | const output = await load(files, config.vCache.dir); 26 | 27 | building.done().log(); 28 | 29 | const counts = Object.values(output).reduce((acc, { data }) => { 30 | acc.total++; 31 | if (data) { 32 | acc.cache++; 33 | } 34 | 35 | return acc; 36 | }, { 37 | total: 0, 38 | cache: 0, 39 | }); 40 | 41 | const cache = new TaskCache(output); 42 | 43 | return { 44 | cache, 45 | output, 46 | counts, 47 | vitest: await createVitest('test', { 48 | ...options?.config.test, 49 | pool: options?.config.test?.pool || null, 50 | reporters: [{}], 51 | }, {}), 52 | }; 53 | }; 54 | 55 | export default (vitest: Vitest): ProcessPool => { 56 | const { config } = vitest; 57 | const { silent } = config.vCache; 58 | const shouldCache = (task: Task) => config.vCache.states.includes(task.result.state); 59 | 60 | const ctx = createCtx(vitest); 61 | 62 | return { 63 | name: 'vCache', 64 | async collectTests() { 65 | throw new Error('Not implemented'); 66 | }, 67 | async runTests(specs) { 68 | if (!config.vCache) { 69 | throw new Error('vCache is not enabled'); 70 | } 71 | 72 | const { cache, vitest } = await ctx; 73 | 74 | for (const { project, moduleId } of specs) { 75 | const methods = createMethodsRPC(project); 76 | const cached = cache.restore(moduleId); 77 | if (cached) { 78 | if (!silent) { 79 | flagCache(cached); 80 | } 81 | await methods.onCollected([cached]); 82 | await methods.onTaskUpdate(getTasks(cached).map(task => [ 83 | task.id, 84 | task.result, 85 | task.meta, 86 | ]), []); 87 | } else { 88 | const specs = await vitest.getRelevantTestSpecifications([moduleId]); 89 | const results = await vitest.runTestSpecifications(specs); 90 | 91 | const files = results.testModules.map((module: TestModuleWithTask) => module.task).filter(({ filepath }) => filepath === moduleId); 92 | 93 | for await (const file of files) { 94 | await methods.onCollected([file]); 95 | await methods.onTaskUpdate(getTasks(file).map(task => [ 96 | task.id, 97 | task.result, 98 | task.meta, 99 | ]), []); 100 | if (shouldCache(file)) { 101 | await cache.save(file.filepath, file); 102 | } 103 | } 104 | } 105 | } 106 | }, 107 | async close() { 108 | const { output, counts, vitest } = await ctx; 109 | await vitest.close(); 110 | if (!silent) { 111 | console.log(format('[vCache]'), formatDim(`${counts.cache}/${counts.total} files read from cache`)); 112 | } 113 | await prune(output, config); 114 | }, 115 | }; 116 | } 117 | -------------------------------------------------------------------------------- /src/prune.ts: -------------------------------------------------------------------------------- 1 | import { createMeasurement } from './util.js'; 2 | import fg from 'fast-glob'; 3 | import { dirname } from 'node:path'; 4 | import fs from 'node:fs/promises'; 5 | import { CacheEntry } from './cache.js'; 6 | import { applyStrategy } from './strategy.js'; 7 | import type { ResolvedConfig } from 'vitest/node'; 8 | 9 | export const prune = async (output: { [k: string]: CacheEntry }, { vCache }: ResolvedConfig) => { 10 | const pruning = createMeasurement(`Pruned`, vCache.silent); 11 | const batches = Object.values(output).map( 12 | ({ path }) => fg(`${dirname(path)}/*`).then( 13 | (files) => Promise.all( 14 | files.map( 15 | (file) => fs.readFile(file, 'utf-8').then(JSON.parse), 16 | ), 17 | ), 18 | ), 19 | ); 20 | const pruned = []; 21 | for await (const batch of batches) { 22 | pruned.push(...(await applyStrategy(batch, vCache.strategy))); 23 | } 24 | if (pruned.length) { 25 | pruning.done().log(` ${pruned.length} caches`); 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /src/runner.ts: -------------------------------------------------------------------------------- 1 | import { File, Task, updateTask, VitestRunner } from '@vitest/runner'; 2 | import { VitestTestRunner } from 'vitest/runners'; 3 | import { TaskCache } from './cache.js'; 4 | import { flagCache } from './util.js'; 5 | import { inject } from 'vitest'; 6 | 7 | declare module 'vitest/runners' { 8 | export interface VitestTestRunner { 9 | onCollected(files: File[]): unknown; 10 | 11 | onAfterRunFiles(files: File[]): Promise; 12 | } 13 | } 14 | 15 | class CachedRunner extends VitestTestRunner implements VitestRunner { 16 | private cache = new TaskCache(inject('v-cache:data')); 17 | private options = inject('v-cache:config'); 18 | 19 | async provideCoverage(path: string) { 20 | try { 21 | await super.importFile(path, 'collect'); 22 | } catch (e) { 23 | } 24 | } 25 | 26 | shouldCache(task: Task): boolean { 27 | return this.options.states.includes(task.result.state); 28 | } 29 | 30 | shouldLog() { 31 | return !this.options.silent; 32 | } 33 | 34 | async onBeforeCollect(paths: string[]) { 35 | const restored = []; 36 | for (const test of paths) { 37 | const cached = this.cache.restore(test); 38 | if (cached) { 39 | paths.splice(paths.indexOf(test), 1); 40 | if (this.shouldLog()) { 41 | flagCache(cached); 42 | } 43 | // @ts-ignore 44 | updateTask(cached, this); 45 | restored.push(cached); 46 | } 47 | if (this.config.coverage.enabled) { 48 | // coverage relies on runner imported sources 49 | await this.provideCoverage(test); 50 | } 51 | } 52 | this.onCollected?.(restored); 53 | } 54 | 55 | async onAfterRunFiles(files?: File[]) { 56 | for await (const file of files) { 57 | if (this.shouldCache(file)) { 58 | await this.cache.save(file.filepath, file); 59 | } 60 | } 61 | return super.onAfterRunFiles(files); 62 | } 63 | } 64 | 65 | export default CachedRunner; 66 | -------------------------------------------------------------------------------- /src/setup.ts: -------------------------------------------------------------------------------- 1 | import { GlobalSetupContext } from 'vitest/node'; 2 | import { createMeasurement, format, formatDim, version } from './util.js'; 3 | import { CacheOptions } from './options.js'; 4 | import { load } from './load.js'; 5 | import { getFiles } from './files.js'; 6 | import { prune } from './prune.js'; 7 | import type { CacheEntry } from './cache'; 8 | 9 | declare module 'vitest/node' { 10 | export interface ResolvedConfig { 11 | vCache: CacheOptions; 12 | } 13 | } 14 | 15 | declare module 'vitest' { 16 | export interface ProvidedContext { 17 | 'v-cache:data': { 18 | [key: string]: CacheEntry; 19 | }; 20 | 'v-cache:config': Omit; 21 | } 22 | } 23 | 24 | export default async ({ config, provide }: GlobalSetupContext) => { 25 | if (!config.vCache.silent) { 26 | console.log(format('[vCache]'), formatDim(version)); 27 | } 28 | 29 | const files = await getFiles(config); 30 | 31 | const building = createMeasurement('built hashes in', config.vCache.silent); 32 | const output = await load(files, config.vCache.dir); 33 | 34 | building.done().log(); 35 | 36 | provide('v-cache:data', output); 37 | provide('v-cache:config', config.vCache); 38 | 39 | const counts = Object.values(output).reduce((acc, { data }) => { 40 | acc.total++; 41 | if (data) { 42 | acc.cache++; 43 | } 44 | 45 | return acc; 46 | }, { 47 | total: 0, 48 | cache: 0, 49 | }); 50 | 51 | return async () => { 52 | if (!config.vCache.silent) { 53 | console.log(format('[vCache]'), formatDim(`${counts.cache}/${counts.total} files read from cache`)); 54 | } 55 | await prune(output, config); 56 | }; 57 | }; 58 | -------------------------------------------------------------------------------- /src/strategy.ts: -------------------------------------------------------------------------------- 1 | import type { CacheEntry } from './cache.js'; 2 | import fs from 'node:fs/promises'; 3 | 4 | interface ExtendedCacheEntry extends CacheEntry { 5 | size: number; 6 | } 7 | 8 | export interface CacheStrategy { 9 | (entries: ExtendedCacheEntry[]): ExtendedCacheEntry[]; 10 | } 11 | 12 | export const extendCacheEntry = (entry: CacheEntry): ExtendedCacheEntry => { 13 | const size = Buffer.from(JSON.stringify(entry)).toString('utf-8').length; 14 | 15 | return { ...entry, size }; 16 | }; 17 | 18 | export const defaultStrategy: CacheStrategy = (entries) => entries.sort((a, b) => b.timestamp - a.timestamp).slice(0, 3); 19 | 20 | export const applyStrategy = async (entries: CacheEntry[], strategy: CacheStrategy = defaultStrategy) => { 21 | const paths = entries.map((entry) => entry.path); 22 | const keep = strategy(entries.map((entry) => extendCacheEntry(entry))).map(({ path }) => path); 23 | 24 | const remove = paths.filter((path) => !keep.includes(path)); 25 | 26 | for await (const path of remove) { 27 | await fs.rm(path, { recursive: true }); 28 | } 29 | 30 | return remove; 31 | }; 32 | -------------------------------------------------------------------------------- /src/tests.vite.config.ts: -------------------------------------------------------------------------------- 1 | import { isBuiltin } from 'node:module'; 2 | import { createFilter, defineConfig, loadConfigFromFile } from 'vite'; 3 | import writer from './writer'; 4 | import { PluginContext } from 'rollup'; 5 | 6 | const isExternal = createFilter(['**/node_modules/**', /\.(svg|png|jpg|jpeg|s?css)$/]); 7 | 8 | const userConfig = loadConfigFromFile( 9 | { 10 | command: 'build', 11 | mode: 'production', 12 | }, 13 | undefined, 14 | process.cwd(), 15 | ); 16 | 17 | const config = userConfig.then(async (config) => 18 | defineConfig({ 19 | plugins: [ 20 | { 21 | name: 'v-cache:measure:start', 22 | enforce: 'pre', 23 | resolveId(id, _, { isEntry }) { 24 | if (isEntry) { 25 | return { 26 | id, 27 | meta: { 28 | start: performance.now(), 29 | }, 30 | }; 31 | } 32 | }, 33 | }, { 34 | name: 'v-cache:measure:end', 35 | moduleParsed(this: PluginContext, module) { 36 | if (module.isEntry) { 37 | module.meta.end = performance.now(); 38 | module.meta.cost = module.meta.end - module.meta.start; 39 | } 40 | }, 41 | }, 42 | writer(), 43 | ], 44 | publicDir: false, 45 | build: { 46 | outDir: '.tests', 47 | target: 'node20', 48 | sourcemap: false, 49 | minify: false, 50 | emptyOutDir: false, 51 | cssCodeSplit: false, 52 | rollupOptions: { 53 | treeshake: { 54 | preset: 'smallest', 55 | moduleSideEffects: true, 56 | }, 57 | preserveEntrySignatures: 'strict', 58 | external: (source) => isBuiltin(source) || isExternal(source), 59 | output: { 60 | format: 'module', 61 | preserveModules: true, 62 | chunkFileNames: '[hash:16]', 63 | assetFileNames: '[hash:16]', 64 | entryFileNames: '[hash:16]', 65 | }, 66 | logLevel: 'silent', 67 | }, 68 | }, 69 | resolve: config?.config.resolve, 70 | logLevel: 'silent', 71 | }), 72 | ); 73 | 74 | export default config; 75 | -------------------------------------------------------------------------------- /src/util.ts: -------------------------------------------------------------------------------- 1 | import { dirname, resolve } from 'node:path'; 2 | import { fileURLToPath } from 'node:url'; 3 | import chalk from 'chalk'; 4 | import fs from 'node:fs'; 5 | import { Task } from '@vitest/runner'; 6 | 7 | const __dirname = globalThis.__dirname || fileURLToPath(dirname(import.meta.url)); 8 | 9 | export const here = (path: string) => resolve(__dirname, path); 10 | 11 | export const version = JSON.parse(fs.readFileSync(here('../package.json'), 'utf-8')).version; 12 | export const name = 'vitest-cache'; 13 | 14 | export const format = chalk.hex('#BE29EC'); 15 | export const formatDim = chalk.dim.hex('#BE29EC'); 16 | 17 | export const createMeasurement = (action: string, silent?: boolean) => { 18 | const start = performance.now(); 19 | return { 20 | done: () => { 21 | const duration = Math.round((performance.now() - start) / 10) / 100; 22 | return { 23 | log: (extra: string = '', flag = format('[vCache]')) => { 24 | if (!silent) { 25 | console.log(flag, formatDim(`${action}${extra} ${duration}s`)); 26 | } 27 | }, 28 | }; 29 | }, 30 | }; 31 | }; 32 | 33 | export const flagCache = (task: T) => { 34 | if (task.type === 'suite') { 35 | task.tasks.forEach(flagCache); 36 | } 37 | task.name = `\b\b${format(`⛁`)} ${task.name}`; 38 | task.result = { 39 | ...task.result, 40 | duration: 0, 41 | }; 42 | 43 | return task; 44 | }; 45 | -------------------------------------------------------------------------------- /src/v2.ts: -------------------------------------------------------------------------------- 1 | import { here, name } from './util.js'; 2 | import type { CacheOptions } from './options.js'; 3 | import type { Plugin } from 'vite'; 4 | 5 | const defaults = { 6 | dir: '.tests', 7 | states: ['pass'], 8 | silent: false, 9 | }; 10 | 11 | export const vCache = (options?: CacheOptions): Plugin => ({ 12 | name, 13 | config: () => ({ 14 | test: { 15 | vCache: { 16 | ...defaults, 17 | ...options, 18 | }, 19 | runner: here('./runner'), 20 | globalSetup: here('./setup'), 21 | }, 22 | }), 23 | }); 24 | -------------------------------------------------------------------------------- /src/v3.ts: -------------------------------------------------------------------------------- 1 | import type { Plugin, UserConfig } from 'vite'; 2 | import { here, name } from './util.js'; 3 | import type { CacheOptions } from './options'; 4 | 5 | declare module 'vitest/node' { 6 | export interface PoolOptions { 7 | vCache: { config: UserConfig }; 8 | } 9 | 10 | export interface ResolvedConfig { 11 | vCache: CacheOptions; 12 | } 13 | } 14 | 15 | const defaults = { 16 | dir: '.tests', 17 | states: ['pass'], 18 | silent: false, 19 | }; 20 | 21 | export const vCache = (options?: CacheOptions): Plugin => ({ 22 | name, 23 | config: (config) => ({ 24 | test: { 25 | vCache: { 26 | ...defaults, 27 | ...options, 28 | }, 29 | pool: here('./pool'), 30 | poolOptions: { 31 | vCache: { 32 | config: { 33 | ...config, 34 | test: { 35 | ...config.test, 36 | }, 37 | }, 38 | }, 39 | }, 40 | }, 41 | }), 42 | }); 43 | -------------------------------------------------------------------------------- /src/writer.ts: -------------------------------------------------------------------------------- 1 | import fs from 'node:fs/promises'; 2 | import path from 'node:path'; 3 | import { Plugin } from 'vite'; 4 | import { PluginContext } from 'rollup'; 5 | import { CacheEntry } from './cache.js'; 6 | 7 | const getResults = async (file: string): Promise => fs.stat(file) 8 | .then(() => fs.readFile(file, { 9 | encoding: 'utf8', 10 | })) 11 | .then(JSON.parse) 12 | .catch(() => ({ 13 | data: null, 14 | })); 15 | 16 | export default (): Plugin => ({ 17 | name: 'v-cache:writer', 18 | async generateBundle(this: PluginContext, { dir }, bundle) { 19 | await Promise.all(Object.entries(bundle).map(async ([file, output]) => { 20 | delete bundle[file]; 21 | 22 | if (output.type !== 'chunk') { 23 | return; 24 | } 25 | 26 | const { isEntry, facadeModuleId, name, fileName: hash } = output; 27 | 28 | if (isEntry) { 29 | const filePath = facadeModuleId.substring(facadeModuleId.indexOf(name)); 30 | const fileName = path.join(filePath, hash); 31 | const resolved = path.resolve(dir, fileName); 32 | 33 | const { data } = await getResults(resolved); 34 | 35 | const { cost } = this.getModuleInfo(facadeModuleId).meta; 36 | 37 | this.emitFile({ 38 | type: 'asset', 39 | fileName, 40 | name: facadeModuleId, 41 | source: JSON.stringify({ 42 | data, 43 | path: resolved, 44 | cost, 45 | timestamp: Date.now(), 46 | }), 47 | }); 48 | } 49 | })); 50 | }, 51 | }) 52 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "target": "ESNext", 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "allowSyntheticDefaultImports": true, 8 | "esModuleInterop": true, 9 | "declaration": true, 10 | "module": "ESNext", 11 | "moduleResolution": "node", 12 | "jsx": "react-jsx", 13 | "resolveJsonModule": true, 14 | "types": [ 15 | "vite/client", 16 | "vitest/config" 17 | ] 18 | }, 19 | "include": ["src"] 20 | } 21 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | watch: false, 6 | alias: [{ 7 | find: /vitest\/node/, 8 | replacement: 'vitest/node', 9 | customResolver(_, importer) { 10 | if (importer.endsWith('__test__/v2.spec.ts') || importer.endsWith('src/files.ts')) { 11 | return this.resolve('vitest2/node'); 12 | } 13 | }, 14 | }], 15 | }, 16 | }); 17 | --------------------------------------------------------------------------------