@rebasepro/cli 0.10.1-canary.18115ba → 0.10.1-canary.811b3da

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.
@@ -100,16 +100,6 @@ export declare function initOutputMode(rawArgs: string[]): boolean;
100
100
  export declare function isJsonMode(): boolean;
101
101
  /** Force the mode (tests only — production latches it via `initOutputMode`). */
102
102
  export declare function setJsonModeForTest(value: boolean): void;
103
- /**
104
- * Write one JSON value to stdout, followed by a newline.
105
- *
106
- * Indented, because the overwhelmingly common reader is a person or an agent
107
- * looking at a terminal — JSON mode is entered automatically whenever stdout is
108
- * not a TTY, so `rebase cloud deployments list` piped anywhere at all produced
109
- * a project's entire deployment history as one unwrapped line. `JSON.parse`
110
- * does not care about the whitespace; everything else does.
111
- */
112
- export declare function printJson(value: unknown): void;
113
103
  /**
114
104
  * The one output primitive every new command uses: in JSON mode emit `json`
115
105
  * (and nothing else); otherwise run `human`. Keeping the two behind a single
@@ -18,10 +18,6 @@ export interface DeploymentRow {
18
18
  triggered_by_user_id?: string;
19
19
  gitCommitHash?: string;
20
20
  gitCommitMessage?: string;
21
- deployMessage?: string;
22
- deploy_message?: string;
23
- frameworkVersion?: string;
24
- framework_version?: string;
25
21
  }
26
22
  /**
27
23
  * The backend's rule EXACTLY: a rollback is honoured only for a successful
@@ -37,18 +33,6 @@ export declare function triggerInfo(dep: DeploymentRow): {
37
33
  };
38
34
  /** Shape one deployment row into the stable JSON view the CLI publishes. */
39
35
  export declare function deploymentView(dep: DeploymentRow): Record<string, unknown>;
40
- /**
41
- * Rows shown when `--limit` is not given.
42
- *
43
- * History is unbounded and grows one row per deploy, so "all of it" is the
44
- * wrong default in both directions: a wall of near-identical lines in a
45
- * terminal, and — since JSON mode is entered automatically for any non-TTY
46
- * stdout — a project's entire history dumped at anything that pipes the
47
- * command. Recent deploys are what the question is almost always about.
48
- */
49
- export declare const DEFAULT_DEPLOYMENTS_LIMIT = 20;
50
- /** `--limit N`, bounded. A garbage value is a refusal, never a silent default. */
51
- export declare function parseDeploymentsLimit(raw: number | undefined): number;
52
36
  export declare function deploymentsListCommand(rawArgs: string[]): Promise<void>;
53
37
  export declare function rollbackCommand(rawArgs: string[]): Promise<void>;
54
38
  export declare function cancelCommand(rawArgs: string[]): Promise<void>;
@@ -4,5 +4,3 @@ export declare function parseEnvAssignment(operands: string[]): {
4
4
  key: string;
5
5
  value: string;
6
6
  } | null;
7
- /** The prefix that makes `key` a build-time variable, or undefined. */
8
- export declare function buildTimeEnvPrefix(key: string): string | undefined;
@@ -1,44 +1,6 @@
1
- /** The control plane's verdict on what a tenant's uploads actually do. */
2
- interface StorageState {
3
- effective?: {
4
- kind?: string;
5
- summary?: string;
6
- storageType?: string;
7
- missing?: string[];
8
- };
9
- source?: string;
10
- configured?: string;
11
- overridden?: boolean;
12
- }
13
- /**
14
- * One line describing this project's storage — or `undefined` when the control
15
- * plane could not be asked, which prints as a blank rather than a guess.
16
- *
17
- * `status` used to render the `storages` row and nothing else, so a project
18
- * whose bucket is configured through its own `STORAGE_TYPE`/`S3_*` variables —
19
- * the supported path, and the one `mergeStorageEnv` deliberately lets WIN over
20
- * the row — was reported as `Storage: none` while its pod logged `Initialized
21
- * storage backends count: 1` against a live bucket. Storage is the thing an app
22
- * refuses to boot without, so that false negative sends someone off to
23
- * provision a bucket they already have. The row is not the answer; the tenant's
24
- * resolved environment is, and the control plane computes it with the same two
25
- * functions the build log uses.
26
- */
27
- export declare function describeStorageState(state: StorageState | undefined): string | undefined;
28
- /**
29
- * One line describing the database.
30
- *
31
- * `connectionStatus` is written `"untested"` at creation and only ever changed
32
- * by `rebase cloud db test`, so `managed (untested)` was reporting the absence
33
- * of a manual test as though it were the database's condition — on a project
34
- * that had just deployed against it. A never-tested database says only its
35
- * type; the verdict appears once there is one.
36
- */
37
- export declare function describeDatabaseState(db: Record<string, unknown> | undefined): string | undefined;
38
1
  export declare function statusCommand(rawArgs: string[]): Promise<void>;
