@scalebun/cli 1.10.2 → 1.12.0

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.
Files changed (98) hide show
  1. package/lib/commands/ci-init.d.ts.map +1 -1
  2. package/lib/commands/ci-init.js +80 -2
  3. package/lib/commands/ci-init.js.map +1 -1
  4. package/lib/commands/doctor.d.ts.map +1 -1
  5. package/lib/commands/doctor.js +148 -3
  6. package/lib/commands/doctor.js.map +1 -1
  7. package/lib/commands/link.d.ts +16 -0
  8. package/lib/commands/link.d.ts.map +1 -0
  9. package/lib/commands/link.js +164 -0
  10. package/lib/commands/link.js.map +1 -0
  11. package/lib/commands/login.d.ts.map +1 -1
  12. package/lib/commands/login.js +29 -7
  13. package/lib/commands/login.js.map +1 -1
  14. package/lib/commands/ota-bundle.d.ts +15 -2
  15. package/lib/commands/ota-bundle.d.ts.map +1 -1
  16. package/lib/commands/ota-bundle.js +142 -12
  17. package/lib/commands/ota-bundle.js.map +1 -1
  18. package/lib/commands/ota-channels.d.ts.map +1 -1
  19. package/lib/commands/ota-channels.js +213 -21
  20. package/lib/commands/ota-channels.js.map +1 -1
  21. package/lib/commands/ota-delete-bundle.d.ts.map +1 -1
  22. package/lib/commands/ota-delete-bundle.js +15 -4
  23. package/lib/commands/ota-delete-bundle.js.map +1 -1
  24. package/lib/commands/ota-inspect.d.ts +3 -0
  25. package/lib/commands/ota-inspect.d.ts.map +1 -0
  26. package/lib/commands/ota-inspect.js +258 -0
  27. package/lib/commands/ota-inspect.js.map +1 -0
  28. package/lib/commands/ota-keys.d.ts +25 -0
  29. package/lib/commands/ota-keys.d.ts.map +1 -1
  30. package/lib/commands/ota-keys.js +329 -27
  31. package/lib/commands/ota-keys.js.map +1 -1
  32. package/lib/commands/ota-promote.d.ts +3 -0
  33. package/lib/commands/ota-promote.d.ts.map +1 -0
  34. package/lib/commands/ota-promote.js +194 -0
  35. package/lib/commands/ota-promote.js.map +1 -0
  36. package/lib/commands/ota-publish.d.ts.map +1 -1
  37. package/lib/commands/ota-publish.js +108 -38
  38. package/lib/commands/ota-publish.js.map +1 -1
  39. package/lib/commands/ota-rollout.d.ts.map +1 -1
  40. package/lib/commands/ota-rollout.js +212 -171
  41. package/lib/commands/ota-rollout.js.map +1 -1
  42. package/lib/commands/quickstart.d.ts.map +1 -1
  43. package/lib/commands/quickstart.js +110 -8
  44. package/lib/commands/quickstart.js.map +1 -1
  45. package/lib/commands/shell.d.ts +28 -0
  46. package/lib/commands/shell.d.ts.map +1 -0
  47. package/lib/commands/shell.js +512 -0
  48. package/lib/commands/shell.js.map +1 -0
  49. package/lib/index.js +140 -4
  50. package/lib/index.js.map +1 -1
  51. package/lib/ui/menu.d.ts +109 -0
  52. package/lib/ui/menu.d.ts.map +1 -0
  53. package/lib/ui/menu.js +314 -0
  54. package/lib/ui/menu.js.map +1 -0
  55. package/lib/utils/bundle.d.ts.map +1 -1
  56. package/lib/utils/bundle.js +7 -1
  57. package/lib/utils/bundle.js.map +1 -1
  58. package/lib/utils/context.d.ts +88 -0
  59. package/lib/utils/context.d.ts.map +1 -0
  60. package/lib/utils/context.js +247 -0
  61. package/lib/utils/context.js.map +1 -0
  62. package/lib/utils/credentials.d.ts +16 -0
  63. package/lib/utils/credentials.d.ts.map +1 -1
  64. package/lib/utils/credentials.js +14 -3
  65. package/lib/utils/credentials.js.map +1 -1
  66. package/lib/utils/guide.d.ts +63 -0
  67. package/lib/utils/guide.d.ts.map +1 -0
  68. package/lib/utils/guide.js +189 -0
  69. package/lib/utils/guide.js.map +1 -0
  70. package/lib/utils/output.d.ts +96 -0
  71. package/lib/utils/output.d.ts.map +1 -0
  72. package/lib/utils/output.js +135 -0
  73. package/lib/utils/output.js.map +1 -0
  74. package/lib/utils/prompt.d.ts +109 -6
  75. package/lib/utils/prompt.d.ts.map +1 -1
  76. package/lib/utils/prompt.js +222 -20
  77. package/lib/utils/prompt.js.map +1 -1
  78. package/lib/utils/provenance.d.ts +30 -0
  79. package/lib/utils/provenance.d.ts.map +1 -0
  80. package/lib/utils/provenance.js +157 -0
  81. package/lib/utils/provenance.js.map +1 -0
  82. package/lib/utils/resolve.d.ts +81 -0
  83. package/lib/utils/resolve.d.ts.map +1 -0
  84. package/lib/utils/resolve.js +139 -0
  85. package/lib/utils/resolve.js.map +1 -0
  86. package/lib/utils/sdkBin.d.ts +18 -0
  87. package/lib/utils/sdkBin.d.ts.map +1 -0
  88. package/lib/utils/sdkBin.js +76 -0
  89. package/lib/utils/sdkBin.js.map +1 -0
  90. package/lib/utils/ui.d.ts +10 -1
  91. package/lib/utils/ui.d.ts.map +1 -1
  92. package/lib/utils/ui.js +18 -57
  93. package/lib/utils/ui.js.map +1 -1
  94. package/lib/utils/validate.d.ts +62 -0
  95. package/lib/utils/validate.d.ts.map +1 -0
  96. package/lib/utils/validate.js +189 -0
  97. package/lib/utils/validate.js.map +1 -0
  98. package/package.json +3 -2
