betterstart-cli 0.0.90 → 0.0.91

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 CHANGED
@@ -22,10 +22,9 @@ import {
22
22
 
23
23
  // cli.ts
24
24
  import { readFileSync } from "fs";
25
- import * as p30 from "@clack/prompts";
25
+ import * as p31 from "@clack/prompts";
26
26
 
27
- // core-engine/commands/require-init.ts
28
- import path2 from "path";
27
+ // core-engine/commands/default-action.ts
29
28
  import * as p from "@clack/prompts";
30
29
 
31
30
  // core-engine/config/resolver.ts
@@ -49,22 +48,9 @@ async function loadConfigFile(configPath) {
49
48
  return mod.default || mod;
50
49
  }
51
50
 
52
- // core-engine/commands/require-init.ts
53
- var INIT_COMMAND = "init";
54
- function resolveCommandCwd(command) {
55
- const options = command.opts();
56
- return typeof options.cwd === "string" ? path2.resolve(options.cwd) : process.cwd();
57
- }
58
- function requireInitializedProject(command) {
59
- if (command.name() === INIT_COMMAND) {
60
- return;
61
- }
62
- const cwd = resolveCommandCwd(command);
63
- if (findConfigFile(cwd)) {
64
- return;
65
- }
66
- p.log.error("Couldn't find betterstart project. Please run `betterstart init` first.");
67
- process.exit(1);
51
+ // core-engine/utils/interactive.ts
52
+ function isInteractiveSession() {
53
+ return Boolean(process.stdin.isTTY) && process.env.CI !== "true";
68
54
  }
69
55
 
70
56
  // core-engine/commands/runtime.ts
@@ -196,9 +182,142 @@ function createUpdateStylesCommand(runtime) {
196
182
  return new Command("update-styles").description("Replace admin-globals.css with the latest version from the CLI").option("--cwd <path>", "Project root path").action((options) => runtime.runUpdateStyles(options));
197
183
  }
198
184
 
185
+ // core-engine/commands/default-action.ts
186
+ var ADD_COMMAND = "add";
187
+ var CREATE_COMMAND = "create";
188
+ var INIT_COMMAND = "init";
189
+ var REMOVE_COMMAND = "remove";
190
+ var REMOVE_SCHEMA_COMMAND = "remove-schema";
191
+ var CANCELLED = /* @__PURE__ */ Symbol("cancelled");
192
+ function cancelled(value) {
193
+ return value === CANCELLED;
194
+ }
195
+ async function runDefaultAction(program2, runtime) {
196
+ if (!isInteractiveSession()) {
197
+ program2.outputHelp();
198
+ return;
199
+ }
200
+ const cwd = process.cwd();
201
+ if (!findConfigFile(cwd)) {
202
+ await program2.parseAsync([INIT_COMMAND], { from: "user" });
203
+ return;
204
+ }
205
+ const argv = await promptInvocation(program2, runtime, cwd);
206
+ if (cancelled(argv)) {
207
+ p.cancel("No command selected.");
208
+ return;
209
+ }
210
+ await program2.parseAsync(argv, { from: "user" });
211
+ }
212
+ async function promptInvocation(program2, runtime, cwd) {
213
+ const name = await p.select({
214
+ message: "What do you want to do?",
215
+ options: program2.commands.map((command) => ({
216
+ value: command.name(),
217
+ label: command.name(),
218
+ hint: command.description()
219
+ }))
220
+ });
221
+ if (p.isCancel(name)) {
222
+ return CANCELLED;
223
+ }
224
+ const args = await promptRequiredArguments(name, runtime, cwd);
225
+ if (cancelled(args)) {
226
+ return CANCELLED;
227
+ }
228
+ return [name, ...args];
229
+ }
230
+ async function promptRequiredArguments(name, runtime, cwd) {
231
+ if (name === CREATE_COMMAND) {
232
+ const kind = await p.select({
233
+ message: "Schema kind",
234
+ options: CREATE_SCHEMA_KINDS.map((value) => ({ value, label: value }))
235
+ });
236
+ return p.isCancel(kind) ? CANCELLED : [kind];
237
+ }
238
+ if (name === ADD_COMMAND || name === REMOVE_COMMAND) {
239
+ return promptInstallables(name, runtime, cwd);
240
+ }
241
+ if (name === REMOVE_SCHEMA_COMMAND) {
242
+ const schemas = await runtime.listSchemaChoices(cwd);
243
+ if (schemas.length === 0) {
244
+ p.log.warn("No schemas to remove.");
245
+ return CANCELLED;
246
+ }
247
+ const schema = await p.select({
248
+ message: "Schema to remove",
249
+ options: schemas.map((value) => ({ value, label: value }))
250
+ });
251
+ return p.isCancel(schema) ? CANCELLED : [schema];
252
+ }
253
+ return [];
254
+ }
255
+ async function promptInstallables(name, runtime, cwd) {
256
+ const removing = name === REMOVE_COMMAND;
257
+ const choices = await runtime.listInstallableChoices(cwd);
258
+ const presets = choices.presets.filter((choice) => choice.installed === removing);
259
+ const integrations = choices.integrations.filter((choice) => choice.installed === removing);
260
+ if (presets.length === 0 && integrations.length === 0) {
261
+ p.log.warn(removing ? "Nothing installed to remove." : "Everything available is installed.");
262
+ return CANCELLED;
263
+ }
264
+ const family = await promptInstallableFamily(presets, integrations);
265
+ if (cancelled(family)) {
266
+ return CANCELLED;
267
+ }
268
+ const items = await p.multiselect({
269
+ message: removing ? "Items to remove" : "Items to install",
270
+ options: (family === "integration" ? integrations : presets).map((choice) => ({
271
+ value: choice.id,
272
+ label: choice.id,
273
+ hint: choice.description
274
+ }))
275
+ });
276
+ if (p.isCancel(items)) {
277
+ return CANCELLED;
278
+ }
279
+ return family === "integration" ? ["--integration", ...items] : items;
280
+ }
281
+ async function promptInstallableFamily(presets, integrations) {
282
+ if (integrations.length === 0) {
283
+ return "preset";
284
+ }
285
+ if (presets.length === 0) {
286
+ return "integration";
287
+ }
288
+ const family = await p.select({
289
+ message: "Presets or integrations?",
290
+ options: [
291
+ { value: "preset", label: "Presets", hint: "content presets (e.g. blog)" },
292
+ { value: "integration", label: "Integrations", hint: "services (e.g. r2, resend)" }
293
+ ]
294
+ });
295
+ return p.isCancel(family) ? CANCELLED : family;
296
+ }
297
+
298
+ // core-engine/commands/require-init.ts
299
+ import path2 from "path";
300
+ import * as p2 from "@clack/prompts";
301
+ var INIT_COMMAND2 = "init";
302
+ function resolveCommandCwd(command) {
303
+ const options = command.opts();
304
+ return typeof options.cwd === "string" ? path2.resolve(options.cwd) : process.cwd();
305
+ }
306
+ function requireInitializedProject(command) {
307
+ if (command.name() === INIT_COMMAND2) {
308
+ return;
309
+ }
310
+ const cwd = resolveCommandCwd(command);
311
+ if (findConfigFile(cwd)) {
312
+ return;
313
+ }
314
+ p2.log.error("Couldn't find betterstart project. Please run `betterstart init` first.");
315
+ process.exit(1);
316
+ }
317
+
199
318
  // adapters/next/commands/add.ts
200
319
  import path27 from "path";
201
- import * as p7 from "@clack/prompts";
320
+ import * as p8 from "@clack/prompts";
202
321
 
203
322
  // core-engine/config/serialize.ts
204
323
  import fs3 from "fs";
@@ -750,7 +869,7 @@ async function resolveConfigOrExit(cwd) {
750
869
  import { execFileSync as execFileSync2 } from "child_process";
751
870
  import fs8 from "fs";
752
871
  import path10 from "path";
753
- import * as p4 from "@clack/prompts";
872
+ import * as p5 from "@clack/prompts";
754
873
 
755
874
  // adapters/next/init/scaffolders/dependencies.ts
756
875
  import { spawn } from "child_process";
@@ -1633,7 +1752,7 @@ async function syncProjectCliDependency(cwd, pm) {
1633
1752
  // adapters/next/utils/drizzle-push.ts
1634
1753
  import { spawn as spawn2 } from "child_process";
1635
1754
  import path9 from "path";
1636
- import * as p2 from "@clack/prompts";
1755
+ import * as p3 from "@clack/prompts";
1637
1756
  var PG_SSL_WARNING_START = "Warning: SECURITY WARNING: The SSL modes 'prefer', 'require', and 'verify-ca' are treated as aliases for 'verify-full'.";
1638
1757
  var PG_SSL_WARNING_END = "See https://www.postgresql.org/docs/current/libpq-ssl.html for libpq SSL mode definitions.";
1639
1758
  var NODE_TRACE_WARNING_HINT = "(Use `node --trace-warnings";
@@ -1809,7 +1928,7 @@ function runDrizzlePush(cwd, options = {}) {
1809
1928
  }
1810
1929
  if (stdoutTtySuppressor.sawError() || stderrTtySuppressor.sawError()) {
1811
1930
  notifyOutput();
1812
- p2.log.info("Database changes need your input \u2014 continuing in drizzle-kit.");
1931
+ p3.log.info("Database changes need your input \u2014 continuing in drizzle-kit.");
1813
1932
  const attached = spawn2(drizzleBin, ["push", "--force"], {
1814
1933
  cwd,
1815
1934
  stdio: "inherit",
@@ -1855,7 +1974,7 @@ ${stderr}`.trim();
1855
1974
  }
1856
1975
 
1857
1976
  // adapters/next/utils/next-steps.ts
1858
- import * as p3 from "@clack/prompts";
1977
+ import * as p4 from "@clack/prompts";
1859
1978
  function printNextSteps(options) {
1860
1979
  const steps = [`1. Review ${options.reviewLabel}`];
1861
1980
  if (options.needsMigration) {
@@ -1864,7 +1983,7 @@ function printNextSteps(options) {
1864
1983
  } else {
1865
1984
  steps.push(`2. Start the dev server and visit ${options.route}`);
1866
1985
  }
1867
- p3.note(steps.join("\n"), "Next steps");
1986
+ p4.note(steps.join("\n"), "Next steps");
1868
1987
  }
1869
1988
 
1870
1989
  // adapters/next/generators/post-generate.ts
@@ -1966,25 +2085,25 @@ function ensureDatabasePushDependencies(cwd, pm) {
1966
2085
  if (missing.length === 0) {
1967
2086
  return true;
1968
2087
  }
1969
- p4.log.info(
2088
+ p5.log.info(
1970
2089
  `Installing database push dependencies (${missing.map((dependency) => dependency.name).join(", ")})...`
1971
2090
  );
1972
2091
  for (const dependency of missing) {
1973
2092
  const installed2 = installDependency(cwd, pm, dependency.name, dependency.dev);
1974
2093
  if (!installed2) {
1975
- p4.log.warn(`Failed to install ${dependency.name}`);
2094
+ p5.log.warn(`Failed to install ${dependency.name}`);
1976
2095
  return false;
1977
2096
  }
1978
2097
  }
1979
2098
  const ready = hasPostgresRuntimeDependency(cwd) && hasDrizzleKitPostgresDriverDependency(cwd);
1980
2099
  if (ready) {
1981
- p4.log.success("Database push dependencies installed");
2100
+ p5.log.success("Database push dependencies installed");
1982
2101
  } else {
1983
2102
  const unresolved = [
1984
2103
  !hasPostgresRuntimeDependency(cwd) ? POSTGRES_RUNTIME_DEP : null,
1985
2104
  !hasDrizzleKitPostgresDriverDependency(cwd) ? DRIZZLE_KIT_POSTGRES_DRIVER_DEP : null
1986
2105
  ].filter((dependency) => Boolean(dependency));
1987
- p4.log.warn(`Installed dependencies but could not resolve ${unresolved.join(", ")}`);
2106
+ p5.log.warn(`Installed dependencies but could not resolve ${unresolved.join(", ")}`);
1988
2107
  }
1989
2108
  return ready;
1990
2109
  }
@@ -2027,8 +2146,8 @@ async function runPostGenerate(cwd, schemaName, options = {}) {
2027
2146
  "Formatting: skipped (biome refuses files with conflict markers)",
2028
2147
  ...(options.conflictPaths ?? []).map((conflictPath) => ` - ${conflictPath}`)
2029
2148
  ];
2030
- p4.log.warn(lines.join("\n"));
2031
- p4.log.message(
2149
+ p5.log.warn(lines.join("\n"));
2150
+ p5.log.message(
2032
2151
  "Resolve markers in the files above and re-run the BetterStart command that wrote them. Post-write tasks run automatically once every file is clean."
2033
2152
  );
2034
2153
  return result;
@@ -2038,7 +2157,7 @@ async function runPostGenerate(cwd, schemaName, options = {}) {
2038
2157
  const dbUrl = process.env.DATABASE_URL;
2039
2158
  if (!dbUrl) {
2040
2159
  result.dbPush = "no-db-url";
2041
- p4.log.warn(
2160
+ p5.log.warn(
2042
2161
  [
2043
2162
  "Database: skipped (no DATABASE_URL configured)",
2044
2163
  " To sync later: run db:push after setting DATABASE_URL"
@@ -2046,43 +2165,43 @@ async function runPostGenerate(cwd, schemaName, options = {}) {
2046
2165
  );
2047
2166
  } else if (!ensureDatabasePushDependencies(cwd, pm)) {
2048
2167
  result.dbPush = "failed";
2049
- p4.log.warn(
2168
+ p5.log.warn(
2050
2169
  "Database push failed (install database dependencies and run drizzle-kit push manually)"
2051
2170
  );
2052
2171
  } else if (hasPkgScript(cwd, "db:push")) {
2053
- p4.log.info("Running db:push...");
2172
+ p5.log.info("Running db:push...");
2054
2173
  const ok = runPmScript(pm, "db:push", cwd);
2055
2174
  result.dbPush = ok ? "success" : "failed";
2056
2175
  if (ok) {
2057
- p4.log.success("Database schema synced");
2176
+ p5.log.success("Database schema synced");
2058
2177
  } else {
2059
- p4.log.warn("Database push failed (run db:push manually)");
2178
+ p5.log.warn("Database push failed (run db:push manually)");
2060
2179
  }
2061
2180
  } else {
2062
- p4.log.info("Running drizzle-kit push...");
2181
+ p5.log.info("Running drizzle-kit push...");
2063
2182
  try {
2064
2183
  const pushResult = await runDrizzlePush(cwd, { interactive: true });
2065
2184
  if (!pushResult.success) {
2066
2185
  throw new Error(pushResult.error ?? "drizzle-kit push failed");
2067
2186
  }
2068
2187
  result.dbPush = "success";
2069
- p4.log.success("Database schema synced");
2188
+ p5.log.success("Database schema synced");
2070
2189
  } catch {
2071
2190
  result.dbPush = "failed";
2072
- p4.log.warn("Database push failed (run drizzle-kit push manually)");
2191
+ p5.log.warn("Database push failed (run drizzle-kit push manually)");
2073
2192
  }
2074
2193
  }
2075
2194
  } else {
2076
- p4.log.info(`Database: skipped (${options.skipMigrationMessage ?? "--skip-migration"})`);
2195
+ p5.log.info(`Database: skipped (${options.skipMigrationMessage ?? "--skip-migration"})`);
2077
2196
  }
2078
2197
  if (hasPkgScript(cwd, "lint:fix")) {
2079
- p4.log.info("Running lint:fix...");
2198
+ p5.log.info("Running lint:fix...");
2080
2199
  const ok = runPmScript(pm, "lint:fix", cwd, BIOME_FORMAT_TIMEOUT_MS);
2081
2200
  result.lintFix = ok ? "success" : "failed";
2082
2201
  if (ok) {
2083
- p4.log.success("Code formatted");
2202
+ p5.log.success("Code formatted");
2084
2203
  } else {
2085
- p4.log.warn("Lint fix had issues (run lint:fix manually)");
2204
+ p5.log.warn("Lint fix had issues (run lint:fix manually)");
2086
2205
  }
2087
2206
  } else {
2088
2207
  try {
@@ -2090,10 +2209,10 @@ async function runPostGenerate(cwd, schemaName, options = {}) {
2090
2209
  throw new Error("Biome binary not found");
2091
2210
  }
2092
2211
  result.lintFix = "success";
2093
- p4.log.success("Code formatted with Biome");
2212
+ p5.log.success("Code formatted with Biome");
2094
2213
  } catch {
2095
2214
  result.lintFix = "failed";
2096
- p4.log.warn("Biome formatting had issues (run biome check --write manually)");
2215
+ p5.log.warn("Biome formatting had issues (run biome check --write manually)");
2097
2216
  }
2098
2217
  }
2099
2218
  if (options.showNextSteps !== false) {
@@ -2110,7 +2229,7 @@ async function runPostGenerate(cwd, schemaName, options = {}) {
2110
2229
  // adapters/next/integration-runtime.ts
2111
2230
  import fs14 from "fs";
2112
2231
  import path17 from "path";
2113
- import * as p5 from "@clack/prompts";
2232
+ import * as p6 from "@clack/prompts";
2114
2233
 
2115
2234
  // core-engine/schema/schema-reader.ts
2116
2235
  import fs9 from "fs";
@@ -2916,15 +3035,15 @@ function collectSchemaSlotLayoutErrors(schema, errors) {
2916
3035
  }
2917
3036
  collectSlotLayoutErrors(input.slot, "slot", errors);
2918
3037
  }
2919
- function collectSlotLayoutErrors(value, path61, errors) {
3038
+ function collectSlotLayoutErrors(value, path62, errors) {
2920
3039
  if (!isRecord(value)) {
2921
- errors.push(`${path61} must be an object with "main" and/or "sidebar" field groups.`);
3040
+ errors.push(`${path62} must be an object with "main" and/or "sidebar" field groups.`);
2922
3041
  return;
2923
3042
  }
2924
3043
  const validKeys = /* @__PURE__ */ new Set(["main", "sidebar"]);
2925
3044
  for (const key of Object.keys(value)) {
2926
3045
  if (!validKeys.has(key)) {
2927
- errors.push(`${path61} has unsupported key "${key}". Expected "main" or "sidebar".`);
3046
+ errors.push(`${path62} has unsupported key "${key}". Expected "main" or "sidebar".`);
2928
3047
  }
2929
3048
  }
2930
3049
  const areas = [
@@ -2935,24 +3054,24 @@ function collectSlotLayoutErrors(value, path61, errors) {
2935
3054
  for (const [name, area] of areas) {
2936
3055
  if (area === void 0) continue;
2937
3056
  hasArea = true;
2938
- collectSlotAreaErrors(area, `${path61}.${name}`, errors);
3057
+ collectSlotAreaErrors(area, `${path62}.${name}`, errors);
2939
3058
  }
2940
3059
  if (!hasArea) {
2941
- errors.push(`${path61} must define at least one of "main" or "sidebar".`);
3060
+ errors.push(`${path62} must define at least one of "main" or "sidebar".`);
2942
3061
  }
2943
3062
  }
2944
- function collectSlotAreaErrors(value, path61, errors) {
3063
+ function collectSlotAreaErrors(value, path62, errors) {
2945
3064
  if (!isRecord(value)) {
2946
- errors.push(`${path61} must be an object with a "fields" array.`);
3065
+ errors.push(`${path62} must be an object with a "fields" array.`);
2947
3066
  return;
2948
3067
  }
2949
3068
  const fields = value.fields;
2950
3069
  if (!Array.isArray(fields)) {
2951
- errors.push(`${path61}.fields must be an array.`);
3070
+ errors.push(`${path62}.fields must be an array.`);
2952
3071
  return;
2953
3072
  }
2954
3073
  for (const field of fields) {
2955
- walkSlot(field, `${path61}.fields.${field.name ?? "unnamed"}`, errors);
3074
+ walkSlot(field, `${path62}.fields.${field.name ?? "unnamed"}`, errors);
2956
3075
  }
2957
3076
  }
2958
3077
  function collectInvalidHeightErrors(topLevelFields, rootPath, errors) {
@@ -3436,12 +3555,12 @@ async function resolveTextEnvValue(options) {
3436
3555
  if (existingValue) {
3437
3556
  return existingValue;
3438
3557
  }
3439
- const result = await p5.text({
3558
+ const result = await p6.text({
3440
3559
  message: options.message,
3441
3560
  defaultValue: options.defaultValue,
3442
3561
  validate: options.validate
3443
3562
  });
3444
- if (p5.isCancel(result)) {
3563
+ if (p6.isCancel(result)) {
3445
3564
  throw new Error(options.cancelMessage);
3446
3565
  }
3447
3566
  options.overwriteEnvKeys.add(options.key);
@@ -3452,11 +3571,11 @@ async function resolvePasswordEnvValue(options) {
3452
3571
  if (existingValue) {
3453
3572
  return existingValue;
3454
3573
  }
3455
- const result = await p5.password({
3574
+ const result = await p6.password({
3456
3575
  message: options.message,
3457
3576
  validate: options.validate
3458
3577
  });
3459
- if (p5.isCancel(result)) {
3578
+ if (p6.isCancel(result)) {
3460
3579
  throw new Error(options.cancelMessage);
3461
3580
  }
3462
3581
  options.overwriteEnvKeys.add(options.key);
@@ -4788,9 +4907,9 @@ function getReadFieldType(field) {
4788
4907
  }
4789
4908
  return getFieldType(field, "output");
4790
4909
  }
4791
- function collectReadSelectFields(fields, path61 = []) {
4910
+ function collectReadSelectFields(fields, path62 = []) {
4792
4911
  const matches = fields.flatMap((field) => {
4793
- const currentPath = [...path61, field.name];
4912
+ const currentPath = [...path62, field.name];
4794
4913
  const matches2 = field.type === "select" ? [{ field, path: currentPath }] : [];
4795
4914
  if (field.fields) {
4796
4915
  matches2.push(...collectReadSelectFields(field.fields, currentPath));
@@ -5837,14 +5956,14 @@ function buildStepsConstant(steps) {
5837
5956
  ${entries.join(",\n")}
5838
5957
  ]`;
5839
5958
  }
5840
- function buildComponentSource(p31) {
5959
+ function buildComponentSource(p32) {
5841
5960
  const providerOpen = ` <NuqsAdapter>
5842
5961
  <React.Suspense fallback={null}>
5843
- <${p31.pascal}FormInner />
5962
+ <${p32.pascal}FormInner />
5844
5963
  </React.Suspense>
5845
5964
  </NuqsAdapter>`;
5846
5965
  const exportWrapper = `
5847
- export function ${p31.pascal}Form() {
5966
+ export function ${p32.pascal}Form() {
5848
5967
  return (
5849
5968
  ${providerOpen}
5850
5969
  )
@@ -5853,22 +5972,22 @@ ${providerOpen}
5853
5972
  return `'use client'
5854
5973
 
5855
5974
  import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'
5856
- import { ChevronLeft, ChevronRight${p31.hasListFields ? ", Trash2" : ""} } from 'lucide-react'
5975
+ import { ChevronLeft, ChevronRight${p32.hasListFields ? ", Trash2" : ""} } from 'lucide-react'
5857
5976
  import { createParser, useQueryState } from 'nuqs'
5858
5977
  import { NuqsAdapter } from 'nuqs/adapters/next/app'
5859
5978
  import * as React from 'react'
5860
- ${p31.rhfImport}
5979
+ ${p32.rhfImport}
5861
5980
  import { z } from 'zod/v3'
5862
- import { create${p31.pascal}Submission } from '@admin/actions/${p31.actionImportPath}'
5981
+ import { create${p32.pascal}Submission } from '@admin/actions/${p32.actionImportPath}'
5863
5982
 
5864
5983
  const formSchema = z.object({
5865
- ${p31.zodFields}
5984
+ ${p32.zodFields}
5866
5985
  })
5867
5986
 
5868
5987
  type FormValues = z.infer<typeof formSchema>
5869
5988
  ${buildFieldErrorHelper()}
5870
5989
 
5871
- ${p31.stepsConst}
5990
+ ${p32.stepsConst}
5872
5991
 
5873
5992
  const stepParser = createParser({
5874
5993
  parse(value) {
@@ -5886,7 +6005,7 @@ const stepParser = createParser({
5886
6005
  }
5887
6006
  }).withDefault(0)
5888
6007
 
5889
- function ${p31.pascal}FormInner() {
6008
+ function ${p32.pascal}FormInner() {
5890
6009
  const [currentStep, setCurrentStep] = useQueryState('step', stepParser)
5891
6010
  const [submitted, setSubmitted] = React.useState(false)
5892
6011
  const [submitting, startSubmitTransition] = React.useTransition()
@@ -5894,11 +6013,11 @@ function ${p31.pascal}FormInner() {
5894
6013
  const form = useForm<FormValues>({
5895
6014
  resolver: standardSchemaResolver(formSchema),
5896
6015
  defaultValues: {
5897
- ${p31.defaults}
6016
+ ${p32.defaults}
5898
6017
  },
5899
6018
  })
5900
6019
 
5901
- ${p31.fieldArraySetup}${p31.watchSetup}
6020
+ ${p32.fieldArraySetup}${p32.watchSetup}
5902
6021
  async function handleNext() {
5903
6022
  const stepFields = STEPS[currentStep].fields as (keyof FormValues)[]
5904
6023
  const isValid = await form.trigger(stepFields, { shouldFocus: true })
@@ -5914,9 +6033,9 @@ ${p31.fieldArraySetup}${p31.watchSetup}
5914
6033
  function onSubmit(values: FormValues) {
5915
6034
  startSubmitTransition(async () => {
5916
6035
  try {
5917
- const result = await create${p31.pascal}Submission(values)
6036
+ const result = await create${p32.pascal}Submission(values)
5918
6037
  if (result.success) {
5919
- ${p31.successHandler}
6038
+ ${p32.successHandler}
5920
6039
  } else {
5921
6040
  form.setError('root', { message: result.error || 'Something went wrong' })
5922
6041
  }
@@ -5930,7 +6049,7 @@ ${p31.fieldArraySetup}${p31.watchSetup}
5930
6049
  return (
5931
6050
  <div className="rounded-sm border p-6 text-center">
5932
6051
  <h3 className="text-lg font-semibold">Thank you!</h3>
5933
- <p className="mt-2 text-muted-foreground">${p31.successMessage}</p>
6052
+ <p className="mt-2 text-muted-foreground">${p32.successMessage}</p>
5934
6053
  </div>
5935
6054
  )
5936
6055
  }
@@ -5947,7 +6066,7 @@ ${p31.fieldArraySetup}${p31.watchSetup}
5947
6066
 
5948
6067
  {/* Step content */}
5949
6068
  <div key={currentStep} className="animate-in fade-in duration-300 space-y-6">
5950
- ${p31.stepContentBlocks}
6069
+ ${p32.stepContentBlocks}
5951
6070
  </div>
5952
6071
 
5953
6072
  {form.formState.errors.root && (
@@ -5981,7 +6100,7 @@ ${p31.stepContentBlocks}
5981
6100
  onClick={() => form.handleSubmit(onSubmit)()}
5982
6101
  className="inline-flex h-9 items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-xs transition-colors hover:bg-primary/90 disabled:pointer-events-none disabled:opacity-50"
5983
6102
  >
5984
- {submitting ? 'Submitting...' : ${p31.submitText}}
6103
+ {submitting ? 'Submitting...' : ${p32.submitText}}
5985
6104
  </button>
5986
6105
  )}
5987
6106
  </div>
@@ -13997,14 +14116,14 @@ function safeIdentifier(value, fallback) {
13997
14116
  const base = pascal ? `${pascal.charAt(0).toLowerCase()}${pascal.slice(1)}` : fallback;
13998
14117
  return /^[A-Za-z_$]/.test(base) ? base : fallback;
13999
14118
  }
14000
- function pathExpression(path61) {
14001
- return `\`${path61.map((part) => typeof part === "string" ? part : `\${${part.expression}}`).join(".")}\``;
14119
+ function pathExpression(path62) {
14120
+ return `\`${path62.map((part) => typeof part === "string" ? part : `\${${part.expression}}`).join(".")}\``;
14002
14121
  }
14003
- function pathNameProp(path61) {
14004
- if (path61.every((part) => typeof part === "string")) {
14005
- return `"${path61.map((part) => part).join(".")}"`;
14122
+ function pathNameProp(path62) {
14123
+ if (path62.every((part) => typeof part === "string")) {
14124
+ return `"${path62.map((part) => part).join(".")}"`;
14006
14125
  }
14007
- return `{${pathExpression(path61)}}`;
14126
+ return `{${pathExpression(path62)}}`;
14008
14127
  }
14009
14128
  function findTitlePath(fields) {
14010
14129
  const stringTypes = ["string", "varchar", "text"];
@@ -14026,23 +14145,23 @@ function findTitlePath(fields) {
14026
14145
  function requiredLeafPaths(fields, prefix = []) {
14027
14146
  return fields.flatMap((field) => {
14028
14147
  if (field.hidden) return [];
14029
- const path61 = [...prefix, field.name];
14148
+ const path62 = [...prefix, field.name];
14030
14149
  if ((field.type === "group" || field.type === "section") && field.fields?.length) {
14031
- return requiredLeafPaths(field.fields, path61);
14150
+ return requiredLeafPaths(field.fields, path62);
14032
14151
  }
14033
- if (field.required) return [path61.join(".")];
14152
+ if (field.required) return [path62.join(".")];
14034
14153
  return [];
14035
14154
  });
14036
14155
  }
14037
14156
  function validationTriggerExpression(basePath, requiredPaths) {
14038
14157
  if (requiredPaths.length === 0) return `\`${basePath}.\${expandedIndex}\` as never`;
14039
- const paths = requiredPaths.map((path61) => `\`${basePath}.\${expandedIndex}.${path61}\``).join(", ");
14158
+ const paths = requiredPaths.map((path62) => `\`${basePath}.\${expandedIndex}.${path62}\``).join(", ");
14040
14159
  return `[${paths}] as never`;
14041
14160
  }
14042
- function renderTextInputField(field, indent, label, nestedHint, path61) {
14161
+ function renderTextInputField(field, indent, label, nestedHint, path62) {
14043
14162
  return `${indent}<FormField
14044
14163
  ${indent} control={form.control}
14045
- ${indent} name=${pathNameProp(path61)}
14164
+ ${indent} name=${pathNameProp(path62)}
14046
14165
  ${indent} render={({ field: formField }) => (
14047
14166
  ${indent} <FormItem${formItemProps(field)}>
14048
14167
  ${indent} ${labelWithDescription(formLabel(field, label), nestedHint, `${indent} `)}
@@ -14054,11 +14173,11 @@ ${indent} </FormItem>
14054
14173
  ${indent} )}
14055
14174
  ${indent}/>`;
14056
14175
  }
14057
- function renderNestedField(field, indent, path61, depth) {
14176
+ function renderNestedField(field, indent, path62, depth) {
14058
14177
  const nestedLabel = field.label || field.name;
14059
14178
  const nestedHint = field.hint ? `<FormDescription>${field.hint}</FormDescription>` : "";
14060
14179
  if ((field.type === "group" || field.type === "section") && field.fields?.length) {
14061
- const groupFields = field.fields.map((child) => renderNestedField(child, `${indent} `, [...path61, child.name], depth)).filter(Boolean).join("\n");
14180
+ const groupFields = field.fields.map((child) => renderNestedField(child, `${indent} `, [...path62, child.name], depth)).filter(Boolean).join("\n");
14062
14181
  if (!groupFields) return "";
14063
14182
  const heading = nestedLabel && nestedLabel !== field.name ? `${indent}<h3 className="text-base font-medium">${nestedLabel}</h3>
14064
14183
  ` : "";
@@ -14068,7 +14187,7 @@ ${groupFields}
14068
14187
  ${indent}</div>`;
14069
14188
  }
14070
14189
  if (field.type === "list" && field.fields?.length) {
14071
- return renderNestedObjectListField(field, indent, nestedLabel, path61, depth);
14190
+ return renderNestedObjectListField(field, indent, nestedLabel, path62, depth);
14072
14191
  }
14073
14192
  if (field.type === "list") {
14074
14193
  const hideLabelProp = field.label ? "" : `
@@ -14076,7 +14195,7 @@ ${indent} hideLabel`;
14076
14195
  const descriptionProp = field.hint ? `
14077
14196
  ${indent} description={${JSON.stringify(field.hint)}}` : "";
14078
14197
  return `${indent}<DynamicListField
14079
- ${indent} name={${pathExpression(path61)}}
14198
+ ${indent} name={${pathExpression(path62)}}
14080
14199
  ${indent} label="${nestedLabel}"${hideLabelProp}${descriptionProp}
14081
14200
  ${indent} disabled={isPending}${field.maxItems ? `
14082
14201
  ${indent} maxItems={${field.maxItems}}` : ""}
@@ -14086,7 +14205,7 @@ ${indent}/>`;
14086
14205
  if (field.type === "boolean") {
14087
14206
  return `${indent}<FormField
14088
14207
  ${indent} control={form.control}
14089
- ${indent} name=${pathNameProp(path61)}
14208
+ ${indent} name=${pathNameProp(path62)}
14090
14209
  ${indent} render={({ field: formField }) => (
14091
14210
  ${indent} <FormItem${formItemProps(field, "flex flex-row items-start space-x-3 space-y-0")}>
14092
14211
  ${indent} <FormControl>
@@ -14101,7 +14220,7 @@ ${indent}/>`;
14101
14220
  const acceptProp = field.type === "image" ? ' accept="image/*"' : field.type === "video" ? ' accept="video/*"' : "";
14102
14221
  return `${indent}<FormField
14103
14222
  ${indent} control={form.control}
14104
- ${indent} name=${pathNameProp(path61)}
14223
+ ${indent} name=${pathNameProp(path62)}
14105
14224
  ${indent} render={({ field: formField }) => (
14106
14225
  ${indent} <FormItem${formItemProps(field)}>
14107
14226
  ${indent} ${labelWithDescription(formLabel(field, nestedLabel), nestedHint, `${indent} `)}
@@ -14116,7 +14235,7 @@ ${indent}/>`;
14116
14235
  if (field.type === "icon") {
14117
14236
  return `${indent}<FormField
14118
14237
  ${indent} control={form.control}
14119
- ${indent} name=${pathNameProp(path61)}
14238
+ ${indent} name=${pathNameProp(path62)}
14120
14239
  ${indent} render={({ field: formField }) => (
14121
14240
  ${indent} <FormItem${formItemProps(field)}>
14122
14241
  ${indent} ${labelWithDescription(formLabel(field, nestedLabel), nestedHint, `${indent} `)}
@@ -14133,7 +14252,7 @@ ${indent}/>`;
14133
14252
  const emptyValue = field.required ? "undefined" : "null";
14134
14253
  return `${indent}<FormField
14135
14254
  ${indent} control={form.control}
14136
- ${indent} name=${pathNameProp(path61)}
14255
+ ${indent} name=${pathNameProp(path62)}
14137
14256
  ${indent} render={({ field: formField }) => (
14138
14257
  ${indent} <FormItem${formItemProps(field)}>
14139
14258
  ${indent} ${labelWithDescription(formLabel(field, nestedLabel), nestedHint, `${indent} `)}
@@ -14158,16 +14277,16 @@ ${indent} </FormItem>
14158
14277
  ${indent} )}
14159
14278
  ${indent}/>`;
14160
14279
  }
14161
- return renderTextInputField(field, indent, nestedLabel, nestedHint, path61);
14280
+ return renderTextInputField(field, indent, nestedLabel, nestedHint, path62);
14162
14281
  }
14163
- function renderNestedObjectListField(field, indent, label, path61, depth) {
14282
+ function renderNestedObjectListField(field, indent, label, path62, depth) {
14164
14283
  const singularLabel = singularize(label);
14165
14284
  const itemIndexVar = `${safeIdentifier(field.name, "nestedList")}Index${depth}`;
14166
14285
  const titlePath = findTitlePath(field.fields ?? []);
14167
14286
  const titlePathSuffix = titlePath ? `.${titlePath.join(".")}` : "";
14168
14287
  const renderTitleProp = titlePath ? `
14169
14288
  ${indent} renderTitle={(${itemIndexVar}) =>
14170
- ${indent} String(form.watch(\`${path61.map((part) => typeof part === "string" ? part : `\${${part.expression}}`).join(
14289
+ ${indent} String(form.watch(\`${path62.map((part) => typeof part === "string" ? part : `\${${part.expression}}`).join(
14171
14290
  "."
14172
14291
  )}.\${${itemIndexVar}}${titlePathSuffix}\` as never) || \`${singularLabel} \${${itemIndexVar} + 1}\`)
14173
14292
  ${indent} }` : "";
@@ -14175,7 +14294,7 @@ ${indent} }` : "";
14175
14294
  (child) => renderNestedField(
14176
14295
  child,
14177
14296
  `${indent} `,
14178
- [...path61, { expression: itemIndexVar }, child.name],
14297
+ [...path62, { expression: itemIndexVar }, child.name],
14179
14298
  depth + 1
14180
14299
  )
14181
14300
  ).filter(Boolean).join("\n");
@@ -14190,7 +14309,7 @@ ${indent} maxItems={${field.maxItems}}` : "";
14190
14309
  const validatePathsProp = validatePaths.length > 0 ? `
14191
14310
  ${indent} validatePaths={${JSON.stringify(validatePaths)}}` : "";
14192
14311
  return `${indent}<NestedObjectListField
14193
- ${indent} name={${pathExpression(path61)}}
14312
+ ${indent} name={${pathExpression(path62)}}
14194
14313
  ${indent} label={${JSON.stringify(label)}}
14195
14314
  ${indent} singularLabel={${JSON.stringify(singularLabel)}}
14196
14315
  ${indent} defaultValue={${defaultItem}}
@@ -17805,7 +17924,7 @@ function readPresetTemplate(presetId, relativePath) {
17805
17924
  // adapters/next/snapshots/apply.ts
17806
17925
  import fs20 from "fs";
17807
17926
  import path24 from "path";
17808
- import * as p6 from "@clack/prompts";
17927
+ import * as p7 from "@clack/prompts";
17809
17928
 
17810
17929
  // core-engine/snapshots/ast-substitution.ts
17811
17930
  import { Node, Project } from "ts-morph";
@@ -17826,7 +17945,7 @@ function applyTextEdits(content, edits) {
17826
17945
  content
17827
17946
  );
17828
17947
  }
17829
- function collectPreviewChanges(path61, beforeContent, afterContent) {
17948
+ function collectPreviewChanges(path62, beforeContent, afterContent) {
17830
17949
  const beforeLines = beforeContent.split("\n");
17831
17950
  const afterLines = afterContent.split("\n");
17832
17951
  const maxLength = Math.max(beforeLines.length, afterLines.length);
@@ -17838,7 +17957,7 @@ function collectPreviewChanges(path61, beforeContent, afterContent) {
17838
17957
  continue;
17839
17958
  }
17840
17959
  changes.push({
17841
- path: path61,
17960
+ path: path62,
17842
17961
  line: index + 1,
17843
17962
  before: before.trim(),
17844
17963
  after: after.trim()
@@ -18468,11 +18587,11 @@ function buildMergeInput(cwd, baseFile, localContent, remoteFile) {
18468
18587
  }
18469
18588
  };
18470
18589
  }
18471
- function isInteractiveSession(interactive) {
18590
+ function isInteractiveSession2(interactive) {
18472
18591
  return interactive && Boolean(process.stdin.isTTY) && process.env.CI !== "true";
18473
18592
  }
18474
18593
  async function promptNoBaseDecision(filePath) {
18475
- const answer = await p6.select({
18594
+ const answer = await p7.select({
18476
18595
  message: `File already exists without snapshot base: ${filePath}`,
18477
18596
  options: [
18478
18597
  { value: "backup", label: "Backup and overwrite", hint: "recommended" },
@@ -18481,7 +18600,7 @@ async function promptNoBaseDecision(filePath) {
18481
18600
  ],
18482
18601
  initialValue: "backup"
18483
18602
  });
18484
- if (p6.isCancel(answer)) {
18603
+ if (p7.isCancel(answer)) {
18485
18604
  throw new Error("Generation cancelled.");
18486
18605
  }
18487
18606
  return answer;
@@ -18517,7 +18636,7 @@ async function applyGeneratedFiles({
18517
18636
  const remoteFiles = sortGeneratedFiles(generatedFiles);
18518
18637
  const remotePaths = new Set(remoteFiles.map((file) => file.path));
18519
18638
  const skipped = new Set(force ? [] : manifest?.skipped ?? []);
18520
- const interactiveSession = isInteractiveSession(interactive);
18639
+ const interactiveSession = isInteractiveSession2(interactive);
18521
18640
  const aliasMap = renamePlan ? buildRenamePlanAliasMap(renamePlan) : /* @__PURE__ */ new Map();
18522
18641
  const consumedBasePaths = /* @__PURE__ */ new Set();
18523
18642
  let baseFiles = /* @__PURE__ */ new Map();
@@ -19362,18 +19481,18 @@ async function runAddCommand(items, options) {
19362
19481
  const presetIds = items.filter(isPresetId);
19363
19482
  const integrationIds = items.filter(isIntegrationId);
19364
19483
  if (!installIntegrationsMode && integrationIds.length > 0) {
19365
- p7.log.error(
19484
+ p8.log.error(
19366
19485
  `Integration IDs require --integration. Run \`betterstart add --integration ${integrationIds.join(" ")}\`.`
19367
19486
  );
19368
19487
  process.exit(1);
19369
19488
  }
19370
19489
  if (installIntegrationsMode && presetIds.length > 0) {
19371
- p7.log.error(`Preset IDs cannot be installed with --integration: ${presetIds.join(", ")}`);
19490
+ p8.log.error(`Preset IDs cannot be installed with --integration: ${presetIds.join(", ")}`);
19372
19491
  process.exit(1);
19373
19492
  }
19374
19493
  const invalidItems = installIntegrationsMode ? items.filter((integrationId) => !isIntegrationId(integrationId)) : items.filter((presetId) => !isPresetId(presetId));
19375
19494
  if (invalidItems.length > 0) {
19376
- p7.log.error(
19495
+ p8.log.error(
19377
19496
  installIntegrationsMode ? formatUnknownIntegrationMessage(invalidItems) : formatUnknownPresetMessage(invalidItems)
19378
19497
  );
19379
19498
  process.exit(1);
@@ -19384,7 +19503,7 @@ async function runAddCommand(items, options) {
19384
19503
  const pm = detectPackageManager(cwd);
19385
19504
  const cliSyncResult = await syncProjectCliDependency(cwd, pm);
19386
19505
  if (cliSyncResult && !cliSyncResult.success) {
19387
- p7.log.error(cliSyncResult.error ?? "Failed to sync betterstart-cli");
19506
+ p8.log.error(cliSyncResult.error ?? "Failed to sync betterstart-cli");
19388
19507
  process.exit(1);
19389
19508
  }
19390
19509
  if (installIntegrationsMode) {
@@ -19398,10 +19517,10 @@ async function runAddCommand(items, options) {
19398
19517
  });
19399
19518
  writeConfigFile(cwd, result2.config);
19400
19519
  if (result2.warnings.length > 0) {
19401
- p7.note(result2.warnings.join("\n"), "Warnings");
19520
+ p8.note(result2.warnings.join("\n"), "Warnings");
19402
19521
  }
19403
19522
  if (result2.installed.length === 0 && result2.activated.length === 0 && result2.skipped.length > 0) {
19404
- p7.outro(`No changes made. Already installed: ${result2.skipped.join(", ")}`);
19523
+ p8.outro(`No changes made. Already installed: ${result2.skipped.join(", ")}`);
19405
19524
  return;
19406
19525
  }
19407
19526
  const conflictPaths2 = scanConflictPaths(cwd);
@@ -19423,12 +19542,12 @@ async function runAddCommand(items, options) {
19423
19542
  result2.installed.length > 0 ? `Installed integration${result2.installed.length === 1 ? "" : "s"}: ${result2.installed.join(", ")}` : null,
19424
19543
  result2.activated.length > 0 ? `Activated integration${result2.activated.length === 1 ? "" : "s"}: ${result2.activated.join(", ")}` : null
19425
19544
  ].filter(Boolean);
19426
- p7.outro(messages.join("\n"));
19545
+ p8.outro(messages.join("\n"));
19427
19546
  return;
19428
19547
  }
19429
19548
  const invalidPresets = items.filter((presetId) => !isPresetId(presetId));
19430
19549
  if (invalidPresets.length > 0) {
19431
- p7.log.error(formatUnknownPresetMessage(invalidPresets));
19550
+ p8.log.error(formatUnknownPresetMessage(invalidPresets));
19432
19551
  process.exit(1);
19433
19552
  }
19434
19553
  const result = await installPresets({
@@ -19441,11 +19560,11 @@ async function runAddCommand(items, options) {
19441
19560
  });
19442
19561
  writeConfigFile(cwd, result.config);
19443
19562
  if (result.installed.length === 0 && result.skipped.length > 0) {
19444
- p7.outro(`No changes made. Already installed: ${result.skipped.join(", ")}`);
19563
+ p8.outro(`No changes made. Already installed: ${result.skipped.join(", ")}`);
19445
19564
  return;
19446
19565
  }
19447
19566
  if (result.warnings.length > 0) {
19448
- p7.note(result.warnings.join("\n"), "Warnings");
19567
+ p8.note(result.warnings.join("\n"), "Warnings");
19449
19568
  }
19450
19569
  const installedSchemaNames = result.installed.flatMap(
19451
19570
  (presetId) => getPresetDefinition(presetId).schemaFiles.map((schemaFile) => schemaFile.replace(/\.json$/, ""))
@@ -19462,14 +19581,14 @@ async function runAddCommand(items, options) {
19462
19581
  if (conflictPaths.length === 0) {
19463
19582
  printAddNextSteps("preset", hasSchemaChanges, postGenerateResult, adminRoutePath);
19464
19583
  }
19465
- p7.outro(
19584
+ p8.outro(
19466
19585
  `Installed preset${result.installed.length === 1 ? "" : "s"}: ${result.installed.join(", ")}`
19467
19586
  );
19468
19587
  }
19469
19588
 
19470
19589
  // adapters/next/commands/add-field.ts
19471
19590
  import path30 from "path";
19472
- import * as p11 from "@clack/prompts";
19591
+ import * as p12 from "@clack/prompts";
19473
19592
 
19474
19593
  // core-engine/schema/add-field.ts
19475
19594
  import fs23 from "fs";
@@ -20121,7 +20240,7 @@ function getTabFields(tab) {
20121
20240
  // adapters/next/commands/generate.ts
20122
20241
  import fs24 from "fs";
20123
20242
  import path29 from "path";
20124
- import * as p9 from "@clack/prompts";
20243
+ import * as p10 from "@clack/prompts";
20125
20244
 
20126
20245
  // core-engine/snapshots/rename-detector.ts
20127
20246
  function levenshtein(a, b) {
@@ -20215,7 +20334,7 @@ function diffSchemas(before, after) {
20215
20334
 
20216
20335
  // core-engine/utils/spinner.ts
20217
20336
  import { stripVTControlCharacters } from "util";
20218
- import * as p8 from "@clack/prompts";
20337
+ import * as p9 from "@clack/prompts";
20219
20338
  var RENDER_OVERHEAD = 7;
20220
20339
  var MIN_MESSAGE_WIDTH = 8;
20221
20340
  function fitSpinnerMessage(message) {
@@ -20262,7 +20381,7 @@ function hasActiveSpinner() {
20262
20381
  return activeSpinners > 0;
20263
20382
  }
20264
20383
  function spinner2(options) {
20265
- const inner = p8.spinner({ ...options, cancelMessage: "Setup cancelled." });
20384
+ const inner = p9.spinner({ ...options, cancelMessage: "Setup cancelled." });
20266
20385
  const guided = options?.withGuide !== false;
20267
20386
  let started = false;
20268
20387
  const setStarted = (next) => {
@@ -20296,7 +20415,7 @@ function spinner2(options) {
20296
20415
  }
20297
20416
 
20298
20417
  // adapters/next/commands/generate.ts
20299
- function isInteractiveSession2() {
20418
+ function isInteractiveSession3() {
20300
20419
  return Boolean(process.stdin.isTTY) && process.env.CI !== "true";
20301
20420
  }
20302
20421
  function isStoredSchemaJson(schemaJson) {
@@ -20381,7 +20500,7 @@ function assertSnapshotStateOrExit(cwd) {
20381
20500
  if (snapshotRootExists(cwd)) {
20382
20501
  return;
20383
20502
  }
20384
- p9.log.error(UNSUPPORTED_PROJECT_STATE_MESSAGE);
20503
+ p10.log.error(UNSUPPORTED_PROJECT_STATE_MESSAGE);
20385
20504
  process.exit(1);
20386
20505
  }
20387
20506
  function printSchemaDiff(scope, loaded, cwd) {
@@ -20416,14 +20535,14 @@ function printSchemaDiff(scope, loaded, cwd) {
20416
20535
  ` custom cells: +[${diff.customComponents.added.join(", ")}] -[${diff.customComponents.removed.join(", ")}]`
20417
20536
  );
20418
20537
  }
20419
- p9.log.message(lines.join("\n"));
20538
+ p10.log.message(lines.join("\n"));
20420
20539
  }
20421
20540
  async function promptConfirm(message) {
20422
- const result = await p9.confirm({
20541
+ const result = await p10.confirm({
20423
20542
  message,
20424
20543
  initialValue: true
20425
20544
  });
20426
- if (p9.isCancel(result)) {
20545
+ if (p10.isCancel(result)) {
20427
20546
  throw new Error("Generation cancelled.");
20428
20547
  }
20429
20548
  return Boolean(result);
@@ -20553,7 +20672,7 @@ async function maybeBuildRenamePlan(loaded, cwd, config, generatedFiles, options
20553
20672
  };
20554
20673
  if (finalPlan.fields.length === 0 && finalPlan.customCells.length === 0) {
20555
20674
  if (validatedCustomCells.warnings.length > 0) {
20556
- p9.log.warn(validatedCustomCells.warnings.join("\n"));
20675
+ p10.log.warn(validatedCustomCells.warnings.join("\n"));
20557
20676
  }
20558
20677
  return void 0;
20559
20678
  }
@@ -20571,10 +20690,10 @@ async function maybeBuildRenamePlan(loaded, cwd, config, generatedFiles, options
20571
20690
  if (preview.previewLines.length > previewLines.length) {
20572
20691
  renameLines.push(` ... ${preview.previewLines.length - previewLines.length} more change(s)`);
20573
20692
  }
20574
- p9.log.message(renameLines.join("\n"));
20693
+ p10.log.message(renameLines.join("\n"));
20575
20694
  const warnings = [...validatedCustomCells.warnings, ...preview.warnings];
20576
20695
  if (warnings.length > 0) {
20577
- p9.log.warn(warnings.join("\n"));
20696
+ p10.log.warn(warnings.join("\n"));
20578
20697
  }
20579
20698
  const confirmed = await promptConfirm("Apply these rename substitutions before merge?");
20580
20699
  return confirmed ? finalPlan : void 0;
@@ -20685,16 +20804,16 @@ function printApplySummary(schemaName, summary) {
20685
20804
  if (summary.skippedCleared.length > 0) {
20686
20805
  lines.push(` skip entries cleared: ${summary.skippedCleared.join(", ")}`);
20687
20806
  }
20688
- p9.log.message(lines.join("\n"));
20807
+ p10.log.message(lines.join("\n"));
20689
20808
  }
20690
20809
  async function runGenerateCommand(schemaName, options) {
20691
20810
  const cwd = options.cwd ? path29.resolve(options.cwd) : process.cwd();
20692
- const interactive = options.all ? options.interactive && isInteractiveSession2() : isInteractiveSession2();
20811
+ const interactive = options.all ? options.interactive && isInteractiveSession3() : isInteractiveSession3();
20693
20812
  let config;
20694
20813
  try {
20695
20814
  config = await resolveConfig(cwd);
20696
20815
  } catch (error) {
20697
- p9.log.error(`Error loading config: ${error instanceof Error ? error.message : String(error)}`);
20816
+ p10.log.error(`Error loading config: ${error instanceof Error ? error.message : String(error)}`);
20698
20817
  process.exit(1);
20699
20818
  }
20700
20819
  assertSnapshotStateOrExit(cwd);
@@ -20704,7 +20823,7 @@ async function runGenerateCommand(schemaName, options) {
20704
20823
  if (options.all) {
20705
20824
  const schemaNames = listSchemaNames(schemasDir);
20706
20825
  if (schemaNames.length === 0) {
20707
- p9.log.error(`No schemas found in ${schemasDir}`);
20826
+ p10.log.error(`No schemas found in ${schemasDir}`);
20708
20827
  process.exit(1);
20709
20828
  }
20710
20829
  const failed = [];
@@ -20712,14 +20831,14 @@ async function runGenerateCommand(schemaName, options) {
20712
20831
  const processedRoutes = [];
20713
20832
  let markdownDepsChecked = false;
20714
20833
  const adminRoutePath2 = resolveAdminNamespace(config.frameworkConfig.next.namespace).routePath;
20715
- p9.intro(`BetterStart Generator \u2014 regenerating ${schemaNames.length} schema(s)`);
20834
+ p10.intro(`BetterStart Generator \u2014 regenerating ${schemaNames.length} schema(s)`);
20716
20835
  for (const name of schemaNames) {
20717
20836
  if (hasTombstone(cwd, name)) {
20718
20837
  if (loadManifest(cwd, name)) {
20719
20838
  clearTombstone(cwd, name);
20720
- p9.log.warn(`${name}: tombstone cleared (manifest present)`);
20839
+ p10.log.warn(`${name}: tombstone cleared (manifest present)`);
20721
20840
  } else {
20722
- p9.log.message(`${name}: skipped (tombstoned)`);
20841
+ p10.log.message(`${name}: skipped (tombstoned)`);
20723
20842
  continue;
20724
20843
  }
20725
20844
  }
@@ -20745,7 +20864,7 @@ async function runGenerateCommand(schemaName, options) {
20745
20864
  processed.push(name);
20746
20865
  processedRoutes.push(getGeneratedSchemaRoutePath(loaded2, adminRoutePath2));
20747
20866
  } catch (error) {
20748
- p9.log.error(`${name}: ${error instanceof Error ? error.message : String(error)}`);
20867
+ p10.log.error(`${name}: ${error instanceof Error ? error.message : String(error)}`);
20749
20868
  failed.push(name);
20750
20869
  }
20751
20870
  }
@@ -20768,14 +20887,14 @@ async function runGenerateCommand(schemaName, options) {
20768
20887
  });
20769
20888
  }
20770
20889
  if (failed.length > 0) {
20771
- p9.log.error(`Failed: ${failed.join(", ")}`);
20890
+ p10.log.error(`Failed: ${failed.join(", ")}`);
20772
20891
  process.exit(1);
20773
20892
  }
20774
- p9.outro(`Regenerated ${processed.length}/${schemaNames.length} schema(s)`);
20893
+ p10.outro(`Regenerated ${processed.length}/${schemaNames.length} schema(s)`);
20775
20894
  return;
20776
20895
  }
20777
20896
  if (!schemaName) {
20778
- p9.log.error("Error: schema name is required (or use --all)");
20897
+ p10.log.error("Error: schema name is required (or use --all)");
20779
20898
  process.exit(1);
20780
20899
  }
20781
20900
  let loaded;
@@ -20783,20 +20902,20 @@ async function runGenerateCommand(schemaName, options) {
20783
20902
  loaded = loadSchema(schemasDir, schemaName);
20784
20903
  } catch (error) {
20785
20904
  if (error instanceof SchemaNotFoundError) {
20786
- p9.log.error(error.message);
20905
+ p10.log.error(error.message);
20787
20906
  } else {
20788
- p9.log.error(`Error loading schema: ${error instanceof Error ? error.message : String(error)}`);
20907
+ p10.log.error(`Error loading schema: ${error instanceof Error ? error.message : String(error)}`);
20789
20908
  }
20790
20909
  process.exit(1);
20791
20910
  }
20792
20911
  const validationErrors = validateLoadedSchema(loaded);
20793
20912
  if (validationErrors.length > 0) {
20794
- p9.log.error(
20913
+ p10.log.error(
20795
20914
  ["Schema validation failed:", ...validationErrors.map((error) => ` - ${error}`)].join("\n")
20796
20915
  );
20797
20916
  process.exit(1);
20798
20917
  }
20799
- p9.intro(`BetterStart Generator \u2014 ${loaded.schema.name}`);
20918
+ p10.intro(`BetterStart Generator \u2014 ${loaded.schema.name}`);
20800
20919
  const needsMarkdownRenderer = schemaNeedsMarkdownRenderer(loaded);
20801
20920
  await ensureMarkdownRendererDependencies(cwd, needsMarkdownRenderer);
20802
20921
  const result = await applySchemaGeneration(loaded, cwd, config, {
@@ -20821,38 +20940,38 @@ async function runGenerateCommand(schemaName, options) {
20821
20940
  adminRoutePath,
20822
20941
  schemaRoutePath: getGeneratedSchemaRoutePath(loaded, adminRoutePath)
20823
20942
  });
20824
- p9.outro(`Generated ${loaded.schema.name}`);
20943
+ p10.outro(`Generated ${loaded.schema.name}`);
20825
20944
  }
20826
20945
 
20827
20946
  // adapters/next/commands/schema-prompts.ts
20828
- import * as p10 from "@clack/prompts";
20829
- function isInteractiveSession3() {
20947
+ import * as p11 from "@clack/prompts";
20948
+ function isInteractiveSession4() {
20830
20949
  return Boolean(process.stdin.isTTY) && process.env.CI !== "true";
20831
20950
  }
20832
20951
  function fail(message) {
20833
- p10.log.error(message);
20952
+ p11.log.error(message);
20834
20953
  process.exit(1);
20835
20954
  }
20836
- function cancel2(context) {
20837
- p10.cancel(context.cancelMessage);
20955
+ function cancel3(context) {
20956
+ p11.cancel(context.cancelMessage);
20838
20957
  process.exit(0);
20839
20958
  }
20840
20959
  function cancelIfNeeded(context, value) {
20841
- if (p10.isCancel(value)) {
20842
- cancel2(context);
20960
+ if (p11.isCancel(value)) {
20961
+ cancel3(context);
20843
20962
  }
20844
20963
  return value;
20845
20964
  }
20846
20965
  async function promptConfirm2(context, message, initialValue = true) {
20847
- const confirmed = await p10.confirm({ message, initialValue });
20848
- if (p10.isCancel(confirmed)) {
20849
- cancel2(context);
20966
+ const confirmed = await p11.confirm({ message, initialValue });
20967
+ if (p11.isCancel(confirmed)) {
20968
+ cancel3(context);
20850
20969
  }
20851
20970
  return Boolean(confirmed);
20852
20971
  }
20853
20972
  async function promptText(context, message, optionsOrDefaultValue) {
20854
20973
  const options = typeof optionsOrDefaultValue === "string" ? { defaultValue: optionsOrDefaultValue } : optionsOrDefaultValue ?? {};
20855
- const value = await p10.text({
20974
+ const value = await p11.text({
20856
20975
  message,
20857
20976
  defaultValue: options.defaultValue,
20858
20977
  placeholder: options.placeholder,
@@ -20869,7 +20988,7 @@ async function promptText(context, message, optionsOrDefaultValue) {
20869
20988
  return String(cancelIfNeeded(context, value)).trim();
20870
20989
  }
20871
20990
  async function promptOptionalText(context, message) {
20872
- const value = await p10.text({
20991
+ const value = await p11.text({
20873
20992
  message,
20874
20993
  placeholder: "Leave blank to skip"
20875
20994
  });
@@ -20877,7 +20996,7 @@ async function promptOptionalText(context, message) {
20877
20996
  return result || void 0;
20878
20997
  }
20879
20998
  async function promptSelectValue(context, message, options, initialValue) {
20880
- const value = await p10.select({
20999
+ const value = await p11.select({
20881
21000
  message,
20882
21001
  options,
20883
21002
  initialValue
@@ -21096,7 +21215,7 @@ async function shouldPromptRequired(type) {
21096
21215
  return !["group", "section", "tabs", "separator"].includes(type);
21097
21216
  }
21098
21217
  async function promptFormFileOptions(context) {
21099
- const selected = await p10.multiselect({
21218
+ const selected = await p11.multiselect({
21100
21219
  message: "Field options",
21101
21220
  options: [
21102
21221
  { value: "required", label: "Required field?" },
@@ -21135,7 +21254,7 @@ async function promptFieldOptions(context, kind, type, creatable) {
21135
21254
  try {
21136
21255
  return parseInteractiveOptionsList(value);
21137
21256
  } catch (error) {
21138
- p10.log.error(error instanceof Error ? error.message : String(error));
21257
+ p11.log.error(error instanceof Error ? error.message : String(error));
21139
21258
  }
21140
21259
  }
21141
21260
  }
@@ -21253,7 +21372,7 @@ async function promptChildFields(context, kind, schemasDir, scope, fields, depth
21253
21372
  const addChild = fields.length === 0 ? await promptConfirm2(context, "Add a child field?", true) : await promptConfirm2(context, "Add another child field?", false);
21254
21373
  if (!addChild) {
21255
21374
  if (fields.length === 0) {
21256
- p10.log.warn("Containers need at least one child field.");
21375
+ p11.log.warn("Containers need at least one child field.");
21257
21376
  continue;
21258
21377
  }
21259
21378
  return;
@@ -21278,7 +21397,7 @@ async function promptTabsField(context, kind, schemasDir, scope, name, label, de
21278
21397
  const addTab = field.tabs.length === 0 ? await promptConfirm2(context, "Add a tab?", true) : await promptConfirm2(context, "Add another tab?", false);
21279
21398
  if (!addTab) {
21280
21399
  if (field.tabs.length === 0) {
21281
- p10.log.warn("Tabs need at least one tab.");
21400
+ p11.log.warn("Tabs need at least one tab.");
21282
21401
  continue;
21283
21402
  }
21284
21403
  return field;
@@ -21303,7 +21422,7 @@ async function promptTabsField(context, kind, schemasDir, scope, name, label, de
21303
21422
  const addChild = mainFields.length + sidebarFields.length === 0 ? await promptConfirm2(context, "Add a tab child field?", true) : await promptConfirm2(context, "Add another tab child field?", false);
21304
21423
  if (!addChild) {
21305
21424
  if (mainFields.length + sidebarFields.length === 0) {
21306
- p10.log.warn("Tabs need at least one child field.");
21425
+ p11.log.warn("Tabs need at least one child field.");
21307
21426
  continue;
21308
21427
  }
21309
21428
  break;
@@ -21374,7 +21493,7 @@ async function applyAdvancedOptions(context, field, kind, type, options) {
21374
21493
  if (Number.isInteger(parsed) && parsed > 0) {
21375
21494
  record.length = parsed;
21376
21495
  } else {
21377
- p10.log.warn("Skipped invalid length.");
21496
+ p11.log.warn("Skipped invalid length.");
21378
21497
  }
21379
21498
  }
21380
21499
  }
@@ -21532,11 +21651,11 @@ function hasNonInteractiveFieldOptions(options) {
21532
21651
  );
21533
21652
  }
21534
21653
  function fail2(message) {
21535
- p11.log.error(message);
21654
+ p12.log.error(message);
21536
21655
  process.exit(1);
21537
21656
  }
21538
- function cancel4(message = "Add field cancelled.") {
21539
- p11.cancel(message);
21657
+ function cancel5(message = "Add field cancelled.") {
21658
+ p12.cancel(message);
21540
21659
  process.exit(0);
21541
21660
  }
21542
21661
  function schemaNameFromLoaded(loaded) {
@@ -21641,7 +21760,7 @@ function printPreview(loaded, owner, firstTimeGeneration, insertion, options) {
21641
21760
  } else {
21642
21761
  lines.push("schema integration: none");
21643
21762
  }
21644
- p11.note(
21763
+ p12.note(
21645
21764
  `${lines.join("\n")}
21646
21765
 
21647
21766
  ${stringifyProjectJson(insertion.field).trim()}`,
@@ -21674,10 +21793,10 @@ Re-run with --yes to confirm these warning cases.`);
21674
21793
  }
21675
21794
  return;
21676
21795
  }
21677
- p11.note(warnings.join("\n"), "Warnings");
21796
+ p12.note(warnings.join("\n"), "Warnings");
21678
21797
  const confirmed = await promptConfirm3("Continue with these warnings?", true);
21679
21798
  if (!confirmed) {
21680
- cancel4();
21799
+ cancel5();
21681
21800
  }
21682
21801
  }
21683
21802
  function collectRelationshipTargetWarnings(cwd, owner, field) {
@@ -21719,7 +21838,7 @@ async function resolveSchemaNameInteractively(schemasDir, schemaName) {
21719
21838
  if (schemaName) {
21720
21839
  return schemaName;
21721
21840
  }
21722
- if (!isInteractiveSession3()) {
21841
+ if (!isInteractiveSession4()) {
21723
21842
  fail2("Schema name is required in non-interactive sessions.");
21724
21843
  }
21725
21844
  const schemaNames = listSchemaNames(schemasDir);
@@ -21747,7 +21866,7 @@ async function runAddFieldCommand(schemaName, options) {
21747
21866
  } catch (error) {
21748
21867
  fail2(error instanceof Error ? error.message : String(error));
21749
21868
  }
21750
- if (!nonInteractive && !isInteractiveSession3()) {
21869
+ if (!nonInteractive && !isInteractiveSession4()) {
21751
21870
  fail2("Interactive add-field requires a TTY. Provide --type, --field, and --label instead.");
21752
21871
  }
21753
21872
  const owner = resolveSchemaOwner(cwd, schemaNameFromLoaded(loaded));
@@ -21787,11 +21906,11 @@ ${validationErrors.map((error) => ` - ${error}`).join("\n")}`
21787
21906
  if (!nonInteractive && !options.yes) {
21788
21907
  const confirmed = await promptConfirm3("Write schema JSON and regenerate this schema?", true);
21789
21908
  if (!confirmed) {
21790
- cancel4();
21909
+ cancel5();
21791
21910
  }
21792
21911
  }
21793
21912
  writeAuthoredGeneratedSchema(loaded);
21794
- p11.log.success(`Updated ${path30.relative(cwd, loaded.filePath)}`);
21913
+ p12.log.success(`Updated ${path30.relative(cwd, loaded.filePath)}`);
21795
21914
  try {
21796
21915
  await runGenerateCommand(selectedSchemaName, {
21797
21916
  force: false,
@@ -21802,8 +21921,8 @@ ${validationErrors.map((error) => ` - ${error}`).join("\n")}`
21802
21921
  cwd
21803
21922
  });
21804
21923
  } catch (error) {
21805
- p11.log.error(error instanceof Error ? error.message : String(error));
21806
- p11.log.info(
21924
+ p12.log.error(error instanceof Error ? error.message : String(error));
21925
+ p12.log.info(
21807
21926
  `Schema JSON was kept. Re-run \`betterstart generate ${selectedSchemaName}${options.skipMigration ? " --skip-migration" : ""}\` after resolving the issue.`
21808
21927
  );
21809
21928
  process.exit(1);
@@ -21813,7 +21932,7 @@ ${validationErrors.map((error) => ` - ${error}`).join("\n")}`
21813
21932
  // adapters/next/commands/create.ts
21814
21933
  import fs25 from "fs";
21815
21934
  import path31 from "path";
21816
- import * as p12 from "@clack/prompts";
21935
+ import * as p13 from "@clack/prompts";
21817
21936
  var CREATE_PROMPT_CONTEXT = {
21818
21937
  cancelMessage: "Create schema cancelled."
21819
21938
  };
@@ -22004,7 +22123,7 @@ async function promptTabSlotFields(kind, schemasDir, titleField) {
22004
22123
  );
22005
22124
  if (!addField) {
22006
22125
  if (!hasFields) {
22007
- p12.log.warn("Tabs need at least one child field.");
22126
+ p13.log.warn("Tabs need at least one child field.");
22008
22127
  continue;
22009
22128
  }
22010
22129
  return { main, sidebar };
@@ -22052,7 +22171,7 @@ async function promptSchemaTab(kind, schemasDir, titleField, existingTabs) {
22052
22171
  while (fields.length === 0) {
22053
22172
  await promptAdditionalSchemaFields(kind, schemasDir, fields);
22054
22173
  if (fields.length === 0) {
22055
- p12.log.warn("Tabs need at least one child field.");
22174
+ p13.log.warn("Tabs need at least one child field.");
22056
22175
  }
22057
22176
  }
22058
22177
  }
@@ -22142,7 +22261,7 @@ async function promptFormSubmissionColumns(schema) {
22142
22261
  }
22143
22262
  const existingColumnNames = schema.columns ? new Set(schema.columns.map((column) => column.accessorKey)) : void 0;
22144
22263
  const initialValues = existingColumnNames ? fields.filter((field) => existingColumnNames.has(field.name)).map((field) => field.name) : fields.map((field) => field.name);
22145
- const selected = await p12.multiselect({
22264
+ const selected = await p13.multiselect({
22146
22265
  message: "Submission table columns",
22147
22266
  options: fields.map((field) => ({
22148
22267
  value: field.name,
@@ -22151,8 +22270,8 @@ async function promptFormSubmissionColumns(schema) {
22151
22270
  initialValues,
22152
22271
  required: false
22153
22272
  });
22154
- if (p12.isCancel(selected)) {
22155
- cancel2(CREATE_PROMPT_CONTEXT);
22273
+ if (p13.isCancel(selected)) {
22274
+ cancel3(CREATE_PROMPT_CONTEXT);
22156
22275
  }
22157
22276
  const selectedNames = new Set(selected);
22158
22277
  schema.columns = fields.filter((field) => selectedNames.has(field.name)).map((field) => {
@@ -22211,7 +22330,7 @@ function schemaFilePath(kind, schemasDir, schemaName) {
22211
22330
  return kind === "form" ? path31.join(schemasDir, "forms", `${schemaName}.json`) : path31.join(schemasDir, `${schemaName}.json`);
22212
22331
  }
22213
22332
  function printPreview2(loaded, cwd) {
22214
- p12.note(
22333
+ p13.note(
22215
22334
  `schema: ${loaded.name} (${loaded.kind})
22216
22335
  path: ${path31.relative(cwd, loaded.filePath)}
22217
22336
  owner: user
@@ -22226,7 +22345,7 @@ async function runCreateCommand(kindInput, schemaName, options) {
22226
22345
  if (!snapshotRootExists(cwd)) {
22227
22346
  fail(UNSUPPORTED_PROJECT_STATE_MESSAGE);
22228
22347
  }
22229
- if (!isInteractiveSession3()) {
22348
+ if (!isInteractiveSession4()) {
22230
22349
  fail("Interactive create requires a TTY.");
22231
22350
  }
22232
22351
  const config = await resolveConfigOrExit(cwd);
@@ -22258,13 +22377,13 @@ ${validationErrors.map((error) => ` - ${error}`).join("\n")}`
22258
22377
  break;
22259
22378
  }
22260
22379
  if (action === "cancel") {
22261
- cancel2(CREATE_PROMPT_CONTEXT);
22380
+ cancel3(CREATE_PROMPT_CONTEXT);
22262
22381
  }
22263
22382
  await promptAdditionalCreateField(kind, schemasDir, schema);
22264
22383
  }
22265
22384
  fs25.mkdirSync(path31.dirname(filePath), { recursive: true });
22266
22385
  writeAuthoredGeneratedSchema(loaded);
22267
- p12.log.success(`Created ${path31.relative(cwd, filePath)}`);
22386
+ p13.log.success(`Created ${path31.relative(cwd, filePath)}`);
22268
22387
  try {
22269
22388
  await runGenerateCommand(metadata.name, {
22270
22389
  force: false,
@@ -22275,8 +22394,8 @@ ${validationErrors.map((error) => ` - ${error}`).join("\n")}`
22275
22394
  cwd
22276
22395
  });
22277
22396
  } catch (error) {
22278
- p12.log.error(error instanceof Error ? error.message : String(error));
22279
- p12.log.info(
22397
+ p13.log.error(error instanceof Error ? error.message : String(error));
22398
+ p13.log.info(
22280
22399
  `Schema JSON was kept. Re-run \`betterstart generate ${metadata.name}${options.skipMigration ? " --skip-migration" : ""}\` after resolving the issue.`
22281
22400
  );
22282
22401
  process.exit(1);
@@ -22288,14 +22407,14 @@ import { execFileSync as execFileSync5, spawn as spawn6 } from "child_process";
22288
22407
  import fs41 from "fs";
22289
22408
  import path52 from "path";
22290
22409
  import { PassThrough } from "stream";
22291
- import * as p25 from "@clack/prompts";
22410
+ import * as p26 from "@clack/prompts";
22292
22411
 
22293
22412
  // core-engine/utils/cancel-guard.ts
22294
- import * as p13 from "@clack/prompts";
22413
+ import * as p14 from "@clack/prompts";
22295
22414
  function installSetupCancelGuard() {
22296
22415
  const onSignal = () => {
22297
22416
  if (!hasActiveSpinner()) {
22298
- p13.cancel("Setup cancelled.");
22417
+ p14.cancel("Setup cancelled.");
22299
22418
  }
22300
22419
  process.exit(0);
22301
22420
  };
@@ -22350,11 +22469,11 @@ function redactSecrets(text7) {
22350
22469
 
22351
22470
  // adapters/next/init/prompts/database.ts
22352
22471
  import { execFileSync as execFileSync4 } from "child_process";
22353
- import * as p14 from "@clack/prompts";
22472
+ import * as p15 from "@clack/prompts";
22354
22473
  import pc from "picocolors";
22355
22474
  var VERCEL_NEON_URL = "https://vercel.com/dashboard/integrations/checkout/neon";
22356
22475
  async function promptServices() {
22357
- const choice = await p14.select({
22476
+ const choice = await p15.select({
22358
22477
  message: "Connect a PostgreSQL Database",
22359
22478
  options: [
22360
22479
  {
@@ -22375,8 +22494,8 @@ async function promptServices() {
22375
22494
  ],
22376
22495
  initialValue: "vercel"
22377
22496
  });
22378
- if (p14.isCancel(choice)) {
22379
- p14.cancel("Setup cancelled.");
22497
+ if (p15.isCancel(choice)) {
22498
+ p15.cancel("Setup cancelled.");
22380
22499
  process.exit(0);
22381
22500
  }
22382
22501
  if (choice === "vercel") {
@@ -22390,7 +22509,7 @@ async function promptServices() {
22390
22509
  }
22391
22510
  function openBrowserVercelNeon() {
22392
22511
  openBrowser(VERCEL_NEON_URL);
22393
- p14.log.info(
22512
+ p15.log.info(
22394
22513
  `Opening Vercel... Create a Neon Postgres database, then copy the ${pc.cyan("DATABASE_URL")} from the dashboard.`
22395
22514
  );
22396
22515
  }
@@ -22400,12 +22519,12 @@ function openBrowserVercelNeonResource(url) {
22400
22519
  return;
22401
22520
  }
22402
22521
  openBrowser(url);
22403
- p14.log.info(
22522
+ p15.log.info(
22404
22523
  `Opening Vercel... Copy the Neon ${pc.cyan("DATABASE_URL")} from the database dashboard, then paste it below.`
22405
22524
  );
22406
22525
  }
22407
22526
  async function promptConnectionString() {
22408
- const input = await p14.text({
22527
+ const input = await p15.text({
22409
22528
  message: "Paste your PostgreSQL connection string",
22410
22529
  placeholder: "postgres://user:pass@host/db",
22411
22530
  validate(val) {
@@ -22419,8 +22538,8 @@ async function promptConnectionString() {
22419
22538
  }
22420
22539
  }
22421
22540
  });
22422
- if (p14.isCancel(input)) {
22423
- p14.cancel("Setup cancelled.");
22541
+ if (p15.isCancel(input)) {
22542
+ p15.cancel("Setup cancelled.");
22424
22543
  process.exit(0);
22425
22544
  }
22426
22545
  return input.replace(/^['"]|['"]$/g, "").trim();
@@ -22440,7 +22559,7 @@ function openBrowser(url) {
22440
22559
  }
22441
22560
 
22442
22561
  // adapters/next/init/prompts/presets.ts
22443
- import * as p15 from "@clack/prompts";
22562
+ import * as p16 from "@clack/prompts";
22444
22563
 
22445
22564
  // adapters/next/init/scaffolders/env.ts
22446
22565
  import crypto2 from "crypto";
@@ -22605,7 +22724,7 @@ async function promptPresets(cwd, options = {}) {
22605
22724
  overwriteKeys.add(key);
22606
22725
  }
22607
22726
  };
22608
- const storage = await p15.select({
22727
+ const storage = await p16.select({
22609
22728
  message: "Choose a file storage",
22610
22729
  options: [
22611
22730
  {
@@ -22629,8 +22748,8 @@ async function promptPresets(cwd, options = {}) {
22629
22748
  ],
22630
22749
  initialValue: "vercel-blob"
22631
22750
  });
22632
- if (p15.isCancel(storage)) {
22633
- p15.cancel("Setup cancelled.");
22751
+ if (p16.isCancel(storage)) {
22752
+ p16.cancel("Setup cancelled.");
22634
22753
  process.exit(0);
22635
22754
  }
22636
22755
  if (storage === "r2") {
@@ -22640,7 +22759,7 @@ async function promptPresets(cwd, options = {}) {
22640
22759
  if (flow?.ok && flow.config) {
22641
22760
  mergeIntegrationConfig(flow.config);
22642
22761
  } else if (flow) {
22643
- p15.log.warn(
22762
+ p16.log.warn(
22644
22763
  "Continuing without Railway bucket credentials \u2014 rerun betterstart add --integration railway-bucket after fixing Railway access."
22645
22764
  );
22646
22765
  } else {
@@ -22657,7 +22776,7 @@ async function promptPresets(cwd, options = {}) {
22657
22776
  });
22658
22777
  overwriteKeys.add("BLOB_READ_WRITE_TOKEN");
22659
22778
  } else if (flow) {
22660
- p15.log.warn(
22779
+ p16.log.warn(
22661
22780
  "Continuing without a Blob token \u2014 add BLOB_READ_WRITE_TOKEN to .env.local from the store on vercel.com/dashboard/stores."
22662
22781
  );
22663
22782
  sections.push({
@@ -22666,7 +22785,7 @@ async function promptPresets(cwd, options = {}) {
22666
22785
  });
22667
22786
  } else {
22668
22787
  if (existingToken) {
22669
- p15.log.info(
22788
+ p16.log.info(
22670
22789
  `Using the existing BLOB_READ_WRITE_TOKEN from .env.local ${pc2.dim(
22671
22790
  `(${maskBlobToken(existingToken)})`
22672
22791
  )}`
@@ -22675,7 +22794,7 @@ async function promptPresets(cwd, options = {}) {
22675
22794
  mergeIntegrationConfig(await collectIntegrationConfig(cwd, ["vercel-blob"]));
22676
22795
  }
22677
22796
  }
22678
- const selectedPresets = await p15.multiselect({
22797
+ const selectedPresets = await p16.multiselect({
22679
22798
  message: "Select presets",
22680
22799
  options: [
22681
22800
  {
@@ -22687,8 +22806,8 @@ async function promptPresets(cwd, options = {}) {
22687
22806
  required: false,
22688
22807
  initialValues: ["blog"]
22689
22808
  });
22690
- if (p15.isCancel(selectedPresets)) {
22691
- p15.cancel("Setup cancelled.");
22809
+ if (p16.isCancel(selectedPresets)) {
22810
+ p16.cancel("Setup cancelled.");
22692
22811
  process.exit(0);
22693
22812
  }
22694
22813
  const integrations = [];
@@ -22715,9 +22834,9 @@ async function promptPresets(cwd, options = {}) {
22715
22834
  }
22716
22835
 
22717
22836
  // adapters/next/init/prompts/project.ts
22718
- import * as p16 from "@clack/prompts";
22837
+ import * as p17 from "@clack/prompts";
22719
22838
  async function promptProject(defaultName) {
22720
- const projectName = await p16.text({
22839
+ const projectName = await p17.text({
22721
22840
  message: "What is your project named?",
22722
22841
  placeholder: defaultName ?? "(Press Enter to use default)",
22723
22842
  defaultValue: defaultName ?? ".",
@@ -22730,15 +22849,15 @@ async function promptProject(defaultName) {
22730
22849
  return void 0;
22731
22850
  }
22732
22851
  });
22733
- if (p16.isCancel(projectName)) {
22734
- p16.cancel("Setup cancelled.");
22852
+ if (p17.isCancel(projectName)) {
22853
+ p17.cancel("Setup cancelled.");
22735
22854
  process.exit(0);
22736
22855
  }
22737
22856
  return { projectName: projectName.trim() || "." };
22738
22857
  }
22739
22858
 
22740
22859
  // adapters/next/init/providers.ts
22741
- import * as p17 from "@clack/prompts";
22860
+ import * as p18 from "@clack/prompts";
22742
22861
  var DATABASE_PROVIDERS = ["vercel", "railway", "manual"];
22743
22862
  var STORAGE_PROVIDERS = ["vercel-blob", "railway-bucket", "r2", "local"];
22744
22863
  var DEPLOY_PROVIDERS = ["vercel", "railway", "none"];
@@ -22795,7 +22914,7 @@ function validateResolvedDatabaseProvider(provider, options) {
22795
22914
  }
22796
22915
  }
22797
22916
  async function promptDeployProvider(initialValue = "none") {
22798
- const provider = await p17.select({
22917
+ const provider = await p18.select({
22799
22918
  message: "Deploy this project",
22800
22919
  options: [
22801
22920
  {
@@ -22813,8 +22932,8 @@ async function promptDeployProvider(initialValue = "none") {
22813
22932
  ],
22814
22933
  initialValue
22815
22934
  });
22816
- if (p17.isCancel(provider)) {
22817
- p17.cancel("Setup cancelled.");
22935
+ if (p18.isCancel(provider)) {
22936
+ p18.cancel("Setup cancelled.");
22818
22937
  process.exit(0);
22819
22938
  }
22820
22939
  return provider;
@@ -22823,7 +22942,7 @@ async function promptDeployProvider(initialValue = "none") {
22823
22942
  // adapters/next/init/railway/deploy.ts
22824
22943
  import fs28 from "fs";
22825
22944
  import path34 from "path";
22826
- import * as p19 from "@clack/prompts";
22945
+ import * as p20 from "@clack/prompts";
22827
22946
 
22828
22947
  // adapters/next/init/deploy/guard.ts
22829
22948
  import { spawn as spawn3 } from "child_process";
@@ -22920,7 +23039,7 @@ function guardBetterstartConfig(cwd, restores) {
22920
23039
  }
22921
23040
 
22922
23041
  // adapters/next/init/railway/project.ts
22923
- import * as p18 from "@clack/prompts";
23042
+ import * as p19 from "@clack/prompts";
22924
23043
 
22925
23044
  // adapters/next/init/railway/runner.ts
22926
23045
  import { spawn as spawn4 } from "child_process";
@@ -23204,15 +23323,15 @@ async function ensureRailwayProject(runner, options) {
23204
23323
  createWorkspace = options.workspaces[0]?.id;
23205
23324
  } else if (!createWorkspace && options.interactive && options.workspaces?.length) {
23206
23325
  projectSpinner.clear();
23207
- const workspace = await p18.select({
23326
+ const workspace = await p19.select({
23208
23327
  message: "Choose a Railway workspace",
23209
23328
  options: options.workspaces.map((candidate) => ({
23210
23329
  value: candidate.id,
23211
23330
  label: candidate.name
23212
23331
  }))
23213
23332
  });
23214
- if (p18.isCancel(workspace)) {
23215
- p18.cancel("Setup cancelled.");
23333
+ if (p19.isCancel(workspace)) {
23334
+ p19.cancel("Setup cancelled.");
23216
23335
  process.exit(0);
23217
23336
  }
23218
23337
  createWorkspace = workspace;
@@ -23738,7 +23857,7 @@ async function runRailwayDeployFlow(options) {
23738
23857
  );
23739
23858
  envSpinner.clear();
23740
23859
  for (const key of sync.failed) {
23741
- p19.log.warn(`Could not set ${pc4.cyan(key)} on Railway.`);
23860
+ p20.log.warn(`Could not set ${pc4.cyan(key)} on Railway.`);
23742
23861
  }
23743
23862
  if (sync.failed.length > 0) {
23744
23863
  return {
@@ -23753,12 +23872,12 @@ async function runRailwayDeployFlow(options) {
23753
23872
  const packageGuard = await guardProjectForDeploy(options.cwd);
23754
23873
  guardSpinner.clear();
23755
23874
  if (packageGuard.lockfile === "failed") {
23756
- p19.log.warn(
23875
+ p20.log.warn(
23757
23876
  "Could not refresh pnpm-lock.yaml after removing betterstart-cli \u2014 the remote install may fail."
23758
23877
  );
23759
23878
  }
23760
23879
  for (const dependency of packageGuard.localSpecDeps) {
23761
- p19.log.warn(
23880
+ p20.log.warn(
23762
23881
  `Dependency ${pc4.cyan(dependency)} uses a local spec that cannot install on Railway.`
23763
23882
  );
23764
23883
  }
@@ -23811,7 +23930,7 @@ ${deploy.stderr}`) ?? deploy.errorMessage
23811
23930
  }
23812
23931
 
23813
23932
  // adapters/next/init/railway/auth.ts
23814
- import * as p20 from "@clack/prompts";
23933
+ import * as p21 from "@clack/prompts";
23815
23934
  import pc5 from "picocolors";
23816
23935
  var WHOAMI_TIMEOUT_MS = 3e4;
23817
23936
  var LOGIN_TIMEOUT_MS = 3e5;
@@ -23881,7 +24000,7 @@ async function ensureRailwayAuth(runner, cwd, options) {
23881
24000
  return { authed: false, reason: existing.reason };
23882
24001
  }
23883
24002
  checkSpinner.clear();
23884
- p20.log.info(
24003
+ p21.log.info(
23885
24004
  "Sign in to Railway to continue. Railway will open your browser or show a device code."
23886
24005
  );
23887
24006
  const login = await runRailway(runner, ["login"], {
@@ -25768,11 +25887,11 @@ function scaffoldTsconfig(cwd, config) {
25768
25887
  }
25769
25888
 
25770
25889
  // adapters/next/init/vercel/flow.ts
25771
- import * as p24 from "@clack/prompts";
25890
+ import * as p25 from "@clack/prompts";
25772
25891
  import pc9 from "picocolors";
25773
25892
 
25774
25893
  // adapters/next/init/vercel/auth.ts
25775
- import * as p21 from "@clack/prompts";
25894
+ import * as p22 from "@clack/prompts";
25776
25895
  import pc6 from "picocolors";
25777
25896
 
25778
25897
  // adapters/next/init/vercel/runner.ts
@@ -26016,7 +26135,7 @@ async function ensureVercelAuth(runner, cwd, options) {
26016
26135
  checkSpinner.clear();
26017
26136
  const signInMessage = `Sign in to Vercel to continue ${pc6.dim("(or press Ctrl-C to enter a connection string manually)")}`;
26018
26137
  const signInRows = clackLogRows(signInMessage);
26019
- p21.log.info(signInMessage);
26138
+ p22.log.info(signInMessage);
26020
26139
  let streamedRows = 0;
26021
26140
  const login = await runVercel(runner, ["login"], {
26022
26141
  cwd,
@@ -26048,7 +26167,7 @@ function signedInMessage(username) {
26048
26167
  }
26049
26168
 
26050
26169
  // adapters/next/init/vercel/blob.ts
26051
- import * as p22 from "@clack/prompts";
26170
+ import * as p23 from "@clack/prompts";
26052
26171
  import pc7 from "picocolors";
26053
26172
 
26054
26173
  // adapters/next/init/vercel/env-pull.ts
@@ -26290,7 +26409,7 @@ async function provisionBlobStoreInteractive(runner, cwd, options) {
26290
26409
  if (terminalFallbackRan) break;
26291
26410
  terminalFallbackRan = true;
26292
26411
  quietSpinner.clear();
26293
- p22.log.info(
26412
+ p23.log.info(
26294
26413
  `Create your Blob store in the Vercel prompts below ${pc7.dim(
26295
26414
  "(connect it to all environments)."
26296
26415
  )}`
@@ -26489,7 +26608,7 @@ function guardEnvLocal(cwd) {
26489
26608
  }
26490
26609
 
26491
26610
  // adapters/next/init/vercel/neon.ts
26492
- import * as p23 from "@clack/prompts";
26611
+ import * as p24 from "@clack/prompts";
26493
26612
  import pc8 from "picocolors";
26494
26613
  var PROVISION_TIMEOUT_MS2 = 18e4;
26495
26614
  var INTERACTIVE_PROVISION_TIMEOUT_MS2 = 6e5;
@@ -26508,7 +26627,7 @@ async function provisionNeonInteractive(runner, cwd, options) {
26508
26627
  termsResolved = true;
26509
26628
  quietSpinner.clear();
26510
26629
  eraseRows(termsNotice.rows);
26511
- p23.log.step(termsNotice.text);
26630
+ p24.log.step(termsNotice.text);
26512
26631
  };
26513
26632
  const quiet = await runVercel(runner, neonAddArgs(options), {
26514
26633
  cwd,
@@ -26527,7 +26646,7 @@ ${pc8.dim(termsUrl)}`,
26527
26646
  rows: clackLogRows(message) + clackLogRows(termsUrl) - 1
26528
26647
  };
26529
26648
  quietSpinner.clear();
26530
- p23.log.info(termsNotice.text);
26649
+ p24.log.info(termsNotice.text);
26531
26650
  quietSpinner.start("Waiting for the terms to be accepted");
26532
26651
  return;
26533
26652
  }
@@ -26543,7 +26662,7 @@ ${pc8.dim(termsUrl)}`,
26543
26662
  return readNeonProvisionInfo(quiet.stdout);
26544
26663
  }
26545
26664
  quietSpinner.clear();
26546
- p23.log.info(
26665
+ p24.log.info(
26547
26666
  `Create your Neon database in the Vercel prompts below ${pc8.dim(
26548
26667
  "(the Free plan is recommended)."
26549
26668
  )}`
@@ -26620,14 +26739,14 @@ async function runVercelNeonFlow(options) {
26620
26739
  allowLogin: options.interactive
26621
26740
  });
26622
26741
  if (!auth.authed) {
26623
- p24.log.warn(authFailureMessage(auth.reason));
26742
+ p25.log.warn(authFailureMessage(auth.reason));
26624
26743
  return { ok: false };
26625
26744
  }
26626
26745
  await ensureLinkedProject(runner, options.cwd, options.projectName, env, auth.username);
26627
26746
  const neon = await provisionNeonForMode(runner, options);
26628
26747
  if (neon.failure) {
26629
- p24.log.warn(neonFailureMessage(neon.failure));
26630
- if (neon.detail) p24.log.message(pc9.dim(redactSecrets(neon.detail)));
26748
+ p25.log.warn(neonFailureMessage(neon.failure));
26749
+ if (neon.detail) p25.log.message(pc9.dim(redactSecrets(neon.detail)));
26631
26750
  return { ok: false };
26632
26751
  }
26633
26752
  const databaseUrl = await pullNeonDatabaseUrl(runner, options.cwd, env);
@@ -26640,7 +26759,7 @@ async function runVercelNeonFlow(options) {
26640
26759
  dismissSignedInNote
26641
26760
  };
26642
26761
  } catch (error) {
26643
- p24.log.warn(
26762
+ p25.log.warn(
26644
26763
  `Vercel provisioning failed: ${error instanceof Error ? error.message : String(error)}`
26645
26764
  );
26646
26765
  return { ok: false };
@@ -26662,14 +26781,14 @@ async function runVercelBlobFlow(options) {
26662
26781
  allowLogin: options.interactive
26663
26782
  });
26664
26783
  if (!auth.authed) {
26665
- p24.log.warn(authFailureMessage(auth.reason));
26784
+ p25.log.warn(authFailureMessage(auth.reason));
26666
26785
  return { ok: false };
26667
26786
  }
26668
26787
  await ensureLinkedProject(runner, options.cwd, options.projectName, env, auth.username);
26669
26788
  const blob = await provisionBlobForMode(runner, options);
26670
26789
  if (blob.failure || !blob.token) {
26671
- p24.log.warn(blobFailureMessage(blob.failure));
26672
- if (blob.detail) p24.log.message(pc9.dim(redactSecrets(blob.detail)));
26790
+ p25.log.warn(blobFailureMessage(blob.failure));
26791
+ if (blob.detail) p25.log.message(pc9.dim(redactSecrets(blob.detail)));
26673
26792
  return { ok: false };
26674
26793
  }
26675
26794
  return {
@@ -26678,7 +26797,7 @@ async function runVercelBlobFlow(options) {
26678
26797
  blobStoreName: blob.storeName
26679
26798
  };
26680
26799
  } catch (error) {
26681
- p24.log.warn(
26800
+ p25.log.warn(
26682
26801
  `Vercel provisioning failed: ${error instanceof Error ? error.message : String(error)}`
26683
26802
  );
26684
26803
  return { ok: false };
@@ -26700,7 +26819,7 @@ async function runVercelDeployFlow(options) {
26700
26819
  allowLogin: options.interactive ?? true
26701
26820
  });
26702
26821
  if (!auth.authed) {
26703
- p24.log.warn(authFailureMessage(auth.reason));
26822
+ p25.log.warn(authFailureMessage(auth.reason));
26704
26823
  printManualDeployHint();
26705
26824
  return { ok: false };
26706
26825
  }
@@ -26710,7 +26829,7 @@ async function runVercelDeployFlow(options) {
26710
26829
  const sync = await syncVercelProductionEnv(runner, options.cwd, env);
26711
26830
  envSpinner.clear();
26712
26831
  for (const key of sync.failed) {
26713
- p24.log.warn(
26832
+ p25.log.warn(
26714
26833
  `Could not set ${pc9.cyan(key)} on Vercel \u2014 add it in the project's environment settings.`
26715
26834
  );
26716
26835
  }
@@ -26720,12 +26839,12 @@ async function runVercelDeployFlow(options) {
26720
26839
  const packageGuard = await guardProjectForDeploy(options.cwd);
26721
26840
  guardSpinner.clear();
26722
26841
  if (packageGuard.lockfile === "failed") {
26723
- p24.log.warn(
26842
+ p25.log.warn(
26724
26843
  "Could not refresh pnpm-lock.yaml after removing betterstart-cli \u2014 the remote install may fail."
26725
26844
  );
26726
26845
  }
26727
26846
  for (const dep of packageGuard.localSpecDeps) {
26728
- p24.log.warn(
26847
+ p25.log.warn(
26729
26848
  `Dependency ${pc9.cyan(dep)} uses a local spec that cannot install on Vercel \u2014 the remote build may fail.`
26730
26849
  );
26731
26850
  }
@@ -26742,7 +26861,7 @@ async function runVercelDeployFlow(options) {
26742
26861
  }
26743
26862
  if (deploy.failure) {
26744
26863
  deploySpinner.stop(`${pc9.yellow("\u25B2")} ${deployFailureMessage(deploy.failure)}`);
26745
- if (deploy.detail) p24.log.message(pc9.dim(redactSecrets(deploy.detail)));
26864
+ if (deploy.detail) p25.log.message(pc9.dim(redactSecrets(deploy.detail)));
26746
26865
  printManualDeployHint();
26747
26866
  return { ok: false };
26748
26867
  }
@@ -26750,7 +26869,7 @@ async function runVercelDeployFlow(options) {
26750
26869
  deploySpinner.stop(url ? `Deployed ${pc9.cyan(url)}` : "Deployed to Vercel");
26751
26870
  return { ok: true, url, syncedEnvKeys: sync.synced };
26752
26871
  } catch (error) {
26753
- p24.log.warn(`Vercel deploy failed: ${error instanceof Error ? error.message : String(error)}`);
26872
+ p25.log.warn(`Vercel deploy failed: ${error instanceof Error ? error.message : String(error)}`);
26754
26873
  printManualDeployHint();
26755
26874
  return { ok: false };
26756
26875
  } finally {
@@ -26758,7 +26877,7 @@ async function runVercelDeployFlow(options) {
26758
26877
  }
26759
26878
  }
26760
26879
  function printManualDeployHint() {
26761
- p24.log.info(`You can deploy manually: ${pc9.cyan("vercel deploy --prod")}`);
26880
+ p25.log.info(`You can deploy manually: ${pc9.cyan("vercel deploy --prod")}`);
26762
26881
  }
26763
26882
  async function ensureLinkedProject(runner, cwd, projectName, env, scope) {
26764
26883
  if (readLinkedProjectId(cwd)) return;
@@ -26841,13 +26960,6 @@ import pc10 from "picocolors";
26841
26960
  import fs40 from "fs";
26842
26961
  import path51 from "path";
26843
26962
  import * as clack2 from "@clack/prompts";
26844
-
26845
- // core-engine/utils/interactive.ts
26846
- function isInteractiveSession4() {
26847
- return Boolean(process.stdin.isTTY) && process.env.CI !== "true";
26848
- }
26849
-
26850
- // adapters/next/commands/seed.ts
26851
26963
  function buildSeedScript(authBasePath = "/api/admin/auth") {
26852
26964
  return `/**
26853
26965
  * BetterStart Admin \u2014 Seed Script
@@ -27029,7 +27141,7 @@ async function runSeedCommand(options) {
27029
27141
  process.exit(1);
27030
27142
  }
27031
27143
  const adminDir = config.paths?.admin ?? "./admin";
27032
- const interactive = isInteractiveSession4();
27144
+ const interactive = isInteractiveSession();
27033
27145
  let email;
27034
27146
  if (options.email) {
27035
27147
  if (!options.email.includes("@")) {
@@ -27194,16 +27306,16 @@ function addVersionToBoxBottomBorder(box2, version2) {
27194
27306
  if (!bottomLine) {
27195
27307
  return box2;
27196
27308
  }
27197
- const leftCornerIndex = bottomLine.indexOf(p25.S_CORNER_BOTTOM_LEFT);
27198
- const rightCornerIndex = bottomLine.lastIndexOf(p25.S_CORNER_BOTTOM_RIGHT);
27309
+ const leftCornerIndex = bottomLine.indexOf(p26.S_CORNER_BOTTOM_LEFT);
27310
+ const rightCornerIndex = bottomLine.lastIndexOf(p26.S_CORNER_BOTTOM_RIGHT);
27199
27311
  const label = ` v${version2} `;
27200
- const borderWidth = rightCornerIndex - leftCornerIndex - p25.S_CORNER_BOTTOM_LEFT.length;
27312
+ const borderWidth = rightCornerIndex - leftCornerIndex - p26.S_CORNER_BOTTOM_LEFT.length;
27201
27313
  if (leftCornerIndex === -1 || rightCornerIndex === -1 || borderWidth < label.length) {
27202
27314
  return box2;
27203
27315
  }
27204
27316
  const leftBorderWidth = Math.floor((borderWidth - label.length) / 2);
27205
27317
  const rightBorderWidth = borderWidth - label.length - leftBorderWidth;
27206
- lines[bottomLineIndex] = `${bottomLine.slice(0, leftCornerIndex + p25.S_CORNER_BOTTOM_LEFT.length)}${p25.S_BAR_H.repeat(leftBorderWidth)}${label}${p25.S_BAR_H.repeat(rightBorderWidth)}${bottomLine.slice(rightCornerIndex)}`;
27318
+ lines[bottomLineIndex] = `${bottomLine.slice(0, leftCornerIndex + p26.S_CORNER_BOTTOM_LEFT.length)}${p26.S_BAR_H.repeat(leftBorderWidth)}${label}${p26.S_BAR_H.repeat(rightBorderWidth)}${bottomLine.slice(rightCornerIndex)}`;
27207
27319
  return lines.join("\n");
27208
27320
  }
27209
27321
  function renderInitBanner() {
@@ -27213,7 +27325,7 @@ function renderInitBanner() {
27213
27325
  output.on("data", (chunk) => {
27214
27326
  box2 += chunk.toString();
27215
27327
  });
27216
- p25.box(
27328
+ p26.box(
27217
27329
  `
27218
27330
  \u2584 \u2597 \u2597 \u2584\u2596\u2597 \u2597
27219
27331
  \u2599\u2598\u2588\u258C\u259C\u2598\u259C\u2598\u2588\u258C\u259B\u2598\u259A \u259C\u2598\u2580\u258C\u259B\u2598\u259C\u2598
@@ -27309,7 +27421,7 @@ async function runInitCommand(name, options) {
27309
27421
  let restoreStdout;
27310
27422
  if (options.json) {
27311
27423
  if (!options.yes) {
27312
- p25.log.error("--json requires --yes.");
27424
+ p26.log.error("--json requires --yes.");
27313
27425
  process.exit(1);
27314
27426
  }
27315
27427
  restoreStdout = redirectStdoutToStderr();
@@ -27330,7 +27442,7 @@ async function runInitCommand(name, options) {
27330
27442
  }
27331
27443
  } catch (error) {
27332
27444
  disposeCancelGuard();
27333
- p25.log.error(error instanceof Error ? error.message : String(error));
27445
+ p26.log.error(error instanceof Error ? error.message : String(error));
27334
27446
  process.exit(1);
27335
27447
  }
27336
27448
  let cwd = process.cwd();
@@ -27341,7 +27453,7 @@ async function runInitCommand(name, options) {
27341
27453
  try {
27342
27454
  namespace = validateAdminNamespace(options.namespace);
27343
27455
  } catch (error) {
27344
- p25.log.error(error instanceof Error ? error.message : String(error));
27456
+ p26.log.error(error instanceof Error ? error.message : String(error));
27345
27457
  process.exit(1);
27346
27458
  }
27347
27459
  }
@@ -27350,13 +27462,13 @@ async function runInitCommand(name, options) {
27350
27462
  try {
27351
27463
  projectPrompt = options.yes ? resolveNonInteractiveProject(name) : await promptProject(name);
27352
27464
  } catch (error) {
27353
- p25.log.error(error instanceof Error ? error.message : String(error));
27465
+ p26.log.error(error instanceof Error ? error.message : String(error));
27354
27466
  process.exit(1);
27355
27467
  }
27356
27468
  }
27357
27469
  if (!options.yes && !options.namespace) {
27358
27470
  const defaultDashboardPath = resolveAdminNamespace(DEFAULT_ADMIN_NAMESPACE).routePath;
27359
- const namespaceInput = await p25.text({
27471
+ const namespaceInput = await p26.text({
27360
27472
  message: "Enter the dashboard path",
27361
27473
  placeholder: `eg. ${defaultDashboardPath}`,
27362
27474
  defaultValue: defaultDashboardPath,
@@ -27369,8 +27481,8 @@ async function runInitCommand(name, options) {
27369
27481
  }
27370
27482
  }
27371
27483
  });
27372
- if (p25.isCancel(namespaceInput)) {
27373
- p25.cancel("Setup cancelled.");
27484
+ if (p26.isCancel(namespaceInput)) {
27485
+ p26.cancel("Setup cancelled.");
27374
27486
  process.exit(0);
27375
27487
  }
27376
27488
  namespace = validateAdminDashboardPath(namespaceInput);
@@ -27382,13 +27494,13 @@ async function runInitCommand(name, options) {
27382
27494
  if (project2.isExisting) {
27383
27495
  srcDir = project2.hasSrcDir;
27384
27496
  if (!project2.hasTypeScript) {
27385
- p25.log.error("TypeScript is required. Please add a tsconfig.json first.");
27497
+ p26.log.error("TypeScript is required. Please add a tsconfig.json first.");
27386
27498
  process.exit(1);
27387
27499
  }
27388
27500
  if (forceMode) {
27389
27501
  const nuked = removeExistingAdminPaths(cwd, await resolveForceInitNamespaces(cwd, namespace));
27390
27502
  if (nuked > 0) {
27391
- p25.log.warn(`${pc10.yellow("Force mode:")} removed ${nuked} existing admin paths`);
27503
+ p26.log.warn(`${pc10.yellow("Force mode:")} removed ${nuked} existing admin paths`);
27392
27504
  }
27393
27505
  project2 = detectProject(cwd, namespace);
27394
27506
  } else if (project2.conflicts.length > 0) {
@@ -27397,14 +27509,14 @@ async function runInitCommand(name, options) {
27397
27509
  "",
27398
27510
  pc10.dim(`Use ${pc10.bold("--force")} to remove existing admin files before scaffolding.`)
27399
27511
  );
27400
- p25.note(conflictLines.join("\n"), pc10.yellow("Conflicts"));
27512
+ p26.note(conflictLines.join("\n"), pc10.yellow("Conflicts"));
27401
27513
  if (options.yes) {
27402
- p25.log.error(
27514
+ p26.log.error(
27403
27515
  "Can't continue with --yes while admin files conflict. Re-run with --force to remove them first."
27404
27516
  );
27405
27517
  process.exit(1);
27406
27518
  }
27407
- const proceed = await p25.confirm({
27519
+ const proceed = await p26.confirm({
27408
27520
  message: [
27409
27521
  `Continue with ${pc10.bold(pc10.cyan("--force"))}?`,
27410
27522
  `${pc10.cyan("\u2502")} ${pc10.dim("This will force overwrite the existing admin code.")}`,
@@ -27412,14 +27524,14 @@ async function runInitCommand(name, options) {
27412
27524
  ].join("\n"),
27413
27525
  initialValue: true
27414
27526
  });
27415
- if (p25.isCancel(proceed) || !proceed) {
27416
- p25.cancel("Setup cancelled.");
27527
+ if (p26.isCancel(proceed) || !proceed) {
27528
+ p26.cancel("Setup cancelled.");
27417
27529
  process.exit(0);
27418
27530
  }
27419
27531
  forceMode = true;
27420
27532
  const nuked = removeExistingAdminPaths(cwd, await resolveForceInitNamespaces(cwd, namespace));
27421
27533
  if (nuked > 0) {
27422
- p25.log.warn(`${pc10.yellow("Force mode:")} removed ${nuked} existing admin paths`);
27534
+ p26.log.warn(`${pc10.yellow("Force mode:")} removed ${nuked} existing admin paths`);
27423
27535
  }
27424
27536
  project2 = detectProject(cwd, namespace);
27425
27537
  }
@@ -27427,7 +27539,7 @@ async function runInitCommand(name, options) {
27427
27539
  const freshProject = projectPrompt;
27428
27540
  srcDir = false;
27429
27541
  if (!options.yes) {
27430
- const pmChoice = await p25.select({
27542
+ const pmChoice = await p26.select({
27431
27543
  message: "Which package manager do you want to use?",
27432
27544
  options: [
27433
27545
  { value: "pnpm", label: "pnpm", hint: "recommended" },
@@ -27435,8 +27547,8 @@ async function runInitCommand(name, options) {
27435
27547
  { value: "bun", label: "bun" }
27436
27548
  ]
27437
27549
  });
27438
- if (p25.isCancel(pmChoice)) {
27439
- p25.cancel("Setup cancelled.");
27550
+ if (p26.isCancel(pmChoice)) {
27551
+ p26.cancel("Setup cancelled.");
27440
27552
  process.exit(0);
27441
27553
  }
27442
27554
  pm = pmChoice;
@@ -27471,8 +27583,8 @@ async function runInitCommand(name, options) {
27471
27583
  process.stderr.write(`${createNextAppResult.output.trimEnd()}
27472
27584
  `);
27473
27585
  }
27474
- p25.log.error(createNextAppResult.error);
27475
- p25.log.info(
27586
+ p26.log.error(createNextAppResult.error);
27587
+ p26.log.info(
27476
27588
  `You can create the project manually:
27477
27589
  ${pc10.cyan(`npx create-next-app@latest ${freshProject.projectName} --typescript --tailwind --app`)}
27478
27590
  Then run ${pc10.cyan("betterstart init")} inside it.`
@@ -27486,11 +27598,11 @@ async function runInitCommand(name, options) {
27486
27598
  );
27487
27599
  if (!hasPackageJson || !hasNextConfig) {
27488
27600
  createNextAppSpinner.stop(`Failed to create Next.js app: ${displayName}`);
27489
- p25.log.error(
27601
+ p26.log.error(
27490
27602
  "create-next-app completed but the project was not created. This can happen with nested npx calls."
27491
27603
  );
27492
27604
  const manualCmd = `npx create-next-app@latest ${freshProject.projectName} --typescript --tailwind --app`;
27493
- p25.log.info(
27605
+ p26.log.info(
27494
27606
  `Create the project manually:
27495
27607
  ${pc10.cyan(manualCmd)}
27496
27608
  Then run ${pc10.cyan("betterstart init")} inside it.`
@@ -27539,13 +27651,13 @@ async function runInitCommand(name, options) {
27539
27651
  try {
27540
27652
  validateResolvedDatabaseProvider(databaseProvider, options);
27541
27653
  } catch (error) {
27542
- p25.log.error(error instanceof Error ? error.message : String(error));
27654
+ p26.log.error(error instanceof Error ? error.message : String(error));
27543
27655
  process.exit(1);
27544
27656
  }
27545
27657
  if (databaseProvider === "manual") {
27546
27658
  const candidate = options.databaseUrl ?? existingDbUrl ?? promptedManualUrl;
27547
27659
  if (candidate && !isValidDbUrl(candidate)) {
27548
- p25.log.error(
27660
+ p26.log.error(
27549
27661
  `Invalid database URL. Must start with ${pc10.cyan("postgres://")} or ${pc10.cyan("postgresql://")}`
27550
27662
  );
27551
27663
  process.exit(1);
@@ -27553,7 +27665,7 @@ async function runInitCommand(name, options) {
27553
27665
  if (candidate) {
27554
27666
  databaseUrl = candidate;
27555
27667
  if (existingDbUrl === candidate && !options.databaseUrl) {
27556
- p25.log.info(
27668
+ p26.log.info(
27557
27669
  `Using the existing DATABASE_URL from .env.local ${pc10.dim(`(${maskDbUrl(candidate)})`)}`
27558
27670
  );
27559
27671
  }
@@ -27573,7 +27685,7 @@ async function runInitCommand(name, options) {
27573
27685
  persistDatabaseUrl(cwd, databaseUrl);
27574
27686
  dismissVercelSignedInNote = flow.dismissSignedInNote;
27575
27687
  } else if (options.yes) {
27576
- p25.log.error(
27688
+ p26.log.error(
27577
27689
  flow.ok ? "Created a Neon database, but DATABASE_URL could not be retrieved from Vercel." : "Vercel database provisioning did not complete."
27578
27690
  );
27579
27691
  process.exit(1);
@@ -27582,7 +27694,7 @@ async function runInitCommand(name, options) {
27582
27694
  databaseUrl = await promptConnectionString();
27583
27695
  persistDatabaseUrl(cwd, databaseUrl);
27584
27696
  } else {
27585
- p25.log.info("Falling back to a manual database connection string.");
27697
+ p26.log.info("Falling back to a manual database connection string.");
27586
27698
  openBrowserVercelNeon();
27587
27699
  databaseUrl = await promptConnectionString();
27588
27700
  }
@@ -27596,11 +27708,11 @@ async function runInitCommand(name, options) {
27596
27708
  } catch (error) {
27597
27709
  const message = error instanceof Error ? error.message : String(error);
27598
27710
  if (options.yes) {
27599
- p25.log.error(`Railway database provisioning failed: ${message}`);
27711
+ p26.log.error(`Railway database provisioning failed: ${message}`);
27600
27712
  process.exit(1);
27601
27713
  }
27602
- p25.log.warn(`Railway database provisioning failed: ${message}`);
27603
- p25.log.info("Falling back to a manual database connection string.");
27714
+ p26.log.warn(`Railway database provisioning failed: ${message}`);
27715
+ p26.log.info("Falling back to a manual database connection string.");
27604
27716
  databaseUrl = await promptConnectionString();
27605
27717
  }
27606
27718
  }
@@ -27630,7 +27742,7 @@ async function runInitCommand(name, options) {
27630
27742
  return { ok: true, config: config2 };
27631
27743
  } catch (error) {
27632
27744
  const message = error instanceof Error ? error.message : String(error);
27633
- p25.log.warn(`Railway bucket provisioning failed: ${message}`);
27745
+ p26.log.warn(`Railway bucket provisioning failed: ${message}`);
27634
27746
  return { ok: false };
27635
27747
  }
27636
27748
  };
@@ -27644,7 +27756,7 @@ async function runInitCommand(name, options) {
27644
27756
  if (storage === "r2") {
27645
27757
  const missingR2Keys = R2_ENV_KEYS.filter((key) => !readEnvVar(cwd, key)?.trim());
27646
27758
  if (options.yes && missingR2Keys.length > 0) {
27647
- p25.log.error(
27759
+ p26.log.error(
27648
27760
  `Cloudflare R2 is missing required environment variables: ${missingR2Keys.join(", ")}.`
27649
27761
  );
27650
27762
  process.exit(1);
@@ -27658,7 +27770,7 @@ async function runInitCommand(name, options) {
27658
27770
  if (flow.ok && flow.config) {
27659
27771
  mergeCollectedIntegrationConfig(flow.config);
27660
27772
  } else if (options.yes) {
27661
- p25.log.error("Railway bucket provisioning did not complete.");
27773
+ p26.log.error("Railway bucket provisioning did not complete.");
27662
27774
  process.exit(1);
27663
27775
  }
27664
27776
  }
@@ -27677,10 +27789,10 @@ async function runInitCommand(name, options) {
27677
27789
  });
27678
27790
  collectedIntegrationConfig.overwriteKeys.add("BLOB_READ_WRITE_TOKEN");
27679
27791
  } else if (options.yes) {
27680
- p25.log.error("Vercel Blob provisioning did not complete.");
27792
+ p26.log.error("Vercel Blob provisioning did not complete.");
27681
27793
  process.exit(1);
27682
27794
  } else {
27683
- p25.log.warn(
27795
+ p26.log.warn(
27684
27796
  "Continuing without a Blob token \u2014 add BLOB_READ_WRITE_TOKEN to .env.local from the store on vercel.com/dashboard/stores."
27685
27797
  );
27686
27798
  collectedIntegrationConfig.sections.push({
@@ -27754,7 +27866,7 @@ async function runInitCommand(name, options) {
27754
27866
  const nextConfigResult = scaffoldNextConfig({ cwd, nextMajorVersion });
27755
27867
  s.clear();
27756
27868
  if (nextConfigResult.status === "unsupported") {
27757
- p25.log.warn("The Next.js config could not be updated automatically \u2014 review it manually.");
27869
+ p26.log.warn("The Next.js config could not be updated automatically \u2014 review it manually.");
27758
27870
  }
27759
27871
  const drizzleConfigPath = path52.join(cwd, "drizzle.config.ts");
27760
27872
  if (!dbFiles.includes("drizzle.config.ts") && fs41.existsSync(drizzleConfigPath)) {
@@ -27765,20 +27877,20 @@ async function runInitCommand(name, options) {
27765
27877
  readNamespacedTemplate("drizzle.config.ts", namespace),
27766
27878
  "utf-8"
27767
27879
  );
27768
- p25.log.success("Updated drizzle.config.ts");
27880
+ p26.log.success("Updated drizzle.config.ts");
27769
27881
  } else if (!options.yes) {
27770
- const overwrite = await p25.confirm({
27882
+ const overwrite = await p26.confirm({
27771
27883
  message: "drizzle.config.ts already exists. Overwrite with latest version?",
27772
27884
  initialValue: true
27773
27885
  });
27774
- if (!p25.isCancel(overwrite) && overwrite) {
27886
+ if (!p26.isCancel(overwrite) && overwrite) {
27775
27887
  const { readNamespacedTemplate } = await import("./template-reader-PVN53GS7.js");
27776
27888
  fs41.writeFileSync(
27777
27889
  drizzleConfigPath,
27778
27890
  readNamespacedTemplate("drizzle.config.ts", namespace),
27779
27891
  "utf-8"
27780
27892
  );
27781
- p25.log.success("Updated drizzle.config.ts");
27893
+ p26.log.success("Updated drizzle.config.ts");
27782
27894
  }
27783
27895
  }
27784
27896
  }
@@ -27803,8 +27915,8 @@ async function runInitCommand(name, options) {
27803
27915
  s.stop("");
27804
27916
  } else {
27805
27917
  s.stop("Failed to install dependencies");
27806
- p25.log.warn(depsResult.error ?? "Unknown error");
27807
- p25.log.info(
27918
+ p26.log.warn(depsResult.error ?? "Unknown error");
27919
+ p26.log.info(
27808
27920
  `You can install them manually:
27809
27921
  ${pc10.cyan(`${pm} add ${depsResult.dependencies.join(" ")}`)}
27810
27922
  ${pc10.cyan(`${pm} add -D ${depsResult.devDeps.join(" ")}`)}`
@@ -27860,22 +27972,22 @@ async function runInitCommand(name, options) {
27860
27972
  writeConfigFile(cwd, resolvedIntegrationInstallResult.config);
27861
27973
  const usesLocalStorage = resolvedIntegrationInstallResult.config.storage.provider === "local";
27862
27974
  for (const err of coreSchemasResult.errors) {
27863
- p25.log.warn(`Core schemas: ${err}`);
27975
+ p26.log.warn(`Core schemas: ${err}`);
27864
27976
  }
27865
27977
  for (const warning of resolvedPresetInstallResult.warnings) {
27866
- p25.log.warn(warning);
27978
+ p26.log.warn(warning);
27867
27979
  }
27868
27980
  for (const warning of resolvedIntegrationInstallResult.warnings) {
27869
- p25.log.warn(warning);
27981
+ p26.log.warn(warning);
27870
27982
  }
27871
27983
  if (usesLocalStorage) {
27872
- p25.log.warn(
27984
+ p26.log.warn(
27873
27985
  "Local filesystem storage is only for development or self-hosted persistent-disk deployments. Use Vercel Blob, Railway Bucket, or Cloudflare R2 for hosted production."
27874
27986
  );
27875
27987
  }
27876
27988
  let dbPushed = false;
27877
27989
  if (depsResult.success && options.skipMigration && hasDbUrl(cwd)) {
27878
- p25.log.info(`Skipping database schema push ${pc10.dim("(--skip-migration)")}`);
27990
+ p26.log.info(`Skipping database schema push ${pc10.dim("(--skip-migration)")}`);
27879
27991
  } else if (depsResult.success && hasDbUrl(cwd)) {
27880
27992
  let driverReady = hasDrizzleKitPostgresDriverDependency(cwd);
27881
27993
  if (!driverReady) {
@@ -27890,8 +28002,8 @@ async function runInitCommand(name, options) {
27890
28002
  });
27891
28003
  if (!driverResult.success) {
27892
28004
  s.stop("Database push failed");
27893
- p25.log.warn(driverResult.error ?? `Failed to install ${DRIZZLE_KIT_POSTGRES_DRIVER_DEP}`);
27894
- p25.log.info(
28005
+ p26.log.warn(driverResult.error ?? `Failed to install ${DRIZZLE_KIT_POSTGRES_DRIVER_DEP}`);
28006
+ p26.log.info(
27895
28007
  `Install ${DRIZZLE_KIT_POSTGRES_DRIVER_DEP} manually, then run: ${pc10.cyan(drizzlePushCommand(pm))}`
27896
28008
  );
27897
28009
  } else {
@@ -27919,8 +28031,8 @@ async function runInitCommand(name, options) {
27919
28031
  const verification = await verifyDatabaseReachable(cwd);
27920
28032
  clearDbSpinner();
27921
28033
  if (!verification.success) {
27922
- p25.log.warn(verification.error);
27923
- p25.log.error("Database was not reachable. Aborting setup.");
28034
+ p26.log.warn(verification.error);
28035
+ p26.log.error("Database was not reachable. Aborting setup.");
27924
28036
  process.exit(1);
27925
28037
  }
27926
28038
  } else {
@@ -27933,12 +28045,12 @@ async function runInitCommand(name, options) {
27933
28045
  s.stop("Database push failed");
27934
28046
  }
27935
28047
  const pushError = pushResult.error ?? "Unknown error";
27936
- p25.log.warn(pushError);
28048
+ p26.log.warn(pushError);
27937
28049
  if (isDatabaseReachabilityError(pushError)) {
27938
- p25.log.error("Database was not reachable. Aborting setup.");
28050
+ p26.log.error("Database was not reachable. Aborting setup.");
27939
28051
  process.exit(1);
27940
28052
  }
27941
- p25.log.info(`You can run it manually: ${pc10.cyan(drizzlePushCommand(pm))}`);
28053
+ p26.log.info(`You can run it manually: ${pc10.cyan(drizzlePushCommand(pm))}`);
27942
28054
  }
27943
28055
  }
27944
28056
  }
@@ -27947,7 +28059,7 @@ async function runInitCommand(name, options) {
27947
28059
  let seedSuccess = false;
27948
28060
  let adminAccountReady = false;
27949
28061
  if (dbPushed && options.skipAdminCreation) {
27950
- p25.log.info(
28062
+ p26.log.info(
27951
28063
  `Skipping admin user creation ${pc10.dim(`(use ${betterstartExecCommand(pm, "seed")} later)`)}`
27952
28064
  );
27953
28065
  }
@@ -27959,14 +28071,14 @@ async function runInitCommand(name, options) {
27959
28071
  const adminCheck = await checkExistingAdmin(cwd, adminDir, authBasePath);
27960
28072
  s.clear();
27961
28073
  if (adminCheck.error) {
27962
- p25.log.warn(`Could not verify existing admin account ${pc10.dim(`(${adminCheck.error})`)}`);
28074
+ p26.log.warn(`Could not verify existing admin account ${pc10.dim(`(${adminCheck.error})`)}`);
27963
28075
  if (isDatabaseReachabilityError(adminCheck.error)) {
27964
- p25.log.error("Database was not reachable. Aborting setup.");
28076
+ p26.log.error("Database was not reachable. Aborting setup.");
27965
28077
  process.exit(1);
27966
28078
  }
27967
28079
  } else if (adminCheck.existingAdmin) {
27968
28080
  const existingAdminLabel = formatAdminIdentity(adminCheck.existingAdmin);
27969
- const adminAction = await p25.select({
28081
+ const adminAction = await p26.select({
27970
28082
  message: "Found an already existing admin account. Do you want to replace it or skip?",
27971
28083
  options: [
27972
28084
  {
@@ -27980,28 +28092,28 @@ async function runInitCommand(name, options) {
27980
28092
  }
27981
28093
  ]
27982
28094
  });
27983
- if (p25.isCancel(adminAction)) {
27984
- p25.cancel("Setup cancelled.");
28095
+ if (p26.isCancel(adminAction)) {
28096
+ p26.cancel("Setup cancelled.");
27985
28097
  process.exit(0);
27986
28098
  }
27987
28099
  if (adminAction === "skip") {
27988
28100
  adminAccountReady = true;
27989
- p25.log.info(`Keeping existing admin account ${pc10.dim(`(${existingAdminLabel})`)}`);
28101
+ p26.log.info(`Keeping existing admin account ${pc10.dim(`(${existingAdminLabel})`)}`);
27990
28102
  } else {
27991
28103
  replaceExistingAdmin = true;
27992
28104
  }
27993
28105
  }
27994
28106
  if (!adminAccountReady) {
27995
- const credentials = await p25.group(
28107
+ const credentials = await p26.group(
27996
28108
  {
27997
- email: () => p25.text({
28109
+ email: () => p26.text({
27998
28110
  message: "Admin email",
27999
28111
  placeholder: "admin@example.com",
28000
28112
  validate: (v) => {
28001
28113
  if (!v || !v.includes("@")) return "Please enter a valid email";
28002
28114
  }
28003
28115
  }),
28004
- password: () => p25.password({
28116
+ password: () => p26.password({
28005
28117
  message: "Admin password",
28006
28118
  validate: (v) => {
28007
28119
  if (!v || v.length < 8) return "Password must be at least 8 characters";
@@ -28010,14 +28122,14 @@ async function runInitCommand(name, options) {
28010
28122
  },
28011
28123
  {
28012
28124
  onCancel: () => {
28013
- p25.cancel("Setup cancelled.");
28125
+ p26.cancel("Setup cancelled.");
28014
28126
  process.exit(0);
28015
28127
  }
28016
28128
  }
28017
28129
  );
28018
28130
  seedEmail = credentials.email;
28019
28131
  seedPassword = credentials.password;
28020
- const credentialPromptRows = clackPromptRows("Admin email", credentials.email) + clackPromptRows("Admin password", p25.S_PASSWORD_MASK.repeat(credentials.password.length));
28132
+ const credentialPromptRows = clackPromptRows("Admin email", credentials.email) + clackPromptRows("Admin password", p26.S_PASSWORD_MASK.repeat(credentials.password.length));
28021
28133
  let rowsBelowCredentialPrompts = 0;
28022
28134
  let seedOverwriteMode = replaceExistingAdmin ? "admin" : void 0;
28023
28135
  s.start(replaceExistingAdmin ? "Replacing admin user" : "Creating admin user");
@@ -28034,7 +28146,7 @@ async function runInitCommand(name, options) {
28034
28146
  s.stop(existingAccountMessage);
28035
28147
  rowsBelowCredentialPrompts += clackLogRows(existingAccountMessage);
28036
28148
  const replaceAccountMessage = "Replace the existing account with this email?";
28037
- const replace = await p25.confirm({
28149
+ const replace = await p26.confirm({
28038
28150
  message: replaceAccountMessage,
28039
28151
  initialValue: false
28040
28152
  });
@@ -28042,7 +28154,7 @@ async function runInitCommand(name, options) {
28042
28154
  replaceAccountMessage,
28043
28155
  replace === true ? "Yes" : "No"
28044
28156
  );
28045
- if (!p25.isCancel(replace) && replace) {
28157
+ if (!p26.isCancel(replace) && replace) {
28046
28158
  seedOverwriteMode = "email";
28047
28159
  s.start("Replacing admin user");
28048
28160
  seedResult = await runSeed(
@@ -28064,14 +28176,14 @@ async function runInitCommand(name, options) {
28064
28176
  adminAccountReady = true;
28065
28177
  } else if (seedResult.error) {
28066
28178
  s.stop(`Failed to create admin user`);
28067
- p25.note(
28179
+ p26.note(
28068
28180
  `${pc10.red(seedResult.error)}
28069
28181
 
28070
28182
  Run manually: ${pc10.cyan(betterstartExecCommand(pm, "seed"))}`,
28071
28183
  pc10.red("Seed failed")
28072
28184
  );
28073
28185
  if (isDatabaseReachabilityError(seedResult.error)) {
28074
- p25.log.error("Database was not reachable. Aborting setup.");
28186
+ p26.log.error("Database was not reachable. Aborting setup.");
28075
28187
  process.exit(1);
28076
28188
  }
28077
28189
  }
@@ -28113,10 +28225,10 @@ Run manually: ${pc10.cyan(betterstartExecCommand(pm, "seed"))}`,
28113
28225
  deployedUrl = deployFlow.url;
28114
28226
  if (!deployFlow.ok) {
28115
28227
  if (options.yes) {
28116
- p25.log.error("Vercel deploy did not complete.");
28228
+ p26.log.error("Vercel deploy did not complete.");
28117
28229
  process.exit(1);
28118
28230
  }
28119
- p25.log.warn("Vercel deploy did not complete; continuing.");
28231
+ p26.log.warn("Vercel deploy did not complete; continuing.");
28120
28232
  }
28121
28233
  } else if (deployProvider === "railway") {
28122
28234
  try {
@@ -28134,29 +28246,29 @@ Run manually: ${pc10.cyan(betterstartExecCommand(pm, "seed"))}`,
28134
28246
  });
28135
28247
  deployedUrl = deployFlow.url;
28136
28248
  if (!deployFlow.ok) {
28137
- if (deployFlow.detail) p25.log.message(pc10.dim(redactSecrets(deployFlow.detail)));
28249
+ if (deployFlow.detail) p26.log.message(pc10.dim(redactSecrets(deployFlow.detail)));
28138
28250
  if (options.yes) {
28139
- p25.log.error("Railway deploy did not complete.");
28251
+ p26.log.error("Railway deploy did not complete.");
28140
28252
  process.exit(1);
28141
28253
  }
28142
- p25.log.warn("Railway deploy did not complete; continuing.");
28254
+ p26.log.warn("Railway deploy did not complete; continuing.");
28143
28255
  }
28144
28256
  } catch (error) {
28145
28257
  const message = error instanceof Error ? error.message : String(error);
28146
28258
  if (options.yes) {
28147
- p25.log.error(`Railway deploy failed: ${message}`);
28259
+ p26.log.error(`Railway deploy failed: ${message}`);
28148
28260
  process.exit(1);
28149
28261
  }
28150
- p25.log.warn(`Railway deploy failed: ${message}`);
28262
+ p26.log.warn(`Railway deploy failed: ${message}`);
28151
28263
  }
28152
28264
  }
28153
28265
  if (!options.yes && !options.skipDevServerStart) {
28154
28266
  const devCmd = runCommand(pm, "dev");
28155
- const startDev = await p25.confirm({
28267
+ const startDev = await p26.confirm({
28156
28268
  message: "Start the development server?",
28157
28269
  initialValue: true
28158
28270
  });
28159
- if (!p25.isCancel(startDev) && startDev) {
28271
+ if (!p26.isCancel(startDev) && startDev) {
28160
28272
  disposeCancelGuard();
28161
28273
  await startManagedDevServer(cwd, devCmd, adminLoginUrl, {
28162
28274
  email: seedSuccess && seedEmail ? seedEmail : void 0,
@@ -28188,7 +28300,7 @@ Run manually: ${pc10.cyan(betterstartExecCommand(pm, "seed"))}`,
28188
28300
  );
28189
28301
  return;
28190
28302
  }
28191
- p25.outro(`Admin ready at ${adminNamespace.routePath}`);
28303
+ p26.outro(`Admin ready at ${adminNamespace.routePath}`);
28192
28304
  }
28193
28305
  function isValidDbUrl(url) {
28194
28306
  return url.startsWith("postgres://") || url.startsWith("postgresql://");
@@ -28581,7 +28693,7 @@ function printAdminReadyNote(state) {
28581
28693
  } else if (state.adminEmail) {
28582
28694
  lines.unshift(`Admin user: ${pc10.cyan(state.adminEmail)}`);
28583
28695
  }
28584
- p25.note(lines.join("\n"), "Admin ready");
28696
+ p26.note(lines.join("\n"), "Admin ready");
28585
28697
  }
28586
28698
  function shouldSuppressDevServerStartupLine(line) {
28587
28699
  const plain = stripAnsi2(line).trim();
@@ -28693,7 +28805,7 @@ function startManagedDevServer(cwd, devCmd, adminLoginUrl, adminCredentials) {
28693
28805
 
28694
28806
  // adapters/next/commands/list-integrations.ts
28695
28807
  import path53 from "path";
28696
- import * as p26 from "@clack/prompts";
28808
+ import * as p27 from "@clack/prompts";
28697
28809
 
28698
28810
  // core-engine/utils/table.ts
28699
28811
  function renderTableRows(rows) {
@@ -28740,15 +28852,15 @@ async function runListIntegrationsCommand(options) {
28740
28852
  integration.kind,
28741
28853
  integration.description
28742
28854
  ]);
28743
- p26.note(renderTableRows(rows).join("\n"), "BetterStart integrations");
28744
- p26.outro(
28855
+ p27.note(renderTableRows(rows).join("\n"), "BetterStart integrations");
28856
+ p27.outro(
28745
28857
  `${installedIntegrations.size} installed, ${rows.length - installedIntegrations.size} available`
28746
28858
  );
28747
28859
  }
28748
28860
 
28749
28861
  // adapters/next/commands/list-presets.ts
28750
28862
  import path54 from "path";
28751
- import * as p27 from "@clack/prompts";
28863
+ import * as p28 from "@clack/prompts";
28752
28864
  async function runListPresetsCommand(options) {
28753
28865
  const cwd = options.cwd ? path54.resolve(options.cwd) : process.cwd();
28754
28866
  if (options.json) {
@@ -28778,48 +28890,73 @@ async function runListPresetsCommand(options) {
28778
28890
  preset.kind,
28779
28891
  preset.description
28780
28892
  ]);
28781
- p27.note(renderTableRows(rows).join("\n"), "BetterStart presets");
28782
- p27.outro(`${installedPresets.size} installed, ${rows.length - installedPresets.size} available`);
28893
+ p28.note(renderTableRows(rows).join("\n"), "BetterStart presets");
28894
+ p28.outro(`${installedPresets.size} installed, ${rows.length - installedPresets.size} available`);
28783
28895
  }
28784
28896
 
28785
- // adapters/next/commands/remove.ts
28897
+ // adapters/next/commands/menu-choices.ts
28786
28898
  import path55 from "path";
28787
- import * as p28 from "@clack/prompts";
28899
+ async function listInstallableChoices(cwd) {
28900
+ const config = await resolveConfigOrExit(cwd);
28901
+ const installedPresets = new Set(config.presets.installed);
28902
+ const installedIntegrations = new Set(config.integrations.installed);
28903
+ return {
28904
+ presets: listAvailablePresets().map((preset) => ({
28905
+ id: preset.id,
28906
+ description: preset.description,
28907
+ installed: installedPresets.has(preset.id)
28908
+ })),
28909
+ integrations: listAvailableIntegrations().map((integration) => ({
28910
+ id: integration.id,
28911
+ description: integration.description,
28912
+ installed: installedIntegrations.has(integration.id)
28913
+ }))
28914
+ };
28915
+ }
28916
+ async function listSchemaChoices(cwd) {
28917
+ const config = await resolveConfigOrExit(cwd);
28918
+ const paths = resolveProjectPaths(config);
28919
+ return listSchemaNames(path55.join(cwd, ...paths.schemasDir.split("/")));
28920
+ }
28921
+
28922
+ // adapters/next/commands/remove.ts
28923
+ import path56 from "path";
28924
+ import * as p29 from "@clack/prompts";
28788
28925
  async function runRemoveCommand(items, options) {
28789
28926
  const removeIntegrationsMode = Boolean(options.integration);
28790
28927
  if (!removeIntegrationsMode && items.includes("core")) {
28791
- p28.log.error("The core Admin cannot be removed.");
28928
+ p29.log.error("The core Admin cannot be removed.");
28792
28929
  process.exit(1);
28793
28930
  }
28794
28931
  const presetIds = items.filter(isPresetId);
28795
28932
  const integrationIds = items.filter(isIntegrationId);
28796
28933
  if (!removeIntegrationsMode && integrationIds.length > 0) {
28797
- p28.log.error(
28934
+ p29.log.error(
28798
28935
  `Integration IDs require --integration. Run \`betterstart remove --integration ${integrationIds.join(" ")}\`.`
28799
28936
  );
28800
28937
  process.exit(1);
28801
28938
  }
28802
28939
  if (removeIntegrationsMode && presetIds.length > 0) {
28803
- p28.log.error(`Preset IDs cannot be removed with --integration: ${presetIds.join(", ")}`);
28940
+ p29.log.error(`Preset IDs cannot be removed with --integration: ${presetIds.join(", ")}`);
28804
28941
  process.exit(1);
28805
28942
  }
28806
28943
  const invalidItems = removeIntegrationsMode ? items.filter((integrationId) => !isIntegrationId(integrationId)) : items.filter((presetId) => !isPresetId(presetId));
28807
28944
  if (invalidItems.length > 0) {
28808
- p28.log.error(
28945
+ p29.log.error(
28809
28946
  removeIntegrationsMode ? formatUnknownIntegrationMessage(invalidItems) : formatUnknownPresetMessage(invalidItems)
28810
28947
  );
28811
28948
  process.exit(1);
28812
28949
  }
28813
- const cwd = options.cwd ? path55.resolve(options.cwd) : process.cwd();
28950
+ const cwd = options.cwd ? path56.resolve(options.cwd) : process.cwd();
28814
28951
  const config = await resolveConfigOrExit(cwd);
28815
28952
  const pm = detectPackageManager(cwd);
28816
28953
  if (!options.force) {
28817
- const confirmed = await p28.confirm({
28954
+ const confirmed = await p29.confirm({
28818
28955
  message: `Remove ${removeIntegrationsMode ? "integration" : "preset"}${items.length === 1 ? "" : "s"} ${items.join(", ")}?`,
28819
28956
  initialValue: false
28820
28957
  });
28821
- if (p28.isCancel(confirmed) || !confirmed) {
28822
- p28.cancel(`${removeIntegrationsMode ? "Integration" : "Preset"} removal cancelled.`);
28958
+ if (p29.isCancel(confirmed) || !confirmed) {
28959
+ p29.cancel(`${removeIntegrationsMode ? "Integration" : "Preset"} removal cancelled.`);
28823
28960
  process.exit(0);
28824
28961
  }
28825
28962
  }
@@ -28832,13 +28969,13 @@ async function runRemoveCommand(items, options) {
28832
28969
  });
28833
28970
  writeConfigFile(cwd, result2.config);
28834
28971
  if (result2.removed.length === 0) {
28835
- p28.outro("No integrations were removed.");
28972
+ p29.outro("No integrations were removed.");
28836
28973
  return;
28837
28974
  }
28838
28975
  if (result2.warnings.length > 0) {
28839
- p28.note(result2.warnings.join("\n"), "Warnings");
28976
+ p29.note(result2.warnings.join("\n"), "Warnings");
28840
28977
  }
28841
- p28.outro(
28978
+ p29.outro(
28842
28979
  `Removed integration${result2.removed.length === 1 ? "" : "s"}: ${result2.removed.join(", ")}`
28843
28980
  );
28844
28981
  return;
@@ -28851,37 +28988,37 @@ async function runRemoveCommand(items, options) {
28851
28988
  });
28852
28989
  writeConfigFile(cwd, result.config);
28853
28990
  if (result.removed.length === 0) {
28854
- p28.outro("No presets were removed.");
28991
+ p29.outro("No presets were removed.");
28855
28992
  return;
28856
28993
  }
28857
28994
  if (result.warnings.length > 0) {
28858
- p28.note(result.warnings.join("\n"), "Warnings");
28995
+ p29.note(result.warnings.join("\n"), "Warnings");
28859
28996
  }
28860
- p28.outro(`Removed preset${result.removed.length === 1 ? "" : "s"}: ${result.removed.join(", ")}`);
28997
+ p29.outro(`Removed preset${result.removed.length === 1 ? "" : "s"}: ${result.removed.join(", ")}`);
28861
28998
  }
28862
28999
 
28863
29000
  // adapters/next/commands/remove-schema.ts
28864
29001
  import fs42 from "fs";
28865
- import path56 from "path";
29002
+ import path57 from "path";
28866
29003
  import * as clack3 from "@clack/prompts";
28867
29004
  function removePath2(cwd, filePath) {
28868
- const fullPath = path56.join(cwd, ...filePath.split("/"));
29005
+ const fullPath = path57.join(cwd, ...filePath.split("/"));
28869
29006
  const existed = fs42.existsSync(fullPath);
28870
29007
  fs42.rmSync(fullPath, { recursive: true, force: true });
28871
29008
  return existed;
28872
29009
  }
28873
29010
  function cleanupEmptyDirs3(cwd, deletedPaths, configPaths) {
28874
29011
  const stopRoots = /* @__PURE__ */ new Set([
28875
- path56.join(cwd, ...configPaths.adminDir.split("/")),
28876
- path56.join(cwd, ...configPaths.adminNavigationDir.split("/")),
28877
- path56.join(cwd, ...configPaths.adminWebhookEventsDir.split("/")),
28878
- path56.join(cwd, ...configPaths.pagesDir.split("/"))
29012
+ path57.join(cwd, ...configPaths.adminDir.split("/")),
29013
+ path57.join(cwd, ...configPaths.adminNavigationDir.split("/")),
29014
+ path57.join(cwd, ...configPaths.adminWebhookEventsDir.split("/")),
29015
+ path57.join(cwd, ...configPaths.pagesDir.split("/"))
28879
29016
  ]);
28880
29017
  for (const deletedPath of deletedPaths) {
28881
- let current = path56.dirname(path56.join(cwd, ...deletedPath.split("/")));
29018
+ let current = path57.dirname(path57.join(cwd, ...deletedPath.split("/")));
28882
29019
  while (!stopRoots.has(current)) {
28883
29020
  if (!fs42.existsSync(current)) {
28884
- current = path56.dirname(current);
29021
+ current = path57.dirname(current);
28885
29022
  continue;
28886
29023
  }
28887
29024
  const entries = fs42.readdirSync(current);
@@ -28889,7 +29026,7 @@ function cleanupEmptyDirs3(cwd, deletedPaths, configPaths) {
28889
29026
  break;
28890
29027
  }
28891
29028
  fs42.rmdirSync(current);
28892
- current = path56.dirname(current);
29029
+ current = path57.dirname(current);
28893
29030
  }
28894
29031
  }
28895
29032
  }
@@ -28905,7 +29042,7 @@ function resolveSchemaOwnerForRemoval(cwd, schemaName) {
28905
29042
  }
28906
29043
  async function runRemoveSchemaCommand(schemaName, options) {
28907
29044
  const owner = resolveSchemaOwnerForRemoval(
28908
- options.cwd ? path56.resolve(options.cwd) : process.cwd(),
29045
+ options.cwd ? path57.resolve(options.cwd) : process.cwd(),
28909
29046
  schemaName
28910
29047
  );
28911
29048
  if (owner === "core") {
@@ -28918,7 +29055,7 @@ async function runRemoveSchemaCommand(schemaName, options) {
28918
29055
  clack3.log.error(`"${schemaName}" is owned by ${owner}. Remove the owning preset instead.`);
28919
29056
  process.exit(1);
28920
29057
  }
28921
- const cwd = options.cwd ? path56.resolve(options.cwd) : process.cwd();
29058
+ const cwd = options.cwd ? path57.resolve(options.cwd) : process.cwd();
28922
29059
  const config = await resolveConfigOrExit(cwd);
28923
29060
  const paths = resolveProjectPaths(config);
28924
29061
  const manifest = loadManifest(cwd, schemaName);
@@ -28931,7 +29068,7 @@ async function runRemoveSchemaCommand(schemaName, options) {
28931
29068
  process.exit(1);
28932
29069
  }
28933
29070
  if (!options.force) {
28934
- if (!isInteractiveSession4()) {
29071
+ if (!isInteractiveSession()) {
28935
29072
  clack3.log.error(
28936
29073
  `Removing generated files for ${schemaName} needs confirmation. Re-run with --force.`
28937
29074
  );
@@ -28954,7 +29091,7 @@ async function runRemoveSchemaCommand(schemaName, options) {
28954
29091
  }
28955
29092
  const loaded = (() => {
28956
29093
  try {
28957
- return loadSchema(path56.join(cwd, ...paths.schemasDir.split("/")), schemaName);
29094
+ return loadSchema(path57.join(cwd, ...paths.schemasDir.split("/")), schemaName);
28958
29095
  } catch {
28959
29096
  return null;
28960
29097
  }
@@ -28999,8 +29136,8 @@ Schema JSON preserved.`
28999
29136
 
29000
29137
  // adapters/next/commands/uninstall.ts
29001
29138
  import fs44 from "fs";
29002
- import path57 from "path";
29003
- import * as p29 from "@clack/prompts";
29139
+ import path58 from "path";
29140
+ import * as p30 from "@clack/prompts";
29004
29141
  import pc11 from "picocolors";
29005
29142
 
29006
29143
  // adapters/next/commands/uninstall-cleaners.ts
@@ -29149,7 +29286,7 @@ function findMainCss2(cwd) {
29149
29286
  "globals.css"
29150
29287
  ];
29151
29288
  for (const candidate of candidates) {
29152
- const filePath = path57.join(cwd, candidate);
29289
+ const filePath = path58.join(cwd, candidate);
29153
29290
  if (fs44.existsSync(filePath)) return filePath;
29154
29291
  }
29155
29292
  return void 0;
@@ -29166,13 +29303,13 @@ function isCLICreatedBiome(biomePath) {
29166
29303
  function buildUninstallPlan(cwd, namespaceValue) {
29167
29304
  const steps = [];
29168
29305
  const namespace = resolveAdminNamespace(namespaceValue);
29169
- const hasSrc = fs44.existsSync(path57.join(cwd, "src"));
29306
+ const hasSrc = fs44.existsSync(path58.join(cwd, "src"));
29170
29307
  const appBase = hasSrc ? "src/app" : "app";
29171
29308
  const dirs = [];
29172
- const adminDir = path57.join(cwd, namespace.segment);
29173
- const legacyAdminDir = path57.join(cwd, "admin");
29174
- const adminRouteGroup = path57.join(cwd, appBase, namespace.routeGroup);
29175
- const legacyAdminRouteGroup = path57.join(cwd, appBase, "(admin)");
29309
+ const adminDir = path58.join(cwd, namespace.segment);
29310
+ const legacyAdminDir = path58.join(cwd, "admin");
29311
+ const adminRouteGroup = path58.join(cwd, appBase, namespace.routeGroup);
29312
+ const legacyAdminRouteGroup = path58.join(cwd, appBase, "(admin)");
29176
29313
  if (fs44.existsSync(adminDir)) dirs.push(`${namespace.segment}/`);
29177
29314
  if (namespace.segment !== "admin" && fs44.existsSync(legacyAdminDir)) dirs.push("admin/");
29178
29315
  if (fs44.existsSync(adminRouteGroup)) dirs.push(`${appBase}/${namespace.routeGroup}/`);
@@ -29200,9 +29337,9 @@ function buildUninstallPlan(cwd, namespaceValue) {
29200
29337
  const configFiles = [];
29201
29338
  const configPaths = [];
29202
29339
  const candidates = [
29203
- [CONFIG_FILE_NAME, path57.join(cwd, CONFIG_FILE_NAME)],
29204
- ["drizzle.config.ts", path57.join(cwd, "drizzle.config.ts")],
29205
- ["ADMIN.md", path57.join(cwd, "ADMIN.md")]
29340
+ [CONFIG_FILE_NAME, path58.join(cwd, CONFIG_FILE_NAME)],
29341
+ ["drizzle.config.ts", path58.join(cwd, "drizzle.config.ts")],
29342
+ ["ADMIN.md", path58.join(cwd, "ADMIN.md")]
29206
29343
  ];
29207
29344
  for (const [label, fullPath] of candidates) {
29208
29345
  if (fs44.existsSync(fullPath)) {
@@ -29210,7 +29347,7 @@ function buildUninstallPlan(cwd, namespaceValue) {
29210
29347
  configPaths.push(fullPath);
29211
29348
  }
29212
29349
  }
29213
- const biomePath = path57.join(cwd, "biome.json");
29350
+ const biomePath = path58.join(cwd, "biome.json");
29214
29351
  if (isCLICreatedBiome(biomePath)) {
29215
29352
  configFiles.push("biome.json (CLI-created)");
29216
29353
  configPaths.push(biomePath);
@@ -29222,13 +29359,13 @@ function buildUninstallPlan(cwd, namespaceValue) {
29222
29359
  count: configFiles.length,
29223
29360
  unit: configFiles.length === 1 ? "file" : "files",
29224
29361
  execute() {
29225
- for (const p31 of configPaths) {
29226
- if (fs44.existsSync(p31)) fs44.unlinkSync(p31);
29362
+ for (const p32 of configPaths) {
29363
+ if (fs44.existsSync(p32)) fs44.unlinkSync(p32);
29227
29364
  }
29228
29365
  }
29229
29366
  });
29230
29367
  }
29231
- const tsconfigPath = path57.join(cwd, "tsconfig.json");
29368
+ const tsconfigPath = path58.join(cwd, "tsconfig.json");
29232
29369
  if (fs44.existsSync(tsconfigPath)) {
29233
29370
  const content = fs44.readFileSync(tsconfigPath, "utf-8");
29234
29371
  const aliasMatches = [
@@ -29255,7 +29392,7 @@ function buildUninstallPlan(cwd, namespaceValue) {
29255
29392
  (l) => new RegExp(`^@source\\s+"[^"]*(?:admin|${namespace.segment})[^"]*";\\s*$`).test(l)
29256
29393
  );
29257
29394
  if (sourceLines.length > 0) {
29258
- const relCss = path57.relative(cwd, cssFile);
29395
+ const relCss = path58.relative(cwd, cssFile);
29259
29396
  steps.push({
29260
29397
  label: `CSS @source lines (${relCss})`,
29261
29398
  items: [`@source lines in ${relCss}`],
@@ -29267,7 +29404,7 @@ function buildUninstallPlan(cwd, namespaceValue) {
29267
29404
  });
29268
29405
  }
29269
29406
  }
29270
- const envPath = path57.join(cwd, ".env.local");
29407
+ const envPath = path58.join(cwd, ".env.local");
29271
29408
  if (fs44.existsSync(envPath)) {
29272
29409
  const envContent = fs44.readFileSync(envPath, "utf-8");
29273
29410
  const bsVars = envContent.split("\n").filter((l) => l.trim().match(/^BETTERSTART_\w+=/)).map((l) => l.split("=")[0]);
@@ -29286,8 +29423,8 @@ function buildUninstallPlan(cwd, namespaceValue) {
29286
29423
  return steps;
29287
29424
  }
29288
29425
  async function runUninstallCommand(options) {
29289
- const cwd = options.cwd ? path57.resolve(options.cwd) : process.cwd();
29290
- p29.intro(pc11.bgRed(pc11.white(" BetterStart Uninstall ")));
29426
+ const cwd = options.cwd ? path58.resolve(options.cwd) : process.cwd();
29427
+ p30.intro(pc11.bgRed(pc11.white(" BetterStart Uninstall ")));
29291
29428
  let namespace = DEFAULT_ADMIN_NAMESPACE;
29292
29429
  try {
29293
29430
  const config = await resolveConfig(cwd);
@@ -29296,8 +29433,8 @@ async function runUninstallCommand(options) {
29296
29433
  }
29297
29434
  const steps = buildUninstallPlan(cwd, namespace);
29298
29435
  if (steps.length === 0) {
29299
- p29.log.success(`${pc11.green("\u2713")} Nothing to remove \u2014 project is already clean.`);
29300
- p29.outro("Project already clean");
29436
+ p30.log.success(`${pc11.green("\u2713")} Nothing to remove \u2014 project is already clean.`);
29437
+ p30.outro("Project already clean");
29301
29438
  return;
29302
29439
  }
29303
29440
  const planLines = steps.map((step) => {
@@ -29305,14 +29442,14 @@ async function runUninstallCommand(options) {
29305
29442
  const countLabel = pc11.dim(`${step.count} ${step.unit}`);
29306
29443
  return `${pc11.red("\u2717")} ${names} ${countLabel}`;
29307
29444
  });
29308
- p29.note(planLines.join("\n"), "Uninstall plan");
29445
+ p30.note(planLines.join("\n"), "Uninstall plan");
29309
29446
  if (!options.force) {
29310
- const confirmed = await p29.confirm({
29447
+ const confirmed = await p30.confirm({
29311
29448
  message: "Proceed with uninstall?",
29312
29449
  initialValue: false
29313
29450
  });
29314
- if (p29.isCancel(confirmed) || !confirmed) {
29315
- p29.cancel("Uninstall cancelled.");
29451
+ if (p30.isCancel(confirmed) || !confirmed) {
29452
+ p30.cancel("Uninstall cancelled.");
29316
29453
  process.exit(0);
29317
29454
  }
29318
29455
  }
@@ -29324,14 +29461,14 @@ async function runUninstallCommand(options) {
29324
29461
  }
29325
29462
  const parts = steps.map((step) => `${step.count} ${step.unit}`);
29326
29463
  s.stop(`Removed ${parts.join(", ")}`);
29327
- p29.note(pc11.dim("Database tables were NOT dropped \u2014 drop them manually if needed."), "Next steps");
29328
- p29.outro("Uninstall complete");
29464
+ p30.note(pc11.dim("Database tables were NOT dropped \u2014 drop them manually if needed."), "Next steps");
29465
+ p30.outro("Uninstall complete");
29329
29466
  }
29330
29467
 
29331
29468
  // adapters/next/commands/update-component.ts
29332
29469
  import { execFileSync as execFileSync6 } from "child_process";
29333
29470
  import fs45 from "fs";
29334
- import path58 from "path";
29471
+ import path59 from "path";
29335
29472
  import * as clack4 from "@clack/prompts";
29336
29473
  import fsExtra from "fs-extra";
29337
29474
  var STATIC_CUSTOM_DEPENDENCIES = {
@@ -29592,14 +29729,14 @@ function copyNamespacedDirectory(srcDir, destDir, namespace) {
29592
29729
  const entries = fs45.readdirSync(srcDir, { withFileTypes: true });
29593
29730
  for (const entry of entries) {
29594
29731
  const namespacedName = applyAdminNamespaceToPath(entry.name, namespace);
29595
- const srcPath = path58.join(srcDir, entry.name);
29596
- const destPath = path58.join(destDir, namespacedName);
29732
+ const srcPath = path59.join(srcDir, entry.name);
29733
+ const destPath = path59.join(destDir, namespacedName);
29597
29734
  if (entry.isDirectory()) {
29598
29735
  fsExtra.ensureDirSync(destPath);
29599
29736
  copyNamespacedDirectory(srcPath, destPath, namespace);
29600
29737
  continue;
29601
29738
  }
29602
- fsExtra.ensureDirSync(path58.dirname(destPath));
29739
+ fsExtra.ensureDirSync(path59.dirname(destPath));
29603
29740
  writeNamespacedFile(srcPath, destPath, namespace);
29604
29741
  }
29605
29742
  }
@@ -29610,7 +29747,7 @@ function hasIntegration(config, integrationId) {
29610
29747
  return config.integrations.installed.includes(integrationId);
29611
29748
  }
29612
29749
  function readProjectPackageJson2(cwd) {
29613
- const pkgPath = path58.join(cwd, "package.json");
29750
+ const pkgPath = path59.join(cwd, "package.json");
29614
29751
  if (!fs45.existsSync(pkgPath)) return null;
29615
29752
  try {
29616
29753
  return JSON.parse(fs45.readFileSync(pkgPath, "utf-8"));
@@ -31146,12 +31283,12 @@ function getStaticAssetComponentEntries(assetDirectory) {
31146
31283
  continue;
31147
31284
  }
31148
31285
  const indexFile = ["index.tsx", "index.ts"].find(
31149
- (file) => fs45.existsSync(path58.join(assetDir, entry.name, file))
31286
+ (file) => fs45.existsSync(path59.join(assetDir, entry.name, file))
31150
31287
  );
31151
31288
  if (indexFile) {
31152
31289
  components.push({
31153
31290
  name: entry.name,
31154
- file: path58.join(entry.name, indexFile)
31291
+ file: path59.join(entry.name, indexFile)
31155
31292
  });
31156
31293
  }
31157
31294
  }
@@ -31160,20 +31297,20 @@ function getStaticAssetComponentEntries(assetDirectory) {
31160
31297
  function findStaticAssetFile(assetDir, componentName) {
31161
31298
  if (!fs45.existsSync(assetDir)) return void 0;
31162
31299
  const isNestedComponentName = /[\\/]/.test(componentName);
31163
- const nestedComponentName = componentName.split(/[\\/]/).filter(Boolean).join(path58.sep);
31164
- if (isNestedComponentName && nestedComponentName && !path58.isAbsolute(componentName) && !nestedComponentName.split(path58.sep).includes("..")) {
31300
+ const nestedComponentName = componentName.split(/[\\/]/).filter(Boolean).join(path59.sep);
31301
+ if (isNestedComponentName && nestedComponentName && !path59.isAbsolute(componentName) && !nestedComponentName.split(path59.sep).includes("..")) {
31165
31302
  for (const extension of [".tsx", ".ts"]) {
31166
31303
  const relPath = `${nestedComponentName}${extension}`;
31167
- const filePath = path58.join(assetDir, relPath);
31304
+ const filePath = path59.join(assetDir, relPath);
31168
31305
  if (fs45.existsSync(filePath) && fs45.statSync(filePath).isFile()) {
31169
31306
  return relPath;
31170
31307
  }
31171
31308
  }
31172
31309
  }
31173
- if (!isNestedComponentName && !componentName.includes("..") && !path58.isAbsolute(componentName)) {
31310
+ if (!isNestedComponentName && !componentName.includes("..") && !path59.isAbsolute(componentName)) {
31174
31311
  for (const extension of [".tsx", ".ts"]) {
31175
- const relPath = path58.join(componentName, `index${extension}`);
31176
- const filePath = path58.join(assetDir, relPath);
31312
+ const relPath = path59.join(componentName, `index${extension}`);
31313
+ const filePath = path59.join(assetDir, relPath);
31177
31314
  if (fs45.existsSync(filePath) && fs45.statSync(filePath).isFile()) {
31178
31315
  return relPath;
31179
31316
  }
@@ -31198,7 +31335,7 @@ function getAllComponentNamesForConfig(config) {
31198
31335
  return [.../* @__PURE__ */ new Set([...staticUi, ...staticCustom, ...templateKeys, "tiptap"])].sort();
31199
31336
  }
31200
31337
  async function runUpdateCommand(components, options) {
31201
- const cwd = options.cwd ? path58.resolve(options.cwd) : process.cwd();
31338
+ const cwd = options.cwd ? path59.resolve(options.cwd) : process.cwd();
31202
31339
  const normalizedOnly = normalizeShadcnPresetOnly(options.only);
31203
31340
  validateShadcnPresetOptions(components, options);
31204
31341
  if (options.json && !options.list) {
@@ -31259,7 +31396,7 @@ async function runUpdateCommand(components, options) {
31259
31396
  return;
31260
31397
  }
31261
31398
  const config = await resolveConfigOrExit(cwd);
31262
- const admin = path58.resolve(cwd, config.paths.admin);
31399
+ const admin = path59.resolve(cwd, config.paths.admin);
31263
31400
  if (!fs45.existsSync(admin)) {
31264
31401
  clack4.cancel(
31265
31402
  `Admin directory not found at ${config.paths.admin}. Run 'betterstart init' first.`
@@ -31314,7 +31451,7 @@ async function runUpdateCommand(components, options) {
31314
31451
  }
31315
31452
  const { relPath, content } = applyNamespaceToTemplateEntry(entry, config, cwd);
31316
31453
  const baseDir = entry.base === "cwd" ? cwd : admin;
31317
- const destPath = path58.join(baseDir, relPath);
31454
+ const destPath = path59.join(baseDir, relPath);
31318
31455
  if (entry.preserveExisting && fs45.existsSync(destPath)) {
31319
31456
  clack4.log.info(`Preserved ${relPath}`);
31320
31457
  updatedTemplateNames.add(name);
@@ -31324,7 +31461,7 @@ async function runUpdateCommand(components, options) {
31324
31461
  pendingWrites.push({
31325
31462
  displayPath: relPath,
31326
31463
  write: () => {
31327
- fsExtra.ensureDirSync(path58.dirname(destPath));
31464
+ fsExtra.ensureDirSync(path59.dirname(destPath));
31328
31465
  fs45.writeFileSync(destPath, content, "utf-8");
31329
31466
  clack4.log.success(`Updated ${relPath}`);
31330
31467
  }
@@ -31356,20 +31493,20 @@ async function runUpdateCommand(components, options) {
31356
31493
  }
31357
31494
  const namespace = config.frameworkConfig.next.namespace;
31358
31495
  const namespacedAssetFile = applyAdminNamespaceToPath(assetFile, namespace);
31359
- const destPath = path58.join(admin, "components", assetDirectory, namespacedAssetFile);
31496
+ const destPath = path59.join(admin, "components", assetDirectory, namespacedAssetFile);
31360
31497
  pendingWrites.push({
31361
31498
  displayPath: `components/${assetDirectory}/${namespacedAssetFile}`,
31362
31499
  write: () => {
31363
- fsExtra.ensureDirSync(path58.dirname(destPath));
31364
- writeNamespacedFile(path58.join(assetDir, assetFile), destPath, namespace);
31500
+ fsExtra.ensureDirSync(path59.dirname(destPath));
31501
+ writeNamespacedFile(path59.join(assetDir, assetFile), destPath, namespace);
31365
31502
  clack4.log.success(`Updated components/${assetDirectory}/${namespacedAssetFile}`);
31366
31503
  }
31367
31504
  });
31368
31505
  if (assetDirectory === "custom") {
31369
- const assetSubdir = path58.join(assetDir, name);
31506
+ const assetSubdir = path59.join(assetDir, name);
31370
31507
  if (fs45.existsSync(assetSubdir) && fs45.statSync(assetSubdir).isDirectory()) {
31371
31508
  const namespacedName = applyAdminNamespaceToPath(name, namespace);
31372
- const destSubdir = path58.join(admin, "components", assetDirectory, namespacedName);
31509
+ const destSubdir = path59.join(admin, "components", assetDirectory, namespacedName);
31373
31510
  pendingWrites.push({
31374
31511
  displayPath: `components/${assetDirectory}/${namespacedName}/ (template files)`,
31375
31512
  write: () => {
@@ -31404,19 +31541,19 @@ async function runUpdateCommand(components, options) {
31404
31541
  "content-editor"
31405
31542
  );
31406
31543
  const namespace = config.frameworkConfig.next.namespace;
31407
- const destBaseDir = path58.join(admin, "components", "custom", "content-editor");
31544
+ const destBaseDir = path59.join(admin, "components", "custom", "content-editor");
31408
31545
  if (!fs45.existsSync(srcBaseDir)) {
31409
31546
  return false;
31410
31547
  }
31411
31548
  const dirsToCopy = [];
31412
31549
  for (const directory of TIPTAP_CONTENT_EDITOR_DIRECTORIES) {
31413
- const srcDir = path58.join(srcBaseDir, directory);
31550
+ const srcDir = path59.join(srcBaseDir, directory);
31414
31551
  if (!fs45.existsSync(srcDir)) {
31415
31552
  continue;
31416
31553
  }
31417
31554
  dirsToCopy.push({
31418
31555
  srcDir,
31419
- destDir: path58.join(destBaseDir, applyAdminNamespaceToPath(directory, namespace))
31556
+ destDir: path59.join(destBaseDir, applyAdminNamespaceToPath(directory, namespace))
31420
31557
  });
31421
31558
  }
31422
31559
  if (dirsToCopy.length === 0) {
@@ -31430,7 +31567,7 @@ async function runUpdateCommand(components, options) {
31430
31567
  copyNamespacedDirectory(srcDir, destDir, namespace);
31431
31568
  }
31432
31569
  clack4.log.success("Updated components/custom/content-editor/tiptap-*/ (template files)");
31433
- removeLegacyDirectory(path58.join(admin, "components", "custom", "tiptap"));
31570
+ removeLegacyDirectory(path59.join(admin, "components", "custom", "tiptap"));
31434
31571
  }
31435
31572
  });
31436
31573
  updatedStaticNames.add(key);
@@ -31490,7 +31627,7 @@ async function runUpdateCommand(components, options) {
31490
31627
  `Overwriting ${displayPaths.length} file${displayPaths.length === 1 ? "" : "s"}`
31491
31628
  );
31492
31629
  if (!options.yes) {
31493
- if (!isInteractiveSession4()) {
31630
+ if (!isInteractiveSession()) {
31494
31631
  clack4.log.error(
31495
31632
  `Overwriting ${displayPaths.length} file${displayPaths.length === 1 ? "" : "s"} needs confirmation. Re-run with --yes.`
31496
31633
  );
@@ -31570,13 +31707,13 @@ function runShadcnPresetUpdate({
31570
31707
  only
31571
31708
  }) {
31572
31709
  const namespace = resolveAdminNamespace(config.frameworkConfig.next.namespace);
31573
- const adminGlobalsPath = path58.join(cwd, config.paths.admin, namespace.globalsFile);
31574
- const componentsJsonPath = path58.join(cwd, "components.json");
31710
+ const adminGlobalsPath = path59.join(cwd, config.paths.admin, namespace.globalsFile);
31711
+ const componentsJsonPath = path59.join(cwd, "components.json");
31575
31712
  const shadcnBackupPath = `${componentsJsonPath}.bak`;
31576
31713
  const restoreAfterApplyPaths = [
31577
31714
  componentsJsonPath,
31578
31715
  shadcnBackupPath,
31579
- path58.join(cwd, config.paths.admin, "lib", "utils.ts"),
31716
+ path59.join(cwd, config.paths.admin, "lib", "utils.ts"),
31580
31717
  ...getHostProjectFilesToRestore(cwd)
31581
31718
  ];
31582
31719
  if (!preset) {
@@ -31585,7 +31722,7 @@ function runShadcnPresetUpdate({
31585
31722
  }
31586
31723
  if (!fs45.existsSync(adminGlobalsPath)) {
31587
31724
  clack4.cancel(
31588
- `Admin globals file not found at ${path58.relative(cwd, adminGlobalsPath)}. Run 'betterstart update admin-globals' first.`
31725
+ `Admin globals file not found at ${path59.relative(cwd, adminGlobalsPath)}. Run 'betterstart update admin-globals' first.`
31589
31726
  );
31590
31727
  process.exit(1);
31591
31728
  }
@@ -31595,7 +31732,7 @@ function runShadcnPresetUpdate({
31595
31732
  snapshot: snapshotFile(filePath)
31596
31733
  }));
31597
31734
  clack4.intro("BetterStart Shadcn Preset");
31598
- clack4.log.info(`Applying preset to ${path58.join(config.paths.admin, "components/ui")}`);
31735
+ clack4.log.info(`Applying preset to ${path59.join(config.paths.admin, "components/ui")}`);
31599
31736
  let failed = false;
31600
31737
  try {
31601
31738
  fs45.writeFileSync(
@@ -31654,7 +31791,7 @@ function toPosixPath(value) {
31654
31791
  }
31655
31792
  function resolveLocalShadcnBin(cwd) {
31656
31793
  const binName = process.platform === "win32" ? "shadcn.cmd" : "shadcn";
31657
- const shadcnBin = path58.join(cwd, "node_modules", ".bin", binName);
31794
+ const shadcnBin = path59.join(cwd, "node_modules", ".bin", binName);
31658
31795
  if (!fs45.existsSync(shadcnBin)) {
31659
31796
  clack4.cancel(
31660
31797
  `shadcn is not installed in this project. Run 'betterstart update-deps' and try again.`
@@ -31676,7 +31813,7 @@ function getHostProjectFilesToRestore(cwd) {
31676
31813
  "app/globals.css",
31677
31814
  "src/app/globals.css"
31678
31815
  ];
31679
- return hostRelativePaths.map((relativePath) => path58.join(cwd, relativePath));
31816
+ return hostRelativePaths.map((relativePath) => path59.join(cwd, relativePath));
31680
31817
  }
31681
31818
  function snapshotFile(filePath) {
31682
31819
  if (!fs45.existsSync(filePath)) {
@@ -31695,10 +31832,10 @@ function restoreFile(filePath, snapshot) {
31695
31832
  }
31696
31833
 
31697
31834
  // adapters/next/commands/update-deps.ts
31698
- import path59 from "path";
31835
+ import path60 from "path";
31699
31836
  import * as clack5 from "@clack/prompts";
31700
31837
  async function runUpdateDepsCommand(options) {
31701
- const cwd = options.cwd ? path59.resolve(options.cwd) : process.cwd();
31838
+ const cwd = options.cwd ? path60.resolve(options.cwd) : process.cwd();
31702
31839
  clack5.intro("BetterStart Update Dependencies");
31703
31840
  const pm = detectPackageManager(cwd);
31704
31841
  clack5.log.info(`Package manager: ${pm}`);
@@ -31733,17 +31870,17 @@ async function runUpdateDepsCommand(options) {
31733
31870
 
31734
31871
  // adapters/next/commands/update-styles.ts
31735
31872
  import fs46 from "fs";
31736
- import path60 from "path";
31873
+ import path61 from "path";
31737
31874
  import * as clack6 from "@clack/prompts";
31738
31875
  async function runUpdateStylesCommand(options) {
31739
- const cwd = options.cwd ? path60.resolve(options.cwd) : process.cwd();
31876
+ const cwd = options.cwd ? path61.resolve(options.cwd) : process.cwd();
31740
31877
  clack6.intro("BetterStart Update Styles");
31741
31878
  const config = await resolveConfigOrExit(cwd);
31742
31879
  const adminDir = config.paths.admin;
31743
31880
  const namespace = resolveAdminNamespace(config.frameworkConfig.next.namespace);
31744
- const targetPath = path60.join(cwd, adminDir, namespace.globalsFile);
31881
+ const targetPath = path61.join(cwd, adminDir, namespace.globalsFile);
31745
31882
  if (!fs46.existsSync(targetPath)) {
31746
- clack6.cancel(`${namespace.globalsFile} not found at ${path60.relative(cwd, targetPath)}`);
31883
+ clack6.cancel(`${namespace.globalsFile} not found at ${path61.relative(cwd, targetPath)}`);
31747
31884
  process.exit(1);
31748
31885
  }
31749
31886
  fs46.writeFileSync(
@@ -31751,12 +31888,14 @@ async function runUpdateStylesCommand(options) {
31751
31888
  applyAdminNamespaceToContent(readTemplate("admin-globals.css"), namespace.segment),
31752
31889
  "utf-8"
31753
31890
  );
31754
- clack6.log.success(`Updated ${path60.relative(cwd, targetPath)}`);
31891
+ clack6.log.success(`Updated ${path61.relative(cwd, targetPath)}`);
31755
31892
  clack6.outro("Styles updated");
31756
31893
  }
31757
31894
 
31758
31895
  // adapters/next/commands-runtime.ts
31759
31896
  var nextCommandRuntime = {
31897
+ listInstallableChoices,
31898
+ listSchemaChoices,
31760
31899
  runAdd: runAddCommand,
31761
31900
  runAddField: runAddFieldCommand,
31762
31901
  runCreate: runCreateCommand,
@@ -31780,7 +31919,7 @@ var { version } = JSON.parse(
31780
31919
  readFileSync(new URL("../package.json", import.meta.url), "utf-8")
31781
31920
  );
31782
31921
  var program = new Command2();
31783
- program.name("betterstart").description("Scaffold a preset- and integration-based Admin into any Next.js 16 application").version(version);
31922
+ program.name("betterstart").description("A production ready dashboard, tailored for you in 5 Minutes.").version(version);
31784
31923
  program.hook("preAction", (_command, actionCommand) => {
31785
31924
  requireInitializedProject(actionCommand);
31786
31925
  });
@@ -31799,14 +31938,18 @@ program.addCommand(createUpdateCommand(nextCommandRuntime));
31799
31938
  program.addCommand(createUpdateDepsCommand(nextCommandRuntime));
31800
31939
  program.addCommand(createUpdateStylesCommand(nextCommandRuntime));
31801
31940
  try {
31802
- await program.parseAsync();
31941
+ if (process.argv.slice(2).length === 0) {
31942
+ await runDefaultAction(program, nextCommandRuntime);
31943
+ } else {
31944
+ await program.parseAsync();
31945
+ }
31803
31946
  } catch (error) {
31804
31947
  if (process.env.BETTERSTART_DEBUG) {
31805
31948
  console.error(error);
31806
31949
  } else {
31807
31950
  const message = error instanceof Error && error.message ? error.message : String(error);
31808
- p30.log.error(message);
31809
- p30.log.message(pc12.dim("Re-run with BETTERSTART_DEBUG=1 for the full stack trace."));
31951
+ p31.log.error(message);
31952
+ p31.log.message(pc12.dim("Re-run with BETTERSTART_DEBUG=1 for the full stack trace."));
31810
31953
  }
31811
31954
  process.exit(1);
31812
31955
  }