betterstart-cli 0.0.32 → 0.0.34

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
@@ -19775,6 +19775,24 @@ function fitSpinnerMessage(message) {
19775
19775
  if (visible.length <= max) return message;
19776
19776
  return `${visible.slice(0, max - 1)}\u2026`;
19777
19777
  }
19778
+ var CLACK_LINE_ROWS = 2;
19779
+ var LOG_PREFIX_WIDTH = 3;
19780
+ function clackLogRows(message) {
19781
+ const columns = process.stdout.columns ?? 80;
19782
+ const width = stripVTControlCharacters(message).length + LOG_PREFIX_WIDTH;
19783
+ return 1 + Math.max(1, Math.ceil(width / columns));
19784
+ }
19785
+ function eraseRows(rows) {
19786
+ if (rows <= 0 || !process.stdout.isTTY || process.env.CI === "true") return;
19787
+ process.stdout.write(`\x1B[${rows}A\x1B[${rows}M`);
19788
+ }
19789
+ function eraseClackLine(options = {}) {
19790
+ if (!process.stdout.isTTY || process.env.CI === "true") return;
19791
+ const below = (options.linesBelow ?? 0) * CLACK_LINE_ROWS;
19792
+ const up = below + CLACK_LINE_ROWS;
19793
+ const restore = below > 0 ? `\x1B[${below}B` : "";
19794
+ process.stdout.write(`\x1B[${up}A\x1B[${CLACK_LINE_ROWS}M${restore}`);
19795
+ }
19778
19796
  function spinner2(options) {
19779
19797
  const inner = p5.spinner(options);
19780
19798
  const guided = options?.withGuide !== false;
@@ -21825,7 +21843,7 @@ async function promptServices(options) {
21825
21843
  options: [
21826
21844
  {
21827
21845
  value: "vercel",
21828
- label: "Vercel",
21846
+ label: "Vercel (Neon)",
21829
21847
  hint: "Automatically provision a Neon Postgres database"
21830
21848
  },
21831
21849
  {
@@ -24235,35 +24253,41 @@ async function ensureVercelAuth(runner, cwd, options) {
24235
24253
  if (existing.authed) {
24236
24254
  if (options.quietIfAuthed) {
24237
24255
  checkSpinner.clear();
24238
- } else {
24239
- checkSpinner.stop(signedInMessage(existing.username));
24256
+ return existing;
24240
24257
  }
24241
- return existing;
24258
+ checkSpinner.stop(signedInMessage(existing.username));
24259
+ return { ...existing, dismissNote: eraseClackLine };
24242
24260
  }
24243
24261
  if (env.VERCEL_TOKEN) {
24244
24262
  checkSpinner.stop("Could not verify VERCEL_TOKEN with Vercel");
24245
24263
  return { authed: false, reason: "login-failed" };
24246
24264
  }
24247
24265
  checkSpinner.clear();
24248
- p13.log.info(
24249
- `Sign in to Vercel to continue ${pc3.dim("(or press Ctrl-C to enter a connection string manually)")}`
24250
- );
24266
+ const signInMessage = `Sign in to Vercel to continue ${pc3.dim("(or press Ctrl-C to enter a connection string manually)")}`;
24267
+ const signInRows = clackLogRows(signInMessage);
24268
+ p13.log.info(signInMessage);
24269
+ let streamedRows = 0;
24251
24270
  const login = await runVercel(runner, ["login"], {
24252
24271
  cwd,
24253
24272
  mode: "stream",
24254
- streamLineFilter: showVercelLoginLine,
24273
+ streamLineFilter: (line) => {
24274
+ const show = showVercelLoginLine(line);
24275
+ if (show) streamedRows += 1;
24276
+ return show;
24277
+ },
24255
24278
  timeoutMs: LOGIN_TIMEOUT_MS,
24256
24279
  env
24257
24280
  });
24258
24281
  if (!login.success) {
24259
24282
  return { authed: false, reason: login.timedOut ? "timeout" : "login-cancelled" };
24260
24283
  }
24284
+ eraseRows(signInRows + streamedRows);
24261
24285
  const verifySpinner = spinner2();
24262
24286
  verifySpinner.start("Verifying Vercel sign-in");
24263
24287
  const after = await checkVercelAuth(runner, cwd, env);
24264
24288
  if (after.authed) {
24265
24289
  verifySpinner.stop(signedInMessage(after.username));
24266
- return after;
24290
+ return { ...after, dismissNote: eraseClackLine };
24267
24291
  }
24268
24292
  verifySpinner.stop("Could not verify your Vercel sign-in");
24269
24293
  return { authed: false, reason: "login-failed" };
@@ -24710,7 +24734,7 @@ async function provisionNeonInteractive(runner, cwd, options) {
24710
24734
  if (!add.success) {
24711
24735
  return { failure: add.timedOut ? "timeout" : "provision-failed" };
24712
24736
  }
24713
- return {};
24737
+ return { usedTerminalFallback: true };
24714
24738
  }
24715
24739
  async function provisionNeon(runner, cwd, options) {
24716
24740
  const provisionSpinner = spinner2();
@@ -24773,7 +24797,7 @@ async function runVercelNeonFlow(options) {
24773
24797
  p16.log.warn(authFailureMessage(auth.reason));
24774
24798
  return { ok: false };
24775
24799
  }
24776
- await ensureLinkedProject(runner, options.cwd, options.projectName, env);
24800
+ const linkLinePrinted = await ensureLinkedProject(runner, options.cwd, options.projectName, env);
24777
24801
  const neon = await provisionNeonForMode(runner, options);
24778
24802
  if (neon.failure) {
24779
24803
  p16.log.warn(neonFailureMessage(neon.failure));
@@ -24781,11 +24805,13 @@ async function runVercelNeonFlow(options) {
24781
24805
  return { ok: false };
24782
24806
  }
24783
24807
  const databaseUrl = await pullNeonDatabaseUrl(runner, options.cwd, env);
24808
+ const dismissSignedInNote = databaseUrl && auth.dismissNote && !neon.usedTerminalFallback ? () => auth.dismissNote?.({ linesBelow: linkLinePrinted ? 1 : 0 }) : void 0;
24784
24809
  return {
24785
24810
  ok: true,
24786
24811
  databaseUrl,
24787
24812
  dashboardUrl: neon.dashboardUrl,
24788
- resourceUrl: neon.resourceUrl
24813
+ resourceUrl: neon.resourceUrl,
24814
+ dismissSignedInNote
24789
24815
  };
24790
24816
  } catch (error) {
24791
24817
  p16.log.warn(
@@ -24899,13 +24925,14 @@ function printManualDeployHint() {
24899
24925
  p16.log.info(`You can deploy manually: ${pc6.cyan("vercel deploy --prod")}`);
24900
24926
  }
24901
24927
  async function ensureLinkedProject(runner, cwd, projectName, env) {
24902
- if (readLinkedProjectId(cwd)) return;
24928
+ if (readLinkedProjectId(cwd)) return false;
24903
24929
  const projectSpinner = spinner2();
24904
24930
  projectSpinner.start(`Creating a Vercel project ${pc6.cyan(projectName)}`);
24905
24931
  const project2 = await createVercelProject(runner, cwd, projectName, env);
24906
24932
  projectSpinner.stop(
24907
24933
  project2.linked ? `Linked Vercel project ${pc6.cyan(project2.name)}` : `Using Vercel project ${pc6.cyan(project2.name)}`
24908
24934
  );
24935
+ return true;
24909
24936
  }
24910
24937
  async function pullNeonDatabaseUrl(runner, cwd, env) {
24911
24938
  const neonSpinner = spinner2();
@@ -25541,6 +25568,7 @@ async function runInitCommand(name, options) {
25541
25568
  isFreshProject = true;
25542
25569
  }
25543
25570
  let databaseUrl;
25571
+ let dismissVercelSignedInNote;
25544
25572
  const existingDbUrl = readExistingDbUrl(cwd);
25545
25573
  if (options.yes) {
25546
25574
  if (options.databaseUrl) {
@@ -25564,10 +25592,9 @@ async function runInitCommand(name, options) {
25564
25592
  if (flow.ok && flow.databaseUrl) {
25565
25593
  databaseUrl = flow.databaseUrl;
25566
25594
  persistDatabaseUrl(cwd, databaseUrl);
25567
- p17.log.success(`Saved DATABASE_URL to ${pc7.cyan(".env.local")}`);
25568
25595
  } else if (flow.ok) {
25569
25596
  p17.log.warn("Created a Neon database, but DATABASE_URL could not be retrieved from Vercel.");
25570
- const resourceUrl = flow.resourceUrl ?? flow.dashboardUrl;
25597
+ const resourceUrl = flow.dashboardUrl ?? flow.resourceUrl;
25571
25598
  if (resourceUrl) {
25572
25599
  p17.log.info(
25573
25600
  `Open ${pc7.cyan(resourceUrl)} to copy DATABASE_URL, then rerun ${pc7.cyan("betterstart init --database-url <url> --yes")}.`
@@ -25598,12 +25625,11 @@ async function runInitCommand(name, options) {
25598
25625
  if (flow.ok && flow.databaseUrl) {
25599
25626
  databaseUrl = flow.databaseUrl;
25600
25627
  persistDatabaseUrl(cwd, databaseUrl);
25601
- p17.log.success(`Saved DATABASE_URL to ${pc7.cyan(".env.local")}`);
25628
+ dismissVercelSignedInNote = flow.dismissSignedInNote;
25602
25629
  } else if (flow.ok) {
25603
- openBrowserVercelNeonResource(flow.resourceUrl ?? flow.dashboardUrl);
25630
+ openBrowserVercelNeonResource(flow.dashboardUrl ?? flow.resourceUrl);
25604
25631
  databaseUrl = await promptConnectionString();
25605
25632
  persistDatabaseUrl(cwd, databaseUrl);
25606
- p17.log.success(`Saved DATABASE_URL to ${pc7.cyan(".env.local")}`);
25607
25633
  } else {
25608
25634
  p17.log.info("Falling back to a manual database connection string.");
25609
25635
  openBrowserVercelNeon();
@@ -25666,6 +25692,7 @@ async function runInitCommand(name, options) {
25666
25692
  } else if (options.yes) {
25667
25693
  pluginSelection = { plugins: [], integrations: [], storage: "local" };
25668
25694
  } else {
25695
+ dismissVercelSignedInNote?.();
25669
25696
  const promptResult = await promptPlugins(cwd, {
25670
25697
  provisionVercelBlob: vercelBlobAllowed ? () => runVercelBlobFlow({ cwd, projectName, interactive: true, env: process.env }) : void 0
25671
25698
  });