@@ -32,11 +32,17 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
35
38
  Object.defineProperty(exports, "__esModule", { value: true });
36
39
  exports.registerOtaDeleteBundleCommand = registerOtaDeleteBundleCommand;
37
40
  const readline = __importStar(require("readline"));
38
41
  const credentials_1 = require("../utils/credentials");
39
42
  const client_1 = require("../api/client");
43
+ const resolve_1 = require("../utils/resolve");
44
+ const output_1 = require("../utils/output");
45
+ const chalk_1 = __importDefault(require("chalk"));
40
46
  /**
41
47
  * `scalebun ota delete-bundle` — permanent, irreversible artifact deletion.
42
48
  *
@@ -50,10 +56,11 @@ function registerOtaDeleteBundleCommand(ota) {
50
56
  .command('delete-bundle')
51
57
  .alias('delete')
52
58
  .description('Delete an OTA bundle permanently')
53
- .requiredOption('--app-id <id>', 'Scalebun app ID')
59
+ .option('--app-id <id>', 'Scalebun app ID (resolved from scalebun.json when omitted)')
54
60
  .requiredOption('--bundle-id <id>', 'OTA bundle ID to delete')
55
61
  .option('--yes', 'Skip the confirmation prompt (required in CI / non-interactive shells)')
56
62
  .action(async (opts) => {
63
+ const appId = await (0, resolve_1.resolveAppId)({ appId: opts.appId });
57
64
  const creds = (0, credentials_1.readCredentials)();
58
65
  if (!creds) {
59
66
  console.error('❌ Not logged in. Run `scalebun login` first.');
@@ -65,7 +72,7 @@ function registerOtaDeleteBundleCommand(ota) {
65
72
  ' Re-run with --yes if this is intentional.');
66
73
  process.exit(1);
67
74
  }
68
- console.log(`\n⚠️ This permanently deletes bundle ${opts.bundleId} from app ${opts.appId}.\n` +
75
+ console.log(`\n⚠️ This permanently deletes bundle ${opts.bundleId} from app ${appId}.\n` +
69
76
  ' Devices still running it keep their local copy, but it can never be\n' +
70
77
  ' re-served, and any release pointing at it becomes undeliverable.\n');
71
78
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -78,9 +85,13 @@ function registerOtaDeleteBundleCommand(ota) {
78
85
  }
79
86
  const client = new client_1.ApiClient(creds);
80
87
  try {
81
- console.log(`🗑️ Deleting bundle ${opts.bundleId} from App ${opts.appId}…`);
82
- await client.delete(`/saas/apps/${opts.appId}/ota/bundles/${opts.bundleId}`);
88
+ console.log(`🗑️ Deleting bundle ${opts.bundleId} from App ${appId}…`);
89
+ await client.delete(`/saas/apps/${appId}/ota/bundles/${opts.bundleId}`);
83
90
  console.log(`✅ Bundle ${opts.bundleId} deleted successfully.`);
91
+ (0, output_1.printNextSteps)([
92
+ { label: 'Check nothing points at it', argv: ['ota', 'releases'] },
93
+ { label: 'List what remains', argv: ['ota', 'bundles'] },
94
+ ], chalk_1.default.cyan);
84
95
  }
85
96
  catch (err) {
86
97
  console.error(`❌ Failed to delete bundle: ${err.message}`);
@@ -1 +1 @@
1
- {"version":3,"file":"ota-delete-bundle.js","sourceRoot":"","sources":["../../src/commands/ota-delete-bundle.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,wEAiDC;AA9DD,mDAAqC;AAErC,sDAAuD;AACvD,0CAA0C;AAE1C;;;;;;;GAOG;AACH,SAAgB,8BAA8B,CAAC,GAAY;IACzD,GAAG;SACA,OAAO,CAAC,eAAe,CAAC;SACxB,KAAK,CAAC,QAAQ,CAAC;SACf,WAAW,CAAC,kCAAkC,CAAC;SAC/C,cAAc,CAAC,eAAe,EAAE,iBAAiB,CAAC;SAClD,cAAc,CAAC,kBAAkB,EAAE,yBAAyB,CAAC;SAC7D,MAAM,CAAC,OAAO,EAAE,wEAAwE,CAAC;SACzF,MAAM,CAAC,KAAK,EAAE,IAAwD,EAAE,EAAE;QACzE,MAAM,KAAK,GAAG,IAAA,6BAAe,GAAE,CAAC;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBACzB,OAAO,CAAC,KAAK,CACX,yEAAyE;oBACvE,8CAA8C,CACjD,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,OAAO,CAAC,GAAG,CACT,yCAAyC,IAAI,CAAC,QAAQ,aAAa,IAAI,CAAC,KAAK,KAAK;gBAChF,0EAA0E;gBAC1E,uEAAuE,CAC1E,CAAC;YACF,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YACtF,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE,CACnD,EAAE,CAAC,QAAQ,CAAC,oCAAoC,EAAE,OAAO,CAAC,CAC3D,CAAC;YACF,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACpC,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;gBAC9C,OAAO;YACT,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,CAAC,QAAQ,aAAa,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;YAC5E,MAAM,MAAM,CAAC,MAAM,CAAM,cAAc,IAAI,CAAC,KAAK,gBAAgB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAClF,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,QAAQ,wBAAwB,CAAC,CAAC;QACjE,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,8BAA8B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
1
+ {"version":3,"file":"ota-delete-bundle.js","sourceRoot":"","sources":["../../src/commands/ota-delete-bundle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerOtaInspectCommands(ota: Command): void;
3
+ //# sourceMappingURL=ota-inspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ota-inspect.d.ts","sourceRoot":"","sources":["../../src/commands/ota-inspect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6GpC,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAkN7D"}
@@ -0,0 +1,258 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerOtaInspectCommands = registerOtaInspectCommands;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const client_1 = require("../api/client");
9
+ const validate_1 = require("../utils/validate");
10
+ const output_1 = require("../utils/output");
11
+ /** Kept beside the flags that accept them so the help text cannot drift. */
12
+ const PLATFORMS = ['android', 'ios'];
13
+ const BUNDLE_SORTS = ['newest', 'oldest', 'version', 'largest'];
14
+ const credentials_1 = require("../utils/credentials");
15
+ const resolve_1 = require("../utils/resolve");
16
+ const context_1 = require("../utils/context");
17
+ const output_2 = require("../utils/output");
18
+ /** Decimal MB, defined once. The dashboard reported MiB on one tab and MB on
19
+ * another, both labelled "MB", so the same bundle showed two sizes. */
20
+ function mb(bytes) {
21
+ if (typeof bytes !== 'number')
22
+ return '—';
23
+ return `${(bytes / 1000000).toFixed(2)} MB`;
24
+ }
25
+ function age(iso) {
26
+ if (!iso)
27
+ return '—';
28
+ const ms = Date.now() - new Date(iso).getTime();
29
+ if (!Number.isFinite(ms) || ms < 0)
30
+ return '—';
31
+ const h = ms / 3600000;
32
+ if (h < 1)
33
+ return `${Math.max(1, Math.round(ms / 60000))}m`;
34
+ if (h < 48)
35
+ return `${Math.round(h)}h`;
36
+ return `${Math.round(h / 24)}d`;
37
+ }
38
+ /**
39
+ * One vocabulary for a rate, used everywhere.
40
+ *
41
+ * The dashboard rendered this five different ways — "no data", "not measured",
42
+ * "too early", a green "0.00% ✓" and a flat "0%". Two of those manufactured a
43
+ * passing grade out of zero installs. Three states only: a number, "collecting"
44
+ * below the floor, or a named reason.
45
+ */
46
+ const RATE_FLOOR = 25;
47
+ function rate(installs = 0, rollbacks = 0) {
48
+ if (installs === 0)
49
+ return chalk_1.default.dim('no installs');
50
+ if (installs < RATE_FLOOR)
51
+ return chalk_1.default.dim(`collecting · ${installs}/${RATE_FLOOR}`);
52
+ const pct = (rollbacks / installs) * 100;
53
+ const s = `${pct.toFixed(1)}%`;
54
+ return pct >= 5 ? chalk_1.default.red(s) : pct >= 2 ? chalk_1.default.yellow(s) : chalk_1.default.green(s);
55
+ }
56
+ function statusLabel(s) {
57
+ switch (s) {
58
+ case 'ACTIVE': return chalk_1.default.cyan('live');
59
+ case 'PAUSED': return chalk_1.default.yellow('paused');
60
+ case 'ROLLED_BACK': return chalk_1.default.red('rolled back');
61
+ // Superseded is the NORMAL end of every release, so it is never coloured
62
+ // like a failure. Painting it red made 7 of 8 rows look like disasters.
63
+ case 'SUPERSEDED': return chalk_1.default.dim('superseded');
64
+ default: return chalk_1.default.dim(s.toLowerCase());
65
+ }
66
+ }
67
+ function registerOtaInspectCommands(ota) {
68
+ // ── ota bundles ───────────────────────────────────────────────────────────
69
+ ota
70
+ .command('bundles')
71
+ .alias('bundle-list')
72
+ .description('List uploaded bundles — the only way to learn a --bundle-id')
73
+ .option('--app-id <id>', 'Scalebun app ID (resolved from scalebun.json when omitted)')
74
+ .option('--platform <p>', 'ios | android')
75
+ .option('--signed <v>', 'signed | unsigned')
76
+ .option('--search <q>', 'Match version, hash or note')
77
+ .option('--sort <s>', 'newest | oldest | version | largest', 'newest')
78
+ .option('--limit <n>', 'How many to show', '20')
79
+ .option('--latest', 'Print only the newest bundle id, for scripting')
80
+ .option('--json', 'Machine-readable output')
81
+ .action(async (opts) => {
82
+ const creds = (0, credentials_1.readCredentials)();
83
+ if (!creds)
84
+ (0, output_2.fail)('Not signed in.', ['Run `scalebun login`.'], output_2.ExitCode.Usage);
85
+ const appId = await (0, resolve_1.resolveAppId)({ appId: opts.appId, nonInteractive: opts.json });
86
+ // Everything is checked BEFORE the round trip: a typo should cost a
87
+ // second, not a request. (--limit was validated after the fetch, so junk
88
+ // still paid for the network.)
89
+ const limit = (0, validate_1.checkedInt)('--limit', opts.limit, { min: 1, max: 1000, fallback: 20 });
90
+ // Every one of these was forwarded to the API verbatim. A typo did not
91
+ // fail — it produced a filtered list that looked authoritative, which is
92
+ // the worst outcome for a command whose whole job is telling you what
93
+ // exists.
94
+ const qs = new URLSearchParams();
95
+ if (opts.platform)
96
+ qs.set('platform', (0, validate_1.checkedEnum)('--platform', opts.platform, PLATFORMS, { caseInsensitive: true }));
97
+ if (opts.signed)
98
+ qs.set('signed', (0, validate_1.checkedEnum)('--signed', opts.signed, ['signed', 'unsigned'], { caseInsensitive: true }));
99
+ if (opts.search)
100
+ qs.set('search', opts.search);
101
+ if (opts.sort)
102
+ qs.set('sort', (0, validate_1.checkedEnum)('--sort', opts.sort, BUNDLE_SORTS, { caseInsensitive: true }));
103
+ let rows;
104
+ try {
105
+ const res = await new client_1.ApiClient(creds).get(`/saas/apps/${appId}/ota/bundles${qs.toString() ? `?${qs}` : ''}`);
106
+ // The endpoint returns a plain array without `page` and an envelope
107
+ // with it — accept both rather than pinning one shape.
108
+ rows = Array.isArray(res) ? res : (res?.rows ?? []);
109
+ }
110
+ catch (err) {
111
+ (0, output_2.failFromError)('Could not list bundles', err);
112
+ }
113
+ const shown = rows.slice(0, limit);
114
+ // --latest exists so a pipeline can do the thing that was impossible:
115
+ // BUNDLE=$(scalebun ota bundles --latest)
116
+ if (opts.latest) {
117
+ const newest = shown[0];
118
+ if (!newest)
119
+ (0, output_2.fail)('No bundles on this app.', [], output_2.ExitCode.Usage);
120
+ (0, output_2.emit)(() => console.log(newest.id), { ok: true, bundleId: newest.id, version: newest.version ?? null });
121
+ return;
122
+ }
123
+ (0, output_2.emit)(() => {
124
+ if (!shown.length) {
125
+ console.log('\nNo bundles match.');
126
+ // The early return skipped the block at the end of this function,
127
+ // so the empty state — the one place a next step is worth most,
128
+ // because there is nothing on screen to act on — offered nothing.
129
+ (0, output_1.printNextSteps)([{ label: 'Build and ship one', argv: ['ota', 'publish'] }], chalk_1.default.cyan);
130
+ return;
131
+ }
132
+ console.log('');
133
+ for (const b of shown) {
134
+ const v = b.version != null ? `v${b.version}` : b.id.slice(0, 8);
135
+ const sig = b.signature ? chalk_1.default.green('signed') : chalk_1.default.yellow('unsigned');
136
+ console.log(` ${chalk_1.default.bold(v.padEnd(6))} ${chalk_1.default.dim((b.platform ?? '?').padEnd(8))} ` +
137
+ `${mb(b.sizeBytes).padStart(9)} ${sig.padEnd(18)} ${chalk_1.default.dim(age(b.createdAt).padStart(4))} ${chalk_1.default.dim(b.id)}`);
138
+ }
139
+ if (rows.length > shown.length) {
140
+ console.log(chalk_1.default.dim(`\n ${rows.length - shown.length} more — raise --limit to see them.`));
141
+ }
142
+ console.log('');
143
+ // This list exists to find something to promote — its own help text
144
+ // calls it "the only way to learn a --bundle-id". The empty case
145
+ // returned above, so there is nothing to branch on here.
146
+ (0, output_1.printNextSteps)([
147
+ { label: 'Make one live', argv: ['ota', 'promote'] },
148
+ { label: 'See what is live', argv: ['ota', 'status'] },
149
+ ], chalk_1.default.cyan);
150
+ }, { ok: true, count: shown.length, total: rows.length, bundles: shown });
151
+ });
152
+ // ── ota status ────────────────────────────────────────────────────────────
153
+ ota
154
+ .command('status')
155
+ .description('What is live, and what needs a decision')
156
+ .option('--app-id <id>', 'Scalebun app ID (resolved from scalebun.json when omitted)')
157
+ .option('--fail-on <level>', 'Exit 3 when an item at this level exists: act | read')
158
+ .option('--json', 'Machine-readable output')
159
+ .action(async (opts) => {
160
+ // Checked here rather than where it is used, at the bottom of the action:
161
+ // a typo used to disable the gate silently — `--fail-on acts` matched no
162
+ // branch, the command exited 0, and the pipeline went green having
163
+ // checked nothing. A gate that a typo can switch off is not a gate. And
164
+ // validating up here means the whole report is not printed before the
165
+ // usage error that invalidates it.
166
+ const failOn = opts.failOn
167
+ ? (0, validate_1.checkedEnum)('--fail-on', opts.failOn, ['act', 'read'], { caseInsensitive: true })
168
+ : undefined;
169
+ const creds = (0, credentials_1.readCredentials)();
170
+ if (!creds)
171
+ (0, output_2.fail)('Not signed in.', ['Run `scalebun login`.'], output_2.ExitCode.Usage);
172
+ const appId = await (0, resolve_1.resolveAppId)({ appId: opts.appId, nonInteractive: opts.json });
173
+ const client = new client_1.ApiClient(creds);
174
+ // Composed from endpoints that already exist. Attention evaluates guards
175
+ // DRY, so asking for status can never pause a live release.
176
+ const [releases, attention] = await Promise.all([
177
+ client.get(`/saas/apps/${appId}/ota/releases`).catch(() => []),
178
+ client.get(`/saas/apps/${appId}/ota/attention`).catch(() => null),
179
+ ]);
180
+ // Any command that fetched releases refreshes the cache the splash reads.
181
+ if (Array.isArray(releases))
182
+ (0, context_1.cacheReleaseCount)(releases.length, process.cwd());
183
+ const live = (releases ?? []).filter((r) => r.status === 'ACTIVE');
184
+ const items = attention?.items ?? [];
185
+ const actItems = items.filter((i) => i.severity === 'act');
186
+ (0, output_2.emit)(() => {
187
+ console.log('');
188
+ if (!live.length) {
189
+ console.log(chalk_1.default.dim(' Nothing is live on this app.'));
190
+ }
191
+ for (const r of live) {
192
+ const v = r.bundle?.version != null ? `v${r.bundle.version}` : r.id.slice(0, 8);
193
+ const s = r.stats ?? {};
194
+ console.log(` ${chalk_1.default.bold(v)} ${statusLabel(r.status)} ${chalk_1.default.dim('@')} ${chalk_1.default.bold(`${r.rolloutPercent ?? 0}%`)}` +
195
+ chalk_1.default.dim(` ${r.bundle?.platform ?? ''} · ${r.bundle?.channel?.name ?? 'default'} · ${age(r.createdAt)} old`));
196
+ console.log(chalk_1.default.dim(` installs `) + String(s.installs ?? 0).padEnd(8) +
197
+ chalk_1.default.dim('rollback rate ') + rate(s.installs, s.rollbacks));
198
+ }
199
+ console.log('');
200
+ if (!attention) {
201
+ console.log(chalk_1.default.yellow(' Could not evaluate what needs a decision.'));
202
+ }
203
+ else {
204
+ const g = attention.guards;
205
+ if (g) {
206
+ // NEVER collapse an unevaluated guard into "0 breaching" — an app
207
+ // that was not measured has not been found clean.
208
+ const breach = g.evaluated
209
+ ? `${g.breaching ?? 0} breaching`
210
+ : chalk_1.default.dim(`not evaluated${g.reason ? ` (${g.reason})` : ''}`);
211
+ console.log(chalk_1.default.dim(` guards ${g.armed} armed · ${breach}`));
212
+ }
213
+ if (!items.length) {
214
+ console.log(chalk_1.default.green(' Nothing needs a decision.'));
215
+ }
216
+ else {
217
+ for (const i of items) {
218
+ const tag = i.severity === 'act' ? chalk_1.default.yellow('act ') : chalk_1.default.dim('read');
219
+ console.log(` ${tag} ${i.title}`);
220
+ if (i.facts?.length)
221
+ console.log(chalk_1.default.dim(` ${i.facts.join(' · ')}`));
222
+ }
223
+ }
224
+ }
225
+ // Offer the levers that match the state. With a release live these
226
+ // are the three things you can do about it; with nothing live the
227
+ // only honest suggestion is to ship something.
228
+ (0, output_1.printNextSteps)(live.length
229
+ ? [
230
+ { label: 'Change the share', argv: ['ota', 'rollout', '--percent', '100'] },
231
+ { label: 'Stop new deliveries', argv: ['ota', 'pause'] },
232
+ { label: 'Revert every device', argv: ['ota', 'rollback'] },
233
+ ]
234
+ : [{ label: 'Ship an update', argv: ['ota', 'publish'] }], chalk_1.default.cyan);
235
+ }, {
236
+ ok: true,
237
+ live: live.map((r) => ({
238
+ id: r.id, version: r.bundle?.version ?? null,
239
+ rolloutPercent: r.rolloutPercent ?? 0, stats: r.stats ?? {},
240
+ })),
241
+ guards: attention?.guards ?? null,
242
+ attention: items,
243
+ });
244
+ // --fail-on turns status into a CI gate. Exit 3 is "a check you asked for
245
+ // said no" — distinct from a 4xx (2) and from the API being down (4).
246
+ if (failOn === 'act' && actItems.length) {
247
+ if (!(0, output_2.isJson)())
248
+ console.error(chalk_1.default.yellow(` ${actItems.length} decision(s) waiting.`));
249
+ process.exit(output_2.ExitCode.Gate);
250
+ }
251
+ if (failOn === 'read' && items.length) {
252
+ if (!(0, output_2.isJson)())
253
+ console.error(chalk_1.default.yellow(` ${items.length} item(s) to review.`));
254
+ process.exit(output_2.ExitCode.Gate);
255
+ }
256
+ });
257
+ }
258
+ //# sourceMappingURL=ota-inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ota-inspect.js","sourceRoot":"","sources":["../../src/commands/ota-inspect.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,32 @@
1
1
  import { Command } from 'commander';
