0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

refactor: use vitest for benchmarks (#12605)

* refactor: use `vitest` for benchmarks

* increase timeout

* increase timeout

* Restore correct label
This commit is contained in:
Emanuele Stoppa 2024-12-03 17:03:24 +00:00 committed by GitHub
parent 30722870da
commit 9b5f3a702d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 324 additions and 147 deletions

View file

@ -50,6 +50,7 @@ jobs:
uses: CodSpeedHQ/action@513a19673a831f139e8717bf45ead67e47f00044 # v3.2.0 uses: CodSpeedHQ/action@513a19673a831f139e8717bf45ead67e47f00044 # v3.2.0
timeout-minutes: 30 timeout-minutes: 30
with: with:
run: pnpm benchmark codspeed working-directory: ./benchmark
run: pnpm bench
token: ${{ secrets.CODSPEED_TOKEN }} token: ${{ secrets.CODSPEED_TOKEN }}

View file

@ -19,3 +19,14 @@ export function calculateStat(numbers) {
const max = Math.max(...numbers); const max = Math.max(...numbers);
return { avg, stdev, max }; 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;
}

View file

@ -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);
});
});

View file

@ -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());
}

View file

@ -1,7 +1,8 @@
import mri from 'mri'; import mri from 'mri';
import fs from 'node:fs/promises'; import fs from 'node:fs/promises';
import path from 'node:path'; 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)); const args = mri(process.argv.slice(2));
@ -14,7 +15,6 @@ Command
memory Run build memory and speed test memory Run build memory and speed test
render Run rendering speed test render Run rendering speed test
server-stress Run server stress test server-stress Run server stress test
codspeed Run codspeed test
cli-startup Run CLI startup speed test cli-startup Run CLI startup speed test
Options Options
@ -30,7 +30,6 @@ const benchmarks = {
render: () => import('./bench/render.js'), render: () => import('./bench/render.js'),
'server-stress': () => import('./bench/server-stress.js'), 'server-stress': () => import('./bench/server-stress.js'),
'cli-startup': () => import('./bench/cli-startup.js'), 'cli-startup': () => import('./bench/cli-startup.js'),
codspeed: () => import('./bench/codspeed.js')
}; };
if (commandName && !(commandName in benchmarks)) { if (commandName && !(commandName in benchmarks)) {
@ -39,26 +38,12 @@ if (commandName && !(commandName in benchmarks)) {
} }
if (commandName) { 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 // Run single benchmark
const bench = benchmarks[commandName]; const bench = benchmarks[commandName];
const benchMod = await bench(); const benchMod = await bench();
const projectDir = await makeProject(args.project || benchMod.defaultProject); const projectDir = await makeProject(args.project || benchMod.defaultProject);
const outputFile = await getOutputFile(commandName); const outputFile = await getOutputFile(commandName);
await benchMod.run(projectDir, outputFile); await benchMod.run(projectDir, outputFile);
}
} else { } else {
// Run all benchmarks // Run all benchmarks
for (const name in 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 * @param {string} benchmarkName
*/ */
async function getOutputFile(benchmarkName) { export async function getOutputFile(benchmarkName) {
let file; let file;
if (args.output) { if (args.output) {
file = pathToFileURL(path.resolve(args.output)); file = pathToFileURL(path.resolve(args.output));

View file

@ -8,11 +8,13 @@ export async function run(projectDir) {
await fs.rm(projectDir, { recursive: true, force: true }); 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/pages/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./src/content/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 = []; const promises = [];
for (let i = 0; i < 10000; i++) { for (let i = 0; i < 10000; i++) {
const content = `\ const content = `\
# Article ${i} # Article ${i}
@ -24,11 +26,10 @@ ${loremIpsumMd}
`; `;
promises.push( 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( await fs.writeFile(
new URL(`./src/pages/blog/[...slug].astro`, projectDir), new URL(`./src/pages/blog/[...slug].astro`, projectDir),
`\ `\
@ -46,7 +47,7 @@ const { Content } = await entry.render();
<h1>{entry.data.title}</h1> <h1>{entry.data.title}</h1>
<Content /> <Content />
`, `,
'utf-8' 'utf-8',
); );
await Promise.all(promises); await Promise.all(promises);
@ -58,6 +59,6 @@ import { defineConfig } from 'astro/config';
export default defineConfig({ export default defineConfig({
});`, });`,
'utf-8' 'utf-8',
); );
} }

View file

@ -23,7 +23,7 @@ ${loremIpsumMd}
`; `;
promises.push( 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 } export const collections = { blog }
` `,
); );
await fs.writeFile( await fs.writeFile(
@ -60,7 +60,7 @@ const { Content } = await render(entry);
<h1>{entry.data.title}</h1> <h1>{entry.data.title}</h1>
<Content /> <Content />
`, `,
'utf-8' 'utf-8',
); );
await Promise.all(promises); await Promise.all(promises);
@ -71,6 +71,6 @@ const { Content } = await render(entry);
import { defineConfig } from 'astro/config'; import { defineConfig } from 'astro/config';
export default defineConfig({});`, export default defineConfig({});`,
'utf-8' 'utf-8',
); );
} }

View file

@ -8,11 +8,13 @@ export async function run(projectDir) {
await fs.rm(projectDir, { recursive: true, force: true }); 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/pages/blog', projectDir), { recursive: true });
await fs.mkdir(new URL('./src/content/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 = []; const promises = [];
for (let i = 0; i < 10000; i++) { for (let i = 0; i < 10000; i++) {
const content = `\ const content = `\
# Article ${i} # Article ${i}
@ -24,11 +26,10 @@ ${loremIpsumMd}
`; `;
promises.push( 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( await fs.writeFile(
new URL(`./src/pages/blog/[...slug].astro`, projectDir), new URL(`./src/pages/blog/[...slug].astro`, projectDir),
`\ `\
@ -46,7 +47,7 @@ const { Content } = await entry.render();
<h1>{entry.data.title}</h1> <h1>{entry.data.title}</h1>
<Content /> <Content />
`, `,
'utf-8' 'utf-8',
); );
await Promise.all(promises); await Promise.all(promises);
@ -61,6 +62,6 @@ import mdx from '@astrojs/mdx';
export default defineConfig({ export default defineConfig({
integrations: [mdx()], integrations: [mdx()],
});`, });`,
'utf-8' 'utf-8',
); );
} }

View file

@ -23,7 +23,7 @@ ${loremIpsumMd}
`; `;
promises.push( 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 } export const collections = { blog }
` `,
); );
await fs.writeFile( await fs.writeFile(
@ -60,7 +60,7 @@ const { Content } = await render(entry);
<h1>{entry.data.title}</h1> <h1>{entry.data.title}</h1>
<Content /> <Content />
`, `,
'utf-8' 'utf-8',
); );
await Promise.all(promises); await Promise.all(promises);
@ -75,6 +75,6 @@ import mdx from '@astrojs/mdx';
export default defineConfig({ export default defineConfig({
integrations: [mdx()], integrations: [mdx()],
});`, });`,
'utf-8' 'utf-8',
); );
} }

View file

@ -20,7 +20,7 @@ const i = ${i};
<span>{i}</span> <span>{i}</span>
`; `;
promises.push( 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} ${loremIpsum}
`; `;
promises.push( 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} ${loremIpsum}
`; `;
promises.push( 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();
<h1>{entry.data.title}</h1> <h1>{entry.data.title}</h1>
<Content /> <Content />
`, `,
'utf-8' 'utf-8',
); );
await Promise.all(promises); await Promise.all(promises);
@ -77,6 +77,6 @@ import mdx from '@astrojs/mdx';
export default defineConfig({ export default defineConfig({
integrations: [mdx()], integrations: [mdx()],
});`, });`,
'utf-8' 'utf-8',
); );
} }

