feat(infra): route package (#10353)

This commit is contained in:
forehalo
2025-04-23 09:49:10 +00:00
parent e501e35d3d
commit 64997d4a0e
14 changed files with 654 additions and 18 deletions
+36
View File
@@ -0,0 +1,36 @@
# Routes
## Usage
### Path Factories
```ts
import { FACTORIES } from '@affine/routes';
const path = FACTORIES.workspace.doc({ workspaceId: '123', docId: '456' });
// ^^^^ with typecheck
```
### Register router
```tsx
import { ROUTES } from '@affine/routes';
function Routes() {
return <Router path={ROUTES.admin.index} element={} />;
}
```
### Path Parameter
```ts
import { RouteParamsTypes } from '@affine/routes';
function Doc() {
const { workspaceId, docId } = useParams<RouteParamsTypes['workspace']['doc']>();
}
function Attachment() {
const { workspaceId, docId, attachmentId } = useParams<RouteParamsTypes['workspace']['doc']['attachment']>();
}
```
+260
View File
@@ -0,0 +1,260 @@
import fs from 'node:fs';
import { join } from 'node:path/posix';
import { Path, prettier } from '@affine-tools/utils';
import { parse } from 'path-to-regexp';
const curdir = Path.dir(import.meta.url);
const inputFile = curdir.join('routes.json').value;
const routerOutputFile = curdir.join('src', 'routes.ts').value;
interface RawRoutesSchema {
route: string;
children: {
[key: string]: string | RawRoutesSchema;
};
}
interface RouteSchema {
name: string;
fromParent: string;
fromRoot: string;
children: Array<RouteSchema>;
}
function loadRoutesSchema(): RouteSchema {
const rawSchema = JSON.parse(
fs.readFileSync(inputFile, 'utf-8')
) as RawRoutesSchema;
const build = (
name: string,
schema: RawRoutesSchema | string,
fromRoot: string = ''
): RouteSchema => {
if (typeof schema === 'string') {
return {
name,
fromParent: schema,
fromRoot: join(fromRoot, schema),
children: [],
};
}
const absolute = join(fromRoot, schema.route);
return {
name,
fromParent: schema.route,
fromRoot: absolute,
children: Object.entries(schema.children).map(([key, value]) => {
return build(key, value, absolute);
}),
};
};
return build('home', rawSchema);
}
interface BuiltRouteSchema {
name: string;
type?: string;
factory: string;
fromRoot: string;
fromParent: string;
children: BuiltRouteSchema[];
parent: BuiltRouteSchema | null;
}
function buildRoutes(
schema: RouteSchema,
parent: BuiltRouteSchema | null = null
): BuiltRouteSchema {
const { tokens } = parse(schema.fromRoot);
const types: string[] = [];
const factories: string[] = [];
for (const token of tokens) {
switch (token.type) {
case 'param':
case 'wildcard':
types.push(token.name);
factories.push(`\${params.${token.name}}`);
break;
case 'text': {
factories.push(token.value);
break;
}
}
}
// [a, b, c] -> '{ a: string; b: string; c: string }'
const type = types.length
? `{ ${types.map(type => `${type}: string`).join('; ')} }`
: undefined;
const builtResult: BuiltRouteSchema = {
name: schema.name,
type,
factory: factories.join(''),
fromRoot: schema.fromRoot,
fromParent: schema.fromParent,
parent: parent,
children: [],
};
builtResult.children = schema.children.map(child =>
buildRoutes(child, builtResult)
);
return builtResult;
}
function printSchemaTypes(schema: BuiltRouteSchema, level: number = 1): string {
const types: string[] = [];
if (schema.type) {
if (schema.children.length) {
types.push(`index: ${schema.type};`);
} else {
return schema.type;
}
}
for (const child of schema.children) {
const childType = printSchemaTypes(child, level + 1);
if (childType) {
types.push(`${child.name}: ${childType};`);
}
}
if (types.length > 0) {
const output = `{ ${types.join('\n')} }`;
return level === 1 ? `export interface RouteParamsTypes ${output}` : output;
}
return '';
}
function printAbsolutePaths(schema: BuiltRouteSchema, level = 1): string {
const absolutes: string[] = [];
if (schema.children.length) {
absolutes.push(`index: '${schema.fromRoot}'`);
} else {
return `'${schema.fromRoot}'`;
}
for (const child of schema.children) {
const childRoute = printAbsolutePaths(child, level + 1);
absolutes.push(`${child.name}: ${childRoute}`);
}
const output = `{ ${absolutes.join('\n,')} }`;
return level === 1 ? `export const ROUTES = ${output}` : output;
}
function printRelativePaths(schema: BuiltRouteSchema, level = 1): string {
const relatives: string[] = [];
if (schema.children.length) {
relatives.push(`index: '${schema.fromParent}'`);
} else {
return `'${schema.fromParent}'`;
}
for (const child of schema.children) {
const childRoute = printRelativePaths(child, level + 1);
relatives.push(`${child.name}: ${childRoute}`);
}
const output = `{ ${relatives.join('\n,')} }`;
return level === 1 ? `export const RELATIVE_ROUTES = ${output}` : output;
}
function printFactories(schema: BuiltRouteSchema): string {
const factories: string[] = [];
const factory = schema.type
? `(params: ${schema.type}) => \`${schema.factory}\``
: `() => '${schema.factory}'`;
let parent: BuiltRouteSchema | null = schema.parent;
let nameFromRoot: string[] = [schema.name];
while (parent) {
// ignore home
if (parent.parent) {
nameFromRoot = [parent.name, ...nameFromRoot];
}
parent = parent.parent;
}
if (schema.children.length) {
// with children, we do
const visitor = nameFromRoot.join('_');
// 1. const workspace_doc = () => 'workspace/doc'
factories.push(`const ${visitor} = ${factory}`);
for (const child of schema.children) {
// 2. generate children for workspace_doc
factories.push(printFactories(child));
}
// 3. workspace.doc = workspace_doc
const parentNameFromRoot = nameFromRoot.slice(0, -1).join('_');
if (parentNameFromRoot) {
factories.push(`${parentNameFromRoot}.${schema.name} = ${visitor}`);
}
} else {
// without children, we directly
const parentNameFromRoot = nameFromRoot.slice(0, -1).join('_');
if (parentNameFromRoot) {
// parent.child = () => 'child'
factories.push(`${parentNameFromRoot}.${schema.name} = ${factory}`);
} else {
// const route = () => 'route'
factories.push(`const ${schema.name} = ${factory}`);
}
}
const output = factories.join('\n');
if (!schema.parent) {
const firstLevelNames = schema.children.map(child => child.name);
firstLevelNames.push(schema.name);
return `${output}\nexport const FACTORIES = { ${firstLevelNames.join(
', '
)} };`;
}
return output;
}
async function printRoutes(schema: BuiltRouteSchema) {
const parts = {
['Path Parameter Types']: printSchemaTypes,
['Absolute Paths']: printAbsolutePaths,
['Relative Paths']: printRelativePaths,
['Path Factories']: printFactories,
};
const content = await prettier(
Object.entries(parts)
.map(([key, print]) => {
return `// #region ${key}\n${print(schema)}\n// #endregion`;
})
.join('\n\n'),
'typescript'
);
fs.writeFileSync(routerOutputFile, content, 'utf-8');
}
async function build() {
const schema = loadRoutesSchema();
const builtSchema = buildRoutes(schema);
await printRoutes(builtSchema);
}
await build();
+22
View File
@@ -0,0 +1,22 @@
{
"name": "@affine/routes",
"version": "0.0.1",
"private": true,
"type": "module",
"exports": {
".": "./src/routes.ts"
},
"scripts": {
"build": "r build.ts"
},
"devDependencies": {
"@affine-tools/cli": "workspace:*",
"@affine-tools/utils": "workspace:*",
"path-to-regexp": "^8.2.0",
"query-string": "^9.1.1",
"vitest": "^3.0.6"
},
"optionalDependencies": {
"react-router-dom": "^6.28.0"
}
}
+21
View File
@@ -0,0 +1,21 @@
{
"$schema": "./schema.json",
"route": "/",
"children": {
"admin": {
"route": "admin",
"children": {
"accounts": "accounts",
"ai": "ai",
"settings": {
"route": "settings",
"children": {
"module": ":module"
}
},
"about": "about",
"notFound": "404"
}
}
}
}
+32
View File
@@ -0,0 +1,32 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"description": "AFFiNE Routes Schema",
"definitions": {
"route": {
"type": "string",
"description": "route path"
},
"children": {
"type": "object",
"additionalProperties": {
"anyOf": [
{
"type": "string"
},
{
"type": "object",
"required": ["route", "children"],
"properties": {
"route": { "$ref": "#/definitions/route" },
"children": { "$ref": "#/definitions/children" }
}
}
]
}
}
},
"properties": {
"route": { "$ref": "#/definitions/route" },
"children": { "$ref": "#/definitions/children" }
}
}
@@ -0,0 +1,13 @@
import { describe, expect, it } from 'vitest';
import { FACTORIES } from '../routes';
describe('PATH_FACTORIES', () => {
it('should generate correct paths', () => {
expect(
FACTORIES.admin.settings.module({
module: 'auth',
})
).toBe('/admin/settings/auth');
});
});
+44
View File
@@ -0,0 +1,44 @@
// #region Path Parameter Types
export interface RouteParamsTypes {
admin: { settings: { module: { module: string } } };
}
// #endregion
// #region Absolute Paths
export const ROUTES = {
index: '/',
admin: {
index: '/admin',
accounts: '/admin/accounts',
ai: '/admin/ai',
settings: { index: '/admin/settings', module: '/admin/settings/:module' },
about: '/admin/about',
},
};
// #endregion
// #region Relative Paths
export const RELATIVE_ROUTES = {
index: '/',
admin: {
index: 'admin',
accounts: 'accounts',
ai: 'ai',
settings: { index: 'settings', module: ':module' },
about: 'about',
},
};
// #endregion
// #region Path Factories
const home = () => '/';
const admin = () => '/admin';
admin.accounts = () => '/admin/accounts';
admin.ai = () => '/admin/ai';
const admin_settings = () => '/admin/settings';
admin_settings.module = (params: { module: string }) =>
`/admin/settings/${params.module}`;
admin.settings = admin_settings;
admin.about = () => '/admin/about';
export const FACTORIES = { admin, home };
// #endregion
+13
View File
@@ -0,0 +1,13 @@
{
"extends": "../../../tsconfig.web.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./dist",
"tsBuildInfoFile": "./dist/tsconfig.tsbuildinfo"
},
"include": ["./src"],
"references": [
{ "path": "../../../tools/cli" },
{ "path": "../../../tools/utils" }
]
}
+2
View File
@@ -4,6 +4,7 @@
"type": "module",
"private": true,
"exports": {
".": "./src/index.ts",
"./path": "./src/path.ts",
"./workspace": "./src/workspace.ts",
"./process": "./src/process.ts",
@@ -16,6 +17,7 @@
"@types/node": "^22.0.0",
"chalk": "^5.3.0",
"lodash-es": "^4.17.21",
"prettier": "^3.3.3",
"typescript": "^5.5.4"
}
}
+17
View File
@@ -0,0 +1,17 @@
import { readFileSync } from 'node:fs';
import { once } from 'lodash-es';
import { type BuiltInParserName, format } from 'prettier';
import { ProjectRoot } from './path';
const readConfig = once(() => {
const path = ProjectRoot.join('.prettierrc').value;
const config = JSON.parse(readFileSync(path, 'utf-8'));
return config;
});
export function prettier(content: string, parser: BuiltInParserName) {
const config = readConfig();
return format(content, { parser, ...config });
}
+2
View File
@@ -0,0 +1,2 @@
export * from './format';
export * from './path';
+6
View File
@@ -1165,6 +1165,11 @@ export const PackageList = [
name: '@affine/native',
workspaceDependencies: [],
},
{
location: 'packages/frontend/routes',
name: '@affine/routes',
workspaceDependencies: ['tools/cli', 'tools/utils'],
},
{
location: 'packages/frontend/templates',
name: '@affine/templates',
@@ -1349,6 +1354,7 @@ export type PackageName =
| '@affine/i18n'
| '@affine/media-capture-playground'
| '@affine/native'
| '@affine/routes'
| '@affine/templates'
| '@affine/track'
| '@affine-test/affine-cloud'
+1
View File
@@ -133,6 +133,7 @@
{ "path": "./packages/frontend/i18n" },
{ "path": "./packages/frontend/media-capture-playground" },
{ "path": "./packages/frontend/native" },
{ "path": "./packages/frontend/routes" },
{ "path": "./packages/frontend/track" },
{ "path": "./tests/affine-cloud" },
{ "path": "./tests/affine-cloud-copilot" },
+185 -18
View File
@@ -167,6 +167,7 @@ __metadata:
"@types/node": "npm:^22.0.0"
chalk: "npm:^5.3.0"
lodash-es: "npm:^4.17.21"
prettier: "npm:^3.3.3"
typescript: "npm:^5.5.4"
languageName: unknown
linkType: soft
@@ -851,6 +852,22 @@ __metadata:
languageName: unknown
linkType: soft
"@affine/routes@workspace:packages/frontend/routes":
version: 0.0.0-use.local
resolution: "@affine/routes@workspace:packages/frontend/routes"
dependencies:
"@affine-tools/cli": "workspace:*"
"@affine-tools/utils": "workspace:*"
path-to-regexp: "npm:^8.2.0"
query-string: "npm:^9.1.1"
react-router-dom: "npm:^6.28.0"
vitest: "npm:^3.0.6"
dependenciesMeta:
react-router-dom:
optional: true
languageName: unknown
linkType: soft
"@affine/server-native@workspace:*, @affine/server-native@workspace:packages/backend/native":
version: 0.0.0-use.local
resolution: "@affine/server-native@workspace:packages/backend/native"
@@ -15958,6 +15975,18 @@ __metadata:
languageName: node
linkType: hard
"@vitest/expect@npm:3.1.2":
version: 3.1.2
resolution: "@vitest/expect@npm:3.1.2"
dependencies:
"@vitest/spy": "npm:3.1.2"
"@vitest/utils": "npm:3.1.2"
chai: "npm:^5.2.0"
tinyrainbow: "npm:^2.0.0"
checksum: 10/3c414e376154c8095f40efe409bb5f2c9380ba05a15b20552ee2e29f73197ab73068177e3da298ac135ef72673d1ea92090c466c78443ee69a7438bc8ab65f4f
languageName: node
linkType: hard
"@vitest/mocker@npm:3.1.1":
version: 3.1.1
resolution: "@vitest/mocker@npm:3.1.1"
@@ -15977,6 +16006,25 @@ __metadata:
languageName: node
linkType: hard
"@vitest/mocker@npm:3.1.2":
version: 3.1.2
resolution: "@vitest/mocker@npm:3.1.2"
dependencies:
"@vitest/spy": "npm:3.1.2"
estree-walker: "npm:^3.0.3"
magic-string: "npm:^0.30.17"
peerDependencies:
msw: ^2.4.9
vite: ^5.0.0 || ^6.0.0
peerDependenciesMeta:
msw:
optional: true
vite:
optional: true
checksum: 10/e6d730400daa7a97fb277159733df1366a932b5b06ac83d72e094e5383191c2597b4a5ae3538b28de6112b9e5d314cb50b44e031e79522f43f3dfc8ab022a584
languageName: node
linkType: hard
"@vitest/pretty-format@npm:2.0.5":
version: 2.0.5
resolution: "@vitest/pretty-format@npm:2.0.5"
@@ -15995,7 +16043,7 @@ __metadata:
languageName: node
linkType: hard
"@vitest/pretty-format@npm:3.1.1, @vitest/pretty-format@npm:^3.1.1":
"@vitest/pretty-format@npm:3.1.1":
version: 3.1.1
resolution: "@vitest/pretty-format@npm:3.1.1"
dependencies:
@@ -16004,6 +16052,15 @@ __metadata:
languageName: node
linkType: hard
"@vitest/pretty-format@npm:3.1.2, @vitest/pretty-format@npm:^3.1.1, @vitest/pretty-format@npm:^3.1.2":
version: 3.1.2
resolution: "@vitest/pretty-format@npm:3.1.2"
dependencies:
tinyrainbow: "npm:^2.0.0"
checksum: 10/454d0a8c250dbe52f7ec9dab4968e7c769fa10c8318eb5c54cb4b6d5b524772c04856e1990279f2c6e76705ffa107fddcbc1973560ed3b88167c231ccfeada16
languageName: node
linkType: hard
"@vitest/runner@npm:3.1.1":
version: 3.1.1
resolution: "@vitest/runner@npm:3.1.1"
@@ -16014,6 +16071,16 @@ __metadata:
languageName: node
linkType: hard
"@vitest/runner@npm:3.1.2":
version: 3.1.2
resolution: "@vitest/runner@npm:3.1.2"
dependencies:
"@vitest/utils": "npm:3.1.2"
pathe: "npm:^2.0.3"
checksum: 10/b09c1ff3a556f318585307e6bb8954d219d0d35d1e17708fdd5d5ae1a230e6f29eba4f37a86faa71192f72406bb96b576c1b620d49d686def87bc5dcb8bf5737
languageName: node
linkType: hard
"@vitest/snapshot@npm:3.1.1":
version: 3.1.1
resolution: "@vitest/snapshot@npm:3.1.1"
@@ -16025,6 +16092,17 @@ __metadata:
languageName: node
linkType: hard
"@vitest/snapshot@npm:3.1.2":
version: 3.1.2
resolution: "@vitest/snapshot@npm:3.1.2"
dependencies:
"@vitest/pretty-format": "npm:3.1.2"
magic-string: "npm:^0.30.17"
pathe: "npm:^2.0.3"
checksum: 10/dda969b697bdcd8616f17e98c74ad5e95a5f3c2284140aa72390ce668db34e70936ee0b8ebe89adb2e0dea332500689d54c8ff03f8adf1e00be70639ec9032bf
languageName: node
linkType: hard
"@vitest/spy@npm:2.0.5":
version: 2.0.5
resolution: "@vitest/spy@npm:2.0.5"
@@ -16043,6 +16121,15 @@ __metadata:
languageName: node
linkType: hard
"@vitest/spy@npm:3.1.2":
version: 3.1.2
resolution: "@vitest/spy@npm:3.1.2"
dependencies:
tinyspy: "npm:^3.0.2"
checksum: 10/c2c638368fa4130f903901fdf4e86da6f90d5d6a8cf7ce880cdd24768a1f8e6b726ea3428501c97e00c34ac2e8e39ac09b3a03606dffd8081559e0a35c892ddc
languageName: node
linkType: hard
"@vitest/ui@npm:3.1.1":
version: 3.1.1
resolution: "@vitest/ui@npm:3.1.1"
@@ -16083,6 +16170,17 @@ __metadata:
languageName: node
linkType: hard
"@vitest/utils@npm:3.1.2":
version: 3.1.2
resolution: "@vitest/utils@npm:3.1.2"
dependencies:
"@vitest/pretty-format": "npm:3.1.2"
loupe: "npm:^3.1.3"
tinyrainbow: "npm:^2.0.0"
checksum: 10/221faaaf6c69ef24eacdcf68581c833cb99bf3e5125945b5dec928af7ef1af4359aa520b90c42413a128b308037bf3217d8c41a41f44ca4aee3ac44e3f0d56b5
languageName: node
linkType: hard
"@vitest/utils@npm:^2.1.1":
version: 2.1.9
resolution: "@vitest/utils@npm:2.1.9"
@@ -21142,7 +21240,7 @@ __metadata:
languageName: node
linkType: hard
"expect-type@npm:^1.2.0":
"expect-type@npm:^1.2.0, expect-type@npm:^1.2.1":
version: 1.2.1
resolution: "expect-type@npm:1.2.1"
checksum: 10/d121d90f4f3f705ca0b656e36f28c0ba91483d0cddf2876e64e23c3dea2f2d5853e9c0c9a4e90eb4b3e4663bf09c2c02e9729c339dcd308c70b2107188e6b286
@@ -21448,15 +21546,15 @@ __metadata:
languageName: node
linkType: hard
"fdir@npm:^6.4.3":
version: 6.4.3
resolution: "fdir@npm:6.4.3"
"fdir@npm:^6.4.4":
version: 6.4.4
resolution: "fdir@npm:6.4.4"
peerDependencies:
picomatch: ^3 || ^4
peerDependenciesMeta:
picomatch:
optional: true
checksum: 10/8e6d20f4590dc168de1374a9cadaa37e20ca6e0b822aa247c230e7ea1d9e9674a68cd816146435e4ecc98f9285091462ab7e5e56eebc9510931a1794e4db68b2
checksum: 10/d0000d6b790059b35f4ed19acc8847a66452e0bc68b28766c929ffd523e5ec2083811fc8a545e4a1d4945ce70e887b3a610c145c681073b506143ae3076342ed
languageName: node
linkType: hard
@@ -26881,8 +26979,8 @@ __metadata:
linkType: hard
"msw@npm:^2.6.8":
version: 2.7.4
resolution: "msw@npm:2.7.4"
version: 2.7.3
resolution: "msw@npm:2.7.3"
dependencies:
"@bundled-es-modules/cookie": "npm:^2.0.1"
"@bundled-es-modules/statuses": "npm:^1.0.1"
@@ -26909,7 +27007,7 @@ __metadata:
optional: true
bin:
msw: cli/index.js
checksum: 10/3ce3cb190b1a036536a047c018fc4f52d23371765c97595127411695c11e73bc7c737fea8fb4a6b46b3cd36223031ffc23a8bbaff10d1daebdda3bb4a817dd34
checksum: 10/f193329a68fc22e477a6f8504aa44a92bd12847f2eeac1dfbd8ec1cc43ff293112ec067de1c7fe312ba02beecb313fb00aeeebf5817432b57af2d796b2dff2fa
languageName: node
linkType: hard
@@ -28261,7 +28359,7 @@ __metadata:
languageName: node
linkType: hard
"path-to-regexp@npm:8.2.0, path-to-regexp@npm:^8.0.0":
"path-to-regexp@npm:8.2.0, path-to-regexp@npm:^8.0.0, path-to-regexp@npm:^8.2.0":
version: 8.2.0
resolution: "path-to-regexp@npm:8.2.0"
checksum: 10/23378276a172b8ba5f5fb824475d1818ca5ccee7bbdb4674701616470f23a14e536c1db11da9c9e6d82b82c556a817bbf4eee6e41b9ed20090ef9427cbb38e13
@@ -29079,7 +29177,7 @@ __metadata:
languageName: node
linkType: hard
"prettier@npm:3.5.3, prettier@npm:^3.2.5, prettier@npm:^3.4.2":
"prettier@npm:3.5.3, prettier@npm:^3.2.5, prettier@npm:^3.3.3, prettier@npm:^3.4.2":
version: 3.5.3
resolution: "prettier@npm:3.5.3"
bin:
@@ -31683,7 +31781,7 @@ __metadata:
languageName: node
linkType: hard
"std-env@npm:^3.7.0, std-env@npm:^3.8.1":
"std-env@npm:^3.7.0, std-env@npm:^3.8.1, std-env@npm:^3.9.0":
version: 3.9.0
resolution: "std-env@npm:3.9.0"
checksum: 10/3044b2c54a74be4f460db56725571241ab3ac89a91f39c7709519bc90fa37148784bc4cd7d3a301aa735f43bd174496f263563f76703ce3e81370466ab7c235b
@@ -32480,13 +32578,13 @@ __metadata:
languageName: node
linkType: hard
"tinyglobby@npm:^0.2.12":
version: 0.2.12
resolution: "tinyglobby@npm:0.2.12"
"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.13":
version: 0.2.13
resolution: "tinyglobby@npm:0.2.13"
dependencies:
fdir: "npm:^6.4.3"
fdir: "npm:^6.4.4"
picomatch: "npm:^4.0.2"
checksum: 10/4ad28701fa9118b32ef0e27f409e0a6c5741e8b02286d50425c1f6f71e6d6c6ded9dd5bbbbb714784b08623c4ec4d150151f1d3d996cfabe0495f908ab4f7002
checksum: 10/b04557ee58ad2be5f2d2cbb4b441476436c92bb45ba2e1fc464d686b793392b305ed0bcb8b877429e9b5036bdd46770c161a08384c0720b6682b7cd6ac80e403
languageName: node
linkType: hard
@@ -33651,7 +33749,7 @@ __metadata:
languageName: node
linkType: hard
"vite-node@npm:3.1.1, vite-node@npm:^3.0.4":
"vite-node@npm:3.1.1":
version: 3.1.1
resolution: "vite-node@npm:3.1.1"
dependencies:
@@ -33666,6 +33764,21 @@ __metadata:
languageName: node
linkType: hard
"vite-node@npm:3.1.2, vite-node@npm:^3.0.4":
version: 3.1.2
resolution: "vite-node@npm:3.1.2"
dependencies:
cac: "npm:^6.7.14"
debug: "npm:^4.4.0"
es-module-lexer: "npm:^1.6.0"
pathe: "npm:^2.0.3"
vite: "npm:^5.0.0 || ^6.0.0"
bin:
vite-node: vite-node.mjs
checksum: 10/8af0465810c6f27200dc899792002320995f3d85c432aaa411bf7ff15580c0b93c4a5153d8a93c7af89b496a6e1a7979a7777984e37ebd7311851ea7572eaac7
languageName: node
linkType: hard
"vite-plugin-istanbul@npm:^7.0.0":
version: 7.0.0
resolution: "vite-plugin-istanbul@npm:7.0.0"
@@ -33811,6 +33924,60 @@ __metadata:
languageName: node
linkType: hard
"vitest@npm:^3.0.6":
version: 3.1.2
resolution: "vitest@npm:3.1.2"
dependencies:
"@vitest/expect": "npm:3.1.2"
"@vitest/mocker": "npm:3.1.2"
"@vitest/pretty-format": "npm:^3.1.2"
"@vitest/runner": "npm:3.1.2"
"@vitest/snapshot": "npm:3.1.2"
"@vitest/spy": "npm:3.1.2"
"@vitest/utils": "npm:3.1.2"
chai: "npm:^5.2.0"
debug: "npm:^4.4.0"
expect-type: "npm:^1.2.1"
magic-string: "npm:^0.30.17"
pathe: "npm:^2.0.3"
std-env: "npm:^3.9.0"
tinybench: "npm:^2.9.0"
tinyexec: "npm:^0.3.2"
tinyglobby: "npm:^0.2.13"
tinypool: "npm:^1.0.2"
tinyrainbow: "npm:^2.0.0"
vite: "npm:^5.0.0 || ^6.0.0"
vite-node: "npm:3.1.2"
why-is-node-running: "npm:^2.3.0"
peerDependencies:
"@edge-runtime/vm": "*"
"@types/debug": ^4.1.12
"@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0
"@vitest/browser": 3.1.2
"@vitest/ui": 3.1.2
happy-dom: "*"
jsdom: "*"
peerDependenciesMeta:
"@edge-runtime/vm":
optional: true
"@types/debug":
optional: true
"@types/node":
optional: true
"@vitest/browser":
optional: true
"@vitest/ui":
optional: true
happy-dom:
optional: true
jsdom:
optional: true
bin:
vitest: vitest.mjs
checksum: 10/aa5638bf37b2811b01ad8ff0563cdec09202f7a28d9dbcb8eabb2e51cadefc57309cba4f5ff2bac4a72edda44055a844236fc4a09eb72127ef1bd34eb25d0808
languageName: node
linkType: hard
"void-elements@npm:3.1.0":
version: 3.1.0
resolution: "void-elements@npm:3.1.0"