From 9b5f3a702d0bdec79c0b33f904d0d3c1a40566f1 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Tue, 3 Dec 2024 17:03:24 +0000 Subject: [PATCH] refactor: use `vitest` for benchmarks (#12605) * refactor: use `vitest` for benchmarks * increase timeout * increase timeout * Restore correct label --- .github/workflows/continuous_benchmark.yml | 3 +- benchmark/bench/_util.js | 11 + benchmark/bench/codspeed.bench.js | 48 ++++ benchmark/bench/codspeed.js | 64 ----- benchmark/index.js | 44 +--- benchmark/make-project/markdown-cc1.js | 13 +- benchmark/make-project/markdown-cc2.js | 8 +- benchmark/make-project/mdx-cc1.js | 13 +- benchmark/make-project/mdx-cc2.js | 8 +- benchmark/make-project/memory-default.js | 10 +- benchmark/make-project/render-bench.js | 4 +- benchmark/make-project/render-default.js | 4 +- .../make-project/server-stress-default.js | 6 +- benchmark/package.json | 7 +- benchmark/vitest.config.js | 7 + biome.jsonc | 2 +- pnpm-lock.yaml | 219 +++++++++++++++++- 17 files changed, 324 insertions(+), 147 deletions(-) create mode 100644 benchmark/bench/codspeed.bench.js delete mode 100644 benchmark/bench/codspeed.js create mode 100644 benchmark/vitest.config.js diff --git a/.github/workflows/continuous_benchmark.yml b/.github/workflows/continuous_benchmark.yml index a1d48bb8d9..1b382f8dc6 100644 --- a/.github/workflows/continuous_benchmark.yml +++ b/.github/workflows/continuous_benchmark.yml @@ -50,6 +50,7 @@ jobs: uses: CodSpeedHQ/action@513a19673a831f139e8717bf45ead67e47f00044 # v3.2.0 timeout-minutes: 30 with: - run: pnpm benchmark codspeed + working-directory: ./benchmark + run: pnpm bench token: ${{ secrets.CODSPEED_TOKEN }} diff --git a/benchmark/bench/_util.js b/benchmark/bench/_util.js index b16a16e1ce..d9dfe5b190 100644 --- a/benchmark/bench/_util.js +++ b/benchmark/bench/_util.js @@ -19,3 +19,14 @@ export function calculateStat(numbers) { const max = Math.max(...numbers); return { avg, stdev, max }; } + +export async function makeProject(name) { + console.log('Making project:', name); + const projectDir = new URL(`../projects/${name}/`, import.meta.url); + + const makeProjectMod = await import(`../make-project/${name}.js`); + await makeProjectMod.run(projectDir); + + console.log('Finished making project:', name); + return projectDir; +} diff --git a/benchmark/bench/codspeed.bench.js b/benchmark/bench/codspeed.bench.js new file mode 100644 index 0000000000..4073ebed85 --- /dev/null +++ b/benchmark/bench/codspeed.bench.js @@ -0,0 +1,48 @@ +import { fileURLToPath } from 'node:url'; +import { exec } from 'tinyexec'; +import { beforeAll, bench, describe } from 'vitest'; +import { astroBin, makeProject } from './_util.js'; +let streamingApp; +let nonStreamingApp; +beforeAll(async () => { + const render = await makeProject('render-bench'); + const root = fileURLToPath(render); + await exec(astroBin, ['build'], { + nodeOptions: { + cwd: root, + stdio: 'inherit', + }, + }); + const entry = new URL('./dist/server/entry.mjs', `file://${root}`); + const { manifest, createApp } = await import(entry); + streamingApp = createApp(manifest, true); + nonStreamingApp = createApp(manifest, false); +}, 900000); + +describe('Bench rendering', () => { + bench('Rendering: streaming [true], .astro file', async () => { + const request = new Request(new URL('http://exmpale.com/astro')); + await streamingApp.render(request); + }); + bench('Rendering: streaming [true], .md file', async () => { + const request = new Request(new URL('http://exmpale.com/md')); + await streamingApp.render(request); + }); + bench('Rendering: streaming [true], .mdx file', async () => { + const request = new Request(new URL('http://exmpale.com/mdx')); + await streamingApp.render(request); + }); + + bench('Rendering: streaming [false], .astro file', async () => { + const request = new Request(new URL('http://exmpale.com/astro')); + await nonStreamingApp.render(request); + }); + bench('Rendering: streaming [false], .md file', async () => { + const request = new Request(new URL('http://exmpale.com/md')); + await nonStreamingApp.render(request); + }); + bench('Rendering: streaming [false], .mdx file', async () => { + const request = new Request(new URL('http://exmpale.com/mdx')); + await nonStreamingApp.render(request); + }); +}); diff --git a/benchmark/bench/codspeed.js b/benchmark/bench/codspeed.js deleted file mode 100644 index 2643b1ec8a..0000000000 --- a/benchmark/bench/codspeed.js +++ /dev/null @@ -1,64 +0,0 @@ -import path from 'node:path'; -import { withCodSpeed } from '@codspeed/tinybench-plugin'; -import { Bench } from 'tinybench'; -import { exec } from 'tinyexec'; -import { astroBin } from './_util.js'; - -export async function run({ memory: _memory, render, stress: _stress }) { - const options = { - iterations: 10, - }; - const bench = process.env.CODSPEED ? withCodSpeed(new Bench(options)) : new Bench(options); - await exec(astroBin, ['build'], { - nodeOptions: { - cwd: render.root, - stdio: 'inherit', - }, - }); - - const entry = new URL('./dist/server/entry.mjs', `file://${render.root}`); - const { manifest, createApp } = await import(entry); - const streamingApp = createApp(manifest, true); - const nonStreamingApp = createApp(manifest, false); - bench - .add('Rendering: streaming [true], .astro file', async () => { - console.info('Start task.'); - const request = new Request(new URL('http://exmpale.com/astro')); - await streamingApp.render(request); - console.info('Finish task.'); - }) - .add('Rendering: streaming [true], .md file', async () => { - console.info('Start task.'); - const request = new Request(new URL('http://exmpale.com/md')); - await streamingApp.render(request); - console.info('Finish task.'); - }) - .add('Rendering: streaming [true], .mdx file', async () => { - console.info('Start task.'); - const request = new Request(new URL('http://exmpale.com/mdx')); - await streamingApp.render(request); - console.info('Finish task.'); - }) - - .add('Rendering: streaming [false], .astro file', async () => { - console.info('Start task.'); - const request = new Request(new URL('http://exmpale.com/astro')); - await nonStreamingApp.render(request); - console.info('Finish task.'); - }) - .add('Rendering: streaming [false], .md file', async () => { - console.info('Start task.'); - const request = new Request(new URL('http://exmpale.com/md')); - await nonStreamingApp.render(request); - console.info('Finish task.'); - }) - .add('Rendering: streaming [false], .mdx file', async () => { - console.info('Start task.'); - const request = new Request(new URL('http://exmpale.com/mdx')); - await nonStreamingApp.render(request); - console.info('Finish task.'); - }); - - await bench.run(); - console.table(bench.table()); -} diff --git a/benchmark/index.js b/benchmark/index.js index 2f2846e1db..127fc4f5bf 100755 --- a/benchmark/index.js +++ b/benchmark/index.js @@ -1,7 +1,8 @@ import mri from 'mri'; import fs from 'node:fs/promises'; import path from 'node:path'; -import {fileURLToPath, pathToFileURL} from 'node:url'; +import { fileURLToPath, pathToFileURL } from 'node:url'; +import { makeProject } from './bench/_util.js'; const args = mri(process.argv.slice(2)); @@ -14,7 +15,6 @@ Command memory Run build memory and speed test render Run rendering speed test server-stress Run server stress test - codspeed Run codspeed test cli-startup Run CLI startup speed test Options @@ -30,7 +30,6 @@ const benchmarks = { render: () => import('./bench/render.js'), 'server-stress': () => import('./bench/server-stress.js'), 'cli-startup': () => import('./bench/cli-startup.js'), - codspeed: () => import('./bench/codspeed.js') }; if (commandName && !(commandName in benchmarks)) { @@ -39,26 +38,12 @@ if (commandName && !(commandName in benchmarks)) { } if (commandName) { - if (commandName === 'codspeed') { - const render = await makeProject('render-bench'); - const rootRender = fileURLToPath(render); - const bench = benchmarks[commandName]; - const benchMod = await bench(); - const payload = { - render: { - root: rootRender, - output: await getOutputFile('render') - }, - }; - await benchMod.run(payload); - } else { - // Run single benchmark - const bench = benchmarks[commandName]; - const benchMod = await bench(); - const projectDir = await makeProject(args.project || benchMod.defaultProject); - const outputFile = await getOutputFile(commandName); - await benchMod.run(projectDir, outputFile); - } + // Run single benchmark + const bench = benchmarks[commandName]; + const benchMod = await bench(); + const projectDir = await makeProject(args.project || benchMod.defaultProject); + const outputFile = await getOutputFile(commandName); + await benchMod.run(projectDir, outputFile); } else { // Run all benchmarks for (const name in benchmarks) { @@ -70,21 +55,10 @@ if (commandName) { } } -export async function makeProject(name) { - console.log('Making project:', name); - const projectDir = new URL(`./projects/${name}/`, import.meta.url); - - const makeProjectMod = await import(`./make-project/${name}.js`); - await makeProjectMod.run(projectDir); - - console.log('Finished making project:', name); - return projectDir; -} - /** * @param {string} benchmarkName */ -async function getOutputFile(benchmarkName) { +export async function getOutputFile(benchmarkName) { let file; if (args.output) { file = pathToFileURL(path.resolve(args.output)); diff --git a/benchmark/make-project/markdown-cc1.js b/benchmark/make-project/markdown-cc1.js index 6c83959601..1e3aaa5177 100644 --- a/benchmark/make-project/markdown-cc1.js +++ b/benchmark/make-project/markdown-cc1.js @@ -8,11 +8,13 @@ export async function run(projectDir) { await fs.rm(projectDir, { recursive: true, force: true }); await fs.mkdir(new URL('./src/pages/blog', projectDir), { recursive: true }); await fs.mkdir(new URL('./src/content/blog', projectDir), { recursive: true }); - await fs.copyFile(new URL('./image.jpg', import.meta.url), new URL('./src/image.jpg', projectDir)); + await fs.copyFile( + new URL('./image.jpg', import.meta.url), + new URL('./src/image.jpg', projectDir), + ); const promises = []; - for (let i = 0; i < 10000; i++) { const content = `\ # Article ${i} @@ -24,11 +26,10 @@ ${loremIpsumMd} `; promises.push( - fs.writeFile(new URL(`./src/content/blog/article-${i}.md`, projectDir), content, 'utf-8') + fs.writeFile(new URL(`./src/content/blog/article-${i}.md`, projectDir), content, 'utf-8'), ); } - await fs.writeFile( new URL(`./src/pages/blog/[...slug].astro`, projectDir), `\ @@ -46,7 +47,7 @@ const { Content } = await entry.render();

{entry.data.title}

`, - 'utf-8' + 'utf-8', ); await Promise.all(promises); @@ -58,6 +59,6 @@ import { defineConfig } from 'astro/config'; export default defineConfig({ });`, - 'utf-8' + 'utf-8', ); } diff --git a/benchmark/make-project/markdown-cc2.js b/benchmark/make-project/markdown-cc2.js index 9ce95f0dc2..ba60813c0d 100644 --- a/benchmark/make-project/markdown-cc2.js +++ b/benchmark/make-project/markdown-cc2.js @@ -23,7 +23,7 @@ ${loremIpsumMd} `; promises.push( - fs.writeFile(new URL(`./data/blog/article-${i}.md`, projectDir), content, 'utf-8') + fs.writeFile(new URL(`./data/blog/article-${i}.md`, projectDir), content, 'utf-8'), ); } @@ -39,7 +39,7 @@ ${loremIpsumMd} export const collections = { blog } - ` + `, ); await fs.writeFile( @@ -60,7 +60,7 @@ const { Content } = await render(entry);

{entry.data.title}

`, - 'utf-8' + 'utf-8', ); await Promise.all(promises); @@ -71,6 +71,6 @@ const { Content } = await render(entry); import { defineConfig } from 'astro/config'; export default defineConfig({});`, - 'utf-8' + 'utf-8', ); } diff --git a/benchmark/make-project/mdx-cc1.js b/benchmark/make-project/mdx-cc1.js index 98e1495d13..a948ce1940 100644 --- a/benchmark/make-project/mdx-cc1.js +++ b/benchmark/make-project/mdx-cc1.js @@ -8,11 +8,13 @@ export async function run(projectDir) { await fs.rm(projectDir, { recursive: true, force: true }); await fs.mkdir(new URL('./src/pages/blog', projectDir), { recursive: true }); await fs.mkdir(new URL('./src/content/blog', projectDir), { recursive: true }); - await fs.copyFile(new URL('./image.jpg', import.meta.url), new URL('./src/image.jpg', projectDir)); + await fs.copyFile( + new URL('./image.jpg', import.meta.url), + new URL('./src/image.jpg', projectDir), + ); const promises = []; - for (let i = 0; i < 10000; i++) { const content = `\ # Article ${i} @@ -24,11 +26,10 @@ ${loremIpsumMd} `; promises.push( - fs.writeFile(new URL(`./src/content/blog/article-${i}.mdx`, projectDir), content, 'utf-8') + fs.writeFile(new URL(`./src/content/blog/article-${i}.mdx`, projectDir), content, 'utf-8'), ); } - await fs.writeFile( new URL(`./src/pages/blog/[...slug].astro`, projectDir), `\ @@ -46,7 +47,7 @@ const { Content } = await entry.render();

