betterstart-cli 0.0.40 → 0.0.41
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.js +30 -154
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -22241,7 +22241,7 @@ async function promptPlugins(cwd, options = {}) {
|
|
|
22241
22241
|
} else {
|
|
22242
22242
|
if (existingToken) {
|
|
22243
22243
|
p12.log.info(
|
|
22244
|
-
`Using the existing
|
|
22244
|
+
`Using the existing BLOB_READ_WRITE_TOKEN from .env.local ${styleText(
|
|
22245
22245
|
"dim",
|
|
22246
22246
|
`(${maskBlobToken(existingToken)})`
|
|
22247
22247
|
)}`
|
|
@@ -22270,30 +22270,13 @@ async function promptPlugins(cwd, options = {}) {
|
|
|
22270
22270
|
process.exit(0);
|
|
22271
22271
|
}
|
|
22272
22272
|
const integrations = [];
|
|
22273
|
-
|
|
22274
|
-
|
|
22275
|
-
|
|
22276
|
-
"
|
|
22277
|
-
|
|
22278
|
-
|
|
22279
|
-
initialValue: true
|
|
22273
|
+
sections.push({
|
|
22274
|
+
header: "Email (Resend)",
|
|
22275
|
+
vars: [
|
|
22276
|
+
{ key: "BETTERSTART_RESEND_API_KEY", value: "" },
|
|
22277
|
+
{ key: "BETTERSTART_EMAIL_FROM", value: "" }
|
|
22278
|
+
]
|
|
22280
22279
|
});
|
|
22281
|
-
if (p12.isCancel(setupResend)) {
|
|
22282
|
-
p12.cancel("Setup cancelled.");
|
|
22283
|
-
process.exit(0);
|
|
22284
|
-
}
|
|
22285
|
-
if (setupResend) {
|
|
22286
|
-
integrations.push("resend");
|
|
22287
|
-
mergeIntegrationConfig(await collectIntegrationConfig(cwd, ["resend"]));
|
|
22288
|
-
} else {
|
|
22289
|
-
sections.push({
|
|
22290
|
-
header: "Email (Resend)",
|
|
22291
|
-
vars: [
|
|
22292
|
-
{ key: "BETTERSTART_RESEND_API_KEY", value: "" },
|
|
22293
|
-
{ key: "BETTERSTART_EMAIL_FROM", value: "" }
|
|
22294
|
-
]
|
|
22295
|
-
});
|
|
22296
|
-
}
|
|
22297
22280
|
if (storage === "r2") {
|
|
22298
22281
|
integrations.push("r2");
|
|
22299
22282
|
} else if (storage === "vercel-blob") {
|
|
@@ -25505,18 +25488,6 @@ function readNamespaceFromConfigSource(source) {
|
|
|
25505
25488
|
const match = source.match(/\bnamespace\s*:\s*(['"`])([^'"`]+)\1/);
|
|
25506
25489
|
return normalizeNamespaceForRemoval(match?.[2]);
|
|
25507
25490
|
}
|
|
25508
|
-
function formatStorageProviderLabel(provider) {
|
|
25509
|
-
switch (provider) {
|
|
25510
|
-
case "vercel-blob":
|
|
25511
|
-
return "Vercel Blob";
|
|
25512
|
-
case "r2":
|
|
25513
|
-
return "Cloudflare R2";
|
|
25514
|
-
case "local":
|
|
25515
|
-
return "local filesystem";
|
|
25516
|
-
default:
|
|
25517
|
-
return provider;
|
|
25518
|
-
}
|
|
25519
|
-
}
|
|
25520
25491
|
function resolveNonInteractiveProject(name) {
|
|
25521
25492
|
const projectName = name?.trim() || "my-app";
|
|
25522
25493
|
if (projectName !== "." && !/^[a-z0-9_-]+$/i.test(projectName)) {
|
|
@@ -25808,7 +25779,7 @@ async function runInitCommand(name, options) {
|
|
|
25808
25779
|
}
|
|
25809
25780
|
} else if (existingDbUrl) {
|
|
25810
25781
|
const masked = maskDbUrl(existingDbUrl);
|
|
25811
|
-
p18.log.info(`Using existing
|
|
25782
|
+
p18.log.info(`Using the existing DATABASE_URL from .env.local ${pc7.dim(`(${masked})`)}`);
|
|
25812
25783
|
databaseUrl = existingDbUrl;
|
|
25813
25784
|
} else {
|
|
25814
25785
|
const databaseStep = deferNextPromptCheck();
|
|
@@ -25913,35 +25884,21 @@ async function runInitCommand(name, options) {
|
|
|
25913
25884
|
config.frameworkConfig.next.paths = deriveNamespacePaths(namespace, srcDir);
|
|
25914
25885
|
config.paths = config.frameworkConfig.next.paths;
|
|
25915
25886
|
config.database.migrationsDir = deriveMigrationsDir(namespace);
|
|
25916
|
-
const results = [];
|
|
25917
25887
|
const s = spinner2();
|
|
25918
25888
|
s.start("Directory structure");
|
|
25919
|
-
|
|
25889
|
+
scaffoldBase({
|
|
25920
25890
|
cwd,
|
|
25921
25891
|
config,
|
|
25922
25892
|
includeEmailTemplatesDir: pluginSelection.integrations.some(isEmailProviderIntegration)
|
|
25923
25893
|
});
|
|
25924
|
-
results.push({ label: "Directory structure", result: `${baseFiles.length} files` });
|
|
25925
25894
|
s.message("TypeScript aliases");
|
|
25926
|
-
|
|
25927
|
-
results.push({
|
|
25928
|
-
label: "TypeScript aliases",
|
|
25929
|
-
result: tsResult.added.length > 0 ? `${tsResult.added.length} paths` : "already set"
|
|
25930
|
-
});
|
|
25895
|
+
scaffoldTsconfig(cwd, config);
|
|
25931
25896
|
s.message("Tailwind CSS");
|
|
25932
|
-
|
|
25933
|
-
results.push({
|
|
25934
|
-
label: "Tailwind CSS",
|
|
25935
|
-
result: twResult.appended ? "updated" : twResult.file ? "already set" : "no CSS file"
|
|
25936
|
-
});
|
|
25897
|
+
scaffoldTailwind(cwd, srcDir, namespace);
|
|
25937
25898
|
s.message("Dev server");
|
|
25938
|
-
|
|
25939
|
-
results.push({
|
|
25940
|
-
label: "Dev server",
|
|
25941
|
-
result: formatDevServerResult(devServerResult)
|
|
25942
|
-
});
|
|
25899
|
+
ensureDefaultDevScriptPort(cwd);
|
|
25943
25900
|
s.message("Environment variables");
|
|
25944
|
-
|
|
25901
|
+
scaffoldEnv(cwd, { databaseUrl, namespace });
|
|
25945
25902
|
if (collectedIntegrationConfig.sections.length > 0) {
|
|
25946
25903
|
appendEnvVars(
|
|
25947
25904
|
cwd,
|
|
@@ -25949,49 +25906,26 @@ async function runInitCommand(name, options) {
|
|
|
25949
25906
|
collectedIntegrationConfig.overwriteKeys
|
|
25950
25907
|
);
|
|
25951
25908
|
}
|
|
25952
|
-
const envCount = envResult.added.length + envResult.updated.length;
|
|
25953
|
-
results.push({
|
|
25954
|
-
label: "Environment variables",
|
|
25955
|
-
result: envCount > 0 ? `${envCount} vars` : "already set"
|
|
25956
|
-
});
|
|
25957
25909
|
s.message("Database");
|
|
25958
25910
|
const dbFiles = scaffoldDatabase({ cwd, config });
|
|
25959
|
-
results.push({ label: "Database", result: `${dbFiles.length} files` });
|
|
25960
25911
|
s.message("Authentication");
|
|
25961
|
-
|
|
25962
|
-
results.push({ label: "Authentication", result: `${authFiles.length} files` });
|
|
25912
|
+
scaffoldAuth({ cwd, config });
|
|
25963
25913
|
s.message("Components");
|
|
25964
|
-
|
|
25965
|
-
results.push({ label: "Components", result: `${compFiles.length} files` });
|
|
25914
|
+
scaffoldComponents({ cwd, config });
|
|
25966
25915
|
s.message("Pages & layouts");
|
|
25967
|
-
|
|
25968
|
-
results.push({ label: "Pages & layouts", result: `${layoutFiles.length} files` });
|
|
25916
|
+
scaffoldLayout({ cwd, config });
|
|
25969
25917
|
s.message("API routes");
|
|
25970
|
-
|
|
25971
|
-
results.push({ label: "API routes", result: `${apiFiles.length} routes` });
|
|
25918
|
+
scaffoldApiRoutes({ cwd, config });
|
|
25972
25919
|
s.message("Linter");
|
|
25973
|
-
let linterResult;
|
|
25974
25920
|
if (project2.linter.type === "none") {
|
|
25975
|
-
|
|
25976
|
-
linterResult = biomeResult.installed ? "biome (new)" : "none";
|
|
25977
|
-
} else {
|
|
25978
|
-
linterResult = project2.linter.type;
|
|
25921
|
+
scaffoldBiome(cwd, project2.linter);
|
|
25979
25922
|
}
|
|
25980
|
-
results.push({ label: "Linter", result: linterResult });
|
|
25981
25923
|
s.message("Next.js config");
|
|
25982
25924
|
const nextConfigResult = scaffoldNextConfig({ cwd, nextMajorVersion });
|
|
25983
|
-
|
|
25984
|
-
|
|
25985
|
-
|
|
25986
|
-
}
|
|
25987
|
-
const maxLabel = Math.max(...results.map((r) => r.label.length));
|
|
25988
|
-
const noteLines = results.map((r) => {
|
|
25989
|
-
const padded = r.label.padEnd(maxLabel + 3);
|
|
25990
|
-
return `${pc7.green("\u2713")} ${padded}${pc7.dim(r.result)}`;
|
|
25991
|
-
});
|
|
25992
|
-
s.stop("");
|
|
25993
|
-
process.stdout.write("\x1B[2A\x1B[J");
|
|
25994
|
-
p18.note(noteLines.join("\n"), "Scaffolded admin");
|
|
25925
|
+
s.clear();
|
|
25926
|
+
if (nextConfigResult.status === "unsupported") {
|
|
25927
|
+
p18.log.warn("The Next.js config could not be updated automatically \u2014 review it manually.");
|
|
25928
|
+
}
|
|
25995
25929
|
const drizzleConfigPath = path50.join(cwd, "drizzle.config.ts");
|
|
25996
25930
|
if (!dbFiles.includes("drizzle.config.ts") && fs39.existsSync(drizzleConfigPath)) {
|
|
25997
25931
|
if (forceMode) {
|
|
@@ -26096,42 +26030,20 @@ async function runInitCommand(name, options) {
|
|
|
26096
26030
|
}
|
|
26097
26031
|
writeConfigFile(cwd, resolvedIntegrationInstallResult.config);
|
|
26098
26032
|
const usesLocalStorage = resolvedIntegrationInstallResult.config.storage.provider === "local";
|
|
26099
|
-
const
|
|
26100
|
-
|
|
26101
|
-
installLines.push(
|
|
26102
|
-
`${pc7.green("\u2713")} Dependencies ${pc7.dim(`${depsResult.dependencies.length} deps + ${depsResult.devDeps.length} dev deps`)}`
|
|
26103
|
-
);
|
|
26104
|
-
}
|
|
26105
|
-
if (coreSchemasResult.errors.length > 0) {
|
|
26106
|
-
installLines.push(
|
|
26107
|
-
`${pc7.yellow("\u25B2")} Core schemas ${pc7.dim(`${coreSchemasResult.errors.length} warning(s)`)}`
|
|
26108
|
-
);
|
|
26109
|
-
for (const err of coreSchemasResult.errors) {
|
|
26110
|
-
installLines.push(` ${pc7.dim(err)}`);
|
|
26111
|
-
}
|
|
26112
|
-
} else {
|
|
26113
|
-
installLines.push(
|
|
26114
|
-
`${pc7.green("\u2713")} Core schemas ${pc7.dim(`${coreSchemasResult.schemas.length} schemas, ${coreSchemasResult.generatedFiles.length} files`)}`
|
|
26115
|
-
);
|
|
26033
|
+
for (const err of coreSchemasResult.errors) {
|
|
26034
|
+
p18.log.warn(`Core schemas: ${err}`);
|
|
26116
26035
|
}
|
|
26117
|
-
installLines.push(
|
|
26118
|
-
`${pc7.green("\u2713")} Plugins ${pc7.dim(resolvedPluginInstallResult.installed.length > 0 ? resolvedPluginInstallResult.installed.join(", ") : "core only")}`
|
|
26119
|
-
);
|
|
26120
26036
|
for (const warning of resolvedPluginInstallResult.warnings) {
|
|
26121
|
-
|
|
26037
|
+
p18.log.warn(warning);
|
|
26122
26038
|
}
|
|
26123
|
-
installLines.push(
|
|
26124
|
-
`${pc7.green("\u2713")} Integrations ${pc7.dim(resolvedIntegrationInstallResult.installed.length > 0 ? resolvedIntegrationInstallResult.installed.join(", ") : "none")}`
|
|
26125
|
-
);
|
|
26126
26039
|
for (const warning of resolvedIntegrationInstallResult.warnings) {
|
|
26127
|
-
|
|
26040
|
+
p18.log.warn(warning);
|
|
26128
26041
|
}
|
|
26129
26042
|
if (usesLocalStorage) {
|
|
26130
|
-
|
|
26131
|
-
|
|
26043
|
+
p18.log.warn(
|
|
26044
|
+
"Local filesystem storage is only for development or self-hosted persistent-disk deployments. Use Vercel Blob or Cloudflare R2 for hosted/serverless production."
|
|
26132
26045
|
);
|
|
26133
26046
|
}
|
|
26134
|
-
p18.note(installLines.join("\n"), "Installed");
|
|
26135
26047
|
let dbPushed = false;
|
|
26136
26048
|
if (depsResult.success && options.skipMigration && hasDbUrl(cwd)) {
|
|
26137
26049
|
p18.log.info(`Skipping database schema push ${pc7.dim("(--skip-migration)")}`);
|
|
@@ -26160,9 +26072,7 @@ async function runInitCommand(name, options) {
|
|
|
26160
26072
|
}
|
|
26161
26073
|
if (driverReady) {
|
|
26162
26074
|
const useTerminalForDbPush = shouldUseTerminalForDbPush(options);
|
|
26163
|
-
if (useTerminalForDbPush) {
|
|
26164
|
-
p18.log.info(`Running ${pc7.cyan("drizzle-kit push --force")}`);
|
|
26165
|
-
} else {
|
|
26075
|
+
if (!useTerminalForDbPush) {
|
|
26166
26076
|
s.start("Pushing database schema (drizzle-kit push)");
|
|
26167
26077
|
}
|
|
26168
26078
|
const pushResult = await runDrizzlePush(cwd, { interactive: useTerminalForDbPush });
|
|
@@ -26174,11 +26084,8 @@ async function runInitCommand(name, options) {
|
|
|
26174
26084
|
p18.log.error("Database was not reachable. Aborting setup.");
|
|
26175
26085
|
process.exit(1);
|
|
26176
26086
|
}
|
|
26177
|
-
}
|
|
26178
|
-
if (useTerminalForDbPush) {
|
|
26179
|
-
p18.log.success("Database schema pushed");
|
|
26180
26087
|
} else {
|
|
26181
|
-
s.
|
|
26088
|
+
s.clear();
|
|
26182
26089
|
}
|
|
26183
26090
|
dbPushed = true;
|
|
26184
26091
|
} else {
|
|
@@ -26243,12 +26150,6 @@ async function runInitCommand(name, options) {
|
|
|
26243
26150
|
}
|
|
26244
26151
|
}
|
|
26245
26152
|
if (!adminAccountReady) {
|
|
26246
|
-
p18.note(
|
|
26247
|
-
pc7.dim(
|
|
26248
|
-
replaceExistingAdmin ? "Replace the existing admin account to access the admin." : "Create your first admin user to access the dashboard."
|
|
26249
|
-
),
|
|
26250
|
-
"Admin account"
|
|
26251
|
-
);
|
|
26252
26153
|
const credentials = await p18.group(
|
|
26253
26154
|
{
|
|
26254
26155
|
email: () => p18.text({
|
|
@@ -26338,19 +26239,8 @@ Run manually: ${pc7.cyan(betterstartExecCommand(pm, "seed"))}`,
|
|
|
26338
26239
|
s.stop("Git commit skipped");
|
|
26339
26240
|
}
|
|
26340
26241
|
}
|
|
26341
|
-
const totalFiles = baseFiles.length + dbFiles.length + authFiles.length + compFiles.length + layoutFiles.length + apiFiles.length;
|
|
26342
26242
|
const adminNamespace = resolveAdminNamespace(namespace);
|
|
26343
26243
|
const adminLoginUrl = `http://localhost:${detectDevPort(cwd)}${adminNamespace.routePath}/login`;
|
|
26344
|
-
const installedPluginList = resolvedPluginInstallResult.installed.length > 0 ? resolvedPluginInstallResult.installed.join(", ") : "core only";
|
|
26345
|
-
const installedIntegrationList = resolvedIntegrationInstallResult.installed.length > 0 ? resolvedIntegrationInstallResult.installed.join(", ") : "none";
|
|
26346
|
-
const summaryLines = [
|
|
26347
|
-
`Plugins: ${pc7.cyan(installedPluginList)}`,
|
|
26348
|
-
`Integrations: ${pc7.cyan(installedIntegrationList)}`,
|
|
26349
|
-
`Storage: ${pc7.cyan(formatStorageProviderLabel(resolvedIntegrationInstallResult.config.storage.provider))}`,
|
|
26350
|
-
`Files created: ${pc7.cyan(String(totalFiles))}`,
|
|
26351
|
-
`Env vars: ${envResult.added.length} added, ${envResult.skipped.length} skipped`
|
|
26352
|
-
];
|
|
26353
|
-
p18.note(summaryLines.join("\n"), "Admin scaffolded successfully");
|
|
26354
26244
|
if (options.vercel !== false && !options.skipDeploy) {
|
|
26355
26245
|
const linkedVercelProject = Boolean(readLinkedProjectId(cwd));
|
|
26356
26246
|
if (!options.yes) {
|
|
@@ -26463,20 +26353,6 @@ function detectInstalledNextVersion(cwd) {
|
|
|
26463
26353
|
return void 0;
|
|
26464
26354
|
}
|
|
26465
26355
|
}
|
|
26466
|
-
function formatDevServerResult(result) {
|
|
26467
|
-
switch (result.status) {
|
|
26468
|
-
case "updated":
|
|
26469
|
-
return `set to ${result.port}`;
|
|
26470
|
-
case "preserved":
|
|
26471
|
-
return `using ${result.port}`;
|
|
26472
|
-
case "skipped":
|
|
26473
|
-
return `custom script preserved; BetterStart uses ${result.port}`;
|
|
26474
|
-
case "missing-script":
|
|
26475
|
-
return `no dev script; BetterStart uses ${result.port}`;
|
|
26476
|
-
case "missing-package":
|
|
26477
|
-
return `package.json missing; BetterStart uses ${result.port}`;
|
|
26478
|
-
}
|
|
26479
|
-
}
|
|
26480
26356
|
function shouldUseTerminalForDbPush(options) {
|
|
26481
26357
|
return !options.yes && process.env.CI !== "true" && Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY);
|
|
26482
26358
|
}
|