@rebasepro/cli 0.19.2-canary.g98b88fd → 0.19.2-canary.gef769df

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/index.es.js CHANGED
@@ -1474,12 +1474,33 @@ async function recordEvent(event, properties = {}, options = {}) {
1474
1474
  }
1475
1475
  //#endregion
1476
1476
  //#region src/telemetry/consent.ts
1477
- /** True when we may ask: nothing forbids it, and there is a question to ask. */
1478
- function shouldPrompt(env = process.env, { reAskDeclined = false } = {}) {
1479
- if (!process.stdin.isTTY) return false;
1480
- const reason = suppressionReason(env);
1481
- if (reason === "not_asked") return true;
1482
- return reAskDeclined && reason === "declined";
1477
+ /**
1478
+ * Asking, and what the question looks like.
1479
+ *
1480
+ * ## Why the prompt comes *after* the work
1481
+ *
1482
+ * The first `rebase init` on a machine is the event most worth having, and it
1483
+ * is the one where no consent exists yet. Asking before scaffolding puts a
1484
+ * privacy negotiation in front of someone who has not yet seen the tool do
1485
+ * anything — the worst possible moment, and a reliable way to get a reflexive
1486
+ * no.
1487
+ *
1488
+ * So the question is asked once the project exists and the user has seen it
1489
+ * work. The event's data is still in memory at that point, so nothing is lost
1490
+ * by waiting, and — this is the part that matters — **nothing has been
1491
+ * transmitted or written**. Declining leaves no id, no file, no record.
1492
+ *
1493
+ * ## Why the payload is shown rather than described
1494
+ *
1495
+ * "Anonymous usage data" is a phrase that has been used to mean almost
1496
+ * anything. Printing the exact JSON costs four lines of output and replaces a
1497
+ * claim the user has to take on faith with something they can read. It is also
1498
+ * the same builder the sender uses, so it cannot drift into a comfortable
1499
+ * fiction.
1500
+ */
1501
+ /** True when we may ask: no decision recorded, and nothing else forbids it. */
1502
+ function shouldPrompt(env = process.env) {
1503
+ return suppressionReason(env) === "not_asked" && Boolean(process.stdin.isTTY);
1483
1504
  }
1484
1505
  function renderPreview(event, properties) {
1485
1506
  const preview = buildEvent(event, properties, {
@@ -1495,9 +1516,8 @@ function renderPreview(event, properties) {
1495
1516
  * CI must behave exactly as it does today, which means not asking and not
1496
1517
  * sending.
1497
1518
  */
1498
- async function promptForConsent(event, properties, options = {}) {
1499
- if (!shouldPrompt(process.env, options)) return false;
1500
- const askedBefore = suppressionReason(process.env) === "declined";
1519
+ async function promptForConsent(event, properties) {
1520
+ if (!shouldPrompt()) return false;
1501
1521
  try {
1502
1522
  console.log("");
1503
1523
  console.log(chalk.bold("Help improve Rebase?"));
@@ -1511,11 +1531,6 @@ async function promptForConsent(event, properties, options = {}) {
1511
1531
  console.log("");
1512
1532
  console.log(chalk.gray(" No project names, paths, schemas, URLs or error messages. Change your"));
1513
1533
  console.log(chalk.gray(` mind any time with ${chalk.cyan("rebase telemetry disable")}.`));
1514
- if (askedBefore) {
1515
- console.log("");
1516
- console.log(chalk.gray(" You declined before, and that is still the answer unless you change it"));
1517
- console.log(chalk.gray(" here. Asked once per new project; never during ordinary work."));
1518
- }
1519
1534
  console.log("");
1520
1535
  const { accepted } = await inquirer.prompt([{
1521
1536
  type: "confirm",
@@ -1524,7 +1539,7 @@ async function promptForConsent(event, properties, options = {}) {
1524
1539
  default: false
1525
1540
  }]);
1526
1541
  setConsent(Boolean(accepted));
1527
- console.log(accepted ? chalk.green(" Thank you — sharing enabled.") : chalk.gray(" Nothing will be sent." + (options.reAskDeclined ? " You will be asked again the next time you scaffold a project." : " You will not be asked again.")));
1542
+ console.log(accepted ? chalk.green(" Thank you — sharing enabled.") : chalk.gray(" Nothing will be sent. You will not be asked again."));
1528
1543
  console.log("");
1529
1544
  return Boolean(accepted);
1530
1545
  } catch {
@@ -1638,7 +1653,7 @@ function buildInitQuestions(params) {
1638
1653
  type: "input",
1639
1654
  name: "projectName",
1640
1655
  message: "Project name:",
1641
- default: "my-app",
1656
+ default: "my-rebase-app",
1642
1657
  validate: (input) => validateProjectName(input) ?? true
1643
1658
  });
1644
1659
  if (headlessArg === void 0) questions.push({
@@ -1706,7 +1721,7 @@ ${chalk.bold("Usage")}
1706
1721
  rebase init ${chalk.blue("[name]")} [options]
1707
1722
 
1708
1723
  ${chalk.gray("The name may be a nested path (apps/my-app) or \".\" for the current directory.")}
1709
- ${chalk.gray("Asks when omitted; defaults to \"my-app\", and takes it without asking under --yes.")}
1724
+ ${chalk.gray("Defaults to \"my-rebase-app\" when omitted with --yes.")}
1710
1725
 
1711
1726
  ${chalk.bold("Options")}
1712
1727
  ${chalk.blue("-t, --template")} ${chalk.gray("<preset>")} blog | ecommerce | blank ${chalk.gray("(default: blog)")}
@@ -1788,7 +1803,7 @@ async function promptForOptions(rawArgs, pm) {
1788
1803
  const installFlag = noInstall ? false : args["--install"] ?? false;
1789
1804
  const hasInstallFlag = noInstall || args["--install"] === true;
1790
1805
  if (isNonInteractive) {
1791
- const projectName = nameArg || "my-app";
1806
+ const projectName = nameArg || "my-rebase-app";
1792
1807
  const targetDirectory = path.resolve(process.cwd(), projectName);
1793
1808
  const templateDirectory = path.resolve(cliRoot, "templates", "template");
1794
1809
  const pmCommands = getPMCommands(pm);
@@ -2124,7 +2139,7 @@ async function createProject$1(options) {
2124
2139
  git: Boolean(options.git),
2125
2140
  duration: durationBucket(Date.now() - startedAt)
2126
2141
  };
2127
- if (await promptForConsent("cli.init", initProperties, { reAskDeclined: true })) await recordEvent("cli.init", initProperties, { projectRoot: options.targetDirectory });
2142
+ if (await promptForConsent("cli.init", initProperties)) await recordEvent("cli.init", initProperties, { projectRoot: options.targetDirectory });
2128
2143
  }
2129
2144
  /**
2130
2145
  * Apply a template preset by replacing the default collection files.
@@ -15159,31 +15174,7 @@ function resolveDeployArgs(rawArgs) {
15159
15174
  appName: positionals[0]
15160
15175
  };
15161
15176
  }
15162
- /**
15163
- * `cli.deploy` — the event that says whether anyone ever ships.
15164
- *
15165
- * Declared in `TelemetryEventName` from the start and recorded nowhere, so a
15166
- * consenting user reported scaffolding, dev servers and schema pushes and never
15167
- * the one act the product exists for.
15168
- *
15169
- * What it carries is deliberately thin. No project id, no app name, no
15170
- * deployment id, no URL: those are the "project names" and "URLs" the consent
15171
- * screen promises are never sent, and a deployment id is a durable handle on
15172
- * somebody's infrastructure. `frameworkVersion` is *our* version, not the
15173
- * user's data, and it is the one field that makes the rest legible — a failure
15174
- * rate means nothing without knowing which release it is a rate for.
15175
- */
15176
- async function recordDeploy(o) {
15177
- await recordEvent("cli.deploy", {
15178
- followed: o.followed,
15179
- status: o.status,
15180
- deduplicated: o.deduplicated,
15181
- framework_version: o.frameworkVersion ?? null,
15182
- duration: durationBucket(Date.now() - o.startedAt)
15183
- }, { projectRoot: process.cwd() });
15184
- }
15185
15177
  async function deployCommand(rawArgs, projectRef) {
15186
- const startedAt = Date.now();
15187
15178
  const { flags: args, appName } = resolveDeployArgs(rawArgs);
15188
15179
  if (args["--wait"] && args["--no-follow"]) fail("--wait and --no-follow ask for opposite things.", "`deploy` follows by default — pass neither, or `--no-follow` to return as soon as the build is triggered.", "usage");
15189
15180
  const { client, url } = await requireClient(rawArgs);
@@ -15267,13 +15258,6 @@ async function deployCommand(rawArgs, projectRef) {
15267
15258
  following: false,
15268
15259
  ...warningPayload(warnings)
15269
15260
  });
15270
- await recordDeploy({
15271
- followed: false,
15272
- status: "not_followed",
15273
- deduplicated,
15274
- frameworkVersion,
15275
- startedAt
15276
- });
15277
15261
  return;
15278
15262
  }
15279
15263
  if (!isJsonMode()) {
@@ -15286,13 +15270,6 @@ async function deployCommand(rawArgs, projectRef) {
15286
15270
  projectId,
15287
15271
  url
15288
15272
  });
15289
- await recordDeploy({
15290
- followed: true,
15291
- status,
15292
- deduplicated,
15293
- frameworkVersion,
15294
- startedAt
15295
- });
15296
15273
  emit(() => {}, {
15297
15274
  deploymentId,
15298
15275
  deduplicated,
@@ -19102,24 +19079,6 @@ async function entry(args) {
19102
19079
  return;
19103
19080
  }
19104
19081
  const effectiveSubcommand = parsedArgs["--help"] && !subcommand ? "--help" : subcommand;
19105
- try {
19106
- await dispatch(command, effectiveSubcommand, args, parsedArgs, namespacedCommands);
19107
- } catch (error) {
19108
- await recordEvent("cli.error", {
19109
- command: command ?? "none",
19110
- subcommand: effectiveSubcommand ?? "none",
19111
- error_type: error instanceof Error ? error.constructor.name : "unknown",
19112
- usage: Boolean(error && typeof error === "object" && error.isUsageError)
19113
- }, { projectRoot: process.cwd() });
19114
- throw error;
19115
- }
19116
- }
19117
- /**
19118
- * The dispatch, lifted out of {@link entry} so the whole of it sits inside one
19119
- * `try`. Inlining the switch there would have put the `catch` around the flag
19120
- * parsing too, which throws its own usage errors before a command is even named.
19121
- */
19122
- async function dispatch(command, effectiveSubcommand, args, parsedArgs, namespacedCommands) {
19123
19082
  switch (command) {
19124
19083
  case "__dev-db-daemon": {
19125
19084
  const { parseDaemonArgs, runDaemon } = await import("./daemon-entry-LTFKtpHy.js");