betterstart-cli 0.0.24 → 0.0.26

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
@@ -5283,14 +5283,14 @@ function buildStepsConstant(steps) {
5283
5283
  ${entries.join(",\n")}
5284
5284
  ]`;
5285
5285
  }
5286
- function buildComponentSource(p19) {
5286
+ function buildComponentSource(p20) {
5287
5287
  const providerOpen = ` <NuqsAdapter>
5288
5288
  <React.Suspense fallback={null}>
5289
- <${p19.pascal}FormInner />
5289
+ <${p20.pascal}FormInner />
5290
5290
  </React.Suspense>
5291
5291
  </NuqsAdapter>`;
5292
5292
  const exportWrapper = `
5293
- export function ${p19.pascal}Form() {
5293
+ export function ${p20.pascal}Form() {
5294
5294
  return (
5295
5295
  ${providerOpen}
5296
5296
  )
@@ -5299,22 +5299,22 @@ ${providerOpen}
5299
5299
  return `'use client'
5300
5300
 
5301
5301
  import { standardSchemaResolver } from '@hookform/resolvers/standard-schema'
5302
- import { ChevronLeft, ChevronRight${p19.hasListFields ? ", Trash2" : ""} } from 'lucide-react'
5302
+ import { ChevronLeft, ChevronRight${p20.hasListFields ? ", Trash2" : ""} } from 'lucide-react'
5303
5303
  import { createParser, useQueryState } from 'nuqs'
5304
5304
  import { NuqsAdapter } from 'nuqs/adapters/next/app'
5305
5305
  import * as React from 'react'
5306
- ${p19.rhfImport}
5306
+ ${p20.rhfImport}
5307
5307
  import { z } from 'zod/v3'
5308
- import { create${p19.pascal}Submission } from '@admin/actions/${p19.actionImportPath}'
5308
+ import { create${p20.pascal}Submission } from '@admin/actions/${p20.actionImportPath}'
5309
5309
 
5310
5310
  const formSchema = z.object({
5311
- ${p19.zodFields}
5311
+ ${p20.zodFields}
5312
5312
  })
5313
5313
 
5314
5314
  type FormValues = z.infer<typeof formSchema>
5315
5315
  ${buildFieldErrorHelper()}
5316
5316
 
5317
- ${p19.stepsConst}
5317
+ ${p20.stepsConst}
5318
5318
 
5319
5319
  const stepParser = createParser({
5320
5320
  parse(value) {
@@ -5332,7 +5332,7 @@ const stepParser = createParser({
5332
5332
  }
5333
5333
  }).withDefault(0)
5334
5334
 
5335
- function ${p19.pascal}FormInner() {
5335
+ function ${p20.pascal}FormInner() {
5336
5336
  const [currentStep, setCurrentStep] = useQueryState('step', stepParser)
5337
5337
  const [submitted, setSubmitted] = React.useState(false)
5338
5338
  const [submitting, startSubmitTransition] = React.useTransition()
@@ -5340,11 +5340,11 @@ function ${p19.pascal}FormInner() {
5340
5340
  const form = useForm<FormValues>({
5341
5341
  resolver: standardSchemaResolver(formSchema),
5342
5342
  defaultValues: {
5343
- ${p19.defaults}
5343
+ ${p20.defaults}
5344
5344
  },
5345
5345
  })
5346
5346
 
5347
- ${p19.fieldArraySetup}${p19.watchSetup}
5347
+ ${p20.fieldArraySetup}${p20.watchSetup}
5348
5348
  async function handleNext() {
5349
5349
  const stepFields = STEPS[currentStep].fields as (keyof FormValues)[]
5350
5350
  const isValid = await form.trigger(stepFields, { shouldFocus: true })
@@ -5360,9 +5360,9 @@ ${p19.fieldArraySetup}${p19.watchSetup}
5360
5360
  function onSubmit(values: FormValues) {
5361
5361
  startSubmitTransition(async () => {
5362
5362
  try {
5363
- const result = await create${p19.pascal}Submission(values)
5363
+ const result = await create${p20.pascal}Submission(values)
5364
5364
  if (result.success) {
5365
- ${p19.successHandler}
5365
+ ${p20.successHandler}
5366
5366
  } else {
5367
5367
  form.setError('root', { message: result.error || 'Something went wrong' })
5368
5368
  }
@@ -5376,7 +5376,7 @@ ${p19.fieldArraySetup}${p19.watchSetup}
5376
5376
  return (
5377
5377
  <div className="rounded-sm border p-6 text-center">
5378
5378
  <h3 className="text-lg font-semibold">Thank you!</h3>
5379
- <p className="mt-2 text-muted-foreground">${p19.successMessage}</p>
5379
+ <p className="mt-2 text-muted-foreground">${p20.successMessage}</p>
5380
5380
  </div>
5381
5381
  )
5382
5382
  }
@@ -5393,7 +5393,7 @@ ${p19.fieldArraySetup}${p19.watchSetup}
5393
5393
 
5394
5394
  {/* Step content */}
5395
5395
  <div key={currentStep} className="animate-in fade-in duration-300 space-y-6">
5396
- ${p19.stepContentBlocks}
5396
+ ${p20.stepContentBlocks}
5397
5397
  </div>
5398
5398
 
5399
5399
  {form.formState.errors.root && (
@@ -5427,7 +5427,7 @@ ${p19.stepContentBlocks}
5427
5427
  onClick={() => form.handleSubmit(onSubmit)()}
5428
5428
  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"
5429
5429
  >
5430
- {submitting ? 'Submitting...' : ${p19.submitText}}
5430
+ {submitting ? 'Submitting...' : ${p20.submitText}}
5431
5431
  </button>
5432
5432
  )}
5433
5433
  </div>
@@ -21743,7 +21743,7 @@ ${validationErrors.map((error) => ` - ${error}`).join("\n")}`
21743
21743
  import { execFileSync as execFileSync5, spawn as spawn4 } from "child_process";
21744
21744
  import fs37 from "fs";
21745
21745
  import path48 from "path";
21746
- import * as p14 from "@clack/prompts";
21746
+ import * as p15 from "@clack/prompts";
21747
21747
 
21748
21748
  // adapters/next/init/prompts/database.ts
21749
21749
  import { execFileSync as execFileSync4 } from "child_process";
@@ -23827,7 +23827,7 @@ function scaffoldTsconfig(cwd, config) {
23827
23827
  }
23828
23828
 
23829
23829
  // adapters/next/init/vercel/flow.ts
23830
- import * as p13 from "@clack/prompts";
23830
+ import * as p14 from "@clack/prompts";
23831
23831
  import pc4 from "picocolors";
23832
23832
 
23833
23833
  // adapters/next/init/vercel/auth.ts
@@ -23836,13 +23836,13 @@ import pc3 from "picocolors";
23836
23836
 
23837
23837
  // adapters/next/init/vercel/runner.ts
23838
23838
  import { spawn as spawn3 } from "child_process";
23839
- var PINNED_VERCEL_VERSION = "48";
23839
+ var VERCEL_CLI_VERSION = "latest";
23840
23840
  var DEFAULT_CAPTURE_TIMEOUT_MS = 12e4;
23841
23841
  function pathRunner() {
23842
23842
  return { bin: "vercel", prefix: [], source: "path" };
23843
23843
  }
23844
23844
  function npxRunner() {
23845
- return { bin: "npx", prefix: ["-y", `vercel@${PINNED_VERCEL_VERSION}`], source: "npx" };
23845
+ return { bin: "npx", prefix: ["-y", `vercel@${VERCEL_CLI_VERSION}`], source: "npx" };
23846
23846
  }
23847
23847
  async function resolveVercelRunner() {
23848
23848
  const probe = await runVercel(pathRunner(), ["--version"], {
@@ -23956,11 +23956,20 @@ async function checkVercelAuth(runner, cwd, env) {
23956
23956
  }
23957
23957
  async function ensureVercelAuth(runner, cwd, options) {
23958
23958
  const env = options.env ?? process.env;
23959
+ const spinner9 = p12.spinner();
23960
+ spinner9.start(
23961
+ runner.source === "npx" ? "Checking Vercel sign-in (first run downloads the Vercel CLI)" : "Checking Vercel sign-in"
23962
+ );
23959
23963
  const existing = await checkVercelAuth(runner, cwd, env);
23960
- if (existing.authed) return existing;
23964
+ if (existing.authed) {
23965
+ spinner9.stop(signedInMessage(existing.username));
23966
+ return existing;
23967
+ }
23961
23968
  if (env.VERCEL_TOKEN) {
23969
+ spinner9.stop("Could not verify VERCEL_TOKEN with Vercel");
23962
23970
  return { authed: false, reason: "login-failed" };
23963
23971
  }
23972
+ spinner9.stop("Not signed in to Vercel yet");
23964
23973
  p12.log.info(
23965
23974
  `Sign in to Vercel to continue \u2014 a browser link and code will appear below. ${pc3.dim(
23966
23975
  "(or press Ctrl-C to enter a connection string manually)"
@@ -23975,14 +23984,25 @@ async function ensureVercelAuth(runner, cwd, options) {
23975
23984
  if (!login.success) {
23976
23985
  return { authed: false, reason: login.timedOut ? "timeout" : "login-cancelled" };
23977
23986
  }
23987
+ const verifySpinner = p12.spinner();
23988
+ verifySpinner.start("Verifying Vercel sign-in");
23978
23989
  const after = await checkVercelAuth(runner, cwd, env);
23979
- return after.authed ? after : { authed: false, reason: "login-failed" };
23990
+ if (after.authed) {
23991
+ verifySpinner.stop(signedInMessage(after.username));
23992
+ return after;
23993
+ }
23994
+ verifySpinner.stop("Could not verify your Vercel sign-in");
23995
+ return { authed: false, reason: "login-failed" };
23996
+ }
23997
+ function signedInMessage(username) {
23998
+ return username ? `Signed in to Vercel as ${pc3.cyan(username)}` : "Signed in to Vercel";
23980
23999
  }
23981
24000
 
23982
24001
  // adapters/next/init/vercel/neon.ts
23983
24002
  import fs34 from "fs";
23984
24003
  import os from "os";
23985
24004
  import path45 from "path";
24005
+ import * as p13 from "@clack/prompts";
23986
24006
  var PROVISION_TIMEOUT_MS = 18e4;
23987
24007
  var INTERACTIVE_PROVISION_TIMEOUT_MS = 6e5;
23988
24008
  var ENV_PULL_TIMEOUT_MS = 6e4;
@@ -23998,13 +24018,21 @@ async function provisionNeonInteractive(runner, cwd, options) {
23998
24018
  if (!add.success) {
23999
24019
  return { failure: add.timedOut ? "timeout" : "provision-failed" };
24000
24020
  }
24021
+ const pullSpinner = p13.spinner();
24022
+ pullSpinner.start("Retrieving the database connection string");
24001
24023
  const databaseUrl = await pullDatabaseUrl(runner, cwd, options.env);
24002
- if (!databaseUrl) return { failure: "env-pull-empty" };
24024
+ if (!databaseUrl) {
24025
+ pullSpinner.stop("No DATABASE_URL came back from Vercel");
24026
+ return { failure: "env-pull-empty" };
24027
+ }
24028
+ pullSpinner.stop("Captured the Neon DATABASE_URL");
24003
24029
  return { databaseUrl };
24004
24030
  }
24005
24031
  async function provisionNeon(runner, cwd, options) {
24006
24032
  const addArgs = ["integration", "add", "neon", "--no-env-pull", "--format", "json"];
24007
24033
  if (options.plan) addArgs.push("--plan", options.plan);
24034
+ const spinner9 = p13.spinner();
24035
+ spinner9.start("Provisioning Neon Postgres via Vercel");
24008
24036
  const add = await runVercel(runner, addArgs, {
24009
24037
  cwd,
24010
24038
  mode: "capture",
@@ -24012,6 +24040,7 @@ async function provisionNeon(runner, cwd, options) {
24012
24040
  env: options.env
24013
24041
  });
24014
24042
  if (!add.success) {
24043
+ spinner9.stop("Neon provisioning did not complete");
24015
24044
  const combined = `${add.stdout}
24016
24045
  ${add.stderr}`.trim();
24017
24046
  const detail = combined || void 0;
@@ -24021,8 +24050,13 @@ ${add.stderr}`.trim();
24021
24050
  }
24022
24051
  const meta = parseVercelJson(add.stdout);
24023
24052
  const resourceName = meta?.resourceName ?? meta?.name;
24053
+ spinner9.message("Retrieving the database connection string");
24024
24054
  const databaseUrl = await pullDatabaseUrl(runner, cwd, options.env);
24025
- if (!databaseUrl) return { resourceName, failure: "env-pull-empty" };
24055
+ if (!databaseUrl) {
24056
+ spinner9.stop("No DATABASE_URL came back from Vercel");
24057
+ return { resourceName, failure: "env-pull-empty" };
24058
+ }
24059
+ spinner9.stop("Captured the Neon DATABASE_URL");
24026
24060
  return { databaseUrl, resourceName };
24027
24061
  }
24028
24062
  async function pullDatabaseUrl(runner, cwd, env) {
@@ -24073,13 +24107,40 @@ function sanitizeVercelProjectName(name) {
24073
24107
  const cleaned = name.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^[-_.]+/, "").replace(/[-_.]+$/, "").slice(0, 100);
24074
24108
  return cleaned || "my-app";
24075
24109
  }
24110
+ var MAX_NAME_ATTEMPTS = 10;
24111
+ var INSPECT_TIMEOUT_MS = 3e4;
24112
+ function versionedVercelProjectName(base, attempt) {
24113
+ if (attempt <= 1) return base;
24114
+ const suffix = `-v${attempt}`;
24115
+ return `${base.slice(0, 100 - suffix.length)}${suffix}`;
24116
+ }
24076
24117
  async function createVercelProject(runner, cwd, name, env) {
24077
- const projectName = sanitizeVercelProjectName(name);
24078
- await runVercel(runner, ["projects", "add", projectName], {
24079
- cwd,
24080
- mode: "capture",
24081
- env
24082
- });
24118
+ const base = sanitizeVercelProjectName(name);
24119
+ let projectName = base;
24120
+ for (let attempt = 1; attempt <= MAX_NAME_ATTEMPTS; attempt++) {
24121
+ const candidate = versionedVercelProjectName(base, attempt);
24122
+ projectName = candidate;
24123
+ const inspect = await runVercel(runner, ["project", "inspect", candidate], {
24124
+ cwd,
24125
+ mode: "capture",
24126
+ timeoutMs: INSPECT_TIMEOUT_MS,
24127
+ env
24128
+ });
24129
+ if (inspect.success) continue;
24130
+ const add = await runVercel(runner, ["projects", "add", candidate], {
24131
+ cwd,
24132
+ mode: "capture",
24133
+ env
24134
+ });
24135
+ if (add.success) break;
24136
+ if (/already exists/i.test(`${add.stdout}
24137
+ ${add.stderr}`)) continue;
24138
+ break;
24139
+ }
24140
+ try {
24141
+ fs35.rmSync(path46.join(cwd, ".vercel", "project.json"), { force: true });
24142
+ } catch {
24143
+ }
24083
24144
  const link = await runVercel(runner, ["link", "--project", projectName, "--yes"], {
24084
24145
  cwd,
24085
24146
  mode: "capture",
@@ -24106,16 +24167,18 @@ function readLinkedProjectId(cwd) {
24106
24167
  async function runVercelNeonFlow(options) {
24107
24168
  const env = options.env ?? process.env;
24108
24169
  try {
24170
+ const runnerSpinner = p14.spinner();
24171
+ runnerSpinner.start("Checking for the Vercel CLI");
24109
24172
  const runner = await resolveVercelRunner();
24173
+ runnerSpinner.stop(
24174
+ runner.source === "path" ? "Using the Vercel CLI from your PATH" : `Using ${pc4.cyan(`npx vercel@${VERCEL_CLI_VERSION}`)}`
24175
+ );
24110
24176
  const auth = await ensureVercelAuth(runner, options.cwd, { env });
24111
24177
  if (!auth.authed) {
24112
- p13.log.warn(authFailureMessage(auth.reason));
24178
+ p14.log.warn(authFailureMessage(auth.reason));
24113
24179
  return { ok: false };
24114
24180
  }
24115
- if (auth.username) {
24116
- p13.log.success(`Signed in to Vercel as ${pc4.cyan(auth.username)}`);
24117
- }
24118
- const projectSpinner = p13.spinner();
24181
+ const projectSpinner = p14.spinner();
24119
24182
  projectSpinner.start(`Creating Vercel project ${pc4.cyan(options.projectName)}`);
24120
24183
  const project2 = await createVercelProject(runner, options.cwd, options.projectName, env);
24121
24184
  projectSpinner.stop(
@@ -24123,11 +24186,11 @@ async function runVercelNeonFlow(options) {
24123
24186
  );
24124
24187
  const neon = await provisionNeonForMode(runner, options);
24125
24188
  if (neon.failure || !neon.databaseUrl) {
24126
- p13.log.warn(neonFailureMessage(neon.failure));
24127
- if (neon.detail) p13.log.message(pc4.dim(neon.detail));
24189
+ p14.log.warn(neonFailureMessage(neon.failure));
24190
+ if (neon.detail) p14.log.message(pc4.dim(neon.detail));
24128
24191
  return { ok: false };
24129
24192
  }
24130
- p13.log.success(`Provisioned Neon Postgres for ${pc4.cyan(project2.name)}`);
24193
+ p14.log.success(`Provisioned Neon Postgres for ${pc4.cyan(project2.name)}`);
24131
24194
  return {
24132
24195
  ok: true,
24133
24196
  databaseUrl: neon.databaseUrl,
@@ -24135,7 +24198,7 @@ async function runVercelNeonFlow(options) {
24135
24198
  neonResourceName: neon.resourceName
24136
24199
  };
24137
24200
  } catch (error) {
24138
- p13.log.warn(
24201
+ p14.log.warn(
24139
24202
  `Vercel provisioning failed: ${error instanceof Error ? error.message : String(error)}`
24140
24203
  );
24141
24204
  return { ok: false };
@@ -24144,7 +24207,7 @@ async function runVercelNeonFlow(options) {
24144
24207
  function provisionNeonForMode(runner, options) {
24145
24208
  const opts = { plan: options.plan, env: options.env };
24146
24209
  if (options.interactive) {
24147
- p13.log.info(
24210
+ p14.log.info(
24148
24211
  `Create your Neon database in the Vercel prompts below ${pc4.dim("(the Free plan is recommended).")}`
24149
24212
  );
24150
24213
  return provisionNeonInteractive(runner, options.cwd, opts);
@@ -24427,13 +24490,13 @@ async function runSeedCommand(options) {
24427
24490
  }
24428
24491
  );
24429
24492
  });
24430
- const spinner7 = clack.spinner();
24431
- spinner7.start("Creating admin user...");
24493
+ const spinner9 = clack.spinner();
24494
+ spinner9.start("Creating admin user...");
24432
24495
  try {
24433
24496
  const result = await runSeed2(false);
24434
24497
  if (result.code === 2) {
24435
24498
  const existingName = result.stdout.split("\n").find((l) => l.startsWith("EXISTING_USER:"))?.replace("EXISTING_USER:", "")?.trim() || "unknown";
24436
- spinner7.stop(`Account already exists for ${email}`);
24499
+ spinner9.stop(`Account already exists for ${email}`);
24437
24500
  const overwrite = await clack.confirm({
24438
24501
  message: `An admin account (${existingName}) already exists with this email. Replace it?`
24439
24502
  });
@@ -24445,14 +24508,14 @@ async function runSeedCommand(options) {
24445
24508
  }
24446
24509
  return;
24447
24510
  }
24448
- spinner7.start("Replacing admin user...");
24511
+ spinner9.start("Replacing admin user...");
24449
24512
  await runSeed2(true);
24450
- spinner7.stop("Admin user replaced");
24513
+ spinner9.stop("Admin user replaced");
24451
24514
  } else {
24452
- spinner7.stop("Admin user created");
24515
+ spinner9.stop("Admin user created");
24453
24516
  }
24454
24517
  } catch (err) {
24455
- spinner7.stop("Failed to create admin user");
24518
+ spinner9.stop("Failed to create admin user");
24456
24519
  const errMsg = err instanceof Error ? err.message : String(err);
24457
24520
  clack.log.error(errMsg);
24458
24521
  clack.log.info("You can run the seed script manually:");
@@ -24552,7 +24615,7 @@ function removeExistingAdminPaths(cwd, namespaces) {
24552
24615
  return removed;
24553
24616
  }
24554
24617
  async function runInitCommand(name, options) {
24555
- p14.intro(pc5.bgCyan(pc5.black(" Setup Your Dashboard ")));
24618
+ p15.intro(pc5.bgCyan(pc5.black(" Setup Your Dashboard ")));
24556
24619
  let cwd = process.cwd();
24557
24620
  let projectName = path48.basename(cwd);
24558
24621
  let forceMode = Boolean(options.force);
@@ -24561,13 +24624,13 @@ async function runInitCommand(name, options) {
24561
24624
  try {
24562
24625
  namespace = validateAdminNamespace(options.namespace);
24563
24626
  } catch (error) {
24564
- p14.log.error(error instanceof Error ? error.message : String(error));
24627
+ p15.log.error(error instanceof Error ? error.message : String(error));
24565
24628
  process.exit(1);
24566
24629
  }
24567
24630
  }
24568
24631
  if (!options.yes && !options.namespace) {
24569
24632
  const defaultDashboardPath = resolveAdminNamespace(DEFAULT_ADMIN_NAMESPACE).routePath;
24570
- const namespaceInput = await p14.text({
24633
+ const namespaceInput = await p15.text({
24571
24634
  message: "What's the path you want the dashboard to be?",
24572
24635
  placeholder: `eg. ${defaultDashboardPath}`,
24573
24636
  defaultValue: defaultDashboardPath,
@@ -24580,8 +24643,8 @@ async function runInitCommand(name, options) {
24580
24643
  }
24581
24644
  }
24582
24645
  });
24583
- if (p14.isCancel(namespaceInput)) {
24584
- p14.cancel("Setup cancelled.");
24646
+ if (p15.isCancel(namespaceInput)) {
24647
+ p15.cancel("Setup cancelled.");
24585
24648
  process.exit(0);
24586
24649
  }
24587
24650
  namespace = validateAdminDashboardPath(namespaceInput);
@@ -24591,16 +24654,16 @@ async function runInitCommand(name, options) {
24591
24654
  let isFreshProject = false;
24592
24655
  let srcDir;
24593
24656
  if (project2.isExisting) {
24594
- p14.log.info(`Next.js app detected ${pc5.dim("\xB7")} ${pc5.cyan(pm)}`);
24657
+ p15.log.info(`Next.js app detected ${pc5.dim("\xB7")} ${pc5.cyan(pm)}`);
24595
24658
  srcDir = project2.hasSrcDir;
24596
24659
  if (!project2.hasTypeScript) {
24597
- p14.log.error("TypeScript is required. Please add a tsconfig.json first.");
24660
+ p15.log.error("TypeScript is required. Please add a tsconfig.json first.");
24598
24661
  process.exit(1);
24599
24662
  }
24600
24663
  if (forceMode) {
24601
24664
  const nuked = removeExistingAdminPaths(cwd, await resolveForceInitNamespaces(cwd, namespace));
24602
24665
  if (nuked > 0) {
24603
- p14.log.warn(`${pc5.yellow("Force mode:")} removed ${nuked} existing admin paths`);
24666
+ p15.log.warn(`${pc5.yellow("Force mode:")} removed ${nuked} existing admin paths`);
24604
24667
  }
24605
24668
  project2 = detectProject(cwd, namespace);
24606
24669
  } else if (project2.conflicts.length > 0) {
@@ -24609,9 +24672,9 @@ async function runInitCommand(name, options) {
24609
24672
  "",
24610
24673
  pc5.dim(`Use ${pc5.bold("--force")} to remove existing admin files before scaffolding.`)
24611
24674
  );
24612
- p14.note(conflictLines.join("\n"), pc5.yellow("Conflicts"));
24675
+ p15.note(conflictLines.join("\n"), pc5.yellow("Conflicts"));
24613
24676
  if (!options.yes) {
24614
- const proceed = await p14.confirm({
24677
+ const proceed = await p15.confirm({
24615
24678
  message: [
24616
24679
  `Continue with ${pc5.bold(pc5.cyan("--force"))}?`,
24617
24680
  `${pc5.cyan("\u2502")} ${pc5.dim("This will force overwrite the existing admin code.")}`,
@@ -24619,8 +24682,8 @@ async function runInitCommand(name, options) {
24619
24682
  ].join("\n"),
24620
24683
  initialValue: true
24621
24684
  });
24622
- if (p14.isCancel(proceed) || !proceed) {
24623
- p14.cancel("Setup cancelled.");
24685
+ if (p15.isCancel(proceed) || !proceed) {
24686
+ p15.cancel("Setup cancelled.");
24624
24687
  process.exit(0);
24625
24688
  }
24626
24689
  forceMode = true;
@@ -24629,23 +24692,23 @@ async function runInitCommand(name, options) {
24629
24692
  await resolveForceInitNamespaces(cwd, namespace)
24630
24693
  );
24631
24694
  if (nuked > 0) {
24632
- p14.log.warn(`${pc5.yellow("Force mode:")} removed ${nuked} existing admin paths`);
24695
+ p15.log.warn(`${pc5.yellow("Force mode:")} removed ${nuked} existing admin paths`);
24633
24696
  }
24634
24697
  project2 = detectProject(cwd, namespace);
24635
24698
  }
24636
24699
  }
24637
24700
  } else {
24638
- p14.log.info("No Next.js app found \u2014 Running the fresh project mode...");
24701
+ p15.log.info("No Next.js app found \u2014 Running the fresh project mode...");
24639
24702
  let projectPrompt;
24640
24703
  try {
24641
24704
  projectPrompt = options.yes ? resolveNonInteractiveProject(name) : await promptProject(name);
24642
24705
  } catch (error) {
24643
- p14.log.error(error instanceof Error ? error.message : String(error));
24706
+ p15.log.error(error instanceof Error ? error.message : String(error));
24644
24707
  process.exit(1);
24645
24708
  }
24646
24709
  srcDir = projectPrompt.useSrcDir;
24647
24710
  if (!options.yes) {
24648
- const pmChoice = await p14.select({
24711
+ const pmChoice = await p15.select({
24649
24712
  message: "Which package manager do you want to use?",
24650
24713
  options: [
24651
24714
  { value: "pnpm", label: "pnpm", hint: "recommended" },
@@ -24654,8 +24717,8 @@ async function runInitCommand(name, options) {
24654
24717
  { value: "bun", label: "bun" }
24655
24718
  ]
24656
24719
  });
24657
- if (p14.isCancel(pmChoice)) {
24658
- p14.cancel("Setup cancelled.");
24720
+ if (p15.isCancel(pmChoice)) {
24721
+ p15.cancel("Setup cancelled.");
24659
24722
  process.exit(0);
24660
24723
  }
24661
24724
  pm = pmChoice;
@@ -24677,7 +24740,7 @@ async function runInitCommand(name, options) {
24677
24740
  ];
24678
24741
  if (srcDir) cnaArgs.push("--src-dir");
24679
24742
  else cnaArgs.push("--no-src-dir");
24680
- const createNextAppSpinner = p14.spinner();
24743
+ const createNextAppSpinner = p15.spinner();
24681
24744
  createNextAppSpinner.start(`Creating a Next.js app (latest)`);
24682
24745
  const createNextAppResult = await runQuietCommand(bin, cnaArgs, {
24683
24746
  cwd,
@@ -24689,8 +24752,8 @@ async function runInitCommand(name, options) {
24689
24752
  process.stderr.write(`${createNextAppResult.output.trimEnd()}
24690
24753
  `);
24691
24754
  }
24692
- p14.log.error(createNextAppResult.error);
24693
- p14.log.info(
24755
+ p15.log.error(createNextAppResult.error);
24756
+ p15.log.info(
24694
24757
  `You can create the project manually:
24695
24758
  ${pc5.cyan(`npx create-next-app@latest ${projectPrompt.projectName} --typescript --tailwind --app`)}
24696
24759
  Then run ${pc5.cyan("betterstart init")} inside it.`
@@ -24704,11 +24767,11 @@ async function runInitCommand(name, options) {
24704
24767
  );
24705
24768
  if (!hasPackageJson || !hasNextConfig) {
24706
24769
  createNextAppSpinner.stop(`Failed to create Next.js app: ${displayName}`);
24707
- p14.log.error(
24770
+ p15.log.error(
24708
24771
  "create-next-app completed but the project was not created. This can happen with nested npx calls."
24709
24772
  );
24710
24773
  const manualCmd = `npx create-next-app@latest ${projectPrompt.projectName} --typescript --tailwind --app`;
24711
- p14.log.info(
24774
+ p15.log.info(
24712
24775
  `Create the project manually:
24713
24776
  ${pc5.cyan(manualCmd)}
24714
24777
  Then run ${pc5.cyan("betterstart init")} inside it.`
@@ -24760,7 +24823,7 @@ async function runInitCommand(name, options) {
24760
24823
  if (options.yes) {
24761
24824
  if (options.databaseUrl) {
24762
24825
  if (!isValidDbUrl(options.databaseUrl)) {
24763
- p14.log.error(
24826
+ p15.log.error(
24764
24827
  `Invalid database URL. Must start with ${pc5.cyan("postgres://")} or ${pc5.cyan("postgresql://")}`
24765
24828
  );
24766
24829
  process.exit(1);
@@ -24779,12 +24842,12 @@ async function runInitCommand(name, options) {
24779
24842
  if (flow.ok && flow.databaseUrl) {
24780
24843
  databaseUrl = flow.databaseUrl;
24781
24844
  } else {
24782
- p14.log.warn("Vercel provisioning did not complete; continuing without a database URL.");
24845
+ p15.log.warn("Vercel provisioning did not complete; continuing without a database URL.");
24783
24846
  }
24784
24847
  }
24785
24848
  } else if (existingDbUrl) {
24786
24849
  const masked = maskDbUrl(existingDbUrl);
24787
- p14.log.info(`Using existing database URL from .env.local ${pc5.dim(`(${masked})`)}`);
24850
+ p15.log.info(`Using existing database URL from .env.local ${pc5.dim(`(${masked})`)}`);
24788
24851
  databaseUrl = existingDbUrl;
24789
24852
  } else {
24790
24853
  const dbResult = await promptDatabase({ allowVercel: options.vercel !== false });
@@ -24799,7 +24862,7 @@ async function runInitCommand(name, options) {
24799
24862
  if (flow.ok && flow.databaseUrl) {
24800
24863
  databaseUrl = flow.databaseUrl;
24801
24864
  } else {
24802
- p14.log.info("Falling back to a manual database connection string.");
24865
+ p15.log.info("Falling back to a manual database connection string.");
24803
24866
  openBrowserVercelNeon();
24804
24867
  databaseUrl = await promptConnectionString();
24805
24868
  }
@@ -24816,7 +24879,7 @@ async function runInitCommand(name, options) {
24816
24879
  config.paths = config.frameworkConfig.next.paths;
24817
24880
  config.database.migrationsDir = deriveMigrationsDir(namespace);
24818
24881
  const results = [];
24819
- const s = p14.spinner();
24882
+ const s = p15.spinner();
24820
24883
  s.start("Directory structure");
24821
24884
  const baseFiles = scaffoldBase({
24822
24885
  cwd,
@@ -24893,7 +24956,7 @@ async function runInitCommand(name, options) {
24893
24956
  });
24894
24957
  s.stop("");
24895
24958
  process.stdout.write("\x1B[2A\x1B[J");
24896
- p14.note(noteLines.join("\n"), "Scaffolded admin");
24959
+ p15.note(noteLines.join("\n"), "Scaffolded admin");
24897
24960
  const drizzleConfigPath = path48.join(cwd, "drizzle.config.ts");
24898
24961
  if (!dbFiles.includes("drizzle.config.ts") && fs37.existsSync(drizzleConfigPath)) {
24899
24962
  if (forceMode) {
@@ -24903,20 +24966,20 @@ async function runInitCommand(name, options) {
24903
24966
  readNamespacedTemplate("drizzle.config.ts", namespace),
24904
24967
  "utf-8"
24905
24968
  );
24906
- p14.log.success("Updated drizzle.config.ts");
24969
+ p15.log.success("Updated drizzle.config.ts");
24907
24970
  } else if (!options.yes) {
24908
- const overwrite = await p14.confirm({
24971
+ const overwrite = await p15.confirm({
24909
24972
  message: "drizzle.config.ts already exists. Overwrite with latest version?",
24910
24973
  initialValue: true
24911
24974
  });
24912
- if (!p14.isCancel(overwrite) && overwrite) {
24975
+ if (!p15.isCancel(overwrite) && overwrite) {
24913
24976
  const { readNamespacedTemplate } = await import("./template-reader-X6KFP7B3.js");
24914
24977
  fs37.writeFileSync(
24915
24978
  drizzleConfigPath,
24916
24979
  readNamespacedTemplate("drizzle.config.ts", namespace),
24917
24980
  "utf-8"
24918
24981
  );
24919
- p14.log.success("Updated drizzle.config.ts");
24982
+ p15.log.success("Updated drizzle.config.ts");
24920
24983
  }
24921
24984
  }
24922
24985
  }
@@ -24942,8 +25005,8 @@ async function runInitCommand(name, options) {
24942
25005
  depsInstalled = true;
24943
25006
  } else {
24944
25007
  s.stop("Failed to install dependencies");
24945
- p14.log.warning(depsResult.error ?? "Unknown error");
24946
- p14.log.info(
25008
+ p15.log.warning(depsResult.error ?? "Unknown error");
25009
+ p15.log.info(
24947
25010
  `You can install them manually:
24948
25011
  ${pc5.cyan(`${pm} add ${depsResult.dependencies.join(" ")}`)}
24949
25012
  ${pc5.cyan(`${pm} add -D ${depsResult.devDeps.join(" ")}`)}`
@@ -25032,10 +25095,10 @@ async function runInitCommand(name, options) {
25032
25095
  ` ${pc5.yellow("\u25B2")} Local filesystem storage is only for development or self-hosted persistent-disk deployments. Use Cloudflare R2 or AWS S3 for hosted/serverless production.`
25033
25096
  );
25034
25097
  }
25035
- p14.note(installLines.join("\n"), "Installed");
25098
+ p15.note(installLines.join("\n"), "Installed");
25036
25099
  let dbPushed = false;
25037
25100
  if (depsResult.success && options.skipMigration && hasDbUrl(cwd)) {
25038
- p14.log.info(`Skipping database schema push ${pc5.dim("(--skip-migration)")}`);
25101
+ p15.log.info(`Skipping database schema push ${pc5.dim("(--skip-migration)")}`);
25039
25102
  } else if (depsResult.success && hasDbUrl(cwd)) {
25040
25103
  let driverReady = hasDrizzleKitPostgresDriverDependency(cwd);
25041
25104
  if (!driverReady) {
@@ -25050,8 +25113,8 @@ async function runInitCommand(name, options) {
25050
25113
  });
25051
25114
  if (!driverResult.success) {
25052
25115
  s.stop("Database push failed");
25053
- p14.log.warning(driverResult.error ?? `Failed to install ${DRIZZLE_KIT_POSTGRES_DRIVER_DEP}`);
25054
- p14.log.info(
25116
+ p15.log.warning(driverResult.error ?? `Failed to install ${DRIZZLE_KIT_POSTGRES_DRIVER_DEP}`);
25117
+ p15.log.info(
25055
25118
  `Install ${DRIZZLE_KIT_POSTGRES_DRIVER_DEP} manually, then run: ${pc5.cyan(drizzlePushCommand(pm))}`
25056
25119
  );
25057
25120
  } else {
@@ -25062,7 +25125,7 @@ async function runInitCommand(name, options) {
25062
25125
  if (driverReady) {
25063
25126
  const useTerminalForDbPush = shouldUseTerminalForDbPush(options);
25064
25127
  if (useTerminalForDbPush) {
25065
- p14.log.info(`Running ${pc5.cyan("drizzle-kit push --force")}`);
25128
+ p15.log.info(`Running ${pc5.cyan("drizzle-kit push --force")}`);
25066
25129
  } else {
25067
25130
  s.start("Pushing database schema (drizzle-kit push)");
25068
25131
  }
@@ -25071,13 +25134,13 @@ async function runInitCommand(name, options) {
25071
25134
  if (useTerminalForDbPush) {
25072
25135
  const verification = await verifyDatabaseReachable(cwd);
25073
25136
  if (!verification.success) {
25074
- p14.log.warning(verification.error);
25075
- p14.log.error("Database was not reachable. Aborting setup.");
25137
+ p15.log.warning(verification.error);
25138
+ p15.log.error("Database was not reachable. Aborting setup.");
25076
25139
  process.exit(1);
25077
25140
  }
25078
25141
  }
25079
25142
  if (useTerminalForDbPush) {
25080
- p14.log.success("Database schema pushed");
25143
+ p15.log.success("Database schema pushed");
25081
25144
  } else {
25082
25145
  s.stop(`${pc5.green("\u2713")} Database schema pushed`);
25083
25146
  }
@@ -25087,12 +25150,12 @@ async function runInitCommand(name, options) {
25087
25150
  s.stop("Database push failed");
25088
25151
  }
25089
25152
  const pushError = pushResult.error ?? "Unknown error";
25090
- p14.log.warning(pushError);
25153
+ p15.log.warning(pushError);
25091
25154
  if (isDatabaseReachabilityError(pushError)) {
25092
- p14.log.error("Database was not reachable. Aborting setup.");
25155
+ p15.log.error("Database was not reachable. Aborting setup.");
25093
25156
  process.exit(1);
25094
25157
  }
25095
- p14.log.info(`You can run it manually: ${pc5.cyan(drizzlePushCommand(pm))}`);
25158
+ p15.log.info(`You can run it manually: ${pc5.cyan(drizzlePushCommand(pm))}`);
25096
25159
  }
25097
25160
  }
25098
25161
  }
@@ -25101,7 +25164,7 @@ async function runInitCommand(name, options) {
25101
25164
  let seedSuccess = false;
25102
25165
  let adminAccountReady = false;
25103
25166
  if (dbPushed && options.skipAdminCreation) {
25104
- p14.log.info(
25167
+ p15.log.info(
25105
25168
  `Skipping admin user creation ${pc5.dim(`(use ${betterstartExecCommand(pm, "seed")} later)`)}`
25106
25169
  );
25107
25170
  }
@@ -25111,14 +25174,14 @@ async function runInitCommand(name, options) {
25111
25174
  let replaceExistingAdmin = false;
25112
25175
  const adminCheck = await checkExistingAdmin(cwd, adminDir, authBasePath);
25113
25176
  if (adminCheck.error) {
25114
- p14.log.warning(`Could not verify existing admin account ${pc5.dim(`(${adminCheck.error})`)}`);
25177
+ p15.log.warning(`Could not verify existing admin account ${pc5.dim(`(${adminCheck.error})`)}`);
25115
25178
  if (isDatabaseReachabilityError(adminCheck.error)) {
25116
- p14.log.error("Database was not reachable. Aborting setup.");
25179
+ p15.log.error("Database was not reachable. Aborting setup.");
25117
25180
  process.exit(1);
25118
25181
  }
25119
25182
  } else if (adminCheck.existingAdmin) {
25120
25183
  const existingAdminLabel = formatAdminIdentity(adminCheck.existingAdmin);
25121
- const adminAction = await p14.select({
25184
+ const adminAction = await p15.select({
25122
25185
  message: "Found an already existing admin account. Do you want to replace it or skip?",
25123
25186
  options: [
25124
25187
  {
@@ -25132,34 +25195,34 @@ async function runInitCommand(name, options) {
25132
25195
  }
25133
25196
  ]
25134
25197
  });
25135
- if (p14.isCancel(adminAction)) {
25136
- p14.cancel("Setup cancelled.");
25198
+ if (p15.isCancel(adminAction)) {
25199
+ p15.cancel("Setup cancelled.");
25137
25200
  process.exit(0);
25138
25201
  }
25139
25202
  if (adminAction === "skip") {
25140
25203
  adminAccountReady = true;
25141
- p14.log.info(`Keeping existing admin account ${pc5.dim(`(${existingAdminLabel})`)}`);
25204
+ p15.log.info(`Keeping existing admin account ${pc5.dim(`(${existingAdminLabel})`)}`);
25142
25205
  } else {
25143
25206
  replaceExistingAdmin = true;
25144
25207
  }
25145
25208
  }
25146
25209
  if (!adminAccountReady) {
25147
- p14.note(
25210
+ p15.note(
25148
25211
  pc5.dim(
25149
25212
  replaceExistingAdmin ? "Replace the existing admin account to access the admin." : "Create your first admin user to access the admin."
25150
25213
  ),
25151
25214
  "Admin account"
25152
25215
  );
25153
- const credentials = await p14.group(
25216
+ const credentials = await p15.group(
25154
25217
  {
25155
- email: () => p14.text({
25218
+ email: () => p15.text({
25156
25219
  message: "Admin email",
25157
25220
  placeholder: "admin@example.com",
25158
25221
  validate: (v) => {
25159
25222
  if (!v || !v.includes("@")) return "Please enter a valid email";
25160
25223
  }
25161
25224
  }),
25162
- password: () => p14.password({
25225
+ password: () => p15.password({
25163
25226
  message: "Admin password",
25164
25227
  validate: (v) => {
25165
25228
  if (!v || v.length < 8) return "Password must be at least 8 characters";
@@ -25168,7 +25231,7 @@ async function runInitCommand(name, options) {
25168
25231
  },
25169
25232
  {
25170
25233
  onCancel: () => {
25171
- p14.cancel("Setup cancelled.");
25234
+ p15.cancel("Setup cancelled.");
25172
25235
  process.exit(0);
25173
25236
  }
25174
25237
  }
@@ -25187,11 +25250,11 @@ async function runInitCommand(name, options) {
25187
25250
  );
25188
25251
  if (seedResult.existingUser) {
25189
25252
  s.stop(`${pc5.yellow("\u25B2")} An account already exists for ${credentials.email}`);
25190
- const replace = await p14.confirm({
25253
+ const replace = await p15.confirm({
25191
25254
  message: "Replace the existing account with this email?",
25192
25255
  initialValue: false
25193
25256
  });
25194
- if (!p14.isCancel(replace) && replace) {
25257
+ if (!p15.isCancel(replace) && replace) {
25195
25258
  seedOverwriteMode = "email";
25196
25259
  s.start("Replacing admin user");
25197
25260
  seedResult = await runSeed(
@@ -25212,14 +25275,14 @@ async function runInitCommand(name, options) {
25212
25275
  adminAccountReady = true;
25213
25276
  } else if (seedResult.error) {
25214
25277
  s.stop(`${pc5.red("\u2717")} Failed to create admin user`);
25215
- p14.note(
25278
+ p15.note(
25216
25279
  `${pc5.red(seedResult.error)}
25217
25280
 
25218
25281
  Run manually: ${pc5.cyan(betterstartExecCommand(pm, "seed"))}`,
25219
25282
  pc5.red("Seed failed")
25220
25283
  );
25221
25284
  if (isDatabaseReachabilityError(seedResult.error)) {
25222
- p14.log.error("Database was not reachable. Aborting setup.");
25285
+ p15.log.error("Database was not reachable. Aborting setup.");
25223
25286
  process.exit(1);
25224
25287
  }
25225
25288
  }
@@ -25273,15 +25336,15 @@ Run manually: ${pc5.cyan(betterstartExecCommand(pm, "seed"))}`,
25273
25336
  ` ${step++}. Run ${pc5.cyan(betterstartExecCommand(pm, "add --integration <name>"))} to install integrations later`
25274
25337
  );
25275
25338
  summaryLines.push("", "Next steps:", ...nextSteps);
25276
- p14.note(summaryLines.join("\n"), "Admin scaffolded successfully");
25339
+ p15.note(summaryLines.join("\n"), "Admin scaffolded successfully");
25277
25340
  if (!options.yes && !options.skipDevServerStart) {
25278
25341
  const devCmd = runCommand(pm, "dev");
25279
- const startDev = await p14.confirm({
25342
+ const startDev = await p15.confirm({
25280
25343
  message: "Start the development server?",
25281
25344
  initialValue: true
25282
25345
  });
25283
- if (!p14.isCancel(startDev) && startDev) {
25284
- p14.outro(`Starting ${pc5.cyan(devCmd)}...`);
25346
+ if (!p15.isCancel(startDev) && startDev) {
25347
+ p15.outro(`Starting ${pc5.cyan(devCmd)}...`);
25285
25348
  await startManagedDevServer(cwd, devCmd, adminLoginUrl, {
25286
25349
  email: seedSuccess && seedEmail ? seedEmail : void 0,
25287
25350
  password: seedSuccess && seedPassword ? seedPassword : void 0
@@ -25289,7 +25352,7 @@ Run manually: ${pc5.cyan(betterstartExecCommand(pm, "seed"))}`,
25289
25352
  return;
25290
25353
  }
25291
25354
  }
25292
- p14.outro("Done!");
25355
+ p15.outro("Done!");
25293
25356
  }
25294
25357
  function isValidDbUrl(url) {
25295
25358
  return url.startsWith("postgres://") || url.startsWith("postgresql://");
@@ -25676,7 +25739,7 @@ function printAdminReadyNote(state) {
25676
25739
  lines.unshift(`Password: ${pc5.cyan(state.adminPassword)}`);
25677
25740
  lines.unshift(`Admin user: ${pc5.cyan(state.adminEmail)}`);
25678
25741
  }
25679
- p14.note(lines.join("\n"), "Admin ready");
25742
+ p15.note(lines.join("\n"), "Admin ready");
25680
25743
  }
25681
25744
  function shouldSuppressDevServerStartupLine(line) {
25682
25745
  const plain = stripAnsi(line).trim();
@@ -25788,7 +25851,7 @@ function startManagedDevServer(cwd, devCmd, adminLoginUrl, adminCredentials) {
25788
25851
 
25789
25852
  // adapters/next/commands/list-integrations.ts
25790
25853
  import path49 from "path";
25791
- import * as p15 from "@clack/prompts";
25854
+ import * as p16 from "@clack/prompts";
25792
25855
  async function runListIntegrationsCommand(options) {
25793
25856
  const cwd = options.cwd ? path49.resolve(options.cwd) : process.cwd();
25794
25857
  const config = await resolveConfig(cwd);
@@ -25797,15 +25860,15 @@ async function runListIntegrationsCommand(options) {
25797
25860
  const status = installedIntegrations.has(integration.id) ? "installed" : "available";
25798
25861
  return `${integration.id.padEnd(10)} ${status.padEnd(10)} ${integration.kind.padEnd(8)} ${integration.description}`;
25799
25862
  });
25800
- p15.note(lines.join("\n"), "BetterStart integrations");
25801
- p15.outro(
25863
+ p16.note(lines.join("\n"), "BetterStart integrations");
25864
+ p16.outro(
25802
25865
  `${installedIntegrations.size} installed, ${lines.length - installedIntegrations.size} available`
25803
25866
  );
25804
25867
  }
25805
25868
 
25806
25869
  // adapters/next/commands/list-plugins.ts
25807
25870
  import path50 from "path";
25808
- import * as p16 from "@clack/prompts";
25871
+ import * as p17 from "@clack/prompts";
25809
25872
  async function runListPluginsCommand(options) {
25810
25873
  const cwd = options.cwd ? path50.resolve(options.cwd) : process.cwd();
25811
25874
  const config = await resolveConfig(cwd);
@@ -25814,34 +25877,34 @@ async function runListPluginsCommand(options) {
25814
25877
  const status = installedPlugins.has(plugin.id) ? "installed" : "available";
25815
25878
  return `${plugin.id.padEnd(10)} ${status.padEnd(10)} ${plugin.kind.padEnd(12)} ${plugin.description}`;
25816
25879
  });
25817
- p16.note(lines.join("\n"), "BetterStart plugins");
25818
- p16.outro(`${installedPlugins.size} installed, ${lines.length - installedPlugins.size} available`);
25880
+ p17.note(lines.join("\n"), "BetterStart plugins");
25881
+ p17.outro(`${installedPlugins.size} installed, ${lines.length - installedPlugins.size} available`);
25819
25882
  }
25820
25883
 
25821
25884
  // adapters/next/commands/remove.ts
25822
25885
  import path51 from "path";
25823
- import * as p17 from "@clack/prompts";
25886
+ import * as p18 from "@clack/prompts";
25824
25887
  async function runRemoveCommand(items, options) {
25825
25888
  const removeIntegrationsMode = Boolean(options.integration);
25826
25889
  if (!removeIntegrationsMode && items.includes("core")) {
25827
- p17.log.error("The core Admin cannot be removed.");
25890
+ p18.log.error("The core Admin cannot be removed.");
25828
25891
  process.exit(1);
25829
25892
  }
25830
25893
  const pluginIds = items.filter(isPluginId);
25831
25894
  const integrationIds = items.filter(isIntegrationId);
25832
25895
  if (!removeIntegrationsMode && integrationIds.length > 0) {
25833
- p17.log.error(
25896
+ p18.log.error(
25834
25897
  `Integration IDs require --integration. Run \`betterstart remove --integration ${integrationIds.join(" ")}\`.`
25835
25898
  );
25836
25899
  process.exit(1);
25837
25900
  }
25838
25901
  if (removeIntegrationsMode && pluginIds.length > 0) {
25839
- p17.log.error(`Plugin IDs cannot be removed with --integration: ${pluginIds.join(", ")}`);
25902
+ p18.log.error(`Plugin IDs cannot be removed with --integration: ${pluginIds.join(", ")}`);
25840
25903
  process.exit(1);
25841
25904
  }
25842
25905
  const invalidItems = removeIntegrationsMode ? items.filter((integrationId) => !isIntegrationId(integrationId)) : items.filter((pluginId) => !isPluginId(pluginId));
25843
25906
  if (invalidItems.length > 0) {
25844
- p17.log.error(
25907
+ p18.log.error(
25845
25908
  removeIntegrationsMode ? formatUnknownIntegrationMessage(invalidItems) : formatUnknownPluginMessage(invalidItems)
25846
25909
  );
25847
25910
  process.exit(1);
@@ -25850,12 +25913,12 @@ async function runRemoveCommand(items, options) {
25850
25913
  const config = await resolveConfig(cwd);
25851
25914
  const pm = detectPackageManager(cwd);
25852
25915
  if (!options.force) {
25853
- const confirmed = await p17.confirm({
25916
+ const confirmed = await p18.confirm({
25854
25917
  message: `Remove ${removeIntegrationsMode ? "integration" : "plugin"}${items.length === 1 ? "" : "s"} ${items.join(", ")}?`,
25855
25918
  initialValue: false
25856
25919
  });
25857
- if (p17.isCancel(confirmed) || !confirmed) {
25858
- p17.cancel(`${removeIntegrationsMode ? "Integration" : "Plugin"} removal cancelled.`);
25920
+ if (p18.isCancel(confirmed) || !confirmed) {
25921
+ p18.cancel(`${removeIntegrationsMode ? "Integration" : "Plugin"} removal cancelled.`);
25859
25922
  process.exit(0);
25860
25923
  }
25861
25924
  }
@@ -25868,13 +25931,13 @@ async function runRemoveCommand(items, options) {
25868
25931
  });
25869
25932
  writeConfigFile(cwd, result2.config);
25870
25933
  if (result2.removed.length === 0) {
25871
- p17.outro("No integrations were removed.");
25934
+ p18.outro("No integrations were removed.");
25872
25935
  return;
25873
25936
  }
25874
25937
  if (result2.warnings.length > 0) {
25875
- p17.note(result2.warnings.join("\n"), "Warnings");
25938
+ p18.note(result2.warnings.join("\n"), "Warnings");
25876
25939
  }
25877
- p17.outro(
25940
+ p18.outro(
25878
25941
  `Removed integration${result2.removed.length === 1 ? "" : "s"}: ${result2.removed.join(", ")}`
25879
25942
  );
25880
25943
  return;
@@ -25887,13 +25950,13 @@ async function runRemoveCommand(items, options) {
25887
25950
  });
25888
25951
  writeConfigFile(cwd, result.config);
25889
25952
  if (result.removed.length === 0) {
25890
- p17.outro("No plugins were removed.");
25953
+ p18.outro("No plugins were removed.");
25891
25954
  return;
25892
25955
  }
25893
25956
  if (result.warnings.length > 0) {
25894
- p17.note(result.warnings.join("\n"), "Warnings");
25957
+ p18.note(result.warnings.join("\n"), "Warnings");
25895
25958
  }
25896
- p17.outro(`Removed plugin${result.removed.length === 1 ? "" : "s"}: ${result.removed.join(", ")}`);
25959
+ p18.outro(`Removed plugin${result.removed.length === 1 ? "" : "s"}: ${result.removed.join(", ")}`);
25897
25960
  }
25898
25961
 
25899
25962
  // adapters/next/commands/remove-schema.ts
@@ -26042,7 +26105,7 @@ async function runRemoveSchemaCommand(schemaName, options) {
26042
26105
  // adapters/next/commands/uninstall.ts
26043
26106
  import fs40 from "fs";
26044
26107
  import path53 from "path";
26045
- import * as p18 from "@clack/prompts";
26108
+ import * as p19 from "@clack/prompts";
26046
26109
  import pc6 from "picocolors";
26047
26110
 
26048
26111
  // adapters/next/commands/uninstall-cleaners.ts
@@ -26264,8 +26327,8 @@ function buildUninstallPlan(cwd, namespaceValue) {
26264
26327
  count: configFiles.length,
26265
26328
  unit: configFiles.length === 1 ? "file" : "files",
26266
26329
  execute() {
26267
- for (const p19 of configPaths) {
26268
- if (fs40.existsSync(p19)) fs40.unlinkSync(p19);
26330
+ for (const p20 of configPaths) {
26331
+ if (fs40.existsSync(p20)) fs40.unlinkSync(p20);
26269
26332
  }
26270
26333
  }
26271
26334
  });
@@ -26329,7 +26392,7 @@ function buildUninstallPlan(cwd, namespaceValue) {
26329
26392
  }
26330
26393
  async function runUninstallCommand(options) {
26331
26394
  const cwd = options.cwd ? path53.resolve(options.cwd) : process.cwd();
26332
- p18.intro(pc6.bgRed(pc6.white(" BetterStart Uninstall ")));
26395
+ p19.intro(pc6.bgRed(pc6.white(" BetterStart Uninstall ")));
26333
26396
  let namespace = DEFAULT_ADMIN_NAMESPACE;
26334
26397
  try {
26335
26398
  const config = await resolveConfig(cwd);
@@ -26338,8 +26401,8 @@ async function runUninstallCommand(options) {
26338
26401
  }
26339
26402
  const steps = buildUninstallPlan(cwd, namespace);
26340
26403
  if (steps.length === 0) {
26341
- p18.log.success(`${pc6.green("\u2713")} Nothing to remove \u2014 project is already clean.`);
26342
- p18.outro("Done");
26404
+ p19.log.success(`${pc6.green("\u2713")} Nothing to remove \u2014 project is already clean.`);
26405
+ p19.outro("Done");
26343
26406
  return;
26344
26407
  }
26345
26408
  const planLines = steps.map((step) => {
@@ -26347,18 +26410,18 @@ async function runUninstallCommand(options) {
26347
26410
  const countLabel = pc6.dim(`${step.count} ${step.unit}`);
26348
26411
  return `${pc6.red("\xD7")} ${names} ${countLabel}`;
26349
26412
  });
26350
- p18.note(planLines.join("\n"), "Uninstall plan");
26413
+ p19.note(planLines.join("\n"), "Uninstall plan");
26351
26414
  if (!options.force) {
26352
- const confirmed = await p18.confirm({
26415
+ const confirmed = await p19.confirm({
26353
26416
  message: "Proceed with uninstall?",
26354
26417
  initialValue: false
26355
26418
  });
26356
- if (p18.isCancel(confirmed) || !confirmed) {
26357
- p18.cancel("Uninstall cancelled.");
26419
+ if (p19.isCancel(confirmed) || !confirmed) {
26420
+ p19.cancel("Uninstall cancelled.");
26358
26421
  process.exit(0);
26359
26422
  }
26360
26423
  }
26361
- const s = p18.spinner();
26424
+ const s = p19.spinner();
26362
26425
  s.start(steps[0].label);
26363
26426
  for (const step of steps) {
26364
26427
  s.message(step.label);
@@ -26366,8 +26429,8 @@ async function runUninstallCommand(options) {
26366
26429
  }
26367
26430
  const parts = steps.map((step) => `${step.count} ${step.unit}`);
26368
26431
  s.stop(`Removed ${parts.join(", ")}`);
26369
- p18.note(pc6.dim("Database tables were NOT dropped \u2014 drop them manually if needed."), "Next steps");
26370
- p18.outro("Uninstall complete");
26432
+ p19.note(pc6.dim("Database tables were NOT dropped \u2014 drop them manually if needed."), "Next steps");
26433
+ p19.outro("Uninstall complete");
26371
26434
  }
26372
26435
 
26373
26436
  // adapters/next/commands/update-component.ts