{entry.data.title}

`, - 'utf-8' + 'utf-8', ); await Promise.all(promises); @@ -61,6 +62,6 @@ import mdx from '@astrojs/mdx'; export default defineConfig({ integrations: [mdx()], });`, - 'utf-8' + 'utf-8', ); } diff --git a/benchmark/make-project/mdx-cc2.js b/benchmark/make-project/mdx-cc2.js index ab6ddeb3b6..f50b63c9ee 100644 --- a/benchmark/make-project/mdx-cc2.js +++ b/benchmark/make-project/mdx-cc2.js @@ -23,7 +23,7 @@ ${loremIpsumMd} `; promises.push( - fs.writeFile(new URL(`./data/blog/article-${i}.mdx`, projectDir), content, 'utf-8') + fs.writeFile(new URL(`./data/blog/article-${i}.mdx`, projectDir), content, 'utf-8'), ); } @@ -39,7 +39,7 @@ ${loremIpsumMd} export const collections = { blog } - ` + `, ); await fs.writeFile( @@ -60,7 +60,7 @@ const { Content } = await render(entry);

{entry.data.title}

`, - 'utf-8' + 'utf-8', ); await Promise.all(promises); @@ -75,6 +75,6 @@ import mdx from '@astrojs/mdx'; export default defineConfig({ integrations: [mdx()], });`, - 'utf-8' + 'utf-8', ); } diff --git a/benchmark/make-project/memory-default.js b/benchmark/make-project/memory-default.js index e3652dd579..1087c3d4aa 100644 --- a/benchmark/make-project/memory-default.js +++ b/benchmark/make-project/memory-default.js @@ -20,7 +20,7 @@ const i = ${i}; {i} `; promises.push( - fs.writeFile(new URL(`./src/pages/page-${i}.astro`, projectDir), content, 'utf-8') + fs.writeFile(new URL(`./src/pages/page-${i}.astro`, projectDir), content, 'utf-8'), ); } @@ -31,7 +31,7 @@ const i = ${i}; ${loremIpsum} `; promises.push( - fs.writeFile(new URL(`./src/content/blog/article-${i}.md`, projectDir), content, 'utf-8') + fs.writeFile(new URL(`./src/content/blog/article-${i}.md`, projectDir), content, 'utf-8'), ); } @@ -42,7 +42,7 @@ ${loremIpsum} ${loremIpsum} `; promises.push( - fs.writeFile(new URL(`./src/content/blog/post-${i}.mdx`, projectDir), content, 'utf-8') + fs.writeFile(new URL(`./src/content/blog/post-${i}.mdx`, projectDir), content, 'utf-8'), ); } @@ -63,7 +63,7 @@ const { Content } = await entry.render();