39
2
  export declare function metricsCommand(rawArgs: string[]): Promise<void>;
40
3
  export declare function webhooksCommand(subcommand: string | undefined, rawArgs: string[]): Promise<void>;
41
4
  export declare function storageCommand(action: string | undefined, rawArgs: string[]): Promise<void>;
42
5
  export declare function clustersCommand(rawArgs: string[]): Promise<void>;
43
6
  export declare function billingCommand(rawArgs: string[]): Promise<void>;
44
- export {};
package/dist/index.es.js CHANGED
@@ -23,61 +23,21 @@ import { createRequire } from "module";
23
23
  * the rest of the CLI never has to hardcode a specific PM.
24
24
  */
25
25
  /**
26
- * How long to wait for `pnpm --version` before giving up on the probe.
27
- *
28
- * `pnpm --version` is a cold Node start, and on a machine that is busy — a
29
- * parallel install, a full test run — it routinely takes seconds. Measured at
30
- * 630ms, 990ms and 4293ms on three consecutive runs of one developer laptop
31
- * under load, so the previous 3s budget was inside the normal spread rather
32
- * than safely outside it.
33
- */
34
- var PNPM_PROBE_TIMEOUT_MS = 5e3;
35
- /** Memoised result of the probe. pnpm cannot appear or vanish mid-process. */
36
- var cachedPnpmAvailable;
37
- /**
38
- * Decide availability from a `spawnSync` outcome.
39
- *
40
- * Split out from the spawn itself so the decision is testable without starting
41
- * a process — which is what made the old test load-sensitive and occasionally
42
- * red for reasons that had nothing to do with the code under test.
43
- *
44
- * The three outcomes are distinguishable, and the old code conflated two of
45
- * them by asking only `status === 0`:
46
- *
47
- * not installed status null, signal null, error.code ENOENT
48
- * timed out status null, signal SIGTERM, error.code ETIMEDOUT
49
- * broken install status non-zero, no error
50
- */
51
- function pnpmAvailabilityFromProbe(res) {
52
- const code = res.error?.code;
53
- if (code === "ENOENT") return false;
54
- if (code === "ETIMEDOUT" || res.signal) return true;
55
- if (res.error) return false;
56
- return res.status === 0;
57
- }
58
- /**
59
26
  * Whether pnpm is runnable on this machine.
60
27
  *
61
28
  * Used to decide whether a fresh project can be scaffolded with pnpm. Kept
62
- * cheap and non-interactive (bounded timeout, output discarded) so it never
63
- * hangs detection if a corepack shim misbehaves, and memoised so that repeated
64
- * detection in one CLI run costs one process rather than one per call.
29
+ * cheap and non-interactive (short timeout, output discarded) so it never
30
+ * hangs detection if a corepack shim misbehaves.
65
31
  */
66
32
  function isPnpmAvailable() {
67
- if (cachedPnpmAvailable !== void 0) return cachedPnpmAvailable;
68
33
  try {
69
- cachedPnpmAvailable = pnpmAvailabilityFromProbe(spawnSync("pnpm", ["--version"], {
34
+ return spawnSync("pnpm", ["--version"], {
70
35
  stdio: "ignore",
71
- timeout: PNPM_PROBE_TIMEOUT_MS
72
- }));
36
+ timeout: 3e3
37
+ }).status === 0;
73
38
  } catch {
74
- cachedPnpmAvailable = false;
39
+ return false;
75
40
  }
76
- return cachedPnpmAvailable;
77
- }
78
- /** Forget the memoised probe. For tests; nothing in a CLI run needs it. */
79
- function resetPnpmAvailabilityCache() {
80
- cachedPnpmAvailable = void 0;
81
41
  }
82
42
  /**
83
43
  * Detect the package manager for a Rebase project.
@@ -676,17 +636,9 @@ var ANSI_RE = /\[[0-9;]*m/g;
676
636
  function stripAnsi(s) {
677
637
  return s.replace(ANSI_RE, "");
678
638
  }
679
- /**
680
- * Write one JSON value to stdout, followed by a newline.
681
- *
682
- * Indented, because the overwhelmingly common reader is a person or an agent
683
- * looking at a terminal — JSON mode is entered automatically whenever stdout is
684
- * not a TTY, so `rebase cloud deployments list` piped anywhere at all produced
685
- * a project's entire deployment history as one unwrapped line. `JSON.parse`
686
- * does not care about the whitespace; everything else does.
687
- */
639
+ /** Write one JSON value to stdout, followed by a newline. */
688
640
  function printJson(value) {
689
- process.stdout.write(JSON.stringify(value, null, 2) + "\n");
641
+ process.stdout.write(JSON.stringify(value) + "\n");
690
642
  }