View file

@ -112,7 +112,7 @@ export async function run(projectDir) {
await Promise.all( await Promise.all(
Object.entries(renderFiles).map(([name, content]) => { Object.entries(renderFiles).map(([name, content]) => {
return fs.writeFile(new URL(`./src/${name}`, projectDir), content, 'utf-8'); return fs.writeFile(new URL(`./src/${name}`, projectDir), content, 'utf-8');
}) }),
); );
await fs.writeFile( await fs.writeFile(
@ -127,6 +127,6 @@ export default defineConfig({
output: 'server', output: 'server',
adapter: adapter(), adapter: adapter(),
});`, });`,
'utf-8' 'utf-8',
); );
} }

View file

@ -112,7 +112,7 @@ export async function run(projectDir) {
await Promise.all( await Promise.all(
Object.entries(renderFiles).map(([name, content]) => { Object.entries(renderFiles).map(([name, content]) => {
return fs.writeFile(new URL(`./src/${name}`, projectDir), content, 'utf-8'); return fs.writeFile(new URL(`./src/${name}`, projectDir), content, 'utf-8');
}) }),
); );
await fs.writeFile( await fs.writeFile(
@ -127,6 +127,6 @@ export default defineConfig({
output: 'server', output: 'server',
adapter: timer(), adapter: timer(),
});`, });`,
'utf-8' 'utf-8',
); );
} }

