@scalebun/cli 2.0.5 → 2.0.6

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.
@@ -2,8 +2,13 @@ import { Command } from 'commander';
2
2
  /**
3
3
  * `scalebun ota delete-bundle` — permanent, irreversible artifact deletion.
4
4
  *
5
- * It asks first. This used to delete on sight: one mis-pasted --bundle-id and
6
- * the artifact was gone, with devices possibly still running it. `ota rollback`
5
+ * `--app-id` resolves from scalebun.json like every other command, and
6
+ * `--bundle-id` opens a picker on a TTY when omitted, so choosing "delete-bundle"
7
+ * from the interactive menu lands on a bundle list instead of erroring on a
8
+ * missing required flag.
9
+ *
10
+ * It still asks first. This used to delete on sight: one mis-pasted --bundle-id
11
+ * and the artifact was gone, with devices possibly still running it. `ota rollback`
7
12
  * already had this shape (prompt on a TTY, explicit --yes off-TTY); a command
8
13
  * whose own description says "permanently" needs it at least as much.
9
14
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ota-delete-bundle.d.ts","sourceRoot":"","sources":["../../src/commands/ota-delete-bundle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAiDjE"}
1
+ {"version":3,"file":"ota-delete-bundle.d.ts","sourceRoot":"","sources":["../../src/commands/ota-delete-bundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC;;;;;;;;;;;;GAYG;AACH,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAyFjE"}
@@ -1,47 +1,25 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
35
5
  Object.defineProperty(exports, "__esModule", { value: true });
36
6
  exports.registerOtaDeleteBundleCommand = registerOtaDeleteBundleCommand;
37
- const readline = __importStar(require("readline"));
7
+ const chalk_1 = __importDefault(require("chalk"));
38
8
  const credentials_1 = require("../utils/credentials");
39
9
  const client_1 = require("../api/client");
10
+ const resolve_1 = require("../utils/resolve");
11
+ const prompt_1 = require("../utils/prompt");
12
+ const output_1 = require("../utils/output");
40
13
  /**
41
14
  * `scalebun ota delete-bundle` — permanent, irreversible artifact deletion.
42
15
  *
43
- * It asks first. This used to delete on sight: one mis-pasted --bundle-id and
44
- * the artifact was gone, with devices possibly still running it. `ota rollback`
16
+ * `--app-id` resolves from scalebun.json like every other command, and
17
+ * `--bundle-id` opens a picker on a TTY when omitted, so choosing "delete-bundle"
18
+ * from the interactive menu lands on a bundle list instead of erroring on a
19
+ * missing required flag.
20
+ *
21
+ * It still asks first. This used to delete on sight: one mis-pasted --bundle-id
22
+ * and the artifact was gone, with devices possibly still running it. `ota rollback`
45
23
  * already had this shape (prompt on a TTY, explicit --yes off-TTY); a command
46
24
  * whose own description says "permanently" needs it at least as much.
47
25
  */