2
2
  import * as crypto from 'crypto';
3
+ /**
4
+ * Keep the private key out of version control WITHOUT relying on the operator
5
+ * reading a warning. The previous behaviour printed "NEVER commit this — add
6
+ * .scalebun/ to .gitignore" and stopped; anyone who scrolled past that line
7
+ * committed their signing key, and a signing key in git history is compromised
8
+ * even after the file is deleted.
9
+ *
10
+ * Rules, in order of caution:
11
+ * - Only the key's directory relative to cwd can be ignored by cwd's
12
+ * .gitignore; if --out points outside the project, we cannot help — report
13
+ * the manual step instead of writing a useless entry.
14
+ * - An existing .gitignore is appended to, never rewritten.
15
+ * - A missing .gitignore is created only when cwd is actually a git repo
16
+ * (a `.git` entry exists) — creating one in a non-repo would be litter.
17
+ *
18
+ * @returns a human-readable sentence describing what happened, for the summary.
19
+ */
20
+ export declare function ensureKeyDirGitignored(outDir: string, cwd?: string): string;
3
21
  /** Hex-encoded raw 32-byte ed25519 public key from a Node KeyObject. */
4
22
  export declare function rawPublicKeyHex(publicKey: crypto.KeyObject): string;
23
+ /**
24
+ * The public half of the local signing key, if one exists — so `register-key`
25
+ * can offer the right value as the default instead of asking the developer to
26
+ * paste a 64-char hex string. Reads the private key at `./.scalebun/…pem` and
27
+ * derives the public key from it; returns null when there is no local key.
28
+ */
29
+ export declare function localPublicKeyHex(keyDir?: string): string | null;
5
30
  export declare function registerOtaKeysCommand(ota: Command): void;
6
31
  /**
7
32
  * Sign a bundle hash with the locally-held private key.
@@ -1 +1 @@
1
- {"version":3,"file":"ota-keys.d.ts","sourceRoot":"","sources":["../../src/commands/ota-keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AA+BjC,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,GAAG,MAAM,CAInE;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CA0JzD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,GAAG,IAAI,CAcf"}
1
+ {"version":3,"file":"ota-keys.d.ts","sourceRoot":"","sources":["../../src/commands/ota-keys.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AA4BjC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,CA8B1F;AAUD,wEAAwE;AACxE,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,GAAG,MAAM,CAInE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,MAAgB,GAAG,MAAM,GAAG,IAAI,CASzE;AA2BD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CA6ZzD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,GAAG,IAAI,CAcf"}