View file

@ -38,13 +38,13 @@ const content = "${loremIpsum}"
</div> </div>
</body> </body>
</html>`, </html>`,
'utf-8' 'utf-8',
); );
await fs.writeFile( await fs.writeFile(
new URL('./src/components/Paragraph.astro', projectDir), new URL('./src/components/Paragraph.astro', projectDir),
`<div>{Astro.props.num} {Astro.props.str}</div>`, `<div>{Astro.props.num} {Astro.props.str}</div>`,
'utf-8' 'utf-8',
); );
await fs.writeFile( await fs.writeFile(
@ -57,6 +57,6 @@ export default defineConfig({
output: 'server', output: 'server',
adapter: nodejs({ mode: 'standalone' }), adapter: nodejs({ mode: 'standalone' }),
});`, });`,
'utf-8' 'utf-8',
); );
} }

View file

@ -6,6 +6,9 @@
"bin": { "bin": {
"astro-benchmark": "./index.js" "astro-benchmark": "./index.js"
}, },
"scripts": {
"bench": "pnpm vitest bench --run"
},
"dependencies": { "dependencies": {
"@astrojs/mdx": "workspace:*", "@astrojs/mdx": "workspace:*",
"@astrojs/node": "^8.3.4", "@astrojs/node": "^8.3.4",
@ -21,7 +24,7 @@
"tinyexec": "^0.3.1" "tinyexec": "^0.3.1"
}, },
"devDependencies": { "devDependencies": {
"@codspeed/tinybench-plugin": "^3.1.1", "@codspeed/vitest-plugin": "3.1.1",
"tinybench": "^2.9.0" "vitest": "2.1.8"
} }
} }

View file

@ -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'],
});

View file