{entry.data.title}

`, - 'utf-8' + 'utf-8', ); await Promise.all(promises); @@ -77,6 +77,6 @@ import mdx from '@astrojs/mdx'; export default defineConfig({ integrations: [mdx()], });`, - 'utf-8' + 'utf-8', ); } diff --git a/benchmark/make-project/render-bench.js b/benchmark/make-project/render-bench.js index 9d10d9bf5f..e2964fbd23 100644 --- a/benchmark/make-project/render-bench.js +++ b/benchmark/make-project/render-bench.js @@ -112,7 +112,7 @@ export async function run(projectDir) { await Promise.all( Object.entries(renderFiles).map(([name, content]) => { return fs.writeFile(new URL(`./src/${name}`, projectDir), content, 'utf-8'); - }) + }), ); await fs.writeFile( @@ -127,6 +127,6 @@ export default defineConfig({ output: 'server', adapter: adapter(), });`, - 'utf-8' + 'utf-8', ); } diff --git a/benchmark/make-project/render-default.js b/benchmark/make-project/render-default.js index f42340fd3b..7ea54b936e 100644 --- a/benchmark/make-project/render-default.js +++ b/benchmark/make-project/render-default.js @@ -112,7 +112,7 @@ export async function run(projectDir) { await Promise.all( Object.entries(renderFiles).map(([name, content]) => { return fs.writeFile(new URL(`./src/${name}`, projectDir), content, 'utf-8'); - }) + }), ); await fs.writeFile( @@ -127,6 +127,6 @@ export default defineConfig({ output: 'server', adapter: timer(), });`, - 'utf-8' + 'utf-8', ); } diff --git a/benchmark/make-project/server-stress-default.js b/benchmark/make-project/server-stress-default.js index 79e8b260af..1724f8f825 100644 --- a/benchmark/make-project/server-stress-default.js +++ b/benchmark/make-project/server-stress-default.js @@ -38,13 +38,13 @@ const content = "${loremIpsum}" `, - 'utf-8' + 'utf-8', ); await fs.writeFile( new URL('./src/components/Paragraph.astro', projectDir), `
{Astro.props.num} {Astro.props.str}
`, - 'utf-8' + 'utf-8', ); await fs.writeFile( @@ -57,6 +57,6 @@ export default defineConfig({ output: 'server', adapter: nodejs({ mode: 'standalone' }), });`, - 'utf-8' + 'utf-8', ); } diff --git a/benchmark/package.json b/benchmark/package.json index 428afe56d2..708ee14d12 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -6,6 +6,9 @@ "bin": { "astro-benchmark": "./index.js" }, + "scripts": { + "bench": "pnpm vitest bench --run" + }, "dependencies": { "@astrojs/mdx": "workspace:*", "@astrojs/node": "^8.3.4", @@ -21,7 +24,7 @@ "tinyexec": "^0.3.1" }, "devDependencies": { - "@codspeed/tinybench-plugin": "^3.1.1", - "tinybench": "^2.9.0" + "@codspeed/vitest-plugin": "3.1.1", + "vitest": "2.1.8" } } diff --git a/benchmark/vitest.config.js b/benchmark/vitest.config.js new file mode 100644 index 0000000000..b8b6e5e52a --- /dev/null +++ b/benchmark/vitest.config.js @@ -0,0 +1,7 @@ +import codspeedPlugin from '@codspeed/vitest-plugin'; +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + plugins: process.env.CODSPEED ? [codspeedPlugin()] : [], + include: ['./bench/codspeed.bench.js'], +}); diff --git a/biome.jsonc b/biome.jsonc index adadd8f597..bab1f1a05b 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -2,7 +2,7 @@ "$schema": "https://biomejs.dev/schemas/1.9.3/schema.json", "files": { "ignore": ["**/smoke/**", "**/fixtures/**", "**/_temp-fixtures/**", "**/vendor/**"], - "include": ["test/**", "e2e/**", "packages/**", "scripts/**", "benchmark/bench"], + "include": ["test/**", "e2e/**", "packages/**", "scripts/**", "benchmark"], }, "vcs": { "enabled": true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e0d3e97eec..ef2e1204d6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -100,12 +100,12 @@ importers: specifier: ^0.3.1 version: 0.3.1 devDependencies: - '@codspeed/tinybench-plugin': - specifier: ^3.1.1 - version: 3.1.1(tinybench@2.9.0) - tinybench: - specifier: ^2.9.0 - version: 2.9.0 + '@codspeed/vitest-plugin': + specifier: 3.1.1 + version: 3.1.1(vite@6.0.1(@types/node@18.19.50)(jiti@1.21.6)(sass@1.81.0)(yaml@2.5.1))(vitest@2.1.8(@types/node@18.19.50)(jsdom@23.2.0)(sass@1.81.0)) + vitest: + specifier: 2.1.8 + version: 2.1.8(@types/node@18.19.50)(jsdom@23.2.0)(sass@1.81.0) benchmark/packages/adapter: dependencies: @@ -5935,10 +5935,11 @@ packages: '@codspeed/core@3.1.1': resolution: {integrity: sha512-ONhERVDAtkm0nc+FYPivDozoMOlNUP2BWRBFDJYATGA18Iap5Kd2mZ1/Lwz54RB5+g+3YDOpsvotHa4hd3Q+7Q==} - '@codspeed/tinybench-plugin@3.1.1': - resolution: {integrity: sha512-LVF4End0kDU9V7CzuwAcmngSPJNnpduPnr+csOKvcG++FsYwfUuBJ1rvLPtv6yTkvxpUmUEsj6VA7/AEIBGZVw==} + '@codspeed/vitest-plugin@3.1.1': + resolution: {integrity: sha512-/PJUgxIfuRqpBSbaD8bgWXtbXxCqgnW89dzr3220fMkx/LA6z6oUb4tJGjeVsOWAzAgu0VBdSA+8hC+7D9BIuQ==} peerDependencies: - tinybench: ^2.3.0 + vite: ^4.2.0 || ^5.0.0 + vitest: '>=1.2.2' '@colors/colors@1.5.0': resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} @@ -7328,6 +7329,9 @@ packages: '@vitest/expect@2.1.6': resolution: {integrity: sha512-9M1UR9CAmrhJOMoSwVnPh2rELPKhYo0m/CSgqw9PyStpxtkwhmdM6XYlXGKeYyERY1N6EIuzkQ7e3Lm1WKCoUg==} + '@vitest/expect@2.1.8': + resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==} + '@vitest/mocker@2.1.6': resolution: {integrity: sha512-MHZp2Z+Q/A3am5oD4WSH04f9B0T7UvwEb+v5W0kCYMhtXGYbdyl2NUk1wdSMqGthmhpiThPDp/hEoVwu16+u1A==} peerDependencies: @@ -7339,21 +7343,47 @@ packages: vite: optional: true + '@vitest/mocker@2.1.8': + resolution: {integrity: sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + '@vitest/pretty-format@2.1.6': resolution: {integrity: sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==} + '@vitest/pretty-format@2.1.8': + resolution: {integrity: sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==} + '@vitest/runner@2.1.6': resolution: {integrity: sha512-SjkRGSFyrA82m5nz7To4CkRSEVWn/rwQISHoia/DB8c6IHIhaE/UNAo+7UfeaeJRE979XceGl00LNkIz09RFsA==} + '@vitest/runner@2.1.8': + resolution: {integrity: sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==} + '@vitest/snapshot@2.1.6': resolution: {integrity: sha512-5JTWHw8iS9l3v4/VSuthCndw1lN/hpPB+mlgn1BUhFbobeIUj1J1V/Bj2t2ovGEmkXLTckFjQddsxS5T6LuVWw==} + '@vitest/snapshot@2.1.8': + resolution: {integrity: sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==} + '@vitest/spy@2.1.6': resolution: {integrity: sha512-oTFObV8bd4SDdRka5O+mSh5w9irgx5IetrD5i+OsUUsk/shsBoHifwCzy45SAORzAhtNiprUVaK3hSCCzZh1jQ==} + '@vitest/spy@2.1.8': + resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==} + '@vitest/utils@2.1.6': resolution: {integrity: sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==} + '@vitest/utils@2.1.8': + resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==} + '@volar/kit@2.4.6': resolution: {integrity: sha512-OaMtpmLns6IYD1nOSd0NdG/F5KzJ7Jr4B7TLeb4byPzu+ExuuRVeO56Dn1C7Frnw6bGudUQd90cpQAmxdB+RlQ==} peerDependencies: @@ -10777,6 +10807,11 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true + vite-node@2.1.8: + resolution: {integrity: sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + vite-plugin-inspect@0.8.7: resolution: {integrity: sha512-/XXou3MVc13A5O9/2Nd6xczjrUwt7ZyI9h8pTnUMkr5SshLcb0PJUOVq2V+XVkdeU4njsqAtmK87THZuO2coGA==} engines: {node: '>=14'} @@ -10813,6 +10848,37 @@ packages: peerDependencies: vue: '>=3.2.13' + vite@5.4.11: + resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + vite@6.0.1: resolution: {integrity: sha512-Ldn6gorLGr4mCdFnmeAOLweJxZ34HjKnDm4HGo6P66IEqTxQb36VEdFJQENKxWjupNfoIjvRUnswjn1hpYEpjQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -10886,6 +10952,31 @@ packages: jsdom: optional: true + vitest@2.1.8: + resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.1.8 + '@vitest/ui': 2.1.8 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + volar-service-css@0.0.61: resolution: {integrity: sha512-Ct9L/w+IB1JU8F4jofcNCGoHy6TF83aiapfZq9A0qYYpq+Kk5dH+ONS+rVZSsuhsunq8UvAuF8Gk6B8IFLfniw==} peerDependencies: @@ -11764,11 +11855,11 @@ snapshots: transitivePeerDependencies: - debug - '@codspeed/tinybench-plugin@3.1.1(tinybench@2.9.0)': + '@codspeed/vitest-plugin@3.1.1(vite@6.0.1(@types/node@18.19.50)(jiti@1.21.6)(sass@1.81.0)(yaml@2.5.1))(vitest@2.1.8(@types/node@18.19.50)(jsdom@23.2.0)(sass@1.81.0))': dependencies: '@codspeed/core': 3.1.1 - stack-trace: 1.0.0-pre2 - tinybench: 2.9.0 + vite: 6.0.1(@types/node@18.19.50)(jiti@1.21.6)(sass@1.81.0)(yaml@2.5.1) + vitest: 2.1.8(@types/node@18.19.50)(jsdom@23.2.0)(sass@1.81.0) transitivePeerDependencies: - debug @@ -13029,6 +13120,13 @@ snapshots: chai: 5.1.2 tinyrainbow: 1.2.0 + '@vitest/expect@2.1.8': + dependencies: + '@vitest/spy': 2.1.8 + '@vitest/utils': 2.1.8 + chai: 5.1.2 + tinyrainbow: 1.2.0 + '@vitest/mocker@2.1.6(vite@6.0.1(@types/node@18.19.50)(jiti@1.21.6)(sass@1.81.0)(yaml@2.5.1))': dependencies: '@vitest/spy': 2.1.6 @@ -13037,31 +13135,64 @@ snapshots: optionalDependencies: vite: 6.0.1(@types/node@18.19.50)(jiti@1.21.6)(sass@1.81.0)(yaml@2.5.1) + '@vitest/mocker@2.1.8(vite@5.4.11(@types/node@18.19.50)(sass@1.81.0))': + dependencies: + '@vitest/spy': 2.1.8 + estree-walker: 3.0.3 + magic-string: 0.30.14 + optionalDependencies: + vite: 5.4.11(@types/node@18.19.50)(sass@1.81.0) + '@vitest/pretty-format@2.1.6': dependencies: tinyrainbow: 1.2.0 + '@vitest/pretty-format@2.1.8': + dependencies: + tinyrainbow: 1.2.0 + '@vitest/runner@2.1.6': dependencies: '@vitest/utils': 2.1.6 pathe: 1.1.2 + '@vitest/runner@2.1.8': + dependencies: + '@vitest/utils': 2.1.8 + pathe: 1.1.2 + '@vitest/snapshot@2.1.6': dependencies: '@vitest/pretty-format': 2.1.6 magic-string: 0.30.14 pathe: 1.1.2 + '@vitest/snapshot@2.1.8': + dependencies: + '@vitest/pretty-format': 2.1.8 + magic-string: 0.30.14 + pathe: 1.1.2 + '@vitest/spy@2.1.6': dependencies: tinyspy: 3.0.2 + '@vitest/spy@2.1.8': + dependencies: + tinyspy: 3.0.2 + '@vitest/utils@2.1.6': dependencies: '@vitest/pretty-format': 2.1.6 loupe: 3.1.2 tinyrainbow: 1.2.0 + '@vitest/utils@2.1.8': + dependencies: + '@vitest/pretty-format': 2.1.8 + loupe: 3.1.2 + tinyrainbow: 1.2.0 + '@volar/kit@2.4.6(typescript@5.7.2)': dependencies: '@volar/language-service': 2.4.6 @@ -17178,6 +17309,24 @@ snapshots: - tsx - yaml + vite-node@2.1.8(@types/node@18.19.50)(sass@1.81.0): + dependencies: + cac: 6.7.14 + debug: 4.3.7 + es-module-lexer: 1.5.4 + pathe: 1.1.2 + vite: 5.4.11(@types/node@18.19.50)(sass@1.81.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vite-plugin-inspect@0.8.7(rollup@4.27.4)(vite@6.0.1(@types/node@18.19.50)(jiti@1.21.6)(sass@1.81.0)(yaml@2.5.1)): dependencies: '@antfu/utils': 0.7.10 @@ -17243,6 +17392,16 @@ snapshots: svgo: 3.3.2 vue: 3.5.13(typescript@5.7.2) + vite@5.4.11(@types/node@18.19.50)(sass@1.81.0): + dependencies: + esbuild: 0.21.5 + postcss: 8.4.49 + rollup: 4.27.4 + optionalDependencies: + '@types/node': 18.19.50 + fsevents: 2.3.3 + sass: 1.81.0 + vite@6.0.1(@types/node@18.19.50)(jiti@1.21.6)(sass@1.81.0)(yaml@2.5.1): dependencies: esbuild: 0.24.0 @@ -17298,6 +17457,42 @@ snapshots: - tsx - yaml + vitest@2.1.8(@types/node@18.19.50)(jsdom@23.2.0)(sass@1.81.0): + dependencies: + '@vitest/expect': 2.1.8 + '@vitest/mocker': 2.1.8(vite@5.4.11(@types/node@18.19.50)(sass@1.81.0)) + '@vitest/pretty-format': 2.1.8 + '@vitest/runner': 2.1.8 + '@vitest/snapshot': 2.1.8 + '@vitest/spy': 2.1.8 + '@vitest/utils': 2.1.8 + chai: 5.1.2 + debug: 4.3.7 + expect-type: 1.1.0 + magic-string: 0.30.14 + pathe: 1.1.2 + std-env: 3.8.0 + tinybench: 2.9.0 + tinyexec: 0.3.1 + tinypool: 1.0.1 + tinyrainbow: 1.2.0 + vite: 5.4.11(@types/node@18.19.50)(sass@1.81.0) + vite-node: 2.1.8(@types/node@18.19.50)(sass@1.81.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 18.19.50 + jsdom: 23.2.0 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + volar-service-css@0.0.61(@volar/language-service@2.4.6): dependencies: vscode-css-languageservice: 6.3.1