create-better-t-stack 3.8.3 → 3.9.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/README.md
CHANGED
|
@@ -90,7 +90,7 @@ You can disable telemetry by setting the `BTS_TELEMETRY_DISABLED` environment va
|
|
|
90
90
|
|
|
91
91
|
```bash
|
|
92
92
|
# Disable telemetry for a single run
|
|
93
|
-
BTS_TELEMETRY_DISABLED=1 npx create-better-t-stack
|
|
93
|
+
BTS_TELEMETRY_DISABLED=1 npx create-better-t-stack
|
|
94
94
|
|
|
95
95
|
# Disable telemetry globally in your shell profile (.bashrc, .zshrc, etc.)
|
|
96
96
|
export BTS_TELEMETRY_DISABLED=1
|
|
@@ -101,85 +101,85 @@ export BTS_TELEMETRY_DISABLED=1
|
|
|
101
101
|
Create a project with default configuration:
|
|
102
102
|
|
|
103
103
|
```bash
|
|
104
|
-
npx create-better-t-stack
|
|
104
|
+
npx create-better-t-stack --yes
|
|
105
105
|
```
|
|
106
106
|
|
|
107
107
|
Create a project with specific options:
|
|
108
108
|
|
|
109
109
|
```bash
|
|
110
|
-
npx create-better-t-stack
|
|
110
|
+
npx create-better-t-stack --database postgres --orm drizzle --auth --addons pwa biome
|
|
111
111
|
```
|
|
112
112
|
|
|
113
113
|
Create a project with Elysia backend and Node.js runtime:
|
|
114
114
|
|
|
115
115
|
```bash
|
|
116
|
-
npx create-better-t-stack
|
|
116
|
+
npx create-better-t-stack --backend elysia --runtime node
|
|
117
117
|
```
|
|
118
118
|
|
|
119
119
|
Create a project with multiple frontend options (one web + one native):
|
|
120
120
|
|
|
121
121
|
```bash
|
|
122
|
-
npx create-better-t-stack
|
|
122
|
+
npx create-better-t-stack --frontend tanstack-router native-bare
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
Create a project with examples:
|
|
126
126
|
|
|
127
127
|
```bash
|
|
128
|
-
npx create-better-t-stack
|
|
128
|
+
npx create-better-t-stack --examples todo ai
|
|
129
129
|
```
|
|
130
130
|
|
|
131
131
|
Create a project with Turso database setup:
|
|
132
132
|
|
|
133
133
|
```bash
|
|
134
|
-
npx create-better-t-stack
|
|
134
|
+
npx create-better-t-stack --database sqlite --orm drizzle --db-setup turso
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
Create a project with Supabase PostgreSQL setup:
|
|
138
138
|
|
|
139
139
|
```bash
|
|
140
|
-
npx create-better-t-stack
|
|
140
|
+
npx create-better-t-stack --database postgres --orm drizzle --db-setup supabase --auth
|
|
141
141
|
```
|
|
142
142
|
|
|
143
143
|
Create a project with Convex backend:
|
|
144
144
|
|
|
145
145
|
```bash
|
|
146
|
-
npx create-better-t-stack
|
|
146
|
+
npx create-better-t-stack --backend convex --frontend tanstack-router
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
Create a project with documentation site:
|
|
150
150
|
|
|
151
151
|
```bash
|
|
152
|
-
npx create-better-t-stack
|
|
152
|
+
npx create-better-t-stack --addons starlight
|
|
153
153
|
```
|
|
154
154
|
|
|
155
155
|
Create a minimal TypeScript project with no backend:
|
|
156
156
|
|
|
157
157
|
```bash
|
|
158
|
-
npx create-better-t-stack
|
|
158
|
+
npx create-better-t-stack --backend none --frontend tanstack-router
|
|
159
159
|
```
|
|
160
160
|
|
|
161
161
|
Create a backend-only project with no frontend:
|
|
162
162
|
|
|
163
163
|
```bash
|
|
164
|
-
npx create-better-t-stack
|
|
164
|
+
npx create-better-t-stack --frontend none --backend hono --database postgres --orm drizzle
|
|
165
165
|
```
|
|
166
166
|
|
|
167
167
|
Create a simple frontend-only project:
|
|
168
168
|
|
|
169
169
|
```bash
|
|
170
|
-
npx create-better-t-stack
|
|
170
|
+
npx create-better-t-stack --backend none --frontend next --addons none --examples none
|
|
171
171
|
```
|
|
172
172
|
|
|
173
173
|
Create a Cloudflare Workers project:
|
|
174
174
|
|
|
175
175
|
```bash
|
|
176
|
-
npx create-better-t-stack
|
|
176
|
+
npx create-better-t-stack --backend hono --runtime workers --database sqlite --orm drizzle --db-setup d1
|
|
177
177
|
```
|
|
178
178
|
|
|
179
179
|
Create a minimal API-only project:
|
|
180
180
|
|
|
181
181
|
```bash
|
|
182
|
-
npx create-better-t-stack
|
|
182
|
+
npx create-better-t-stack --frontend none --backend hono --api trpc --database none --addons none
|
|
183
183
|
```
|
|
184
184
|
|
|
185
185
|
## Compatibility Notes
|
package/dist/cli.mjs
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as router, i as init, n as createBtsCli, o as sponsors, r as docs, t as builder } from "./src-
|
|
2
|
+
import { a as router, i as init, n as createBtsCli, o as sponsors, r as docs, t as builder } from "./src-DLvUK0Qf.mjs";
|
|
3
3
|
|
|
4
4
|
export { builder, createBtsCli, docs, init, router, sponsors };
|
|
@@ -15,7 +15,7 @@ import { $, execa } from "execa";
|
|
|
15
15
|
import { IndentationText, Node, Project, QuoteKind, SyntaxKind } from "ts-morph";
|
|
16
16
|
import { glob } from "tinyglobby";
|
|
17
17
|
import handlebars from "handlebars";
|
|
18
|
-
import {
|
|
18
|
+
import { format } from "oxfmt";
|
|
19
19
|
import yaml from "yaml";
|
|
20
20
|
import os$1 from "node:os";
|
|
21
21
|
|
|
@@ -96,6 +96,7 @@ const dependencyVersionMap = {
|
|
|
96
96
|
"@tauri-apps/cli": "^2.4.0",
|
|
97
97
|
"@biomejs/biome": "^2.2.0",
|
|
98
98
|
oxlint: "^1.32.0",
|
|
99
|
+
oxfmt: "^0.19.0",
|
|
99
100
|
husky: "^9.1.7",
|
|
100
101
|
"lint-staged": "^16.1.2",
|
|
101
102
|
tsx: "^4.19.2",
|
|
@@ -363,7 +364,7 @@ function getAddonDisplay(addon) {
|
|
|
363
364
|
break;
|
|
364
365
|
case "oxlint":
|
|
365
366
|
label = "Oxlint";
|
|
366
|
-
hint = "
|
|
367
|
+
hint = "Oxlint + Oxfmt (linting & formatting)";
|
|
367
368
|
break;
|
|
368
369
|
case "ultracite":
|
|
369
370
|
label = "Ultracite";
|
|
@@ -2031,6 +2032,38 @@ async function setupFumadocs(config) {
|
|
|
2031
2032
|
}
|
|
2032
2033
|
}
|
|
2033
2034
|
|
|
2035
|
+
//#endregion
|
|
2036
|
+
//#region src/helpers/addons/oxlint-setup.ts
|
|
2037
|
+
async function setupOxlint(projectDir, packageManager) {
|
|
2038
|
+
await addPackageDependency({
|
|
2039
|
+
devDependencies: ["oxlint", "oxfmt"],
|
|
2040
|
+
projectDir
|
|
2041
|
+
});
|
|
2042
|
+
const packageJsonPath = path.join(projectDir, "package.json");
|
|
2043
|
+
if (await fs.pathExists(packageJsonPath)) {
|
|
2044
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
|
2045
|
+
packageJson.scripts = {
|
|
2046
|
+
...packageJson.scripts,
|
|
2047
|
+
check: "oxlint && oxfmt --write"
|
|
2048
|
+
};
|
|
2049
|
+
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
2050
|
+
}
|
|
2051
|
+
const s = spinner();
|
|
2052
|
+
const oxlintInitCommand = getPackageExecutionCommand(packageManager, "oxlint@latest --init");
|
|
2053
|
+
s.start("Initializing oxlint and oxfmt...");
|
|
2054
|
+
await execa(oxlintInitCommand, {
|
|
2055
|
+
cwd: projectDir,
|
|
2056
|
+
env: { CI: "true" },
|
|
2057
|
+
shell: true
|
|
2058
|
+
});
|
|
2059
|
+
await execa(getPackageExecutionCommand(packageManager, "oxfmt@latest --init"), {
|
|
2060
|
+
cwd: projectDir,
|
|
2061
|
+
env: { CI: "true" },
|
|
2062
|
+
shell: true
|
|
2063
|
+
});
|
|
2064
|
+
s.stop("oxlint and oxfmt initialized successfully!");
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2034
2067
|
//#endregion
|
|
2035
2068
|
//#region src/helpers/addons/ruler-setup.ts
|
|
2036
2069
|
async function setupRuler(config) {
|
|
@@ -2400,7 +2433,7 @@ ${pc.cyan("Docs:")} ${pc.underline("https://turborepo.com/docs")}
|
|
|
2400
2433
|
await setupHusky(projectDir, linter);
|
|
2401
2434
|
}
|
|
2402
2435
|
}
|
|
2403
|
-
if (
|
|
2436
|
+
if (hasOxlint) await setupOxlint(projectDir, packageManager);
|
|
2404
2437
|
if (addons.includes("starlight")) await setupStarlight(config);
|
|
2405
2438
|
if (addons.includes("ruler")) await setupRuler(config);
|
|
2406
2439
|
if (addons.includes("fumadocs")) await setupFumadocs(config);
|
|
@@ -2442,7 +2475,7 @@ async function setupHusky(projectDir, linter) {
|
|
|
2442
2475
|
...packageJson.scripts,
|
|
2443
2476
|
prepare: "husky"
|
|
2444
2477
|
};
|
|
2445
|
-
if (linter === "oxlint") packageJson["lint-staged"] = { "
|
|
2478
|
+
if (linter === "oxlint") packageJson["lint-staged"] = { "*": ["oxlint", "oxfmt --write"] };
|
|
2446
2479
|
else if (linter === "biome") packageJson["lint-staged"] = { "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}": ["biome check --write ."] };
|
|
2447
2480
|
else packageJson["lint-staged"] = { "**/*.{js,mjs,cjs,jsx,ts,mts,cts,tsx,vue,astro,svelte}": "" };
|
|
2448
2481
|
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
@@ -2473,30 +2506,6 @@ async function setupPwa(projectDir, frontends) {
|
|
|
2473
2506
|
const viteConfigTs = path.join(clientPackageDir, "vite.config.ts");
|
|
2474
2507
|
if (await fs.pathExists(viteConfigTs)) await addPwaToViteConfig(viteConfigTs, path.basename(projectDir));
|
|
2475
2508
|
}
|
|
2476
|
-
async function setupOxlint(projectDir, packageManager) {
|
|
2477
|
-
await addPackageDependency({
|
|
2478
|
-
devDependencies: ["oxlint"],
|
|
2479
|
-
projectDir
|
|
2480
|
-
});
|
|
2481
|
-
const packageJsonPath = path.join(projectDir, "package.json");
|
|
2482
|
-
if (await fs.pathExists(packageJsonPath)) {
|
|
2483
|
-
const packageJson = await fs.readJson(packageJsonPath);
|
|
2484
|
-
packageJson.scripts = {
|
|
2485
|
-
...packageJson.scripts,
|
|
2486
|
-
check: "oxlint"
|
|
2487
|
-
};
|
|
2488
|
-
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
|
2489
|
-
}
|
|
2490
|
-
const oxlintInitCommand = getPackageExecutionCommand(packageManager, "oxlint@latest --init");
|
|
2491
|
-
const s = spinner();
|
|
2492
|
-
s.start("Initializing oxlint...");
|
|
2493
|
-
await execa(oxlintInitCommand, {
|
|
2494
|
-
cwd: projectDir,
|
|
2495
|
-
env: { CI: "true" },
|
|
2496
|
-
shell: true
|
|
2497
|
-
});
|
|
2498
|
-
s.stop("oxlint initialized successfully!");
|
|
2499
|
-
}
|
|
2500
2509
|
|
|
2501
2510
|
//#endregion
|
|
2502
2511
|
//#region src/helpers/core/detect-project-config.ts
|
|
@@ -2552,61 +2561,16 @@ async function installDependencies({ projectDir, packageManager }) {
|
|
|
2552
2561
|
}
|
|
2553
2562
|
|
|
2554
2563
|
//#endregion
|
|
2555
|
-
//#region src/utils/
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
formatter: {
|
|
2562
|
-
enabled: true,
|
|
2563
|
-
indentStyle: "tab",
|
|
2564
|
-
indentWidth: 2,
|
|
2565
|
-
lineWidth: 80
|
|
2566
|
-
},
|
|
2567
|
-
linter: { enabled: false },
|
|
2568
|
-
javascript: { formatter: { enabled: true } },
|
|
2569
|
-
json: { formatter: { enabled: true } }
|
|
2570
|
-
});
|
|
2571
|
-
return {
|
|
2572
|
-
biome,
|
|
2573
|
-
projectKey
|
|
2574
|
-
};
|
|
2575
|
-
} catch {
|
|
2576
|
-
return null;
|
|
2577
|
-
}
|
|
2578
|
-
}
|
|
2579
|
-
function isSupportedFile(filePath) {
|
|
2580
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
2581
|
-
return [
|
|
2582
|
-
".js",
|
|
2583
|
-
".jsx",
|
|
2584
|
-
".ts",
|
|
2585
|
-
".tsx",
|
|
2586
|
-
".json",
|
|
2587
|
-
".jsonc"
|
|
2588
|
-
].includes(ext);
|
|
2589
|
-
}
|
|
2590
|
-
function shouldSkipFile(filePath) {
|
|
2591
|
-
const basename = path.basename(filePath);
|
|
2592
|
-
return [
|
|
2593
|
-
".hbs",
|
|
2594
|
-
"package-lock.json",
|
|
2595
|
-
"yarn.lock",
|
|
2596
|
-
"pnpm-lock.yaml",
|
|
2597
|
-
"bun.lock",
|
|
2598
|
-
".d.ts"
|
|
2599
|
-
].some((pattern) => basename.includes(pattern));
|
|
2600
|
-
}
|
|
2601
|
-
function formatFileWithBiome(filePath, content) {
|
|
2602
|
-
if (!isSupportedFile(filePath) || shouldSkipFile(filePath)) return null;
|
|
2564
|
+
//#region src/utils/file-formatter.ts
|
|
2565
|
+
const formatOptions = {
|
|
2566
|
+
experimentalSortPackageJson: true,
|
|
2567
|
+
experimentalSortImports: { order: "asc" }
|
|
2568
|
+
};
|
|
2569
|
+
async function formatFile(filePath, content) {
|
|
2603
2570
|
try {
|
|
2604
|
-
const
|
|
2605
|
-
if (
|
|
2606
|
-
|
|
2607
|
-
const result = biome.formatContent(projectKey, content, { filePath: path.basename(filePath) });
|
|
2608
|
-
if (result.diagnostics && result.diagnostics.length > 0) consola.debug(`Biome formatting diagnostics for ${filePath}:`, result.diagnostics);
|
|
2609
|
-
return result.content;
|
|
2571
|
+
const result = await format(path.basename(filePath), content, formatOptions);
|
|
2572
|
+
if (result.errors && result.errors.length > 0) return null;
|
|
2573
|
+
return result.code;
|
|
2610
2574
|
} catch {
|
|
2611
2575
|
return null;
|
|
2612
2576
|
}
|
|
@@ -2636,7 +2600,7 @@ async function processTemplate(srcPath, destPath, context) {
|
|
|
2636
2600
|
content = handlebars.compile(templateContent)(context);
|
|
2637
2601
|
} else content = await fs.readFile(srcPath, "utf-8");
|
|
2638
2602
|
try {
|
|
2639
|
-
const formattedContent = await
|
|
2603
|
+
const formattedContent = await formatFile(destPath, content);
|
|
2640
2604
|
if (formattedContent) content = formattedContent;
|
|
2641
2605
|
} catch (formatError) {
|
|
2642
2606
|
consola.debug(`Failed to format ${destPath}:`, formatError);
|
|
@@ -5949,6 +5913,7 @@ function generateFeaturesList(database, auth, addons, orm, runtime, frontend, ba
|
|
|
5949
5913
|
for (const addon of addons) if (addon === "pwa") addonsList.push("- **PWA** - Progressive Web App support");
|
|
5950
5914
|
else if (addon === "tauri") addonsList.push("- **Tauri** - Build native desktop applications");
|
|
5951
5915
|
else if (addon === "biome") addonsList.push("- **Biome** - Linting and formatting");
|
|
5916
|
+
else if (addon === "oxlint") addonsList.push("- **Oxlint** - Oxlint + Oxfmt (linting & formatting)");
|
|
5952
5917
|
else if (addon === "husky") addonsList.push("- **Husky** - Git hooks for code quality");
|
|
5953
5918
|
else if (addon === "starlight") addonsList.push("- **Starlight** - Documentation site with Astro");
|
|
5954
5919
|
else if (addon === "turborepo") addonsList.push("- **Turborepo** - Optimized monorepo build system");
|
|
@@ -6024,6 +5989,8 @@ function generateScriptsList(packageManagerRunCmd, database, orm, _auth, hasNati
|
|
|
6024
5989
|
}
|
|
6025
5990
|
if (addons.includes("biome")) scripts += `
|
|
6026
5991
|
- \`${packageManagerRunCmd} check\`: Run Biome formatting and linting`;
|
|
5992
|
+
if (addons.includes("oxlint")) scripts += `
|
|
5993
|
+
- \`${packageManagerRunCmd} check\`: Run Oxlint and Oxfmt`;
|
|
6027
5994
|
if (addons.includes("pwa")) scripts += `
|
|
6028
5995
|
- \`cd apps/web && ${packageManagerRunCmd} generate-pwa-assets\`: Generate PWA assets`;
|
|
6029
5996
|
if (addons.includes("tauri")) scripts += `
|
|
@@ -6175,10 +6142,12 @@ async function displayPostInstallInstructions(config) {
|
|
|
6175
6142
|
const isBackendSelf = backend === "self";
|
|
6176
6143
|
const runCmd = packageManager === "npm" ? "npm run" : packageManager === "pnpm" ? "pnpm run" : "bun run";
|
|
6177
6144
|
const cdCmd = `cd ${relativePath}`;
|
|
6178
|
-
const
|
|
6145
|
+
const hasHusky = addons?.includes("husky");
|
|
6146
|
+
const hasLinting = addons?.includes("biome") || addons?.includes("oxlint");
|
|
6179
6147
|
const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, serverDeploy, backend) : "";
|
|
6180
6148
|
const tauriInstructions = addons?.includes("tauri") ? getTauriInstructions(runCmd) : "";
|
|
6181
|
-
const
|
|
6149
|
+
const huskyInstructions = hasHusky ? getHuskyInstructions(runCmd) : "";
|
|
6150
|
+
const lintingInstructions = hasLinting ? getLintingInstructions(runCmd) : "";
|
|
6182
6151
|
const nativeInstructions = (frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles")) && backend !== "none" ? getNativeInstructions(isConvex, isBackendSelf, frontend || []) : "";
|
|
6183
6152
|
const pwaInstructions = addons?.includes("pwa") && frontend?.includes("react-router") ? getPwaInstructions() : "";
|
|
6184
6153
|
const starlightInstructions = addons?.includes("starlight") ? getStarlightInstructions(runCmd) : "";
|
|
@@ -6232,6 +6201,7 @@ async function displayPostInstallInstructions(config) {
|
|
|
6232
6201
|
if (nativeInstructions) output += `\n${nativeInstructions.trim()}\n`;
|
|
6233
6202
|
if (databaseInstructions) output += `\n${databaseInstructions.trim()}\n`;
|
|
6234
6203
|
if (tauriInstructions) output += `\n${tauriInstructions.trim()}\n`;
|
|
6204
|
+
if (huskyInstructions) output += `\n${huskyInstructions.trim()}\n`;
|
|
6235
6205
|
if (lintingInstructions) output += `\n${lintingInstructions.trim()}\n`;
|
|
6236
6206
|
if (pwaInstructions) output += `\n${pwaInstructions.trim()}\n`;
|
|
6237
6207
|
if (alchemyDeployInstructions) output += `\n${alchemyDeployInstructions.trim()}\n`;
|
|
@@ -6253,6 +6223,9 @@ function getNativeInstructions(isConvex, isBackendSelf, _frontend) {
|
|
|
6253
6223
|
if (isConvex) instructions += `\n${pc.yellow("IMPORTANT:")} When using local development with Convex and native apps,\n ensure you use your local IP address instead of localhost or 127.0.0.1\n for proper connectivity.\n`;
|
|
6254
6224
|
return instructions;
|
|
6255
6225
|
}
|
|
6226
|
+
function getHuskyInstructions(runCmd) {
|
|
6227
|
+
return `${pc.bold("Git hooks with Husky:")}\n${pc.cyan("•")} Initialize hooks: ${`${runCmd} prepare`}\n`;
|
|
6228
|
+
}
|
|
6256
6229
|
function getLintingInstructions(runCmd) {
|
|
6257
6230
|
return `${pc.bold("Linting and formatting:")}\n${pc.cyan("•")} Format and lint fix: ${`${runCmd} check`}\n`;
|
|
6258
6231
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-t-stack",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.9.0",
|
|
4
4
|
"description": "A modern CLI tool for scaffolding end-to-end type-safe TypeScript projects with best practices and customizable configurations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,8 +51,10 @@
|
|
|
51
51
|
"build": "tsdown --publint",
|
|
52
52
|
"dev": "tsdown --watch",
|
|
53
53
|
"check-types": "tsc --noEmit",
|
|
54
|
-
"test": "bun run build &&
|
|
55
|
-
"test:
|
|
54
|
+
"test": "bun run build && bun test",
|
|
55
|
+
"test:watch": "bun run build && bun test --watch",
|
|
56
|
+
"test:coverage": "bun run build && bun test --coverage",
|
|
57
|
+
"test:ci": "bun run build && AGENT=1 bun test --bail=5",
|
|
56
58
|
"prepublishOnly": "npm run build"
|
|
57
59
|
},
|
|
58
60
|
"exports": {
|
|
@@ -65,9 +67,7 @@
|
|
|
65
67
|
}
|
|
66
68
|
},
|
|
67
69
|
"dependencies": {
|
|
68
|
-
"@better-t-stack/types": "^3.
|
|
69
|
-
"@biomejs/js-api": "^4.0.0",
|
|
70
|
-
"@biomejs/wasm-nodejs": "^2.3.8",
|
|
70
|
+
"@better-t-stack/types": "^3.9.0",
|
|
71
71
|
"@clack/prompts": "^1.0.0-alpha.8",
|
|
72
72
|
"@orpc/server": "^1.12.2",
|
|
73
73
|
"consola": "^3.4.2",
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
"gradient-string": "^3.0.0",
|
|
77
77
|
"handlebars": "^4.7.8",
|
|
78
78
|
"jsonc-parser": "^3.3.1",
|
|
79
|
+
"oxfmt": "^0.19.0",
|
|
79
80
|
"picocolors": "^1.1.1",
|
|
80
81
|
"tinyglobby": "^0.2.15",
|
|
81
82
|
"trpc-cli": "^0.12.1",
|
|
@@ -84,12 +85,11 @@
|
|
|
84
85
|
"zod": "^4.1.13"
|
|
85
86
|
},
|
|
86
87
|
"devDependencies": {
|
|
88
|
+
"@types/bun": "^1.2.17",
|
|
87
89
|
"@types/fs-extra": "^11.0.4",
|
|
88
90
|
"@types/node": "^24.10.2",
|
|
89
|
-
"@vitest/ui": "^4.0.15",
|
|
90
91
|
"publint": "^0.3.16",
|
|
91
92
|
"tsdown": "^0.17.2",
|
|
92
|
-
"typescript": "^5.9.3"
|
|
93
|
-
"vitest": "^4.0.15"
|
|
93
|
+
"typescript": "^5.9.3"
|
|
94
94
|
}
|
|
95
95
|
}
|