@ -2,7 +2,7 @@
"$schema": "https://biomejs.dev/schemas/1.9.3/schema.json", "$schema": "https://biomejs.dev/schemas/1.9.3/schema.json",
"files": { "files": {
"ignore": ["**/smoke/**", "**/fixtures/**", "**/_temp-fixtures/**", "**/vendor/**"], "ignore": ["**/smoke/**", "**/fixtures/**", "**/_temp-fixtures/**", "**/vendor/**"],
"include": ["test/**", "e2e/**", "packages/**", "scripts/**", "benchmark/bench"], "include": ["test/**", "e2e/**", "packages/**", "scripts/**", "benchmark"],
}, },
"vcs": { "vcs": {
"enabled": true, "enabled": true,

View file

@ -100,12 +100,12 @@ importers:
specifier: ^0.3.1 specifier: ^0.3.1
version: 0.3.1 version: 0.3.1
devDependencies: devDependencies:
'@codspeed/tinybench-plugin': '@codspeed/vitest-plugin':
specifier: ^3.1.1 specifier: 3.1.1
version: 3.1.1(tinybench@2.9.0) 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))
tinybench: vitest:
specifier: ^2.9.0 specifier: 2.1.8
version: 2.9.0 version: 2.1.8(@types/node@18.19.50)(jsdom@23.2.0)(sass@1.81.0)
benchmark/packages/adapter: benchmark/packages/adapter:
dependencies: dependencies:
@ -5935,10 +5935,11 @@ packages:
'@codspeed/core@3.1.1': '@codspeed/core@3.1.1':
resolution: {integrity: sha512-ONhERVDAtkm0nc+FYPivDozoMOlNUP2BWRBFDJYATGA18Iap5Kd2mZ1/Lwz54RB5+g+3YDOpsvotHa4hd3Q+7Q==} resolution: {integrity: sha512-ONhERVDAtkm0nc+FYPivDozoMOlNUP2BWRBFDJYATGA18Iap5Kd2mZ1/Lwz54RB5+g+3YDOpsvotHa4hd3Q+7Q==}
'@codspeed/tinybench-plugin@3.1.1': '@codspeed/vitest-plugin@3.1.1':
resolution: {integrity: sha512-LVF4End0kDU9V7CzuwAcmngSPJNnpduPnr+csOKvcG++FsYwfUuBJ1rvLPtv6yTkvxpUmUEsj6VA7/AEIBGZVw==} resolution: {integrity: sha512-/PJUgxIfuRqpBSbaD8bgWXtbXxCqgnW89dzr3220fMkx/LA6z6oUb4tJGjeVsOWAzAgu0VBdSA+8hC+7D9BIuQ==}
peerDependencies: peerDependencies:
tinybench: ^2.3.0 vite: ^4.2.0 || ^5.0.0
vitest: '>=1.2.2'
'@colors/colors@1.5.0': '@colors/colors@1.5.0':
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
@ -7328,6 +7329,9 @@ packages:
'@vitest/expect@2.1.6': '@vitest/expect@2.1.6':
resolution: {integrity: sha512-9M1UR9CAmrhJOMoSwVnPh2rELPKhYo0m/CSgqw9PyStpxtkwhmdM6XYlXGKeYyERY1N6EIuzkQ7e3Lm1WKCoUg==} resolution: {integrity: sha512-9M1UR9CAmrhJOMoSwVnPh2rELPKhYo0m/CSgqw9PyStpxtkwhmdM6XYlXGKeYyERY1N6EIuzkQ7e3Lm1WKCoUg==}
'@vitest/expect@2.1.8':
resolution: {integrity: sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==}
'@vitest/mocker@2.1.6': '@vitest/mocker@2.1.6':
resolution: {integrity: sha512-MHZp2Z+Q/A3am5oD4WSH04f9B0T7UvwEb+v5W0kCYMhtXGYbdyl2NUk1wdSMqGthmhpiThPDp/hEoVwu16+u1A==} resolution: {integrity: sha512-MHZp2Z+Q/A3am5oD4WSH04f9B0T7UvwEb+v5W0kCYMhtXGYbdyl2NUk1wdSMqGthmhpiThPDp/hEoVwu16+u1A==}
peerDependencies: peerDependencies:
@ -7339,21 +7343,47 @@ packages:
vite: vite:
optional: true 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': '@vitest/pretty-format@2.1.6':
resolution: {integrity: sha512-exZyLcEnHgDMKc54TtHca4McV4sKT+NKAe9ix/yhd/qkYb/TP8HTyXRFDijV19qKqTZM0hPL4753zU/U8L/gAA==} 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': '@vitest/runner@2.1.6':
resolution: {integrity: sha512-SjkRGSFyrA82m5nz7To4CkRSEVWn/rwQISHoia/DB8c6IHIhaE/UNAo+7UfeaeJRE979XceGl00LNkIz09RFsA==} 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': '@vitest/snapshot@2.1.6':
resolution: {integrity: sha512-5JTWHw8iS9l3v4/VSuthCndw1lN/hpPB+mlgn1BUhFbobeIUj1J1V/Bj2t2ovGEmkXLTckFjQddsxS5T6LuVWw==} 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': '@vitest/spy@2.1.6':
resolution: {integrity: sha512-oTFObV8bd4SDdRka5O+mSh5w9irgx5IetrD5i+OsUUsk/shsBoHifwCzy45SAORzAhtNiprUVaK3hSCCzZh1jQ==} resolution: {integrity: sha512-oTFObV8bd4SDdRka5O+mSh5w9irgx5IetrD5i+OsUUsk/shsBoHifwCzy45SAORzAhtNiprUVaK3hSCCzZh1jQ==}
'@vitest/spy@2.1.8':
resolution: {integrity: sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==}
'@vitest/utils@2.1.6': '@vitest/utils@2.1.6':
resolution: {integrity: sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==} resolution: {integrity: sha512-ixNkFy3k4vokOUTU2blIUvOgKq/N2PW8vKIjZZYsGJCMX69MRa9J2sKqX5hY/k5O5Gty3YJChepkqZ3KM9LyIQ==}
'@vitest/utils@2.1.8':
resolution: {integrity: sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==}
'@volar/kit@2.4.6': '@volar/kit@2.4.6':
resolution: {integrity: sha512-OaMtpmLns6IYD1nOSd0NdG/F5KzJ7Jr4B7TLeb4byPzu+ExuuRVeO56Dn1C7Frnw6bGudUQd90cpQAmxdB+RlQ==} resolution: {integrity: sha512-OaMtpmLns6IYD1nOSd0NdG/F5KzJ7Jr4B7TLeb4byPzu+ExuuRVeO56Dn1C7Frnw6bGudUQd90cpQAmxdB+RlQ==}
peerDependencies: peerDependencies:
@ -10777,6 +10807,11 @@ packages:
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true 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: vite-plugin-inspect@0.8.7:
resolution: {integrity: sha512-/XXou3MVc13A5O9/2Nd6xczjrUwt7ZyI9h8pTnUMkr5SshLcb0PJUOVq2V+XVkdeU4njsqAtmK87THZuO2coGA==} resolution: {integrity: sha512-/XXou3MVc13A5O9/2Nd6xczjrUwt7ZyI9h8pTnUMkr5SshLcb0PJUOVq2V+XVkdeU4njsqAtmK87THZuO2coGA==}
engines: {node: '>=14'} engines: {node: '>=14'}
@ -10813,6 +10848,37 @@ packages:
peerDependencies: peerDependencies:
vue: '>=3.2.13' 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: vite@6.0.1:
resolution: {integrity: sha512-Ldn6gorLGr4mCdFnmeAOLweJxZ34HjKnDm4HGo6P66IEqTxQb36VEdFJQENKxWjupNfoIjvRUnswjn1hpYEpjQ==} resolution: {integrity: sha512-Ldn6gorLGr4mCdFnmeAOLweJxZ34HjKnDm4HGo6P66IEqTxQb36VEdFJQENKxWjupNfoIjvRUnswjn1hpYEpjQ==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
@ -10886,6 +10952,31 @@ packages:
jsdom: jsdom:
optional: true 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: volar-service-css@0.0.61:
resolution: {integrity: sha512-Ct9L/w+IB1JU8F4jofcNCGoHy6TF83aiapfZq9A0qYYpq+Kk5dH+ONS+rVZSsuhsunq8UvAuF8Gk6B8IFLfniw==} resolution: {integrity: sha512-Ct9L/w+IB1JU8F4jofcNCGoHy6TF83aiapfZq9A0qYYpq+Kk5dH+ONS+rVZSsuhsunq8UvAuF8Gk6B8IFLfniw==}
peerDependencies: peerDependencies:
@ -11764,11 +11855,11 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- debug - 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: dependencies:
'@codspeed/core': 3.1.1 '@codspeed/core': 3.1.1
stack-trace: 1.0.0-pre2 vite: 6.0.1(@types/node@18.19.50)(jiti@1.21.6)(sass@1.81.0)(yaml@2.5.1)
tinybench: 2.9.0 vitest: 2.1.8(@types/node@18.19.50)(jsdom@23.2.0)(sass@1.81.0)
transitivePeerDependencies: transitivePeerDependencies:
- debug - debug
@ -13029,6 +13120,13 @@ snapshots:
chai: 5.1.2 chai: 5.1.2
tinyrainbow: 1.2.0 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))': '@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: dependencies:
'@vitest/spy': 2.1.6 '@vitest/spy': 2.1.6
@ -13037,31 +13135,64 @@ snapshots:
optionalDependencies: optionalDependencies:
vite: 6.0.1(@types/node@18.19.50)(jiti@1.21.6)(sass@1.81.0)(yaml@2.5.1) 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': '@vitest/pretty-format@2.1.6':
dependencies: dependencies:
tinyrainbow: 1.2.0 tinyrainbow: 1.2.0
'@vitest/pretty-format@2.1.8':
dependencies:
tinyrainbow: 1.2.0
'@vitest/runner@2.1.6': '@vitest/runner@2.1.6':
dependencies: dependencies:
'@vitest/utils': 2.1.6 '@vitest/utils': 2.1.6
pathe: 1.1.2 pathe: 1.1.2
'@vitest/runner@2.1.8':
dependencies:
'@vitest/utils': 2.1.8
pathe: 1.1.2
'@vitest/snapshot@2.1.6': '@vitest/snapshot@2.1.6':
dependencies: dependencies:
'@vitest/pretty-format': 2.1.6 '@vitest/pretty-format': 2.1.6
magic-string: 0.30.14 magic-string: 0.30.14
pathe: 1.1.2 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': '@vitest/spy@2.1.6':
dependencies: dependencies:
tinyspy: 3.0.2 tinyspy: 3.0.2
'@vitest/spy@2.1.8':
dependencies:
tinyspy: 3.0.2
'@vitest/utils@2.1.6': '@vitest/utils@2.1.6':
dependencies: dependencies:
'@vitest/pretty-format': 2.1.6 '@vitest/pretty-format': 2.1.6
loupe: 3.1.2 loupe: 3.1.2
tinyrainbow: 1.2.0 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)': '@volar/kit@2.4.6(typescript@5.7.2)':
dependencies: dependencies:
'@volar/language-service': 2.4.6 '@volar/language-service': 2.4.6
@ -17178,6 +17309,24 @@ snapshots:
- tsx - tsx
- yaml - 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)): 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: dependencies:
'@antfu/utils': 0.7.10 '@antfu/utils': 0.7.10
@ -17243,6 +17392,16 @@ snapshots:
svgo: 3.3.2 svgo: 3.3.2
vue: 3.5.13(typescript@5.7.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): vite@6.0.1(@types/node@18.19.50)(jiti@1.21.6)(sass@1.81.0)(yaml@2.5.1):
dependencies: dependencies:
esbuild: 0.24.0 esbuild: 0.24.0
@ -17298,6 +17457,42 @@ snapshots:
- tsx - tsx
- yaml - 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): volar-service-css@0.0.61(@volar/language-service@2.4.6):
dependencies: dependencies:
vscode-css-languageservice: 6.3.1 vscode-css-languageservice: 6.3.1