@@ -50,41 +28,68 @@ function registerOtaDeleteBundleCommand(ota) {
50
28
  .command('delete-bundle')
51
29
  .alias('delete')
52
30
  .description('Delete an OTA bundle permanently')
53
- .requiredOption('--app-id <id>', 'Scalebun app ID')
54
- .requiredOption('--bundle-id <id>', 'OTA bundle ID to delete')
31
+ .option('--app-id <id>', 'Scalebun app ID (resolved from scalebun.json when omitted)')
32
+ .option('--bundle-id <id>', 'OTA bundle ID to delete (picker on a TTY when omitted)')
55
33
  .option('--yes', 'Skip the confirmation prompt (required in CI / non-interactive shells)')
56
34
  .action(async (opts) => {
57
35
  const creds = (0, credentials_1.readCredentials)();
58
- if (!creds) {
59
- console.error('Not logged in. Run `scalebun login` first.');
60
- process.exit(1);
36
+ if (!creds)
37
+ (0, output_1.fail)('Not logged in. Run `scalebun login` first.', [], output_1.ExitCode.Usage);
38
+ const appId = await (0, resolve_1.resolveAppId)({ appId: opts.appId });
39
+ const client = new client_1.ApiClient(creds);
40
+ // Resolve the bundle: an explicit --bundle-id, or a picker on a TTY.
41
+ let bundleId = opts.bundleId;
42
+ let picked;
43
+ if (!bundleId) {
44
+ if (!process.stdin.isTTY) {
45
+ (0, output_1.fail)('--bundle-id is required.', [
46
+ 'Find one with `scalebun ota bundles`.',
47
+ 'This shell is not interactive, so the bundle cannot be chosen here.',
48
+ ], output_1.ExitCode.Usage);
49
+ }
50
+ let rows;
51
+ try {
52
+ const res = await client.get(`/saas/apps/${appId}/ota/bundles?sort=newest`);
53
+ rows = Array.isArray(res) ? res : (res?.rows ?? []);
54
+ }
55
+ catch (err) {
56
+ (0, output_1.failFromError)('Could not list bundles', err);
57
+ }
58
+ if (!rows.length) {
59
+ (0, output_1.fail)('No bundles on this app.', ['Nothing to delete.'], output_1.ExitCode.Usage);
60
+ }
61
+ picked = await (0, prompt_1.select)('Which bundle should be deleted permanently?', rows.slice(0, 15).map((b) => ({
62
+ label: `${b.version != null ? `v${b.version}` : b.id.slice(0, 8)} ` +
63
+ chalk_1.default.dim(`${b.platform ?? '?'} · ${b.channel?.name ?? 'default'} · ${b.signature ? 'signed' : 'unsigned'}`),
64
+ value: b,
65
+ })));
66
+ (0, prompt_1.closePrompts)();
67
+ bundleId = picked.id;
61
68
  }
69
+ const label = picked?.version != null ? `v${picked.version}` : bundleId.slice(0, 8);
70
+ // Confirmation. --yes skips it; a non-interactive shell without --yes is a
71
+ // hard stop rather than a silent destructive delete.
62
72
  if (!opts.yes) {
63
73
  if (!process.stdin.isTTY) {
64
- console.error('Refusing to delete without confirmation in a non-interactive shell.\n' +
65
- ' Re-run with --yes if this is intentional.');
66
- process.exit(1);
74
+ (0, output_1.fail)('Refusing to delete without confirmation in a non-interactive shell.', ['Re-run with --yes if this is intentional.'], output_1.ExitCode.Usage);
67
75
  }
68
- console.log(`\n⚠️ This permanently deletes bundle ${opts.bundleId} from app ${opts.appId}.\n` +
76
+ console.log(`\n⚠️ This permanently deletes bundle ${label} (${bundleId}) from app ${appId}.\n` +
69
77
  ' Devices still running it keep their local copy, but it can never be\n' +
70
78
  ' re-served, and any release pointing at it becomes undeliverable.\n');
71
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
72
- const answer = await new Promise((resolve) => rl.question(' Type the bundle id to confirm: ', resolve));
73
- rl.close();
74
- if (answer.trim() !== opts.bundleId) {
79
+ const ok = await (0, prompt_1.confirmPhrase)('Type the bundle id to confirm:', bundleId);
80
+ (0, prompt_1.closePrompts)();
81
+ if (!ok) {
75
82
  console.log('Aborted — nothing was deleted.');
76
83
  return;
77
84
  }
78
85
  }
79
- const client = new client_1.ApiClient(creds);
80
86
  try {
81
- console.log(`🗑️ Deleting bundle ${opts.bundleId} from App ${opts.appId}…`);
82
- await client.delete(`/saas/apps/${opts.appId}/ota/bundles/${opts.bundleId}`);
83
- console.log(`✅ Bundle ${opts.bundleId} deleted successfully.`);
87
+ console.log(`🗑️ Deleting bundle ${label} from app ${appId}…`);
88
+ await client.delete(`/saas/apps/${appId}/ota/bundles/${bundleId}`);
89
+ console.log(`✅ Bundle ${label} deleted successfully.`);
84
90
  }
85
91
  catch (err) {
86
- console.error(`❌ Failed to delete bundle: ${err.message}`);
87
- process.exit(1);
92
+ (0, output_1.failFromError)('Failed to delete bundle', err);
88
93
  }
89
94
  });
90
95
  }
@@ -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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scalebun/cli",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "description": "Scalebun CLI — OTA bundle publishing and management",
5
5
  "license": "MIT",
6
6
  "bin": {