691
643
  /**
692
644
  * The one output primitive every new command uses: in JSON mode emit `json`
@@ -3469,35 +3421,6 @@ async function createSourceTarball(sourceDir) {
3469
3421
  }
3470
3422
  return tarPath;
3471
3423
  }
3472
- /**
3473
- * The `@rebasepro/*` version this source directory actually resolves.
3474
- *
3475
- * Recorded on the deployment so a row in Deployment History says which
3476
- * framework build shipped. Nothing else on the platform knows: an app that
3477
- * links the framework locally pins it at package time, and a silent bump is
3478
- * invisible afterwards — it has already cost one debugging session.
3479
- *
3480
- * `@rebasepro/server` first, because that is what the deployed backend runs;
3481
- * `@rebasepro/client` is the fallback for a frontend-only bundle. Resolution is
3482
- * a plain walk up from the source directory rather than `require.resolve`,
3483
- * which would answer for the CLI's own install tree instead of the app's.
3484
- *
3485
- * Best effort by construction: a version that cannot be read is simply not
3486
- * recorded. Nothing about a deploy should fail over a bookkeeping string.
3487
- */
3488
- function resolveFrameworkVersion(sourceDir) {
3489
- let dir = path.resolve(sourceDir);
3490
- for (;;) {
3491
- for (const pkg of ["@rebasepro/server", "@rebasepro/client"]) try {
3492
- const manifest = path.join(dir, "node_modules", ...pkg.split("/"), "package.json");
3493
- const version = JSON.parse(fs.readFileSync(manifest, "utf8")).version;
3494
- if (typeof version === "string" && version.trim() !== "") return version.trim();
3495
- } catch {}
3496
- const parent = path.dirname(dir);
3497
- if (parent === dir) return void 0;
3498
- dir = parent;
3499
- }
3500
- }
3501
3424
  /** Upload a build-context tarball; returns the opaque `source` ref for deploy. */
