create-template-project 1.3.3 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/dependencies.json +13 -13
- package/dist/index.js +61 -30
- package/dist/templates/base/files/_oxc.config.ts +7 -2
- package/dist/templates/base/files/_oxfmt.config.ts +9 -2
- package/dist/templates/base/files/_oxlint.config.ts +18 -2
- package/dist/templates/web-app/files/src/App.test.tsx +1 -1
- package/dist/templates/web-app/files/tests/e2e/basic.e2e-test.ts +1 -1
- package/dist/templates/web-fullstack/files/client/src/App.test.tsx +1 -1
- package/dist/templates/web-fullstack/files/server/src/index.test.ts +1 -1
- package/dist/templates/web-fullstack/files/tests/e2e/basic.e2e-test.ts +1 -1
- package/dist/templates/web-vanilla/files/tests/e2e/basic.e2e-test.ts +1 -1
- package/package.json +8 -9
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dependencies": {
|
|
3
3
|
"vite": {
|
|
4
|
-
"version": "8.0.
|
|
4
|
+
"version": "8.0.11",
|
|
5
5
|
"description": "Native-ESM powered web dev build tool"
|
|
6
6
|
},
|
|
7
7
|
"@vitejs/plugin-react": {
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
"description": "A tiny JavaScript debugging utility modelled after Node.js core debugging technique."
|
|
26
26
|
},
|
|
27
27
|
"@commitlint/cli": {
|
|
28
|
-
"version": "
|
|
28
|
+
"version": "21.0.0",
|
|
29
29
|
"description": "Lint commit messages to ensure they follow conventional commits."
|
|
30
30
|
},
|
|
31
31
|
"@commitlint/config-conventional": {
|
|
32
|
-
"version": "
|
|
32
|
+
"version": "21.0.0",
|
|
33
33
|
"description": "Shareable commitlint config enforcing conventional commits."
|
|
34
34
|
},
|
|
35
35
|
"@types/debug": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"description": "TypeScript definitions for debug."
|
|
38
38
|
},
|
|
39
39
|
"@types/node": {
|
|
40
|
-
"version": "25.6.
|
|
40
|
+
"version": "25.6.2",
|
|
41
41
|
"description": "TypeScript definitions for Node.js."
|
|
42
42
|
},
|
|
43
43
|
"@vitest/coverage-v8": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"description": "Modern native git hooks made easy."
|
|
54
54
|
},
|
|
55
55
|
"oxlint": {
|
|
56
|
-
"version": "1.
|
|
56
|
+
"version": "1.63.0",
|
|
57
57
|
"description": "A JavaScript linter written in Rust."
|
|
58
58
|
},
|
|
59
59
|
"oxlint-tsgolint": {
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"description": "TypeScript-specific rules for oxlint."
|
|
62
62
|
},
|
|
63
63
|
"oxfmt": {
|
|
64
|
-
"version": "0.
|
|
64
|
+
"version": "0.48.0",
|
|
65
65
|
"description": "High performance JavaScript / TypeScript formatter."
|
|
66
66
|
},
|
|
67
67
|
"typescript": {
|
|
@@ -93,19 +93,19 @@
|
|
|
93
93
|
"description": "TypeScript definitions for Express."
|
|
94
94
|
},
|
|
95
95
|
"react": {
|
|
96
|
-
"version": "19.2.
|
|
96
|
+
"version": "19.2.6",
|
|
97
97
|
"description": "A JavaScript library for building user interfaces."
|
|
98
98
|
},
|
|
99
99
|
"react-dom": {
|
|
100
|
-
"version": "19.2.
|
|
100
|
+
"version": "19.2.6",
|
|
101
101
|
"description": "React package for working with the DOM."
|
|
102
102
|
},
|
|
103
103
|
"@mui/material": {
|
|
104
|
-
"version": "9.0.
|
|
104
|
+
"version": "9.0.1",
|
|
105
105
|
"description": "Material UI components."
|
|
106
106
|
},
|
|
107
107
|
"@mui/icons-material": {
|
|
108
|
-
"version": "9.0.
|
|
108
|
+
"version": "9.0.1",
|
|
109
109
|
"description": "Material Design icons distributed as SVG React components."
|
|
110
110
|
},
|
|
111
111
|
"@emotion/react": {
|
|
@@ -141,15 +141,15 @@
|
|
|
141
141
|
"description": "tRPC integration for React Query."
|
|
142
142
|
},
|
|
143
143
|
"@tanstack/react-query": {
|
|
144
|
-
"version": "5.
|
|
144
|
+
"version": "5.100.9",
|
|
145
145
|
"description": "Powerful asynchronous state management for TS/JS."
|
|
146
146
|
},
|
|
147
147
|
"zod": {
|
|
148
|
-
"version": "4.3
|
|
148
|
+
"version": "4.4.3",
|
|
149
149
|
"description": "TypeScript-first schema validation with static type inference."
|
|
150
150
|
},
|
|
151
151
|
"react-router-dom": {
|
|
152
|
-
"version": "7.
|
|
152
|
+
"version": "7.15.0",
|
|
153
153
|
"description": "Declarative routing for React web applications."
|
|
154
154
|
},
|
|
155
155
|
"release-it": {
|
package/dist/index.js
CHANGED
|
@@ -79,8 +79,8 @@ var githubWorkflowProcessor = (content, { filePath, opts }) => {
|
|
|
79
79
|
let playwrightSetup = "";
|
|
80
80
|
if (template === "web-fullstack" || template === "web-app" || template === "web-vanilla") playwrightSetup = WORKFLOW_PLAYWRIGHT_SETUP;
|
|
81
81
|
let processed = content.replaceAll("{{installCommand}}", installCommand).replaceAll("# [PM_SETUP]", pmSetup).replaceAll("# [PLAYWRIGHT_SETUP]", playwrightSetup);
|
|
82
|
-
processed = processed.replace(/^\s*# \[PM_SETUP\]\s*\n/
|
|
83
|
-
processed = processed.replace(/^\s*# \[PLAYWRIGHT_SETUP\]\s*\n/
|
|
82
|
+
processed = processed.replace(/^\s*# \[PM_SETUP\]\s*\n/mu, "");
|
|
83
|
+
processed = processed.replace(/^\s*# \[PLAYWRIGHT_SETUP\]\s*\n/mu, "");
|
|
84
84
|
return processed;
|
|
85
85
|
};
|
|
86
86
|
//#endregion
|
|
@@ -99,8 +99,8 @@ var tsconfigProcessor = (content, { filePath, opts }) => {
|
|
|
99
99
|
if (filePath !== "tsconfig.json") return content;
|
|
100
100
|
const { template } = opts;
|
|
101
101
|
let processed = content;
|
|
102
|
-
if (template === "web-fullstack" || template === "web-vanilla" || template === "web-app") processed = processed.replace(/\/\* Language and Environment \*\/[\s\S]*?\/\* Strict Type-Checking Options
|
|
103
|
-
if (template === "web-fullstack") processed = processed.replace(/"include":\s*\[\s*"src\/\*\*\/\*"\s*\]
|
|
102
|
+
if (template === "web-fullstack" || template === "web-vanilla" || template === "web-app") processed = processed.replace(/\/\* Language and Environment \*\/[\s\S]*?\/\* Strict Type-Checking Options \*\//u, `${WEB_ENV}\n\n\t\t/* Strict Type-Checking Options */`);
|
|
103
|
+
if (template === "web-fullstack") processed = processed.replace(/"include":\s*\[\s*"src\/\*\*\/\*"\s*\]/u, "\"include\": [\"client/src/**/*\", \"server/src/**/*\"]");
|
|
104
104
|
return processed;
|
|
105
105
|
};
|
|
106
106
|
//#endregion
|
|
@@ -1073,6 +1073,7 @@ var isFileRequired = (relativePath, type) => {
|
|
|
1073
1073
|
].includes(type);
|
|
1074
1074
|
return true;
|
|
1075
1075
|
};
|
|
1076
|
+
var isCustomConfigFile = (relativePath) => relativePath === "oxlint.config.ts" || relativePath === "oxfmt.config.ts";
|
|
1076
1077
|
var buildSimpleUnifiedDiff = (filePath, before, after) => {
|
|
1077
1078
|
const beforeLines = before.split("\n");
|
|
1078
1079
|
const afterLines = after.split("\n");
|
|
@@ -1286,6 +1287,14 @@ var generateProject = async (opts) => {
|
|
|
1286
1287
|
relativePath = relativePath.slice(1);
|
|
1287
1288
|
targetPath = path.join(projectDir, relativePath);
|
|
1288
1289
|
}
|
|
1290
|
+
if (isUpdate && (relativePath === "oxlint.config.ts" || relativePath === "oxfmt.config.ts")) {
|
|
1291
|
+
actions.push({
|
|
1292
|
+
type: "SKIP",
|
|
1293
|
+
path: relativePath,
|
|
1294
|
+
reason: "Custom config file - preserved on update"
|
|
1295
|
+
});
|
|
1296
|
+
continue;
|
|
1297
|
+
}
|
|
1289
1298
|
if (relativePath === "package.json") continue;
|
|
1290
1299
|
const finalTargetPath = targetPath;
|
|
1291
1300
|
const finalRelativePath = relativePath;
|
|
@@ -1306,21 +1315,28 @@ var generateProject = async (opts) => {
|
|
|
1306
1315
|
};
|
|
1307
1316
|
actions.push(action);
|
|
1308
1317
|
pendingOperations.push(async () => {
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
action.type = "MERGE";
|
|
1312
|
-
action.reason = "Merged template updates with your manual changes";
|
|
1313
|
-
action.recommendedAction = "Review changes for correct integration";
|
|
1314
|
-
log.info(`ℹ Merged: ${finalRelativePath}`);
|
|
1315
|
-
} else if (result === "conflict") {
|
|
1316
|
-
action.type = "CONFLICT";
|
|
1317
|
-
action.reason = "Conflicting changes between template and your code";
|
|
1318
|
-
action.recommendedAction = "Resolve git conflict markers in this file";
|
|
1319
|
-
log.warn(`⚠ Conflict: ${finalRelativePath}`);
|
|
1320
|
-
} else if (result === "updated") {
|
|
1318
|
+
if (finalRelativePath === "oxc.config.ts") {
|
|
1319
|
+
await fs.writeFile(finalTargetPath, content);
|
|
1321
1320
|
action.type = "UPDATED";
|
|
1322
|
-
action.reason = "
|
|
1321
|
+
action.reason = "Default config was updated to the latest template version";
|
|
1323
1322
|
log.info(`✔ Updated: ${finalRelativePath}`);
|
|
1323
|
+
} else {
|
|
1324
|
+
const result = await mergeFile(finalTargetPath, existingContent, content, log);
|
|
1325
|
+
if (result === "merged") {
|
|
1326
|
+
action.type = "MERGE";
|
|
1327
|
+
action.reason = "Merged template updates with your manual changes";
|
|
1328
|
+
action.recommendedAction = "Review changes for correct integration";
|
|
1329
|
+
log.info(`ℹ Merged: ${finalRelativePath}`);
|
|
1330
|
+
} else if (result === "conflict") {
|
|
1331
|
+
action.type = "CONFLICT";
|
|
1332
|
+
action.reason = "Conflicting changes between template and your code";
|
|
1333
|
+
action.recommendedAction = "Resolve git conflict markers in this file";
|
|
1334
|
+
log.warn(`⚠ Conflict: ${finalRelativePath}`);
|
|
1335
|
+
} else if (result === "updated") {
|
|
1336
|
+
action.type = "UPDATED";
|
|
1337
|
+
action.reason = "File was updated to the latest template version";
|
|
1338
|
+
log.info(`✔ Updated: ${finalRelativePath}`);
|
|
1339
|
+
}
|
|
1324
1340
|
}
|
|
1325
1341
|
});
|
|
1326
1342
|
}
|
|
@@ -1354,6 +1370,14 @@ var generateProject = async (opts) => {
|
|
|
1354
1370
|
});
|
|
1355
1371
|
continue;
|
|
1356
1372
|
}
|
|
1373
|
+
if (isUpdate && isCustomConfigFile(file.path)) {
|
|
1374
|
+
actions.push({
|
|
1375
|
+
type: "SKIP",
|
|
1376
|
+
path: file.path,
|
|
1377
|
+
reason: "Custom config file - preserved on update"
|
|
1378
|
+
});
|
|
1379
|
+
continue;
|
|
1380
|
+
}
|
|
1357
1381
|
if (!isFileRequired(file.path, type)) {
|
|
1358
1382
|
if (isUpdate && await pathExists(targetPath)) {
|
|
1359
1383
|
actions.push({
|
|
@@ -1385,21 +1409,28 @@ var generateProject = async (opts) => {
|
|
|
1385
1409
|
};
|
|
1386
1410
|
actions.push(action);
|
|
1387
1411
|
pendingOperations.push(async () => {
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
action.type = "MERGE";
|
|
1391
|
-
action.reason = "Merged template updates with your manual changes";
|
|
1392
|
-
action.recommendedAction = "Review changes for correct integration";
|
|
1393
|
-
log.info(`ℹ Merged: ${file.path}`);
|
|
1394
|
-
} else if (result === "conflict") {
|
|
1395
|
-
action.type = "CONFLICT";
|
|
1396
|
-
action.reason = "Conflicting changes between template and your code";
|
|
1397
|
-
action.recommendedAction = "Resolve git conflict markers in this file";
|
|
1398
|
-
log.warn(`⚠ Conflict: ${file.path}`);
|
|
1399
|
-
} else if (result === "updated") {
|
|
1412
|
+
if (file.path === "oxc.config.ts") {
|
|
1413
|
+
await fs.writeFile(targetPath, content);
|
|
1400
1414
|
action.type = "UPDATED";
|
|
1401
|
-
action.reason = "
|
|
1415
|
+
action.reason = "Default config was updated to the latest template version";
|
|
1402
1416
|
log.info(`✔ Updated: ${file.path}`);
|
|
1417
|
+
} else {
|
|
1418
|
+
const result = await mergeFile(targetPath, existingContent, content, log);
|
|
1419
|
+
if (result === "merged") {
|
|
1420
|
+
action.type = "MERGE";
|
|
1421
|
+
action.reason = "Merged template updates with your manual changes";
|
|
1422
|
+
action.recommendedAction = "Review changes for correct integration";
|
|
1423
|
+
log.info(`ℹ Merged: ${file.path}`);
|
|
1424
|
+
} else if (result === "conflict") {
|
|
1425
|
+
action.type = "CONFLICT";
|
|
1426
|
+
action.reason = "Conflicting changes between template and your code";
|
|
1427
|
+
action.recommendedAction = "Resolve git conflict markers in this file";
|
|
1428
|
+
log.warn(`⚠ Conflict: ${file.path}`);
|
|
1429
|
+
} else if (result === "updated") {
|
|
1430
|
+
action.type = "UPDATED";
|
|
1431
|
+
action.reason = "File was updated to the latest template version";
|
|
1432
|
+
log.info(`✔ Updated: ${file.path}`);
|
|
1433
|
+
}
|
|
1403
1434
|
}
|
|
1404
1435
|
});
|
|
1405
1436
|
}
|
|
@@ -65,6 +65,10 @@ export const linter = defineConfig({
|
|
|
65
65
|
'eslint/sort-imports': 'off',
|
|
66
66
|
'eslint/sort-keys': 'off',
|
|
67
67
|
'eslint/no-ternary': 'off',
|
|
68
|
+
'eslint/no-void': ['error', {allowAsStatement: true}],
|
|
69
|
+
'typescript/consistent-type-definitions': ['error', 'type'],
|
|
70
|
+
'typescript/dot-notation': ['error', {allowPattern: '^[a-zA-Z]+(_[a-zA-Z]+)+$'}],
|
|
71
|
+
'typescript/no-import-type-side-effects': 'off',
|
|
68
72
|
'typescript/no-unused-vars': [
|
|
69
73
|
'error',
|
|
70
74
|
{
|
|
@@ -72,8 +76,6 @@ export const linter = defineConfig({
|
|
|
72
76
|
argsIgnorePattern: '^_',
|
|
73
77
|
},
|
|
74
78
|
],
|
|
75
|
-
'typescript/consistent-type-definitions': ['error', 'type'],
|
|
76
|
-
'typescript/no-import-type-side-effects': 'off',
|
|
77
79
|
'typescript/prefer-readonly-parameter-types': 'off',
|
|
78
80
|
'import/consistent-type-specifier-style': ['error', 'prefer-inline'],
|
|
79
81
|
'import/exports-last': 'off',
|
|
@@ -151,6 +153,7 @@ export const linter = defineConfig({
|
|
|
151
153
|
'unicorn/no-array-sort': 'off', // TODO: consider enabling
|
|
152
154
|
'unicorn/no-hex-escape': 'off',
|
|
153
155
|
'unicorn/no-immediate-mutation': 'off',
|
|
156
|
+
'unicorn/no-negated-condition': 'off',
|
|
154
157
|
'unicorn/no-nested-ternary': 'off',
|
|
155
158
|
'unicorn/no-null': 'off', // TODO: consider enabling
|
|
156
159
|
'unicorn/no-process-exit': 'off', // TODO: consider enabling
|
|
@@ -165,8 +168,10 @@ export const linter = defineConfig({
|
|
|
165
168
|
'vitest/no-importing-vitest-globals': 'off',
|
|
166
169
|
'vitest/prefer-describe-function-title': 'off',
|
|
167
170
|
'vitest/prefer-expect-assertions': 'off',
|
|
171
|
+
'vitest/prefer-lowercase-title': 'off',
|
|
168
172
|
'vitest/prefer-to-be-falsy': 'off', // NOTE: Pick strictness: keep prefer-strict-boolean-matchers, disable truthy/falsy rules.
|
|
169
173
|
'vitest/prefer-to-be-truthy': 'off', // NOTE: Pick strictness: keep prefer-strict-boolean-matchers, disable truthy/falsy rules.
|
|
174
|
+
'vitest/require-hook': 'off',
|
|
170
175
|
'vitest/require-test-timeout': 'off',
|
|
171
176
|
},
|
|
172
177
|
overrides: [
|
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
import {formatter} from './oxc.config.ts';
|
|
2
|
-
|
|
1
|
+
import {formatter as defaults} from './oxc.config.ts';
|
|
2
|
+
|
|
3
|
+
// Add custom oxfmt formatter overrides here.
|
|
4
|
+
// This file is preserved on template updates.
|
|
5
|
+
const formatter: Partial<typeof defaults> = {};
|
|
6
|
+
|
|
7
|
+
const config = {...defaults, ...formatter};
|
|
8
|
+
|
|
9
|
+
export default config;
|
|
@@ -1,2 +1,18 @@
|
|
|
1
|
-
import {linter} from './oxc.config.ts';
|
|
2
|
-
|
|
1
|
+
import {linter as defaults} from './oxc.config.ts';
|
|
2
|
+
|
|
3
|
+
// Add custom oxlint rule overrides here.
|
|
4
|
+
// This file is preserved on template updates.
|
|
5
|
+
//
|
|
6
|
+
// Example:
|
|
7
|
+
// rules: { 'no-console': 'off' }
|
|
8
|
+
// overrides: [{ files: ['scripts/**'], rules: { 'no-console': 'off' } }]
|
|
9
|
+
const rules: Partial<typeof defaults.rules> = {};
|
|
10
|
+
const overrides: Partial<NonNullable<typeof defaults.overrides>[number]>[] = [];
|
|
11
|
+
|
|
12
|
+
const config = {
|
|
13
|
+
...defaults,
|
|
14
|
+
rules: {...defaults.rules, ...rules},
|
|
15
|
+
overrides: [...(defaults.overrides ?? []), ...overrides],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default config;
|
|
@@ -6,6 +6,6 @@ import {App} from './App.js';
|
|
|
6
6
|
describe('App', () => {
|
|
7
7
|
it('renders hello message in the browser', async () => {
|
|
8
8
|
await render(<App />);
|
|
9
|
-
await expect.element(page.getByText(/Hello from React!/
|
|
9
|
+
await expect.element(page.getByText(/Hello from React!/iu)).toBeVisible();
|
|
10
10
|
});
|
|
11
11
|
});
|
|
@@ -2,7 +2,7 @@ import {test, expect} from '@playwright/test';
|
|
|
2
2
|
|
|
3
3
|
test('has title', async ({page}) => {
|
|
4
4
|
await page.goto('/');
|
|
5
|
-
await expect(page).toHaveTitle(/{{projectName}}/);
|
|
5
|
+
await expect(page).toHaveTitle(/{{projectName}}/u);
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
test('api is reachable', async ({page}) => {
|
|
@@ -6,6 +6,6 @@ import {App} from './App.js';
|
|
|
6
6
|
describe('App', () => {
|
|
7
7
|
it('should render in the browser', async () => {
|
|
8
8
|
await render(<App />);
|
|
9
|
-
await expect.element(page.getByRole('heading', {name: /Login/
|
|
9
|
+
await expect.element(page.getByRole('heading', {name: /Login/iu}).or(page.getByRole('heading', {name: /Dashboard/iu}))).toBeVisible();
|
|
10
10
|
});
|
|
11
11
|
});
|
|
@@ -2,7 +2,7 @@ import {test, expect} from '@playwright/test';
|
|
|
2
2
|
|
|
3
3
|
test('has title', async ({page}) => {
|
|
4
4
|
await page.goto('/');
|
|
5
|
-
await expect(page).toHaveTitle(/{{projectName}}/);
|
|
5
|
+
await expect(page).toHaveTitle(/{{projectName}}/u);
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
test('header is visible', async ({page}) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-template-project",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "An ultra-modular, type-safe Node.js CLI tool used to scaffold new project templates (CLI, Webpage, Webapp, Fullstack) with best-practice configurations pre-installed.",
|
|
6
6
|
"keywords": [
|
|
@@ -56,27 +56,26 @@
|
|
|
56
56
|
"commander": "14.0.3",
|
|
57
57
|
"debug": "4.4.3",
|
|
58
58
|
"execa": "9.6.1",
|
|
59
|
-
"zod": "4.4.
|
|
59
|
+
"zod": "4.4.3"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|
|
62
|
-
"@commitlint/cli": "
|
|
63
|
-
"@commitlint/config-conventional": "
|
|
62
|
+
"@commitlint/cli": "21.0.0",
|
|
63
|
+
"@commitlint/config-conventional": "21.0.0",
|
|
64
64
|
"@types/cli-progress": "3.11.6",
|
|
65
65
|
"@types/debug": "4.1.13",
|
|
66
|
-
"@types/node": "25.6.
|
|
66
|
+
"@types/node": "25.6.2",
|
|
67
67
|
"@vitest/coverage-v8": "4.1.5",
|
|
68
68
|
"conventional-changelog": "7.2.0",
|
|
69
69
|
"conventional-changelog-angular": "8.3.1",
|
|
70
70
|
"eslint-plugin-regexp": "3.1.0",
|
|
71
71
|
"husky": "9.1.7",
|
|
72
|
-
"oxfmt": "0.
|
|
73
|
-
"oxlint": "1.
|
|
72
|
+
"oxfmt": "0.48.0",
|
|
73
|
+
"oxlint": "1.63.0",
|
|
74
74
|
"oxlint-tsgolint": "0.22.1",
|
|
75
|
-
"pnpm": "11.0.3",
|
|
76
75
|
"release-it": "20.0.1",
|
|
77
76
|
"rimraf": "6.1.3",
|
|
78
77
|
"typescript": "6.0.3",
|
|
79
|
-
"vite": "8.0.
|
|
78
|
+
"vite": "8.0.11",
|
|
80
79
|
"vitest": "4.1.5"
|
|
81
80
|
},
|
|
82
81
|
"engines": {
|