create-better-fullstack 1.1.5 → 1.1.7
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/cli.mjs +1 -1
- package/dist/index.d.mts +7 -0
- package/dist/index.mjs +1 -1
- package/dist/{src-hrWVF5Yi.mjs → src-bp7xdTNG.mjs} +266 -70
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -467,6 +467,13 @@ declare const router: {
|
|
|
467
467
|
sponsors: _orpc_server0.Procedure<_orpc_server0.MergedInitialContext<Record<never, never>, Record<never, never>, Record<never, never>>, Record<never, never>, _orpc_server0.Schema<unknown, unknown>, _orpc_server0.Schema<void, void>, _orpc_server0.MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
|
|
468
468
|
docs: _orpc_server0.Procedure<_orpc_server0.MergedInitialContext<Record<never, never>, Record<never, never>, Record<never, never>>, Record<never, never>, _orpc_server0.Schema<unknown, unknown>, _orpc_server0.Schema<void, void>, _orpc_server0.MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
|
|
469
469
|
builder: _orpc_server0.Procedure<_orpc_server0.MergedInitialContext<Record<never, never>, Record<never, never>, Record<never, never>>, Record<never, never>, _orpc_server0.Schema<unknown, unknown>, _orpc_server0.Schema<void, void>, _orpc_server0.MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
|
|
470
|
+
"update-deps": _orpc_server0.Procedure<_orpc_server0.MergedInitialContext<Record<never, never>, Record<never, never>, Record<never, never>>, Record<never, never>, z.ZodObject<{
|
|
471
|
+
check: z.ZodDefault<z.ZodBoolean>;
|
|
472
|
+
patch: z.ZodDefault<z.ZodBoolean>;
|
|
473
|
+
all: z.ZodDefault<z.ZodBoolean>;
|
|
474
|
+
ecosystem: z.ZodOptional<z.ZodString>;
|
|
475
|
+
"list-ecosystems": z.ZodDefault<z.ZodBoolean>;
|
|
476
|
+
}, z.core.$strip>, _orpc_server0.Schema<void, void>, _orpc_server0.MergedErrorMap<Record<never, never>, Record<never, never>>, Record<never, never>>;
|
|
470
477
|
};
|
|
471
478
|
declare function createBtsCli(): trpc_cli0.TrpcCli;
|
|
472
479
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as create, c as docs, d as sponsors, i as builder, l as generateVirtualProject, n as TEMPLATE_COUNT, o as createBtsCli, r as VirtualFileSystem, s as createVirtual, t as EMBEDDED_TEMPLATES, u as router } from "./src-
|
|
2
|
+
import { a as create, c as docs, d as sponsors, i as builder, l as generateVirtualProject, n as TEMPLATE_COUNT, o as createBtsCli, r as VirtualFileSystem, s as createVirtual, t as EMBEDDED_TEMPLATES, u as router } from "./src-bp7xdTNG.mjs";
|
|
3
3
|
|
|
4
4
|
export { EMBEDDED_TEMPLATES, TEMPLATE_COUNT, VirtualFileSystem, builder, create, createBtsCli, createVirtual, docs, generateVirtualProject, router, sponsors };
|
|
@@ -5,11 +5,12 @@ import { createRouterClient, os } from "@orpc/server";
|
|
|
5
5
|
import pc from "picocolors";
|
|
6
6
|
import { createCli } from "trpc-cli";
|
|
7
7
|
import z from "zod";
|
|
8
|
-
import
|
|
8
|
+
import { ECOSYSTEM_GROUPS, EMBEDDED_TEMPLATES, EMBEDDED_TEMPLATES as EMBEDDED_TEMPLATES$1, TEMPLATE_COUNT, VirtualFileSystem, checkAllVersions, dependencyVersionMap, generateCliReport, generateVirtualProject, generateVirtualProject as generateVirtualProject$1, listEcosystems } from "@better-fullstack/template-generator";
|
|
9
9
|
import fs from "fs-extra";
|
|
10
|
-
import path from "
|
|
10
|
+
import path from "path";
|
|
11
|
+
import consola, { consola as consola$1 } from "consola";
|
|
12
|
+
import path$1 from "node:path";
|
|
11
13
|
import { fileURLToPath } from "node:url";
|
|
12
|
-
import { EMBEDDED_TEMPLATES, EMBEDDED_TEMPLATES as EMBEDDED_TEMPLATES$1, TEMPLATE_COUNT, VirtualFileSystem, dependencyVersionMap, generateVirtualProject, generateVirtualProject as generateVirtualProject$1 } from "@better-fullstack/template-generator";
|
|
13
14
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
14
15
|
import { ConfirmPrompt, GroupMultiSelectPrompt, MultiSelectPrompt, SelectPrompt, isCancel as isCancel$1 } from "@clack/core";
|
|
15
16
|
import gradient from "gradient-string";
|
|
@@ -19,6 +20,183 @@ import * as JSONC from "jsonc-parser";
|
|
|
19
20
|
import { format } from "oxfmt";
|
|
20
21
|
import os$1 from "node:os";
|
|
21
22
|
|
|
23
|
+
//#region src/commands/update-deps.ts
|
|
24
|
+
/**
|
|
25
|
+
* CLI command to check and update dependency versions
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Format a version update for display
|
|
29
|
+
*/
|
|
30
|
+
function formatUpdate(info) {
|
|
31
|
+
const colorFn = {
|
|
32
|
+
major: pc.red,
|
|
33
|
+
minor: pc.yellow,
|
|
34
|
+
patch: pc.green,
|
|
35
|
+
none: pc.gray
|
|
36
|
+
}[info.updateType];
|
|
37
|
+
return `${colorFn(`[${info.updateType.toUpperCase()}]`.padEnd(8))} ${pc.cyan(info.name.padEnd(45))} ${pc.dim(info.current)} ${pc.dim("->")} ${pc.green(info.latest)}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get the path to add-deps.ts
|
|
41
|
+
*/
|
|
42
|
+
function getAddDepsPath() {
|
|
43
|
+
const possiblePaths = [
|
|
44
|
+
path.join(process.cwd(), "packages/template-generator/src/utils/add-deps.ts"),
|
|
45
|
+
path.join(process.cwd(), "../../packages/template-generator/src/utils/add-deps.ts"),
|
|
46
|
+
path.join(process.cwd(), "node_modules/@better-fullstack/template-generator/src/utils/add-deps.ts")
|
|
47
|
+
];
|
|
48
|
+
for (const p of possiblePaths) if (fs.existsSync(p)) return p;
|
|
49
|
+
return possiblePaths[0];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Update the add-deps.ts file with new versions
|
|
53
|
+
*/
|
|
54
|
+
async function updateAddDepsFile(updates) {
|
|
55
|
+
const filePath = getAddDepsPath();
|
|
56
|
+
if (!fs.existsSync(filePath)) {
|
|
57
|
+
log.error(`Could not find add-deps.ts at ${filePath}`);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
let content = await fs.readFile(filePath, "utf-8");
|
|
61
|
+
let updated = false;
|
|
62
|
+
for (const update of updates) {
|
|
63
|
+
const escapedName = update.name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
64
|
+
const pattern = new RegExp(`(["']${escapedName}["']:\\s*["'])([^"']+)(["'])`, "g");
|
|
65
|
+
const newContent = content.replace(pattern, `$1${update.latest}$3`);
|
|
66
|
+
if (newContent !== content) {
|
|
67
|
+
content = newContent;
|
|
68
|
+
updated = true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (updated) {
|
|
72
|
+
await fs.writeFile(filePath, content, "utf-8");
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Interactive mode: prompt for each update
|
|
79
|
+
*/
|
|
80
|
+
async function interactiveUpdate(updates) {
|
|
81
|
+
const toApply = [];
|
|
82
|
+
for (const update of updates) {
|
|
83
|
+
console.log("\n" + pc.bold("-----------------------------------"));
|
|
84
|
+
console.log(formatUpdate(update));
|
|
85
|
+
if (update.ecosystem) console.log(pc.dim(` Ecosystem: ${update.ecosystem}`));
|
|
86
|
+
if (update.updateType === "major") console.log(pc.yellow(" Warning: Breaking changes possible. Check changelog."));
|
|
87
|
+
const action = await select({
|
|
88
|
+
message: "What would you like to do?",
|
|
89
|
+
options: [
|
|
90
|
+
{
|
|
91
|
+
value: "update",
|
|
92
|
+
label: "Update to latest"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
value: "skip",
|
|
96
|
+
label: "Skip this package"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
value: "quit",
|
|
100
|
+
label: "Quit (apply selected updates)"
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
});
|
|
104
|
+
if (isCancel(action) || action === "quit") break;
|
|
105
|
+
if (action === "update") toApply.push(update);
|
|
106
|
+
}
|
|
107
|
+
return toApply;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Main handler for the update-deps command
|
|
111
|
+
*/
|
|
112
|
+
async function updateDepsHandler(options) {
|
|
113
|
+
const { check = false, patch = false, all = false, ecosystem } = options;
|
|
114
|
+
if (ecosystem) {
|
|
115
|
+
const validEcosystems = listEcosystems();
|
|
116
|
+
if (!validEcosystems.includes(ecosystem)) {
|
|
117
|
+
log.error(`Invalid ecosystem: ${ecosystem}. Valid options: ${validEcosystems.join(", ")}`);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const s = spinner();
|
|
122
|
+
s.start(ecosystem ? `Checking ${ecosystem} packages for updates...` : "Checking all packages for updates...");
|
|
123
|
+
let result;
|
|
124
|
+
try {
|
|
125
|
+
result = await checkAllVersions({
|
|
126
|
+
ecosystem,
|
|
127
|
+
concurrency: 5,
|
|
128
|
+
delayMs: 100,
|
|
129
|
+
onProgress: (checked, total, current) => {
|
|
130
|
+
s.message(`Checking packages (${checked}/${total})...`);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
} catch (error) {
|
|
134
|
+
s.stop("Failed to check versions");
|
|
135
|
+
log.error(String(error));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
s.stop("Version check complete");
|
|
139
|
+
console.log(generateCliReport(result));
|
|
140
|
+
if (check || result.outdated.length === 0) return;
|
|
141
|
+
let toApply = [];
|
|
142
|
+
if (patch) {
|
|
143
|
+
toApply = result.outdated.filter((u) => u.updateType === "patch" || u.updateType === "minor");
|
|
144
|
+
if (toApply.length === 0) {
|
|
145
|
+
log.info("No patch/minor updates available.");
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
log.info(`Found ${toApply.length} patch/minor updates to apply automatically.`);
|
|
149
|
+
const shouldProceed = await confirm({ message: `Apply ${toApply.length} safe updates?` });
|
|
150
|
+
if (isCancel(shouldProceed) || !shouldProceed) {
|
|
151
|
+
log.info("Cancelled.");
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
} else if (all) {
|
|
155
|
+
log.info("\nEntering interactive mode...");
|
|
156
|
+
toApply = await interactiveUpdate(result.outdated);
|
|
157
|
+
if (toApply.length === 0) {
|
|
158
|
+
log.info("No updates selected.");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
} else {
|
|
162
|
+
const shouldProceed = await confirm({ message: `Apply all ${result.outdated.length} updates?` });
|
|
163
|
+
if (isCancel(shouldProceed) || !shouldProceed) {
|
|
164
|
+
log.info("Cancelled. Use --check to only view updates without prompting.");
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
toApply = result.outdated;
|
|
168
|
+
}
|
|
169
|
+
const updateSpinner = spinner();
|
|
170
|
+
updateSpinner.start(`Applying ${toApply.length} updates...`);
|
|
171
|
+
try {
|
|
172
|
+
if (await updateAddDepsFile(toApply)) {
|
|
173
|
+
updateSpinner.stop("Updates applied successfully!");
|
|
174
|
+
console.log("\n" + pc.green("Updated packages:"));
|
|
175
|
+
for (const update of toApply) console.log(` ${pc.cyan(update.name)}: ${update.current} -> ${update.latest}`);
|
|
176
|
+
console.log("\n" + pc.yellow("Next steps:"));
|
|
177
|
+
console.log(" 1. Review the changes in add-deps.ts");
|
|
178
|
+
console.log(" 2. Run: bun run build (in packages/template-generator)");
|
|
179
|
+
console.log(" 3. Run tests to verify compatibility");
|
|
180
|
+
console.log(" 4. Update any hardcoded versions in template files");
|
|
181
|
+
} else {
|
|
182
|
+
updateSpinner.stop("No changes were made");
|
|
183
|
+
log.warn("Could not apply updates. The file may have changed.");
|
|
184
|
+
}
|
|
185
|
+
} catch (error) {
|
|
186
|
+
updateSpinner.stop("Failed to apply updates");
|
|
187
|
+
log.error(String(error));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Show available ecosystems
|
|
192
|
+
*/
|
|
193
|
+
function showEcosystems() {
|
|
194
|
+
console.log("\nAvailable ecosystems:\n");
|
|
195
|
+
for (const [name, packages] of Object.entries(ECOSYSTEM_GROUPS)) console.log(` ${pc.cyan(name.padEnd(15))} (${packages.length} packages)`);
|
|
196
|
+
console.log(`\nUsage: update-deps --ecosystem <name>`);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
//#endregion
|
|
22
200
|
//#region src/utils/get-package-manager.ts
|
|
23
201
|
const getUserPkgManager = () => {
|
|
24
202
|
const userAgent = process.env.npm_config_user_agent;
|
|
@@ -30,8 +208,8 @@ const getUserPkgManager = () => {
|
|
|
30
208
|
//#endregion
|
|
31
209
|
//#region src/constants.ts
|
|
32
210
|
const __filename = fileURLToPath(import.meta.url);
|
|
33
|
-
const distPath = path.dirname(__filename);
|
|
34
|
-
const PKG_ROOT = path.join(distPath, "../");
|
|
211
|
+
const distPath = path$1.dirname(__filename);
|
|
212
|
+
const PKG_ROOT = path$1.join(distPath, "../");
|
|
35
213
|
const DEFAULT_CONFIG_BASE = {
|
|
36
214
|
projectName: "my-better-t-app",
|
|
37
215
|
relativePath: "my-better-t-app",
|
|
@@ -78,7 +256,7 @@ const DEFAULT_CONFIG_BASE = {
|
|
|
78
256
|
function getDefaultConfig() {
|
|
79
257
|
return {
|
|
80
258
|
...DEFAULT_CONFIG_BASE,
|
|
81
|
-
projectDir: path.resolve(process.cwd(), DEFAULT_CONFIG_BASE.projectName),
|
|
259
|
+
projectDir: path$1.resolve(process.cwd(), DEFAULT_CONFIG_BASE.projectName),
|
|
82
260
|
packageManager: getUserPkgManager(),
|
|
83
261
|
frontend: [...DEFAULT_CONFIG_BASE.frontend],
|
|
84
262
|
addons: [...DEFAULT_CONFIG_BASE.addons],
|
|
@@ -3036,9 +3214,9 @@ async function gatherConfig(flags, projectName, projectDir, relativePath) {
|
|
|
3036
3214
|
//#endregion
|
|
3037
3215
|
//#region src/prompts/project-name.ts
|
|
3038
3216
|
function isPathWithinCwd(targetPath) {
|
|
3039
|
-
const resolved = path.resolve(targetPath);
|
|
3040
|
-
const rel = path.relative(process.cwd(), resolved);
|
|
3041
|
-
return !rel.startsWith("..") && !path.isAbsolute(rel);
|
|
3217
|
+
const resolved = path$1.resolve(targetPath);
|
|
3218
|
+
const rel = path$1.relative(process.cwd(), resolved);
|
|
3219
|
+
return !rel.startsWith("..") && !path$1.isAbsolute(rel);
|
|
3042
3220
|
}
|
|
3043
3221
|
function validateDirectoryName(name) {
|
|
3044
3222
|
if (name === ".") return void 0;
|
|
@@ -3048,8 +3226,8 @@ function validateDirectoryName(name) {
|
|
|
3048
3226
|
async function getProjectName(initialName) {
|
|
3049
3227
|
if (initialName) {
|
|
3050
3228
|
if (initialName === ".") return initialName;
|
|
3051
|
-
if (!validateDirectoryName(path.basename(initialName))) {
|
|
3052
|
-
if (isPathWithinCwd(path.resolve(process.cwd(), initialName))) return initialName;
|
|
3229
|
+
if (!validateDirectoryName(path$1.basename(initialName))) {
|
|
3230
|
+
if (isPathWithinCwd(path$1.resolve(process.cwd(), initialName))) return initialName;
|
|
3053
3231
|
consola.error(pc.red("Project path must be within current directory"));
|
|
3054
3232
|
}
|
|
3055
3233
|
}
|
|
@@ -3057,7 +3235,7 @@ async function getProjectName(initialName) {
|
|
|
3057
3235
|
let projectPath = "";
|
|
3058
3236
|
let defaultName = DEFAULT_CONFIG.projectName;
|
|
3059
3237
|
let counter = 1;
|
|
3060
|
-
while (await fs.pathExists(path.resolve(process.cwd(), defaultName)) && (await fs.readdir(path.resolve(process.cwd(), defaultName))).length > 0) {
|
|
3238
|
+
while (await fs.pathExists(path$1.resolve(process.cwd(), defaultName)) && (await fs.readdir(path$1.resolve(process.cwd(), defaultName))).length > 0) {
|
|
3061
3239
|
defaultName = `${DEFAULT_CONFIG.projectName}-${counter}`;
|
|
3062
3240
|
counter++;
|
|
3063
3241
|
}
|
|
@@ -3069,10 +3247,10 @@ async function getProjectName(initialName) {
|
|
|
3069
3247
|
defaultValue: defaultName,
|
|
3070
3248
|
validate: (value) => {
|
|
3071
3249
|
const nameToUse = String(value ?? "").trim() || defaultName;
|
|
3072
|
-
const validationError = validateDirectoryName(path.basename(nameToUse));
|
|
3250
|
+
const validationError = validateDirectoryName(path$1.basename(nameToUse));
|
|
3073
3251
|
if (validationError) return validationError;
|
|
3074
3252
|
if (nameToUse !== ".") {
|
|
3075
|
-
if (!isPathWithinCwd(path.resolve(process.cwd(), nameToUse))) return "Project path must be within current directory";
|
|
3253
|
+
if (!isPathWithinCwd(path$1.resolve(process.cwd(), nameToUse))) return "Project path must be within current directory";
|
|
3076
3254
|
}
|
|
3077
3255
|
}
|
|
3078
3256
|
});
|
|
@@ -3086,7 +3264,7 @@ async function getProjectName(initialName) {
|
|
|
3086
3264
|
//#endregion
|
|
3087
3265
|
//#region src/utils/get-latest-cli-version.ts
|
|
3088
3266
|
const getLatestCLIVersion = () => {
|
|
3089
|
-
const packageJsonPath = path.join(PKG_ROOT, "package.json");
|
|
3267
|
+
const packageJsonPath = path$1.join(PKG_ROOT, "package.json");
|
|
3090
3268
|
return fs.readJSONSync(packageJsonPath).version ?? "1.0.0";
|
|
3091
3269
|
};
|
|
3092
3270
|
|
|
@@ -3108,7 +3286,7 @@ function isTelemetryEnabled() {
|
|
|
3108
3286
|
|
|
3109
3287
|
//#endregion
|
|
3110
3288
|
//#region src/utils/analytics.ts
|
|
3111
|
-
const CONVEX_INGEST_URL = "https://
|
|
3289
|
+
const CONVEX_INGEST_URL = "https://curious-elephant-653.convex.site/api/analytics/ingest";
|
|
3112
3290
|
async function sendConvexEvent(payload) {
|
|
3113
3291
|
try {
|
|
3114
3292
|
await fetch(CONVEX_INGEST_URL, {
|
|
@@ -3216,7 +3394,7 @@ function generateReproducibleCommand(config) {
|
|
|
3216
3394
|
//#region src/utils/project-directory.ts
|
|
3217
3395
|
async function handleDirectoryConflict(currentPathInput) {
|
|
3218
3396
|
while (true) {
|
|
3219
|
-
const resolvedPath = path.resolve(process.cwd(), currentPathInput);
|
|
3397
|
+
const resolvedPath = path$1.resolve(process.cwd(), currentPathInput);
|
|
3220
3398
|
if (!(await fs.pathExists(resolvedPath) && (await fs.readdir(resolvedPath)).length > 0)) return {
|
|
3221
3399
|
finalPathInput: currentPathInput,
|
|
3222
3400
|
shouldClearDirectory: false
|
|
@@ -3273,10 +3451,10 @@ async function setupProjectDirectory(finalPathInput, shouldClearDirectory) {
|
|
|
3273
3451
|
let finalBaseName;
|
|
3274
3452
|
if (finalPathInput === ".") {
|
|
3275
3453
|
finalResolvedPath = process.cwd();
|
|
3276
|
-
finalBaseName = path.basename(finalResolvedPath);
|
|
3454
|
+
finalBaseName = path$1.basename(finalResolvedPath);
|
|
3277
3455
|
} else {
|
|
3278
|
-
finalResolvedPath = path.resolve(process.cwd(), finalPathInput);
|
|
3279
|
-
finalBaseName = path.basename(finalResolvedPath);
|
|
3456
|
+
finalResolvedPath = path$1.resolve(process.cwd(), finalPathInput);
|
|
3457
|
+
finalBaseName = path$1.basename(finalResolvedPath);
|
|
3280
3458
|
}
|
|
3281
3459
|
if (shouldClearDirectory) {
|
|
3282
3460
|
const s = spinner();
|
|
@@ -3415,7 +3593,7 @@ function processArrayOption(options) {
|
|
|
3415
3593
|
}
|
|
3416
3594
|
function deriveProjectName(projectName, projectDirectory) {
|
|
3417
3595
|
if (projectName) return projectName;
|
|
3418
|
-
if (projectDirectory) return path.basename(path.resolve(process.cwd(), projectDirectory));
|
|
3596
|
+
if (projectDirectory) return path$1.basename(path$1.resolve(process.cwd(), projectDirectory));
|
|
3419
3597
|
return "";
|
|
3420
3598
|
}
|
|
3421
3599
|
function processFlags(options, projectName) {
|
|
@@ -3678,9 +3856,9 @@ function validateProjectNameThrow(name) {
|
|
|
3678
3856
|
if (!result.success) throw new Error(`Invalid project name: ${result.error.issues[0]?.message}`);
|
|
3679
3857
|
}
|
|
3680
3858
|
function extractAndValidateProjectName(projectName, projectDirectory, throwOnError = false) {
|
|
3681
|
-
const derivedName = projectName || (projectDirectory ? path.basename(path.resolve(process.cwd(), projectDirectory)) : "");
|
|
3859
|
+
const derivedName = projectName || (projectDirectory ? path$1.basename(path$1.resolve(process.cwd(), projectDirectory)) : "");
|
|
3682
3860
|
if (!derivedName) return "";
|
|
3683
|
-
const nameToValidate = projectName ? path.basename(projectName) : derivedName;
|
|
3861
|
+
const nameToValidate = projectName ? path$1.basename(projectName) : derivedName;
|
|
3684
3862
|
if (throwOnError) validateProjectNameThrow(nameToValidate);
|
|
3685
3863
|
else validateProjectName(nameToValidate);
|
|
3686
3864
|
return projectName || derivedName;
|
|
@@ -3844,7 +4022,7 @@ async function writeBtsConfig(projectConfig) {
|
|
|
3844
4022
|
// safe to delete
|
|
3845
4023
|
|
|
3846
4024
|
${configContent}`;
|
|
3847
|
-
const configPath = path.join(projectConfig.projectDir, BTS_CONFIG_FILE);
|
|
4025
|
+
const configPath = path$1.join(projectConfig.projectDir, BTS_CONFIG_FILE);
|
|
3848
4026
|
await fs.writeFile(configPath, finalContent, "utf-8");
|
|
3849
4027
|
}
|
|
3850
4028
|
|
|
@@ -3856,7 +4034,7 @@ const formatOptions = {
|
|
|
3856
4034
|
};
|
|
3857
4035
|
async function formatCode(filePath, content) {
|
|
3858
4036
|
try {
|
|
3859
|
-
const result = await format(path.basename(filePath), content, formatOptions);
|
|
4037
|
+
const result = await format(path$1.basename(filePath), content, formatOptions);
|
|
3860
4038
|
if (result.errors && result.errors.length > 0) return null;
|
|
3861
4039
|
return result.code;
|
|
3862
4040
|
} catch {
|
|
@@ -3867,7 +4045,7 @@ async function formatProject(projectDir) {
|
|
|
3867
4045
|
async function formatDirectory(dir) {
|
|
3868
4046
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
3869
4047
|
await Promise.all(entries.map(async (entry) => {
|
|
3870
|
-
const fullPath = path.join(dir, entry.name);
|
|
4048
|
+
const fullPath = path$1.join(dir, entry.name);
|
|
3871
4049
|
if (entry.isDirectory()) await formatDirectory(fullPath);
|
|
3872
4050
|
else if (entry.isFile()) try {
|
|
3873
4051
|
const content = await fs.readFile(fullPath, "utf-8");
|
|
@@ -3883,7 +4061,7 @@ async function formatProject(projectDir) {
|
|
|
3883
4061
|
//#region src/utils/add-package-deps.ts
|
|
3884
4062
|
const addPackageDependency = async (opts) => {
|
|
3885
4063
|
const { dependencies = [], devDependencies = [], customDependencies = {}, customDevDependencies = {}, projectDir } = opts;
|
|
3886
|
-
const pkgJsonPath = path.join(projectDir, "package.json");
|
|
4064
|
+
const pkgJsonPath = path$1.join(projectDir, "package.json");
|
|
3887
4065
|
const pkgJson = await fs.readJson(pkgJsonPath);
|
|
3888
4066
|
if (!pkgJson.dependencies) pkgJson.dependencies = {};
|
|
3889
4067
|
if (!pkgJson.devDependencies) pkgJson.devDependencies = {};
|
|
@@ -4003,7 +4181,7 @@ async function setupFumadocs(config) {
|
|
|
4003
4181
|
});
|
|
4004
4182
|
if (isCancel(template)) return exitCancelled("Operation cancelled");
|
|
4005
4183
|
const args = getPackageExecutionArgs(packageManager, `create-fumadocs-app@latest fumadocs --template ${TEMPLATES$2[template].value} --src --pm ${packageManager} --no-git`);
|
|
4006
|
-
const appsDir = path.join(projectDir, "apps");
|
|
4184
|
+
const appsDir = path$1.join(projectDir, "apps");
|
|
4007
4185
|
await fs.ensureDir(appsDir);
|
|
4008
4186
|
const s = spinner();
|
|
4009
4187
|
s.start("Running Fumadocs create command...");
|
|
@@ -4011,8 +4189,8 @@ async function setupFumadocs(config) {
|
|
|
4011
4189
|
cwd: appsDir,
|
|
4012
4190
|
env: { CI: "true" }
|
|
4013
4191
|
})`${args}`;
|
|
4014
|
-
const fumadocsDir = path.join(projectDir, "apps", "fumadocs");
|
|
4015
|
-
const packageJsonPath = path.join(fumadocsDir, "package.json");
|
|
4192
|
+
const fumadocsDir = path$1.join(projectDir, "apps", "fumadocs");
|
|
4193
|
+
const packageJsonPath = path$1.join(fumadocsDir, "package.json");
|
|
4016
4194
|
if (await fs.pathExists(packageJsonPath)) {
|
|
4017
4195
|
const packageJson = await fs.readJson(packageJsonPath);
|
|
4018
4196
|
packageJson.name = "fumadocs";
|
|
@@ -4033,7 +4211,7 @@ async function setupOxlint(projectDir, packageManager) {
|
|
|
4033
4211
|
devDependencies: ["oxlint", "oxfmt"],
|
|
4034
4212
|
projectDir
|
|
4035
4213
|
});
|
|
4036
|
-
const packageJsonPath = path.join(projectDir, "package.json");
|
|
4214
|
+
const packageJsonPath = path$1.join(projectDir, "package.json");
|
|
4037
4215
|
if (await fs.pathExists(packageJsonPath)) {
|
|
4038
4216
|
const packageJson = await fs.readJson(packageJsonPath);
|
|
4039
4217
|
packageJson.scripts = {
|
|
@@ -4063,7 +4241,7 @@ async function setupRuler(config) {
|
|
|
4063
4241
|
const { packageManager, projectDir } = config;
|
|
4064
4242
|
try {
|
|
4065
4243
|
log.info("Setting up Ruler...");
|
|
4066
|
-
const rulerDir = path.join(projectDir, ".ruler");
|
|
4244
|
+
const rulerDir = path$1.join(projectDir, ".ruler");
|
|
4067
4245
|
if (!await fs.pathExists(rulerDir)) {
|
|
4068
4246
|
log.error(pc.red("Ruler template directory not found. Please ensure ruler addon is properly installed."));
|
|
4069
4247
|
return;
|
|
@@ -4112,7 +4290,7 @@ async function setupRuler(config) {
|
|
|
4112
4290
|
log.info(pc.cyan(`${getPackageExecutionCommand(packageManager, "@intellectronica/ruler@latest apply --local-only")}`));
|
|
4113
4291
|
return;
|
|
4114
4292
|
}
|
|
4115
|
-
const configFile = path.join(rulerDir, "ruler.toml");
|
|
4293
|
+
const configFile = path$1.join(rulerDir, "ruler.toml");
|
|
4116
4294
|
let updatedConfig = await fs.readFile(configFile, "utf-8");
|
|
4117
4295
|
const defaultAgentsLine = `default_agents = [${selectedEditors.map((editor) => `"${editor}"`).join(", ")}]`;
|
|
4118
4296
|
updatedConfig = updatedConfig.replace(/default_agents = \[\]/, defaultAgentsLine);
|
|
@@ -4136,7 +4314,7 @@ async function setupRuler(config) {
|
|
|
4136
4314
|
}
|
|
4137
4315
|
}
|
|
4138
4316
|
async function addRulerScriptToPackageJson(projectDir, packageManager) {
|
|
4139
|
-
const rootPackageJsonPath = path.join(projectDir, "package.json");
|
|
4317
|
+
const rootPackageJsonPath = path$1.join(projectDir, "package.json");
|
|
4140
4318
|
if (!await fs.pathExists(rootPackageJsonPath)) {
|
|
4141
4319
|
log.warn("Root package.json not found, skipping ruler:apply script addition");
|
|
4142
4320
|
return;
|
|
@@ -4165,7 +4343,7 @@ async function setupStarlight(config) {
|
|
|
4165
4343
|
"--no-git",
|
|
4166
4344
|
"--skip-houston"
|
|
4167
4345
|
].join(" ")}`);
|
|
4168
|
-
const appsDir = path.join(projectDir, "apps");
|
|
4346
|
+
const appsDir = path$1.join(projectDir, "apps");
|
|
4169
4347
|
await fs.ensureDir(appsDir);
|
|
4170
4348
|
await $({
|
|
4171
4349
|
cwd: appsDir,
|
|
@@ -4183,7 +4361,7 @@ async function setupStarlight(config) {
|
|
|
4183
4361
|
async function setupTauri(config) {
|
|
4184
4362
|
const { packageManager, frontend, projectDir } = config;
|
|
4185
4363
|
const s = spinner();
|
|
4186
|
-
const clientPackageDir = path.join(projectDir, "apps/web");
|
|
4364
|
+
const clientPackageDir = path$1.join(projectDir, "apps/web");
|
|
4187
4365
|
if (!await fs.pathExists(clientPackageDir)) return;
|
|
4188
4366
|
try {
|
|
4189
4367
|
s.start("Setting up Tauri desktop app support...");
|
|
@@ -4196,8 +4374,8 @@ async function setupTauri(config) {
|
|
|
4196
4374
|
const tauriArgs = [
|
|
4197
4375
|
"@tauri-apps/cli@latest",
|
|
4198
4376
|
"init",
|
|
4199
|
-
`--app-name=${path.basename(projectDir)}`,
|
|
4200
|
-
`--window-title=${path.basename(projectDir)}`,
|
|
4377
|
+
`--app-name=${path$1.basename(projectDir)}`,
|
|
4378
|
+
`--window-title=${path$1.basename(projectDir)}`,
|
|
4201
4379
|
`--frontend-dist=${frontendDist}`,
|
|
4202
4380
|
`--dev-url=${devUrl}`,
|
|
4203
4381
|
`--before-dev-command=${packageManager} run dev`,
|
|
@@ -4246,7 +4424,7 @@ async function setupTui(config) {
|
|
|
4246
4424
|
});
|
|
4247
4425
|
if (isCancel(template)) return exitCancelled("Operation cancelled");
|
|
4248
4426
|
const args = getPackageExecutionArgs(packageManager, `create-tui@latest --template ${template} --no-git --no-install tui`);
|
|
4249
|
-
const appsDir = path.join(projectDir, "apps");
|
|
4427
|
+
const appsDir = path$1.join(projectDir, "apps");
|
|
4250
4428
|
await fs.ensureDir(appsDir);
|
|
4251
4429
|
const s = spinner();
|
|
4252
4430
|
s.start("Running OpenTUI create command...");
|
|
@@ -4450,7 +4628,7 @@ async function setupWxt(config) {
|
|
|
4450
4628
|
});
|
|
4451
4629
|
if (isCancel(template)) return exitCancelled("Operation cancelled");
|
|
4452
4630
|
const args = getPackageExecutionArgs(packageManager, `wxt@latest init extension --template ${template} --pm ${packageManager}`);
|
|
4453
|
-
const appsDir = path.join(projectDir, "apps");
|
|
4631
|
+
const appsDir = path$1.join(projectDir, "apps");
|
|
4454
4632
|
await fs.ensureDir(appsDir);
|
|
4455
4633
|
const s = spinner();
|
|
4456
4634
|
s.start("Running WXT init command...");
|
|
@@ -4458,8 +4636,8 @@ async function setupWxt(config) {
|
|
|
4458
4636
|
cwd: appsDir,
|
|
4459
4637
|
env: { CI: "true" }
|
|
4460
4638
|
})`${args}`;
|
|
4461
|
-
const extensionDir = path.join(projectDir, "apps", "extension");
|
|
4462
|
-
const packageJsonPath = path.join(extensionDir, "package.json");
|
|
4639
|
+
const extensionDir = path$1.join(projectDir, "apps", "extension");
|
|
4640
|
+
const packageJsonPath = path$1.join(extensionDir, "package.json");
|
|
4463
4641
|
if (await fs.pathExists(packageJsonPath)) {
|
|
4464
4642
|
const packageJson = await fs.readJson(packageJsonPath);
|
|
4465
4643
|
packageJson.name = "extension";
|
|
@@ -4515,7 +4693,7 @@ async function setupBiome(projectDir) {
|
|
|
4515
4693
|
devDependencies: ["@biomejs/biome"],
|
|
4516
4694
|
projectDir
|
|
4517
4695
|
});
|
|
4518
|
-
const packageJsonPath = path.join(projectDir, "package.json");
|
|
4696
|
+
const packageJsonPath = path$1.join(projectDir, "package.json");
|
|
4519
4697
|
if (await fs.pathExists(packageJsonPath)) {
|
|
4520
4698
|
const packageJson = await fs.readJson(packageJsonPath);
|
|
4521
4699
|
packageJson.scripts = {
|
|
@@ -4530,7 +4708,7 @@ async function setupHusky(projectDir, linter) {
|
|
|
4530
4708
|
devDependencies: ["husky", "lint-staged"],
|
|
4531
4709
|
projectDir
|
|
4532
4710
|
});
|
|
4533
|
-
const packageJsonPath = path.join(projectDir, "package.json");
|
|
4711
|
+
const packageJsonPath = path$1.join(projectDir, "package.json");
|
|
4534
4712
|
if (await fs.pathExists(packageJsonPath)) {
|
|
4535
4713
|
const packageJson = await fs.readJson(packageJsonPath);
|
|
4536
4714
|
packageJson.scripts = {
|
|
@@ -4586,14 +4764,14 @@ async function setupCloudflareD1(config) {
|
|
|
4586
4764
|
const { projectDir, serverDeploy, orm, backend } = config;
|
|
4587
4765
|
if (serverDeploy === "cloudflare" && orm === "prisma") {
|
|
4588
4766
|
const targetApp2 = backend === "self" ? "apps/web" : "apps/server";
|
|
4589
|
-
await addEnvVariablesToFile(path.join(projectDir, targetApp2, ".env"), [{
|
|
4767
|
+
await addEnvVariablesToFile(path$1.join(projectDir, targetApp2, ".env"), [{
|
|
4590
4768
|
key: "DATABASE_URL",
|
|
4591
|
-
value: `file:${path.join(projectDir, "apps/server", "local.db")}`,
|
|
4769
|
+
value: `file:${path$1.join(projectDir, "apps/server", "local.db")}`,
|
|
4592
4770
|
condition: true
|
|
4593
4771
|
}]);
|
|
4594
4772
|
await addPackageDependency({
|
|
4595
4773
|
dependencies: ["@prisma/adapter-d1"],
|
|
4596
|
-
projectDir: path.join(projectDir, backend === "self" ? "apps/web" : "apps/server")
|
|
4774
|
+
projectDir: path$1.join(projectDir, backend === "self" ? "apps/web" : "apps/server")
|
|
4597
4775
|
});
|
|
4598
4776
|
}
|
|
4599
4777
|
}
|
|
@@ -4611,7 +4789,7 @@ async function setupDockerCompose(config) {
|
|
|
4611
4789
|
}
|
|
4612
4790
|
async function writeEnvFile$4(projectDir, database, projectName, backend) {
|
|
4613
4791
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
4614
|
-
await addEnvVariablesToFile(path.join(projectDir, targetApp, ".env"), [{
|
|
4792
|
+
await addEnvVariablesToFile(path$1.join(projectDir, targetApp, ".env"), [{
|
|
4615
4793
|
key: "DATABASE_URL",
|
|
4616
4794
|
value: getDatabaseUrl(database, projectName),
|
|
4617
4795
|
condition: true
|
|
@@ -4684,7 +4862,7 @@ async function initMongoDBAtlas(serverDir) {
|
|
|
4684
4862
|
async function writeEnvFile$3(projectDir, backend, config) {
|
|
4685
4863
|
try {
|
|
4686
4864
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
4687
|
-
await addEnvVariablesToFile(path.join(projectDir, targetApp, ".env"), [{
|
|
4865
|
+
await addEnvVariablesToFile(path$1.join(projectDir, targetApp, ".env"), [{
|
|
4688
4866
|
key: "DATABASE_URL",
|
|
4689
4867
|
value: config?.connectionString ?? "mongodb://localhost:27017/mydb",
|
|
4690
4868
|
condition: true
|
|
@@ -4713,7 +4891,7 @@ ${pc.green("MongoDB Atlas Manual Setup Instructions:")}
|
|
|
4713
4891
|
async function setupMongoDBAtlas(config, cliInput) {
|
|
4714
4892
|
const { projectDir, backend } = config;
|
|
4715
4893
|
const manualDb = cliInput?.manualDb ?? false;
|
|
4716
|
-
const serverDir = path.join(projectDir, "packages/db");
|
|
4894
|
+
const serverDir = path$1.join(projectDir, "packages/db");
|
|
4717
4895
|
try {
|
|
4718
4896
|
await fs.ensureDir(serverDir);
|
|
4719
4897
|
if (manualDb) {
|
|
@@ -4832,7 +5010,7 @@ async function createNeonProject(projectName, regionId, packageManager) {
|
|
|
4832
5010
|
}
|
|
4833
5011
|
async function writeEnvFile$2(projectDir, backend, config) {
|
|
4834
5012
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
4835
|
-
await addEnvVariablesToFile(path.join(projectDir, targetApp, ".env"), [{
|
|
5013
|
+
await addEnvVariablesToFile(path$1.join(projectDir, targetApp, ".env"), [{
|
|
4836
5014
|
key: "DATABASE_URL",
|
|
4837
5015
|
value: config?.connectionString ?? "postgresql://postgres:postgres@localhost:5432/mydb?schema=public",
|
|
4838
5016
|
condition: true
|
|
@@ -4844,7 +5022,7 @@ async function setupWithNeonDb(projectDir, packageManager, backend) {
|
|
|
4844
5022
|
const s = spinner();
|
|
4845
5023
|
s.start("Creating Neon database using get-db...");
|
|
4846
5024
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
4847
|
-
const targetDir = path.join(projectDir, targetApp);
|
|
5025
|
+
const targetDir = path$1.join(projectDir, targetApp);
|
|
4848
5026
|
await fs.ensureDir(targetDir);
|
|
4849
5027
|
const packageArgs = getPackageExecutionArgs(packageManager, "get-db@latest --yes");
|
|
4850
5028
|
await $({ cwd: targetDir })`${packageArgs}`;
|
|
@@ -4909,7 +5087,7 @@ async function setupNeonPostgres(config, cliInput) {
|
|
|
4909
5087
|
if (isCancel(setupMethod)) return exitCancelled("Operation cancelled");
|
|
4910
5088
|
if (setupMethod === "neondb") await setupWithNeonDb(projectDir, packageManager, backend);
|
|
4911
5089
|
else {
|
|
4912
|
-
const suggestedProjectName = path.basename(projectDir);
|
|
5090
|
+
const suggestedProjectName = path$1.basename(projectDir);
|
|
4913
5091
|
const projectName = await text({
|
|
4914
5092
|
message: "Enter a name for your Neon project:",
|
|
4915
5093
|
defaultValue: suggestedProjectName,
|
|
@@ -4940,7 +5118,7 @@ async function setupNeonPostgres(config, cliInput) {
|
|
|
4940
5118
|
async function setupPlanetScale(config) {
|
|
4941
5119
|
const { projectDir, database, orm, backend } = config;
|
|
4942
5120
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
4943
|
-
const envPath = path.join(projectDir, targetApp, ".env");
|
|
5121
|
+
const envPath = path$1.join(projectDir, targetApp, ".env");
|
|
4944
5122
|
if (database === "mysql" && orm === "drizzle") {
|
|
4945
5123
|
const variables = [
|
|
4946
5124
|
{
|
|
@@ -4964,7 +5142,7 @@ async function setupPlanetScale(config) {
|
|
|
4964
5142
|
condition: true
|
|
4965
5143
|
}
|
|
4966
5144
|
];
|
|
4967
|
-
await fs.ensureDir(path.join(projectDir, targetApp));
|
|
5145
|
+
await fs.ensureDir(path$1.join(projectDir, targetApp));
|
|
4968
5146
|
await addEnvVariablesToFile(envPath, variables);
|
|
4969
5147
|
}
|
|
4970
5148
|
if (database === "postgres" && orm === "prisma") {
|
|
@@ -4973,7 +5151,7 @@ async function setupPlanetScale(config) {
|
|
|
4973
5151
|
value: "postgresql://username:password@host/database?sslaccept=strict",
|
|
4974
5152
|
condition: true
|
|
4975
5153
|
}];
|
|
4976
|
-
await fs.ensureDir(path.join(projectDir, targetApp));
|
|
5154
|
+
await fs.ensureDir(path$1.join(projectDir, targetApp));
|
|
4977
5155
|
await addEnvVariablesToFile(envPath, variables);
|
|
4978
5156
|
}
|
|
4979
5157
|
if (database === "postgres" && orm === "drizzle") {
|
|
@@ -4982,7 +5160,7 @@ async function setupPlanetScale(config) {
|
|
|
4982
5160
|
value: "postgresql://username:password@host/database?sslmode=verify-full",
|
|
4983
5161
|
condition: true
|
|
4984
5162
|
}];
|
|
4985
|
-
await fs.ensureDir(path.join(projectDir, targetApp));
|
|
5163
|
+
await fs.ensureDir(path$1.join(projectDir, targetApp));
|
|
4986
5164
|
await addEnvVariablesToFile(envPath, variables);
|
|
4987
5165
|
}
|
|
4988
5166
|
if (database === "mysql" && orm === "prisma") {
|
|
@@ -4991,7 +5169,7 @@ async function setupPlanetScale(config) {
|
|
|
4991
5169
|
value: "mysql://username:password@host/database?sslaccept=strict",
|
|
4992
5170
|
condition: true
|
|
4993
5171
|
}];
|
|
4994
|
-
await fs.ensureDir(path.join(projectDir, targetApp));
|
|
5172
|
+
await fs.ensureDir(path$1.join(projectDir, targetApp));
|
|
4995
5173
|
await addEnvVariablesToFile(envPath, variables);
|
|
4996
5174
|
}
|
|
4997
5175
|
}
|
|
@@ -5057,7 +5235,7 @@ async function setupWithCreateDb(serverDir, packageManager) {
|
|
|
5057
5235
|
async function writeEnvFile$1(projectDir, backend, config) {
|
|
5058
5236
|
try {
|
|
5059
5237
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
5060
|
-
const envPath = path.join(projectDir, targetApp, ".env");
|
|
5238
|
+
const envPath = path$1.join(projectDir, targetApp, ".env");
|
|
5061
5239
|
const variables = [{
|
|
5062
5240
|
key: "DATABASE_URL",
|
|
5063
5241
|
value: config?.databaseUrl ?? "postgresql://postgres:postgres@localhost:5432/mydb?schema=public",
|
|
@@ -5086,7 +5264,7 @@ DATABASE_URL="your_database_url"`);
|
|
|
5086
5264
|
async function setupPrismaPostgres(config, cliInput) {
|
|
5087
5265
|
const { packageManager, projectDir, backend } = config;
|
|
5088
5266
|
const manualDb = cliInput?.manualDb ?? false;
|
|
5089
|
-
const dbDir = path.join(projectDir, "packages/db");
|
|
5267
|
+
const dbDir = path$1.join(projectDir, "packages/db");
|
|
5090
5268
|
try {
|
|
5091
5269
|
await fs.ensureDir(dbDir);
|
|
5092
5270
|
if (manualDb) {
|
|
@@ -5137,7 +5315,7 @@ async function setupPrismaPostgres(config, cliInput) {
|
|
|
5137
5315
|
async function writeSupabaseEnvFile(projectDir, backend, databaseUrl) {
|
|
5138
5316
|
try {
|
|
5139
5317
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
5140
|
-
const envPath = path.join(projectDir, targetApp, ".env");
|
|
5318
|
+
const envPath = path$1.join(projectDir, targetApp, ".env");
|
|
5141
5319
|
const dbUrlToUse = databaseUrl || "postgresql://postgres:postgres@127.0.0.1:54322/postgres";
|
|
5142
5320
|
await addEnvVariablesToFile(envPath, [{
|
|
5143
5321
|
key: "DATABASE_URL",
|
|
@@ -5221,7 +5399,7 @@ ${pc.dim(output)}` : ""}
|
|
|
5221
5399
|
async function setupSupabase(config, cliInput) {
|
|
5222
5400
|
const { projectDir, packageManager, backend } = config;
|
|
5223
5401
|
const manualDb = cliInput?.manualDb ?? false;
|
|
5224
|
-
const serverDir = path.join(projectDir, "packages", "db");
|
|
5402
|
+
const serverDir = path$1.join(projectDir, "packages", "db");
|
|
5225
5403
|
try {
|
|
5226
5404
|
await fs.ensureDir(serverDir);
|
|
5227
5405
|
if (manualDb) {
|
|
@@ -5387,7 +5565,7 @@ async function createTursoDatabase(dbName, groupName) {
|
|
|
5387
5565
|
}
|
|
5388
5566
|
async function writeEnvFile(projectDir, backend, config) {
|
|
5389
5567
|
const targetApp = backend === "self" ? "apps/web" : "apps/server";
|
|
5390
|
-
await addEnvVariablesToFile(path.join(projectDir, targetApp, ".env"), [{
|
|
5568
|
+
await addEnvVariablesToFile(path$1.join(projectDir, targetApp, ".env"), [{
|
|
5391
5569
|
key: "DATABASE_URL",
|
|
5392
5570
|
value: config?.dbUrl ?? "",
|
|
5393
5571
|
condition: true
|
|
@@ -5465,7 +5643,7 @@ async function setupTurso(config, cliInput) {
|
|
|
5465
5643
|
const selectedGroup = await selectTursoGroup();
|
|
5466
5644
|
let success = false;
|
|
5467
5645
|
let dbName = "";
|
|
5468
|
-
let suggestedName = path.basename(projectDir);
|
|
5646
|
+
let suggestedName = path$1.basename(projectDir);
|
|
5469
5647
|
while (!success) {
|
|
5470
5648
|
const dbNameResponse = await text({
|
|
5471
5649
|
message: "Enter a name for your database:",
|
|
@@ -5506,12 +5684,12 @@ async function setupDatabase(config, cliInput) {
|
|
|
5506
5684
|
const { database, dbSetup, backend, projectDir } = config;
|
|
5507
5685
|
if (backend === "convex" || database === "none") {
|
|
5508
5686
|
if (backend !== "convex") {
|
|
5509
|
-
const serverDbDir = path.join(projectDir, "apps/server/src/db");
|
|
5687
|
+
const serverDbDir = path$1.join(projectDir, "apps/server/src/db");
|
|
5510
5688
|
if (await fs.pathExists(serverDbDir)) await fs.remove(serverDbDir);
|
|
5511
5689
|
}
|
|
5512
5690
|
return;
|
|
5513
5691
|
}
|
|
5514
|
-
const dbPackageDir = path.join(projectDir, "packages/db");
|
|
5692
|
+
const dbPackageDir = path$1.join(projectDir, "packages/db");
|
|
5515
5693
|
if (!await fs.pathExists(dbPackageDir)) return;
|
|
5516
5694
|
try {
|
|
5517
5695
|
if (dbSetup === "docker") await setupDockerCompose(config);
|
|
@@ -5830,7 +6008,7 @@ async function createProject(options, cliInput = {}) {
|
|
|
5830
6008
|
}
|
|
5831
6009
|
}
|
|
5832
6010
|
async function setPackageManagerVersion(projectDir, packageManager) {
|
|
5833
|
-
const pkgJsonPath = path.join(projectDir, "package.json");
|
|
6011
|
+
const pkgJsonPath = path$1.join(projectDir, "package.json");
|
|
5834
6012
|
if (!await fs.pathExists(pkgJsonPath)) return;
|
|
5835
6013
|
try {
|
|
5836
6014
|
const { stdout } = await $`${packageManager} -v`;
|
|
@@ -5862,7 +6040,7 @@ async function createProjectHandler(input, options = {}) {
|
|
|
5862
6040
|
const defaultConfig = getDefaultConfig();
|
|
5863
6041
|
let defaultName = defaultConfig.relativePath;
|
|
5864
6042
|
let counter = 1;
|
|
5865
|
-
while (await fs.pathExists(path.resolve(process.cwd(), defaultName)) && (await fs.readdir(path.resolve(process.cwd(), defaultName))).length > 0) {
|
|
6043
|
+
while (await fs.pathExists(path$1.resolve(process.cwd(), defaultName)) && (await fs.readdir(path$1.resolve(process.cwd(), defaultName))).length > 0) {
|
|
5866
6044
|
defaultName = `${defaultConfig.projectName}-${counter}`;
|
|
5867
6045
|
counter++;
|
|
5868
6046
|
}
|
|
@@ -6038,7 +6216,7 @@ async function createProjectHandler(input, options = {}) {
|
|
|
6038
6216
|
});
|
|
6039
6217
|
}
|
|
6040
6218
|
async function handleDirectoryConflictProgrammatically(currentPathInput, strategy) {
|
|
6041
|
-
const currentPath = path.resolve(process.cwd(), currentPathInput);
|
|
6219
|
+
const currentPath = path$1.resolve(process.cwd(), currentPathInput);
|
|
6042
6220
|
if (!await fs.pathExists(currentPath)) return {
|
|
6043
6221
|
finalPathInput: currentPathInput,
|
|
6044
6222
|
shouldClearDirectory: false
|
|
@@ -6060,7 +6238,7 @@ async function handleDirectoryConflictProgrammatically(currentPathInput, strateg
|
|
|
6060
6238
|
let counter = 1;
|
|
6061
6239
|
const baseName = currentPathInput;
|
|
6062
6240
|
let finalPathInput = `${baseName}-${counter}`;
|
|
6063
|
-
while (await fs.pathExists(path.resolve(process.cwd(), finalPathInput)) && (await fs.readdir(path.resolve(process.cwd(), finalPathInput))).length > 0) {
|
|
6241
|
+
while (await fs.pathExists(path$1.resolve(process.cwd(), finalPathInput)) && (await fs.readdir(path$1.resolve(process.cwd(), finalPathInput))).length > 0) {
|
|
6064
6242
|
counter++;
|
|
6065
6243
|
finalPathInput = `${baseName}-${counter}`;
|
|
6066
6244
|
}
|
|
@@ -6221,6 +6399,24 @@ const router = os.router({
|
|
|
6221
6399
|
} catch {
|
|
6222
6400
|
log.message(`Please visit ${BUILDER_URL}`);
|
|
6223
6401
|
}
|
|
6402
|
+
}),
|
|
6403
|
+
"update-deps": os.meta({ description: "Check and update dependency versions in add-deps.ts" }).input(z.object({
|
|
6404
|
+
check: z.boolean().default(false).describe("Report only, no changes"),
|
|
6405
|
+
patch: z.boolean().default(false).describe("Apply patch/minor updates only"),
|
|
6406
|
+
all: z.boolean().default(false).describe("Interactive mode for all updates"),
|
|
6407
|
+
ecosystem: z.string().optional().describe("Filter by ecosystem (effect, tanstack, prisma, etc.)"),
|
|
6408
|
+
"list-ecosystems": z.boolean().default(false).describe("List available ecosystems")
|
|
6409
|
+
})).handler(async ({ input }) => {
|
|
6410
|
+
if (input["list-ecosystems"]) {
|
|
6411
|
+
showEcosystems();
|
|
6412
|
+
return;
|
|
6413
|
+
}
|
|
6414
|
+
await updateDepsHandler({
|
|
6415
|
+
check: input.check,
|
|
6416
|
+
patch: input.patch,
|
|
6417
|
+
all: input.all,
|
|
6418
|
+
ecosystem: input.ecosystem
|
|
6419
|
+
});
|
|
6224
6420
|
})
|
|
6225
6421
|
});
|
|
6226
6422
|
const caller = createRouterClient(router, { context: {} });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-better-fullstack",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"description": "A CLI-first toolkit for building Full Stack applications. Skip the configuration. Ship the code.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"better-auth",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"prepublishOnly": "npm run build"
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@better-fullstack/template-generator": "^1.1.
|
|
76
|
-
"@better-fullstack/types": "^1.1.
|
|
75
|
+
"@better-fullstack/template-generator": "^1.1.7",
|
|
76
|
+
"@better-fullstack/types": "^1.1.7",
|
|
77
77
|
"@clack/core": "^0.5.0",
|
|
78
78
|
"@clack/prompts": "^1.0.0-alpha.8",
|
|
79
79
|
"@orpc/server": "^1.13.0",
|