3502
3425
  async function uploadSource(url, token, projectId, tarPath) {
3503
3426
  const bytes = fs.readFileSync(tarPath);
@@ -3523,9 +3446,7 @@ async function uploadSource(url, token, projectId, tarPath) {
3523
3446
  async function deployCommand(rawArgs, projectRef) {
3524
3447
  const args = arg({
3525
3448
  "--no-follow": Boolean,
3526
- "--source": String,
3527
- "--message": String,
3528
- "-m": "--message"
3449
+ "--source": String
3529
3450
  }, {
3530
3451
  argv: rawArgs.slice(2),
3531
3452
  permissive: true
@@ -3545,87 +3466,32 @@ async function deployCommand(rawArgs, projectRef) {
3545
3466
  }
3546
3467
  console.log("");
3547
3468
  console.log(` 🚀 Triggering deployment for project ${chalk.bold(projectRef)}${source ? " from uploaded source" : ""}...`);
3548
- const body = { projectId };
3549
- if (source) body.source = source;
3550
- if (args["--message"]) body.message = args["--message"];
3551
- body.client = "cli";
3552
- const frameworkVersion = resolveFrameworkVersion(args["--source"] ?? process.cwd());
3553
- if (frameworkVersion) body.frameworkVersion = frameworkVersion;
3554
- let triggered;
3469
+ let deploymentId;
3555
3470
  try {
3556
- const res = await client.functions.invoke("deploy", body);
3471
+ const res = await client.functions.invoke("deploy", source ? {
3472
+ projectId,
3473
+ source
3474
+ } : { projectId });
3557
3475
  if (!res?.deployment?.id) fail("Control plane did not return a deployment id.");
3558
- triggered = {
3559
- deploymentId: String(res.deployment.id),
3560
- deduplicated: res.deduplicated === true
3561
- };
3476
+ deploymentId = String(res.deployment.id);
3562
3477
  } catch (e) {
3563
- triggered = resolveTriggerFailure(e);
3478
+ const err = e;
3479
+ if (err?.status === 409) fail("A deployment is already in progress for this project.");
3480
+ if (err?.status === 402) fail(err.message || "Payment required before deploying.", "Attach a card once with `rebase cloud billing setup`, then deploy again.");
3481
+ reportError(e, "Failed to trigger deployment");
3564
3482
  }
3565
- const { deploymentId, deduplicated } = triggered;
3566
- if (!isJsonMode()) console.log(chalk.gray(deduplicated ? ` Deployment ${deploymentId} is already running — following it.` : ` Deployment ${deploymentId} created.${frameworkVersion ? ` (@rebasepro/* ${frameworkVersion})` : ""}`));
3483
+ console.log(chalk.gray(` Deployment ${deploymentId} created.`));
3567
3484
  if (args["--no-follow"]) {
3568
- emit(() => {
3569
- console.log(chalk.gray(" Not following logs (--no-follow). Check status with `rebase cloud logs`."));
3570
- console.log("");
3571
- }, {
3572
- deploymentId,
3573
- deduplicated,
3574
- frameworkVersion: frameworkVersion ?? null,
3575
- following: false
3576
- });
3577
- return;
3578
- }
3579
- if (!isJsonMode()) {
3580
- console.log(chalk.gray(" Streaming build logs (Ctrl-C to stop watching — the build keeps running):"));
3485
+ console.log(chalk.gray(" Not following logs (--no-follow). Check status with `rebase cloud logs`."));
3581
3486
  console.log("");
3487
+ return;
3582
3488
  }
3583
- const status = await streamBuildLogs(client, deploymentId, { quiet: isJsonMode() });
3584
- emit(() => {}, {
3585
- deploymentId,
3586
- deduplicated,
3587
- frameworkVersion: frameworkVersion ?? null,
3588
- following: true,
3589
- status
3590
- });
3591
- }
3592
- /**
3593
- * Turn a failed trigger into either a deployment to follow, or an exit.
3594
- *
3595
- * The 409 is the interesting one. A deploy trigger can reach the control plane
3596
- * twice without anybody asking twice — the SDK transport replays a request once
3597
- * after refreshing an expired token, and any lost response has the same effect
3598
- * — so "a deployment is already in progress" was routinely describing the
3599
- * deployment this very command had just created. With no id in the message the
3600
- * only available reading was "someone else is deploying, back off", and the
3601
- * build stream was lost either way.
3602
- *
3603
- * So: if the control plane says the blocking deployment is ours, we attach to
3604
- * it. If it is not ours, we still name it, because "which one, since when, from
3605
- * where" is the difference between an actionable refusal and a dead end.
3606
- */
3607
- function resolveTriggerFailure(e) {
3608
- const err = e;
3609
- if (err?.status === 409) {
3610
- const blocking = err.details?.deployment;
3611
- if (blocking?.id && blocking.mine) return {
3612
- deploymentId: String(blocking.id),
3613
- deduplicated: true
3614
- };
3615
- fail(blocking?.id ? `Deployment ${blocking.id} is already in progress for this project${blocking.triggerSource && blocking.triggerSource !== "unknown" ? `, triggered from the ${blocking.triggerSource}` : ""}${blocking.createdAt ? ` at ${fmtDate(blocking.createdAt)}` : ""}.` : "A deployment is already in progress for this project.", blocking?.id ? `Follow it with \`rebase cloud logs -f\`, or stop it with \`rebase cloud cancel ${blocking.id}\`.` : "Follow it with `rebase cloud logs -f`.", "deploy_in_progress");
3616
- }
3617
- if (err?.status === 402) fail(err.message || "Payment required before deploying.", "Attach a card once with `rebase cloud billing setup`, then deploy again.", "payment_required");
3618
- reportError(e, "Failed to trigger deployment");
3489
+ console.log(chalk.gray(" Streaming build logs (Ctrl-C to stop watching — the build keeps running):"));
3490
+ console.log("");
3491
+ await streamBuildLogs(client, deploymentId);
3619
3492
  }
3620
- /**
3621
- * Poll a deployment record and print new log output as it arrives. Returns the
3622
- * terminal status; a non-success still exits non-zero, as it always has.
3623
- *
3624
- * `quiet` follows without printing — JSON mode, where the log stream would
3625
- * corrupt the one object the caller is parsing.
3626
- */
3627
- async function streamBuildLogs(client, deploymentId, opts = {}) {
3628
- const quiet = opts.quiet === true;
3493
+ /** Poll a deployment record and print new log output as it arrives. */
3494
+ async function streamBuildLogs(client, deploymentId) {
3629
3495
  let printed = 0;
3630
3496
  const started = Date.now();
3631
3497
  for (;;) {
@@ -3635,37 +3501,26 @@ async function streamBuildLogs(client, deploymentId, opts = {}) {
3635
3501
  } catch (e) {
3636
3502
  reportError(e, "Failed to read deployment status");
3637
3503
  }
3638
- if (!dep) fail(`Deployment ${deploymentId} disappeared.`, void 0, "not_found");
3504
+ if (!dep) fail(`Deployment ${deploymentId} disappeared.`);
3639
3505
  const logs = dep.logs ?? "";
3640
- if (!quiet && logs.length > printed) process.stdout.write(logs.slice(printed));
3641
- printed = logs.length;
3506
+ if (logs.length > printed) {
3507
+ process.stdout.write(logs.slice(printed));
3508
+ printed = logs.length;
3509
+ }
3642
3510
  if (dep.status && dep.status !== "deploying") {
3643
- if (dep.status !== "success") {
3644
- if (quiet) {
3645
- printJson({ error: {
3646
- message: `Deployment ${deploymentId} ${dep.status}.`,
3647
- code: "deploy_failed",
3648
- status: null,
3649
- deploymentId,
3650
- logs
3651
- } });
3652
- process.exit(1);
3653
- }
3654
- console.log("");
3511
+ console.log("");
3512
+ if (dep.status === "success") console.log(chalk.bold.green(" ✓ Deployment succeeded"));
3513
+ else {
3655
3514
  console.log(chalk.bold.red(` ✗ Deployment ${dep.status}`));
3656
3515
  console.log("");
3657
3516
  process.exit(1);
3658
3517
  }
3659
- if (!quiet) {
3660
- console.log("");
3661
- console.log(chalk.bold.green(" ✓ Deployment succeeded"));
3662
- console.log("");
3663
- }
3664
- return dep.status;
3518
+ console.log("");
3519
+ return;
3665
3520
  }
3666
3521
  if (Date.now() - started > POLL_TIMEOUT_MS) {
3667
- if (!quiet) console.log("");
3668
- fail("Timed out waiting for the build to finish.", "The deployment may still be running — check `rebase cloud logs`.", "timeout");
3522
+ console.log("");
3523
+ fail("Timed out waiting for the build to finish.", "The deployment may still be running — check `rebase cloud logs`.");
3669
3524
  }
3670
3525
  await sleep(POLL_INTERVAL_MS);
3671
3526
  }
@@ -4378,35 +4233,9 @@ function parseEnvAssignment(operands) {
4378
4233
  value: operands[1] ?? ""
4379
4234
  };
4380
4235
  }
4381
- /**
4382
- * Prefixes whose variables are read by a BUNDLER at build time, not by the
4383
- * process at run time.
4384
- *
4385
- * These are the ones this command cannot deliver. A project's environment is
4386
- * applied at rollout — after Kaniko has already built the image — so a
4387
- * `VITE_API_URL` set here is present in the running container and absent from
4388
- * the JavaScript that was compiled minutes earlier. Nothing fails: the variable
4389
- * exists, the deploy succeeds, and the bundle carries `undefined` where the
4390
- * value should be. The bug then presents in the browser as missing
4391
- * configuration, which is several steps away from the cause.
4392
- *
4393
- * `import.meta.env` inlining is Vite's; `NEXT_PUBLIC_`/`PUBLIC_`/`REACT_APP_`
4394
- * are the same contract in Next, Astro/SvelteKit and CRA.
4395
- */
4396
- var BUILD_TIME_ENV_PREFIXES = [
4397
- "VITE_",
4398
- "NEXT_PUBLIC_",
4399
- "PUBLIC_",
4400
- "REACT_APP_"
4401
- ];
4402
- /** The prefix that makes `key` a build-time variable, or undefined. */
4403
- function buildTimeEnvPrefix(key) {
4404
- return BUILD_TIME_ENV_PREFIXES.find((prefix) => key.toUpperCase().startsWith(prefix));
4405
- }
4406
4236
  async function setEnv(rawArgs) {
4407
4237
  const args = arg({
4408
4238
  "--secret": Boolean,
4409
- "--force": Boolean,
4410
4239
  "--project": String,
4411
4240
  "-p": "--project"
4412
4241
  }, {
@@ -4418,8 +4247,6 @@ async function setEnv(rawArgs) {
4418
4247
  displayProjectRef(rawArgs);
4419
4248
  const parsed = parseEnvAssignment(cloudPositionals(rawArgs).slice(2));
4420
4249
  if (!parsed || !parsed.key) fail("Usage: rebase cloud env set KEY=VALUE [--secret]", void 0, "usage");
4421
- const buildTimePrefix = buildTimeEnvPrefix(parsed.key);
4422
- if (buildTimePrefix && !args["--force"]) fail(`${parsed.key} is read by your bundler at BUILD time, and project variables are applied at rollout — after the image is built. Setting it here would not reach the bundle.`, `Put ${buildTimePrefix}* variables in the source you deploy (a committed .env, or your build config), then \`rebase cloud deploy\`. Pass --force if your build genuinely reads this at run time.`, "build_time_variable");
4423
4250
  const body = {
4424
4251
  key: parsed.key,
4425
4252
  value: parsed.value
@@ -4576,13 +4403,10 @@ ${chalk.green.bold("Commands")}
4576
4403
 
4577
4404
  ${chalk.green.bold("Options")}
4578
4405
  ${chalk.blue("--secret")} Mark a variable write-only ${chalk.gray("(set)")}
4579
- ${chalk.blue("--force")} Set a build-time key anyway ${chalk.gray("(set)")}
4580
4406
  ${chalk.blue("--json")} Machine-readable output
4581
4407
  ${chalk.blue("--project, -p")} Project slug ${chalk.gray("(defaults to the linked project)")}
4582
4408
 
4583
4409
  ${chalk.gray("Values are encrypted at rest (AES-256-GCM) and only decrypted at deploy time.")}
4584
- ${chalk.gray("VITE_* / NEXT_PUBLIC_* / PUBLIC_* / REACT_APP_* are read by your bundler at BUILD time;")}
4585
- ${chalk.gray("these are applied at rollout, after the image is built, so they never reach the bundle.")}
4586
4410
  `);
4587
4411
  }
4588
4412
  function printEnvHelpJson() {
@@ -5178,8 +5002,6 @@ function deploymentView(dep) {
5178
5002
  isRollback: str(dep, "rollbackOf", "rollback_of") !== null,
5179
5003
  rollbackable: isRollbackable(dep),
5180
5004
  trigger: triggerInfo(dep),
5181
- message: str(dep, "deployMessage", "deploy_message"),
5182
- frameworkVersion: str(dep, "frameworkVersion", "framework_version"),
5183
5005
  commit: {
5184
5006
  hash: str(dep, "gitCommitHash", "gitCommitHash"),
5185
5007
  message: str(dep, "gitCommitMessage", "gitCommitMessage")
@@ -5193,31 +5015,12 @@ async function fetchDeployments(client, projectId, limit = 100) {
5193
5015
  limit
5194
5016
  })).data;
5195
5017
  }
5196
- /** Hard ceiling on `--limit`, matching the backend's own page size. */
5197
- var MAX_DEPLOYMENTS_LIMIT = 100;
5198
- /** `--limit N`, bounded. A garbage value is a refusal, never a silent default. */
5199
- function parseDeploymentsLimit(raw) {
5200
- if (raw === void 0) return 20;
5201
- if (!Number.isInteger(raw) || raw < 1 || raw > MAX_DEPLOYMENTS_LIMIT) fail(`--limit must be a whole number between 1 and ${MAX_DEPLOYMENTS_LIMIT}.`, void 0, "usage");
5202
- return raw;
5203
- }
5204
5018
  async function deploymentsListCommand(rawArgs) {
5205
- const args = arg({
5206
- "--limit": Number,
5207
- "--all": Boolean,
5208
- "--project": String,
5209
- "-p": "--project"
5210
- }, {
5211
- argv: rawArgs.slice(2),
5212
- permissive: true
5213
- });
5214
- const limit = args["--all"] ? MAX_DEPLOYMENTS_LIMIT : parseDeploymentsLimit(args["--limit"]);
5215
5019
  const { client } = await requireClient(rawArgs);
5216
5020
  const projectId = await requireProject(rawArgs, client);
5217
5021
  const projectRef = displayProjectRef(rawArgs);
5218
5022
  try {
5219
- const views = (await fetchDeployments(client, projectId, limit)).map(deploymentView);
5220
- const truncated = views.length === limit;
5023
+ const views = (await fetchDeployments(client, projectId)).map(deploymentView);
5221
5024
  emit(() => {
5222
5025
  console.log("");
5223
5026
  console.log(chalk.bold(` 🚀 Deployments — project ${projectRef}`));
@@ -5232,18 +5035,10 @@ async function deploymentsListCommand(rawArgs) {
5232
5035
  const trig = v.trigger.source;
5233
5036
  const roll = v.rollbackable ? chalk.green(" ↺ rollbackable") : "";
5234
5037
  console.log(` ${chalk.gray(`[${v.id}]`)} ${colorStatus(v.status)} ${chalk.gray(String(v.createdAt ?? "—"))} ${dur} ${chalk.gray(trig)}${roll}`);
5235
- const label = [v.message, v.frameworkVersion ? `@rebasepro/* ${v.frameworkVersion}` : null].filter(Boolean).join(" · ");
5236
- if (label) console.log(` ${chalk.gray(label)}`);
5237
- }
5238
- if (truncated) {
5239
- console.log("");
5240
- console.log(chalk.gray(` Showing the ${limit} most recent. Use \`--limit N\` or \`--all\` for more.`));
5241
5038
  }
5242
5039
  console.log("");
5243
5040
  }, {
5244
5041
  projectId,
5245
- limit,
5246
- truncated,
5247
5042
  deployments: views
5248
5043
  });
5249
5044
  } catch (e) {
@@ -6143,95 +5938,29 @@ ${chalk.gray("so it works in a deploy script. To restart a workload, use `rebase
6143
5938
  * `rebase cloud` resource subcommands: status, metrics, webhooks, storage,
6144
5939
  * clusters, billing.
6145
5940
  */
6146
- /**
6147
- * One line describing this project's storage — or `undefined` when the control
6148
- * plane could not be asked, which prints as a blank rather than a guess.
6149
- *
6150
- * `status` used to render the `storages` row and nothing else, so a project
6151
- * whose bucket is configured through its own `STORAGE_TYPE`/`S3_*` variables —
6152
- * the supported path, and the one `mergeStorageEnv` deliberately lets WIN over
6153
- * the row — was reported as `Storage: none` while its pod logged `Initialized
6154
- * storage backends count: 1` against a live bucket. Storage is the thing an app
6155
- * refuses to boot without, so that false negative sends someone off to
6156
- * provision a bucket they already have. The row is not the answer; the tenant's
6157
- * resolved environment is, and the control plane computes it with the same two
6158
- * functions the build log uses.
6159
- */
6160
- function describeStorageState(state) {
6161
- const verdict = state?.effective;
6162
- if (!verdict?.kind) return void 0;
6163
- const via = state?.overridden ? chalk.gray(" · from env vars") : "";
6164
- switch (verdict.kind) {
6165
- case "durable": return `${chalk.green("durable")}${verdict.summary ? ` · ${verdict.summary}` : ""}${via}`;
6166
- case "ephemeral": return `${chalk.yellow("ephemeral")} ${chalk.gray("· uploads are lost on restart")}`;
6167
- case "incomplete": return `${chalk.red("incomplete")} ${chalk.gray(`· missing ${(verdict.missing ?? []).join(", ")}`)}`;
6168
- case "unrecognized": return `${chalk.red("unrecognized")} ${chalk.gray(`· STORAGE_TYPE=${verdict.storageType ?? "?"}`)}`;
6169
- default: return;
6170
- }
6171
- }
6172
- /**
6173
- * One line describing the database.
6174
- *
6175
- * `connectionStatus` is written `"untested"` at creation and only ever changed
6176
- * by `rebase cloud db test`, so `managed (untested)` was reporting the absence
6177
- * of a manual test as though it were the database's condition — on a project
6178
- * that had just deployed against it. A never-tested database says only its
6179
- * type; the verdict appears once there is one.
6180
- */
6181
- function describeDatabaseState(db) {
6182
- if (!db) return void 0;
6183
- const type = typeof db.type === "string" ? db.type : "database";
6184
- const connection = db.connectionStatus;
6185
- if (connection === "connected" || connection === "failed") return `${type} (${colorStatus(connection)})`;
6186
- return `${type} ${chalk.gray("· not tested (`rebase cloud db test`)")}`;
6187
- }
6188
5941
  async function statusCommand(rawArgs) {
6189
5942
  const { client, url } = await requireClient(rawArgs);
6190
5943
  const projectId = await requireProject(rawArgs, client);
6191
5944
  try {
6192
5945
  const project = await client.data.collection("projects").findById(projectId);
6193
- if (!project) fail(`Project ${displayProjectRef(rawArgs)} not found.`, void 0, "not_found");
5946
+ if (!project) fail(`Project ${displayProjectRef(rawArgs)} not found.`);
6194
5947
  const [db, storage, deploy, baseDomain] = await Promise.all([
6195
5948
  firstRow(client, "databases", projectId),
6196
- client.functions.invoke("storage-provision", void 0, {
6197
- method: "GET",
6198
- path: projectId
6199
- }).catch(() => void 0),
5949
+ firstRow(client, "storages", projectId),
6200
5950
  latestDeployment(client, projectId),
6201
5951
  fetchTenantBaseDomain(client, url)
6202
5952
  ]);
6203
- const storageLine = describeStorageState(storage);
6204
- const databaseLine = describeDatabaseState(db);
6205
- emit(() => {
6206
- console.log("");
6207
- console.log(` ${chalk.bold(project.name ?? project.subdomain ?? "")} ${chalk.gray(`[${project.subdomain ?? displayProjectRef(rawArgs)}]`)} ${colorStatus(project.status)}`);
6208
- console.log("");
6209
- keyValues([
6210
- ["URL", projectHost(project, baseDomain)],
6211
- ["Branch", project.gitBranch],
6212
- ["Last deploy", deploy ? `${colorStatus(deploy.status)} · ${fmtDate(deploy.createdAt)}` : "never"],
6213
- ["Database", databaseLine],
6214
- ["Storage", storageLine]
6215
- ]);
6216
- console.log("");
6217
- }, {
6218
- projectId: String(project.id),
6219
- name: project.name ?? null,
6220
- subdomain: project.subdomain ?? null,
6221
- status: project.status ?? null,
6222
- url: projectHost(project, baseDomain) ?? null,
6223
- branch: project.gitBranch ?? null,
6224
- lastDeploy: deploy ? {
6225
- id: String(deploy.id),
6226
- status: deploy.status ?? null,
6227
- createdAt: deploy.createdAt ?? null
6228
- } : null,
6229
- database: db ? {
6230
- type: db.type ?? null,
6231
- connectionStatus: db.connectionStatus ?? null
6232
- } : null,
6233
- storage: storage ?? null
6234
- });
5953
+ console.log("");
5954
+ console.log(` ${chalk.bold(project.name ?? project.subdomain ?? "")} ${chalk.gray(`[${project.subdomain ?? displayProjectRef(rawArgs)}]`)} ${colorStatus(project.status)}`);
5955
+ console.log("");
5956
+ keyValues([
5957
+ ["URL", projectHost(project, baseDomain)],
5958
+ ["Branch", project.gitBranch],
5959
+ ["Last deploy", deploy ? `${colorStatus(deploy.status)} · ${fmtDate(deploy.createdAt)}` : "never"],
5960
+ ["Database", db ? `${db.type} (${colorStatus(db.connectionStatus)})` : "none"],
5961
+ ["Storage", storage ? `${storage.type} (${colorStatus(storage.status)})` : "none"]
5962
+ ]);
5963
+ console.log("");
6235
5964
  } catch (e) {
6236
5965
  reportError(e, "Failed to load status");
6237
5966
  }
@@ -6742,9 +6471,9 @@ ${chalk.green.bold("Projects")}
6742
6471
  ${chalk.blue.bold("projects delete")} ${chalk.gray("[id]")} Delete a project
6743
6472
 
6744
6473
  ${chalk.green.bold("Deploy & observe")}
6745
- ${chalk.blue.bold("deploy")} ${chalk.gray("[--source .] [-m msg]")} Deploy the linked project + stream build logs
6474
+ ${chalk.blue.bold("deploy")} ${chalk.gray("[--source .]")} Deploy the linked project + stream build logs
6746
6475
  ${chalk.blue.bold("logs")} ${chalk.gray("[--runtime] [-f]")} Show build (or runtime) logs
6747
- ${chalk.blue.bold("deployments list")} ${chalk.gray("[--limit N|--all]")} Deployment history ${chalk.gray("(status, duration, trigger)")}
6476
+ ${chalk.blue.bold("deployments list")} Deployment history ${chalk.gray("(status, duration, trigger)")}
6748
6477
  ${chalk.blue.bold("rollback")} ${chalk.gray("[id] [-y]")} Roll back to a successful deploy
6749
6478
  ${chalk.blue.bold("cancel")} ${chalk.gray("[-y]")} Cancel the in-flight build
6750
6479
  ${chalk.blue.bold("start|stop|restart")} ${chalk.gray("[-y]")} Power ops ${chalk.gray("(stop/restart need -y)")}
@@ -6943,6 +6672,6 @@ ${chalk.gray("Documentation: https://rebase.pro/docs")}
6943
6672
  `);
6944
6673
  }
6945
6674
  //#endregion
6946
- export { authCommand, buildCommand, buildInitQuestions, cloudCommand, configureEnvFile, createRebaseApp, dbCommand, detectPackageManager, devCommand, doctorCommand, entry, findBackendDir, findEnvFile, findFrontendDir, findProjectRoot, formatCdTarget, generateSdkCommand, getActiveBackendPlugin, getPMCommands, isPnpmAvailable, pnpmAvailabilityFromProbe, printInitHelp, requireBackendDir, requireProjectRoot, resetPnpmAvailabilityCache, resolveLocalBin, resolvePluginCliScript, resolveTsx, schemaCommand, startCommand, validateProjectName, validateTsxInstallation };
6675
+ export { authCommand, buildCommand, buildInitQuestions, cloudCommand, configureEnvFile, createRebaseApp, dbCommand, detectPackageManager, devCommand, doctorCommand, entry, findBackendDir, findEnvFile, findFrontendDir, findProjectRoot, formatCdTarget, generateSdkCommand, getActiveBackendPlugin, getPMCommands, isPnpmAvailable, printInitHelp, requireBackendDir, requireProjectRoot, resolveLocalBin, resolvePluginCliScript, resolveTsx, schemaCommand, startCommand, validateProjectName, validateTsxInstallation };
6947
6676
 
6948
6677
  //# sourceMappingURL=index.es.js.map