@amaster.ai/runtime-cli 1.1.7 → 1.1.8

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
@@ -2,20 +2,14 @@
2
2
  import { existsSync, rmSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
3
3
  import { join, resolve } from 'path';
4
4
  import { homedir } from 'os';
5
- import { Command } from 'commander';
5
+ import { Command, Option } from 'commander';
6
6
  import chalk7 from 'chalk';
7
7
  import { createClient } from '@amaster.ai/client';
8
- import ora2 from 'ora';
8
+ import ora from 'ora';
9
9
  import yaml from 'yaml';
10
10
 
11
11
  var __defProp = Object.defineProperty;
12
12
  var __getOwnPropNames = Object.getOwnPropertyNames;
13
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
14
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
15
- }) : x)(function(x) {
16
- if (typeof require !== "undefined") return require.apply(this, arguments);
17
- throw Error('Dynamic require of "' + x + '" is not supported');
18
- });
19
13
  var __esm = (fn, res) => function __init() {
20
14
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
21
15
  };
@@ -55,8 +49,7 @@ function getConfig() {
55
49
  }
56
50
  function saveConfig(config) {
57
51
  if (!existsSync(AMASTER_CONFIG_DIR)) {
58
- const fs = __require("fs");
59
- fs.mkdirSync(AMASTER_CONFIG_DIR, { recursive: true });
52
+ mkdirSync(AMASTER_CONFIG_DIR, { recursive: true });
60
53
  }
61
54
  writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
62
55
  }
@@ -124,8 +117,7 @@ function getAuthSession(appCode) {
124
117
  }
125
118
  function saveAuthSession(appCode, session) {
126
119
  if (!existsSync(AMASTER_CONFIG_DIR)) {
127
- const fs = __require("fs");
128
- fs.mkdirSync(AMASTER_CONFIG_DIR, { recursive: true });
120
+ mkdirSync(AMASTER_CONFIG_DIR, { recursive: true });
129
121
  }
130
122
  const authFile = join(AMASTER_CONFIG_DIR, `auth-${appCode}.json`);
131
123
  writeFileSync(authFile, JSON.stringify(session, null, 2), { mode: 384 });
@@ -172,8 +164,163 @@ init_config();
172
164
 
173
165
  // src/commands/auth.ts
174
166
  init_config();
167
+ var OUTPUT_FORMATS = ["json", "pretty", "table", "ndjson", "csv"];
168
+ function createFormatOption(description = "Output format") {
169
+ return new Option(
170
+ "--format <format>",
171
+ `${description}: ${OUTPUT_FORMATS.join(", ")}`
172
+ ).choices([...OUTPUT_FORMATS]).default("json");
173
+ }
174
+ function resolveOutputFormat(format) {
175
+ if (!format) {
176
+ return "json";
177
+ }
178
+ if (OUTPUT_FORMATS.includes(format)) {
179
+ return format;
180
+ }
181
+ throw new Error(`Unsupported output format: ${format}`);
182
+ }
183
+ function isPrettyOutput(format) {
184
+ return resolveOutputFormat(format) === "pretty";
185
+ }
186
+ function createSpinner(text, format) {
187
+ return ora({
188
+ text,
189
+ isSilent: !isPrettyOutput(format)
190
+ }).start();
191
+ }
192
+ function renderOutput(data, options = {}) {
193
+ const format = resolveOutputFormat(options.format);
194
+ switch (format) {
195
+ case "pretty":
196
+ if (options.pretty) {
197
+ options.pretty();
198
+ return;
199
+ }
200
+ renderPrettyFallback(data);
201
+ return;
202
+ case "json":
203
+ console.log(JSON.stringify(data ?? null, null, 2));
204
+ return;
205
+ case "ndjson":
206
+ renderNdjson(options.ndjsonItems ?? data);
207
+ return;
208
+ case "table":
209
+ renderTable(options.tableRows ?? inferRows(data));
210
+ return;
211
+ case "csv":
212
+ renderCsv(options.csvRows ?? inferRows(data));
213
+ return;
214
+ }
215
+ }
216
+ function renderPrettyFallback(data) {
217
+ const rows = inferRows(data);
218
+ if (rows.length === 0) {
219
+ console.log(JSON.stringify(data ?? null, null, 2));
220
+ return;
221
+ }
222
+ renderTable(rows);
223
+ }
224
+ function renderNdjson(data) {
225
+ const items = inferNdjsonItems(data);
226
+ for (const item of items) {
227
+ console.log(JSON.stringify(item ?? null));
228
+ }
229
+ }
230
+ function renderTable(rows) {
231
+ console.table(rows);
232
+ }
233
+ function renderCsv(rows) {
234
+ if (rows.length === 0) {
235
+ return;
236
+ }
237
+ const headers = [];
238
+ for (const row of rows) {
239
+ for (const key of Object.keys(row)) {
240
+ if (!headers.includes(key)) {
241
+ headers.push(key);
242
+ }
243
+ }
244
+ }
245
+ if (headers.length === 0) {
246
+ return;
247
+ }
248
+ console.log(headers.join(","));
249
+ for (const row of rows) {
250
+ console.log(headers.map((header) => escapeCsv(row[header])).join(","));
251
+ }
252
+ }
253
+ function inferNdjsonItems(data) {
254
+ const collection = extractCollection(data);
255
+ if (collection) {
256
+ return collection;
257
+ }
258
+ if (Array.isArray(data)) {
259
+ return data;
260
+ }
261
+ return [data ?? null];
262
+ }
263
+ function inferRows(data) {
264
+ const collection = extractCollection(data);
265
+ if (collection) {
266
+ return normalizeRows(collection);
267
+ }
268
+ if (Array.isArray(data)) {
269
+ return normalizeRows(data);
270
+ }
271
+ if (isPlainObject(data)) {
272
+ return [normalizeRow(data)];
273
+ }
274
+ return [{ value: normalizeCell(data) }];
275
+ }
276
+ function extractCollection(data) {
277
+ if (!isPlainObject(data)) {
278
+ return null;
279
+ }
280
+ if (Array.isArray(data.items)) {
281
+ return data.items;
282
+ }
283
+ if (Array.isArray(data.list)) {
284
+ return data.list;
285
+ }
286
+ return null;
287
+ }
288
+ function normalizeRows(items) {
289
+ return items.map((item) => {
290
+ if (isPlainObject(item)) {
291
+ return normalizeRow(item);
292
+ }
293
+ return { value: normalizeCell(item) };
294
+ });
295
+ }
296
+ function normalizeRow(row) {
297
+ return Object.fromEntries(
298
+ Object.entries(row).map(([key, value]) => [key, normalizeCell(value)])
299
+ );
300
+ }
301
+ function normalizeCell(value) {
302
+ if (value === null || value === void 0) {
303
+ return null;
304
+ }
305
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
306
+ return value;
307
+ }
308
+ return JSON.stringify(value);
309
+ }
310
+ function escapeCsv(value) {
311
+ const cell = value === null || value === void 0 ? "" : typeof value === "string" ? value : typeof value === "number" || typeof value === "boolean" ? String(value) : JSON.stringify(value);
312
+ if (/[",\n]/.test(cell)) {
313
+ return `"${cell.replace(/"/g, '""')}"`;
314
+ }
315
+ return cell;
316
+ }
317
+ function isPlainObject(value) {
318
+ return typeof value === "object" && value !== null && !Array.isArray(value);
319
+ }
320
+
321
+ // src/commands/auth.ts
175
322
  async function login(appCode, options) {
176
- const spinner = ora2(`Logging in to ${appCode}...`).start();
323
+ const spinner = createSpinner(`Logging in to ${appCode}...`, options.format);
177
324
  try {
178
325
  const appConfig = getAppConfig(appCode);
179
326
  if (!appConfig) {
@@ -183,16 +330,16 @@ async function login(appCode, options) {
183
330
  console.log(chalk7.yellow(`Initialize it first: amaster init --app-code ${appCode} --url <url>`));
184
331
  process.exit(1);
185
332
  }
333
+ let username = options.username;
186
334
  let email = options.email;
187
335
  let password = options.password;
188
- if (!email || !password) {
336
+ if (!username && !email) {
189
337
  const { default: inquirer } = await import('inquirer');
190
338
  const answers = await inquirer.prompt([
191
339
  {
192
340
  type: "input",
193
- name: "email",
194
- message: "Email:",
195
- when: !email
341
+ name: "login",
342
+ message: "Username or Email:"
196
343
  },
197
344
  {
198
345
  type: "password",
@@ -201,11 +348,32 @@ async function login(appCode, options) {
201
348
  when: !password
202
349
  }
203
350
  ]);
204
- email = email || answers.email;
351
+ const login2 = answers.login;
352
+ if (login2.includes("@")) {
353
+ email = login2;
354
+ } else {
355
+ username = login2;
356
+ }
205
357
  password = password || answers.password;
358
+ } else if (!password) {
359
+ const { default: inquirer } = await import('inquirer');
360
+ const answers = await inquirer.prompt([
361
+ {
362
+ type: "password",
363
+ name: "password",
364
+ message: "Password:"
365
+ }
366
+ ]);
367
+ password = answers.password;
206
368
  }
207
369
  const client = createClient({ baseURL: appConfig.baseURL });
208
- const result = await client.auth.login({ email, password });
370
+ const loginParams = { password };
371
+ if (email) {
372
+ loginParams.email = email;
373
+ } else if (username) {
374
+ loginParams.username = username;
375
+ }
376
+ const result = await client.auth.login(loginParams);
209
377
  if (result.error) {
210
378
  spinner.fail("Login failed");
211
379
  console.error(chalk7.red(result.error.message));
@@ -216,29 +384,53 @@ async function login(appCode, options) {
216
384
  spinner.fail("Login failed: No access token received");
217
385
  process.exit(1);
218
386
  }
387
+ const loggedInAt = (/* @__PURE__ */ new Date()).toISOString();
388
+ const expiresAt = loginData.expiresIn ? new Date(Date.now() + loginData.expiresIn * 1e3).toISOString() : void 0;
389
+ const sessionUser = loginData.user ? {
390
+ uid: loginData.user.uid,
391
+ email: loginData.user.email || "",
392
+ name: loginData.user.displayName || loginData.user.username || void 0
393
+ } : void 0;
219
394
  saveAuthSession(appCode, {
220
395
  accessToken: loginData.accessToken,
221
- refreshToken: loginData.refreshToken,
222
- expiresAt: loginData.expiresAt,
223
- user: loginData.user,
224
- loggedInAt: (/* @__PURE__ */ new Date()).toISOString()
396
+ expiresAt,
397
+ user: sessionUser,
398
+ loggedInAt
225
399
  });
226
400
  spinner.succeed(`Login successful: ${appCode}`);
227
- console.log(chalk7.green(`
228
- Welcome, ${loginData.user?.name || loginData.user?.email || email}!`));
229
- console.log(chalk7.gray(`App: ${appCode}`));
230
- console.log(chalk7.gray(`URL: ${appConfig.baseURL}`));
231
- if (loginData.expiresAt) {
232
- const expires = new Date(loginData.expiresAt);
233
- console.log(chalk7.gray(`Session expires: ${expires.toLocaleString()}`));
234
- }
401
+ renderOutput(
402
+ {
403
+ appCode,
404
+ baseURL: appConfig.baseURL,
405
+ user: loginData.user ?? null,
406
+ expiresAt: expiresAt ?? null,
407
+ loggedInAt
408
+ },
409
+ {
410
+ format: options.format,
411
+ pretty: () => {
412
+ console.log(
413
+ chalk7.green(
414
+ `
415
+ Welcome, ${loginData.user?.displayName || loginData.user?.email || loginData.user?.username || email}!`
416
+ )
417
+ );
418
+ console.log(chalk7.gray(`App: ${appCode}`));
419
+ console.log(chalk7.gray(`URL: ${appConfig.baseURL}`));
420
+ if (expiresAt) {
421
+ const expires = new Date(expiresAt);
422
+ console.log(chalk7.gray(`Session expires: ${expires.toLocaleString()}`));
423
+ }
424
+ }
425
+ }
426
+ );
235
427
  } catch (error) {
236
428
  spinner.fail("Login failed");
237
429
  throw error;
238
430
  }
239
431
  }
240
- async function logout(appCode) {
241
- const spinner = ora2(`Logging out from ${appCode}...`).start();
432
+ async function logout(appCode, options = {}) {
433
+ const spinner = createSpinner(`Logging out from ${appCode}...`, options.format);
242
434
  try {
243
435
  const appConfig = getAppConfig(appCode);
244
436
  if (appConfig) {
@@ -255,13 +447,25 @@ async function logout(appCode) {
255
447
  }
256
448
  clearAuthSession(appCode);
257
449
  spinner.succeed(`Logout successful: ${appCode}`);
450
+ renderOutput(
451
+ {
452
+ appCode,
453
+ loggedOut: true
454
+ },
455
+ {
456
+ format: options.format,
457
+ pretty: () => {
458
+ console.log(chalk7.green(`Logged out from ${appCode}`));
459
+ }
460
+ }
461
+ );
258
462
  } catch (error) {
259
463
  spinner.fail("Logout failed");
260
464
  throw error;
261
465
  }
262
466
  }
263
- async function getMe(getClient) {
264
- const spinner = ora2("Fetching user info...").start();
467
+ async function getMe(getClient, options = {}) {
468
+ const spinner = createSpinner("Fetching user info...", options.format);
265
469
  try {
266
470
  const client = getClient();
267
471
  const result = await client.auth.getMe();
@@ -272,160 +476,462 @@ async function getMe(getClient) {
272
476
  }
273
477
  spinner.succeed("User info retrieved");
274
478
  const user = result.data;
275
- console.log(chalk7.blue("\n\u{1F464} User Profile\n"));
276
- console.log(` ${chalk7.bold("UID:")} ${user?.uid}`);
277
- console.log(` ${chalk7.bold("Email:")} ${user?.email}`);
278
- console.log(` ${chalk7.bold("Name:")} ${user?.name || "N/A"}`);
279
- console.log(` ${chalk7.bold("Status:")} ${user?.status || "N/A"}`);
479
+ renderOutput(user, {
480
+ format: options.format,
481
+ pretty: () => {
482
+ console.log(chalk7.blue("\n\u{1F464} User Profile\n"));
483
+ console.log(` ${chalk7.bold("UID:")} ${user?.uid}`);
484
+ console.log(` ${chalk7.bold("Email:")} ${user?.email}`);
485
+ console.log(` ${chalk7.bold("Name:")} ${user?.displayName || user?.username || "N/A"}`);
486
+ console.log(` ${chalk7.bold("Status:")} ${user?.isActive ? "Active" : "Inactive"}`);
487
+ }
488
+ });
280
489
  } catch (error) {
281
490
  spinner.fail("Failed to fetch user info");
282
491
  throw error;
283
492
  }
284
493
  }
494
+ function isPlainObject2(value) {
495
+ return typeof value === "object" && value !== null && !Array.isArray(value);
496
+ }
497
+ function resolveInputSource(input) {
498
+ if (!input.startsWith("@")) {
499
+ return input;
500
+ }
501
+ const filePath = input.slice(1);
502
+ if (!filePath) {
503
+ throw new Error("File path is required after '@'.");
504
+ }
505
+ return readFileSync(filePath, "utf8");
506
+ }
507
+ function parseJsonInput(input, label) {
508
+ const source = resolveInputSource(input).trim();
509
+ if (!source) {
510
+ throw new Error(`${label} is required.`);
511
+ }
512
+ try {
513
+ return JSON.parse(source);
514
+ } catch (error) {
515
+ const reason = error instanceof Error ? error.message : String(error);
516
+ throw new Error(`Invalid ${label}: ${reason}`);
517
+ }
518
+ }
519
+ async function promptForJson(message, defaultValue) {
520
+ const { default: inquirer } = await import('inquirer');
521
+ const { jsonData } = await inquirer.prompt([
522
+ {
523
+ type: "editor",
524
+ name: "jsonData",
525
+ message,
526
+ default: defaultValue
527
+ }
528
+ ]);
529
+ return jsonData;
530
+ }
531
+ async function loadJsonObjectInput(input, label, promptMessage) {
532
+ const source = input ?? await promptForJson(promptMessage, "{}");
533
+ const value = parseJsonInput(source, label);
534
+ if (!isPlainObject2(value)) {
535
+ throw new Error(`${label} must be a JSON object.`);
536
+ }
537
+ return value;
538
+ }
539
+ async function loadJsonArrayInput(input, label, promptMessage) {
540
+ const source = input ?? await promptForJson(promptMessage, "[]");
541
+ const value = parseJsonInput(source, label);
542
+ if (!Array.isArray(value)) {
543
+ throw new Error(`${label} must be a JSON array.`);
544
+ }
545
+ return value;
546
+ }
547
+ function loadOptionalJsonObjectInput(input, label) {
548
+ if (!input) {
549
+ return {};
550
+ }
551
+ const value = parseJsonInput(input, label);
552
+ if (!isPlainObject2(value)) {
553
+ throw new Error(`${label} must be a JSON object.`);
554
+ }
555
+ return value;
556
+ }
557
+ function parseCommaSeparatedValues(value) {
558
+ if (!value) {
559
+ return void 0;
560
+ }
561
+ const values = value.split(",").map((entry) => entry.trim()).filter(Boolean);
562
+ return values.length > 0 ? values : void 0;
563
+ }
564
+ function validateBulkUpdateItems(items) {
565
+ return items.map((item, index) => {
566
+ if (!isPlainObject2(item)) {
567
+ throw new Error(`Bulk update item at index ${index} must be a JSON object.`);
568
+ }
569
+ if (typeof item.id !== "string" && typeof item.id !== "number") {
570
+ throw new Error(`Bulk update item at index ${index} must include an 'id'.`);
571
+ }
572
+ return item;
573
+ });
574
+ }
575
+ function parseIdsInput(input) {
576
+ const source = resolveInputSource(input).trim();
577
+ if (!source) {
578
+ throw new Error("IDs are required.");
579
+ }
580
+ if (source.startsWith("[")) {
581
+ const value = parseJsonInput(input, "IDs");
582
+ if (!Array.isArray(value)) {
583
+ throw new Error("IDs must be a JSON array.");
584
+ }
585
+ return value.map((id, index) => {
586
+ if (typeof id !== "string" && typeof id !== "number") {
587
+ throw new Error(`ID at index ${index} must be a string or number.`);
588
+ }
589
+ return id;
590
+ });
591
+ }
592
+ const ids = source.split(/[,\n]/).map((id) => id.trim()).filter(Boolean);
593
+ if (ids.length === 0) {
594
+ throw new Error("IDs are required.");
595
+ }
596
+ return ids;
597
+ }
598
+ async function loadIdsInput(input) {
599
+ if (input) {
600
+ return parseIdsInput(input);
601
+ }
602
+ const { default: inquirer } = await import('inquirer');
603
+ const { ids } = await inquirer.prompt([
604
+ {
605
+ type: "input",
606
+ name: "ids",
607
+ message: "Enter IDs (comma-separated or JSON array):"
608
+ }
609
+ ]);
610
+ return parseIdsInput(ids);
611
+ }
612
+ function exitWithCommandError(spinner, failureMessage, error) {
613
+ spinner.fail(failureMessage);
614
+ const details = error instanceof Error ? error.message : String(error);
615
+ if (details) {
616
+ console.error(chalk7.red(details));
617
+ }
618
+ process.exit(1);
619
+ }
620
+ function buildListQueryParams(options) {
621
+ const params = loadOptionalJsonObjectInput(options.query, "query params");
622
+ const fields = parseCommaSeparatedValues(options.fields);
623
+ const relations = parseCommaSeparatedValues(options.relations);
624
+ const keywordFields = parseCommaSeparatedValues(options.keywordFields);
625
+ if (keywordFields && !options.keyword) {
626
+ throw new Error("--keyword-fields requires --keyword.");
627
+ }
628
+ if (options.orderDir && !options.orderBy) {
629
+ throw new Error("--order-dir requires --order-by.");
630
+ }
631
+ if (options.orders && (options.orderBy || options.orderDir)) {
632
+ throw new Error("--orders cannot be used together with --order-by or --order-dir.");
633
+ }
634
+ if (fields) {
635
+ params.__fields = fields;
636
+ }
637
+ if (relations) {
638
+ params.__relations = relations;
639
+ }
640
+ if (options.keyword) {
641
+ params.__keywords = keywordFields ? { fields: keywordFields, value: options.keyword } : options.keyword;
642
+ }
643
+ if (options.orderBy) {
644
+ params.orderBy = options.orderBy;
645
+ }
646
+ if (options.orderDir) {
647
+ params.orderDir = options.orderDir;
648
+ }
649
+ if (options.orders) {
650
+ params.__orders = options.orders;
651
+ }
652
+ if (options.filter) {
653
+ params.__filter = loadOptionalJsonObjectInput(options.filter, "filter");
654
+ }
655
+ if (options.limit !== void 0) {
656
+ params.limit = options.limit;
657
+ }
658
+ if (options.offset !== void 0) {
659
+ params.offset = options.offset;
660
+ }
661
+ return params;
662
+ }
285
663
  async function listEntities(client, options) {
286
- const spinner = ora2(`Fetching ${options.entity}...`).start();
664
+ const spinner = createSpinner(`Fetching ${options.entity}...`, options.format);
287
665
  try {
288
- const result = await client.entity.list(options.namespace, options.entity, {
666
+ const entityClient = client.entity;
667
+ const query = buildListQueryParams(options);
668
+ const result = await entityClient.list(options.namespace, options.entity, {
669
+ ...query,
289
670
  page: options.page || 1,
290
- pageSize: options.pageSize || 10
671
+ perPage: options.pageSize || 10
291
672
  });
292
673
  if (result.error) {
293
674
  spinner.fail("Failed to fetch entities");
294
675
  console.error(chalk7.red(result.error.message));
295
676
  process.exit(1);
296
677
  }
297
- spinner.succeed(`Found ${result.data?.total || 0} ${options.entity}`);
298
- const items = result.data?.list || [];
299
- console.log(chalk7.blue(`
300
- \u{1F4E6} ${options.entity} in ${options.namespace}
678
+ spinner.stop();
679
+ const listData = result.data;
680
+ let items = [];
681
+ let total = 0;
682
+ if (Array.isArray(listData)) {
683
+ items = listData;
684
+ total = items.length;
685
+ } else if (listData?.items) {
686
+ items = listData.items;
687
+ total = listData.total || items.length;
688
+ } else if (listData?.list) {
689
+ items = listData.list;
690
+ total = listData.total || items.length;
691
+ }
692
+ renderOutput(result.data, {
693
+ format: options.format,
694
+ pretty: () => {
695
+ console.log(chalk7.blue(`
696
+ \u{1F4E6} ${options.entity} in ${options.namespace}`));
697
+ console.log(chalk7.gray(`\u5171 ${total} \u6761\u8BB0\u5F55:
301
698
  `));
302
- for (const item of items.slice(0, 10)) {
303
- const id = item.id || item.uid || item._id;
304
- console.log(` ${chalk7.green("\u2022")} ${chalk7.bold(id)}`);
305
- const entries = Object.entries(item).slice(0, 5);
306
- for (const [key, value] of entries) {
307
- if (key !== "id" && key !== "uid" && key !== "_id") {
308
- const displayValue = typeof value === "object" ? JSON.stringify(value).slice(0, 50) : String(value).slice(0, 50);
309
- console.log(` ${chalk7.gray(key + ":")} ${displayValue}`);
699
+ if (items.length === 0) {
700
+ console.log(chalk7.gray(" \u6682\u65E0\u6570\u636E"));
701
+ return;
702
+ }
703
+ const firstItem = items[0];
704
+ const keys = Object.keys(firstItem).slice(0, 8);
705
+ const widths = {};
706
+ keys.forEach((key) => {
707
+ const maxValueWidth = Math.max(
708
+ key.length,
709
+ ...items.map((item) => {
710
+ const val = item[key];
711
+ if (val === null || val === void 0) return 4;
712
+ const str = typeof val === "object" ? JSON.stringify(val) : String(val);
713
+ return str.length;
714
+ })
715
+ );
716
+ widths[key] = Math.min(maxValueWidth + 2, 30);
717
+ });
718
+ const headerLine = keys.map((key) => {
719
+ const width = widths[key] ?? 0;
720
+ return chalk7.bold(key.slice(0, width).padEnd(width));
721
+ }).join("\u2502");
722
+ console.log(" " + headerLine);
723
+ console.log(" " + keys.map((key) => "\u2500".repeat(widths[key] ?? 0)).join("\u253C"));
724
+ for (const item of items) {
725
+ const rowLine = keys.map((key) => {
726
+ const width = widths[key] ?? 0;
727
+ let val = item[key];
728
+ if (val === null || val === void 0) val = "null";
729
+ const str = typeof val === "object" ? JSON.stringify(val).slice(0, width - 2) : String(val).slice(0, width - 2);
730
+ return str.padEnd(width);
731
+ }).join("\u2502");
732
+ console.log(" " + rowLine);
733
+ }
734
+ console.log();
735
+ if (items.length < total) {
736
+ console.log(chalk7.gray(` ... \u8FD8\u6709 ${total - items.length} \u6761\u8BB0\u5F55`));
310
737
  }
311
738
  }
312
- if (Object.keys(item).length > 6) {
313
- console.log(` ${chalk7.gray("...")}`);
314
- }
315
- console.log();
316
- }
317
- if (items.length > 10) {
318
- console.log(chalk7.gray(` ... and ${items.length - 10} more`));
319
- }
739
+ });
320
740
  } catch (error) {
321
- spinner.fail("Failed to fetch entities");
322
- throw error;
741
+ exitWithCommandError(spinner, "Failed to fetch entities", error);
323
742
  }
324
743
  }
325
744
  async function getEntity(client, options) {
326
- const spinner = ora2(`Fetching ${options.entity}...`).start();
745
+ const spinner = createSpinner(`Fetching ${options.entity}...`, options.format);
327
746
  try {
328
- const result = await client.entity.get(options.namespace, options.entity, options.id);
747
+ const entityClient = client.entity;
748
+ const result = await entityClient.get(options.namespace, options.entity, options.id);
329
749
  if (result.error) {
330
750
  spinner.fail("Failed to fetch entity");
331
751
  console.error(chalk7.red(result.error.message));
332
752
  process.exit(1);
333
753
  }
334
754
  spinner.succeed("Entity retrieved");
335
- console.log(chalk7.blue(`
755
+ renderOutput(result.data, {
756
+ format: options.format,
757
+ pretty: () => {
758
+ console.log(chalk7.blue(`
336
759
  \u{1F4C4} ${options.entity}
337
760
  `));
338
- console.log(JSON.stringify(result.data, null, 2));
761
+ console.log(JSON.stringify(result.data, null, 2));
762
+ }
763
+ });
339
764
  } catch (error) {
340
- spinner.fail("Failed to fetch entity");
341
- throw error;
765
+ exitWithCommandError(spinner, "Failed to fetch entity", error);
342
766
  }
343
767
  }
344
768
  async function createEntity(client, options) {
345
- const spinner = ora2(`Creating ${options.entity}...`).start();
769
+ const spinner = createSpinner(`Creating ${options.entity}...`, options.format);
346
770
  try {
347
- let data = {};
348
- if (options.data) {
349
- data = JSON.parse(options.data);
350
- } else {
351
- const { default: inquirer } = await import('inquirer');
352
- const { jsonData } = await inquirer.prompt([
353
- {
354
- type: "editor",
355
- name: "jsonData",
356
- message: "Enter JSON data:",
357
- default: "{}"
358
- }
359
- ]);
360
- data = JSON.parse(jsonData);
361
- }
362
- const result = await client.entity.create(options.namespace, options.entity, data);
771
+ const entityClient = client.entity;
772
+ const data = await loadJsonObjectInput(options.data, "entity data", "Enter JSON data:");
773
+ const result = await entityClient.create(options.namespace, options.entity, data);
363
774
  if (result.error) {
364
775
  spinner.fail("Failed to create entity");
365
776
  console.error(chalk7.red(result.error.message));
366
777
  process.exit(1);
367
778
  }
368
779
  spinner.succeed("Entity created");
369
- console.log(chalk7.green("\nCreated entity:"));
370
- console.log(JSON.stringify(result.data, null, 2));
780
+ renderOutput(result.data, {
781
+ format: options.format,
782
+ pretty: () => {
783
+ console.log(chalk7.green("\nCreated entity:"));
784
+ console.log(JSON.stringify(result.data, null, 2));
785
+ }
786
+ });
371
787
  } catch (error) {
372
- spinner.fail("Failed to create entity");
373
- throw error;
788
+ exitWithCommandError(spinner, "Failed to create entity", error);
374
789
  }
375
790
  }
376
791
  async function updateEntity(client, options) {
377
- const spinner = ora2(`Updating ${options.entity}...`).start();
792
+ const spinner = createSpinner(`Updating ${options.entity}...`, options.format);
378
793
  try {
379
- let data = {};
380
- if (options.data) {
381
- data = JSON.parse(options.data);
382
- } else {
383
- const { default: inquirer } = await import('inquirer');
384
- const { jsonData } = await inquirer.prompt([
385
- {
386
- type: "editor",
387
- name: "jsonData",
388
- message: "Enter JSON data:",
389
- default: "{}"
390
- }
391
- ]);
392
- data = JSON.parse(jsonData);
393
- }
394
- const result = await client.entity.update(options.namespace, options.entity, options.id, data);
794
+ const entityClient = client.entity;
795
+ const data = await loadJsonObjectInput(options.data, "entity data", "Enter JSON data:");
796
+ const result = await entityClient.update(options.namespace, options.entity, options.id, data);
395
797
  if (result.error) {
396
798
  spinner.fail("Failed to update entity");
397
799
  console.error(chalk7.red(result.error.message));
398
800
  process.exit(1);
399
801
  }
400
802
  spinner.succeed("Entity updated");
401
- console.log(chalk7.green("\nUpdated entity:"));
402
- console.log(JSON.stringify(result.data, null, 2));
803
+ renderOutput(result.data, {
804
+ format: options.format,
805
+ pretty: () => {
806
+ console.log(chalk7.green("\nUpdated entity:"));
807
+ console.log(JSON.stringify(result.data, null, 2));
808
+ }
809
+ });
403
810
  } catch (error) {
404
- spinner.fail("Failed to update entity");
405
- throw error;
811
+ exitWithCommandError(spinner, "Failed to update entity", error);
406
812
  }
407
813
  }
408
814
  async function deleteEntity(client, options) {
409
- const spinner = ora2(`Deleting ${options.entity}...`).start();
815
+ const spinner = createSpinner(`Deleting ${options.entity}...`, options.format);
410
816
  try {
411
- const result = await client.entity.delete(options.namespace, options.entity, options.id);
817
+ const entityClient = client.entity;
818
+ const result = await entityClient.delete(options.namespace, options.entity, options.id);
412
819
  if (result.error) {
413
820
  spinner.fail("Failed to delete entity");
414
821
  console.error(chalk7.red(result.error.message));
415
822
  process.exit(1);
416
823
  }
417
824
  spinner.succeed("Entity deleted");
418
- console.log(chalk7.green(`
825
+ renderOutput(
826
+ {
827
+ namespace: options.namespace,
828
+ entity: options.entity,
829
+ id: options.id,
830
+ deleted: true
831
+ },
832
+ {
833
+ format: options.format,
834
+ pretty: () => {
835
+ console.log(chalk7.green(`
419
836
  Deleted ${options.entity} with ID: ${options.id}`));
837
+ }
838
+ }
839
+ );
420
840
  } catch (error) {
421
- spinner.fail("Failed to delete entity");
422
- throw error;
841
+ exitWithCommandError(spinner, "Failed to delete entity", error);
842
+ }
843
+ }
844
+ async function listEntityOptions(client, options) {
845
+ const spinner = createSpinner(`Fetching ${options.entity} options...`, options.format);
846
+ try {
847
+ const entityClient = client.entity;
848
+ const fields = parseCommaSeparatedValues(options.fields);
849
+ const result = await entityClient.options(options.namespace, options.entity, fields);
850
+ if (result.error) {
851
+ spinner.fail("Failed to fetch entity options");
852
+ console.error(chalk7.red(result.error.message));
853
+ process.exit(1);
854
+ }
855
+ spinner.succeed(`Found ${result.data?.length || 0} options`);
856
+ renderOutput(result.data || [], {
857
+ format: options.format,
858
+ pretty: () => {
859
+ console.log(chalk7.blue(`
860
+ \u{1F9FE} ${options.entity} options
861
+ `));
862
+ console.log(JSON.stringify(result.data || [], null, 2));
863
+ }
864
+ });
865
+ } catch (error) {
866
+ exitWithCommandError(spinner, "Failed to fetch entity options", error);
423
867
  }
424
868
  }
425
- async function listProcesses(client) {
426
- const spinner = ora2("Fetching process definitions...").start();
869
+ async function bulkUpdateEntities(client, options) {
870
+ const spinner = createSpinner(`Bulk updating ${options.entity}...`, options.format);
427
871
  try {
428
- const result = await client.bpm.getProcessDefinitions();
872
+ const entityClient = client.entity;
873
+ const rawItems = await loadJsonArrayInput(
874
+ options.items,
875
+ "bulk update items",
876
+ "Enter JSON array of items:"
877
+ );
878
+ const items = validateBulkUpdateItems(rawItems);
879
+ const result = await entityClient.bulkUpdate(options.namespace, options.entity, items);
880
+ if (result.error) {
881
+ spinner.fail("Failed to bulk update entities");
882
+ console.error(chalk7.red(result.error.message));
883
+ process.exit(1);
884
+ }
885
+ spinner.succeed(`Updated ${items.length} entities`);
886
+ renderOutput(result.data, {
887
+ format: options.format,
888
+ pretty: () => {
889
+ console.log(chalk7.green(`
890
+ Bulk updated ${items.length} ${options.entity} records:`));
891
+ console.log(JSON.stringify(result.data, null, 2));
892
+ }
893
+ });
894
+ } catch (error) {
895
+ exitWithCommandError(spinner, "Failed to bulk update entities", error);
896
+ }
897
+ }
898
+ async function bulkDeleteEntities(client, options) {
899
+ const spinner = createSpinner(`Bulk deleting ${options.entity}...`, options.format);
900
+ try {
901
+ const entityClient = client.entity;
902
+ const ids = await loadIdsInput(options.ids);
903
+ const result = await entityClient.bulkDelete(options.namespace, options.entity, ids);
904
+ if (result.error) {
905
+ spinner.fail("Failed to bulk delete entities");
906
+ console.error(chalk7.red(result.error.message));
907
+ process.exit(1);
908
+ }
909
+ spinner.succeed(`Deleted ${ids.length} entities`);
910
+ renderOutput(
911
+ {
912
+ namespace: options.namespace,
913
+ entity: options.entity,
914
+ ids,
915
+ deleted: true,
916
+ count: ids.length
917
+ },
918
+ {
919
+ format: options.format,
920
+ pretty: () => {
921
+ console.log(chalk7.green(`
922
+ Deleted ${ids.length} ${options.entity} records.`));
923
+ }
924
+ }
925
+ );
926
+ } catch (error) {
927
+ exitWithCommandError(spinner, "Failed to bulk delete entities", error);
928
+ }
929
+ }
930
+ async function listProcesses(client, options = {}) {
931
+ const spinner = createSpinner("Fetching process definitions...", options.format);
932
+ try {
933
+ const bpmClient = client.bpm;
934
+ const result = await bpmClient.getProcessDefinitions();
429
935
  if (result.error) {
430
936
  spinner.fail("Failed to fetch processes");
431
937
  console.error(chalk7.red(result.error.message));
@@ -433,23 +939,29 @@ async function listProcesses(client) {
433
939
  }
434
940
  spinner.succeed(`Found ${result.data?.length || 0} process definitions`);
435
941
  const processes = result.data || [];
436
- console.log(chalk7.blue("\n\u{1F4CA} Process Definitions\n"));
437
- for (const proc of processes) {
438
- console.log(` ${chalk7.green("\u2022")} ${chalk7.bold(proc.key)}`);
439
- console.log(` ${chalk7.gray("Name:")} ${proc.name || "N/A"}`);
440
- console.log(` ${chalk7.gray("Version:")} ${proc.version || "N/A"}`);
441
- console.log();
442
- }
942
+ renderOutput(processes, {
943
+ format: options.format,
944
+ pretty: () => {
945
+ console.log(chalk7.blue("\n\u{1F4CA} Process Definitions\n"));
946
+ for (const proc of processes) {
947
+ console.log(` ${chalk7.green("\u2022")} ${chalk7.bold(proc.key)}`);
948
+ console.log(` ${chalk7.gray("Name:")} ${proc.name || "N/A"}`);
949
+ console.log(` ${chalk7.gray("Version:")} ${proc.version || "N/A"}`);
950
+ console.log();
951
+ }
952
+ }
953
+ });
443
954
  } catch (error) {
444
955
  spinner.fail("Failed to fetch processes");
445
956
  throw error;
446
957
  }
447
958
  }
448
959
  async function startProcess(client, options) {
449
- const spinner = ora2(`Starting process: ${options.key}...`).start();
960
+ const spinner = createSpinner(`Starting process: ${options.key}...`, options.format);
450
961
  try {
962
+ const bpmClient = client.bpm;
451
963
  const variables = options.variables ? JSON.parse(options.variables) : {};
452
- const result = await client.bpm.startProcess({
964
+ const result = await bpmClient.startProcess({
453
965
  processKey: options.key,
454
966
  variables
455
967
  });
@@ -459,24 +971,30 @@ async function startProcess(client, options) {
459
971
  process.exit(1);
460
972
  }
461
973
  spinner.succeed("Process started");
462
- console.log(chalk7.green("\nProcess Instance:"));
463
- console.log(` ${chalk7.bold("ID:")} ${result.data?.id}`);
464
- console.log(` ${chalk7.bold("Definition ID:")} ${result.data?.definitionId}`);
465
- console.log(` ${chalk7.bold("Business Key:")} ${result.data?.businessKey || "N/A"}`);
466
- console.log(` ${chalk7.bold("Status:")} ${result.data?.suspended ? "Suspended" : "Active"}`);
974
+ renderOutput(result.data, {
975
+ format: options.format,
976
+ pretty: () => {
977
+ console.log(chalk7.green("\nProcess Instance:"));
978
+ console.log(` ${chalk7.bold("ID:")} ${result.data?.id}`);
979
+ console.log(` ${chalk7.bold("Definition ID:")} ${result.data?.definitionId}`);
980
+ console.log(` ${chalk7.bold("Business Key:")} ${result.data?.businessKey || "N/A"}`);
981
+ console.log(` ${chalk7.bold("Status:")} ${result.data?.suspended ? "Suspended" : "Active"}`);
982
+ }
983
+ });
467
984
  } catch (error) {
468
985
  spinner.fail("Failed to start process");
469
986
  throw error;
470
987
  }
471
988
  }
472
989
  async function listTasks(client, options) {
473
- const spinner = ora2("Fetching tasks...").start();
990
+ const spinner = createSpinner("Fetching tasks...", options.format);
474
991
  try {
992
+ const bpmClient = client.bpm;
475
993
  const params = {};
476
994
  if (options.assignee) {
477
995
  params.assignee = options.assignee;
478
996
  }
479
- const result = await client.bpm.getMyTasks(params);
997
+ const result = await bpmClient.getMyTasks(params);
480
998
  if (result.error) {
481
999
  spinner.fail("Failed to fetch tasks");
482
1000
  console.error(chalk7.red(result.error.message));
@@ -484,39 +1002,58 @@ async function listTasks(client, options) {
484
1002
  }
485
1003
  spinner.succeed(`Found ${result.data?.length || 0} tasks`);
486
1004
  const tasks = result.data || [];
487
- console.log(chalk7.blue("\n\u{1F4DD} Tasks\n"));
488
- for (const task of tasks) {
489
- console.log(` ${chalk7.green("\u2022")} ${chalk7.bold(task.name || task.id)}`);
490
- console.log(` ${chalk7.gray("ID:")} ${task.id}`);
491
- console.log(` ${chalk7.gray("Assignee:")} ${task.assignee || "Unassigned"}`);
492
- console.log(` ${chalk7.gray("Created:")} ${task.created || "N/A"}`);
493
- console.log();
494
- }
1005
+ renderOutput(tasks, {
1006
+ format: options.format,
1007
+ pretty: () => {
1008
+ console.log(chalk7.blue("\n\u{1F4DD} Tasks\n"));
1009
+ for (const task of tasks) {
1010
+ console.log(` ${chalk7.green("\u2022")} ${chalk7.bold(task.name || task.id)}`);
1011
+ console.log(` ${chalk7.gray("ID:")} ${task.id}`);
1012
+ console.log(` ${chalk7.gray("Assignee:")} ${task.assignee || "Unassigned"}`);
1013
+ console.log(` ${chalk7.gray("Created:")} ${task.created || "N/A"}`);
1014
+ console.log();
1015
+ }
1016
+ }
1017
+ });
495
1018
  } catch (error) {
496
1019
  spinner.fail("Failed to fetch tasks");
497
1020
  throw error;
498
1021
  }
499
1022
  }
500
1023
  async function completeTask(client, options) {
501
- const spinner = ora2(`Completing task: ${options.id}...`).start();
1024
+ const spinner = createSpinner(`Completing task: ${options.id}...`, options.format);
502
1025
  try {
1026
+ const bpmClient = client.bpm;
503
1027
  const variables = options.variables ? JSON.parse(options.variables) : {};
504
- const result = await client.bpm.completeTask(options.id, { variables });
1028
+ const result = await bpmClient.completeTask(options.id, { variables });
505
1029
  if (result.error) {
506
1030
  spinner.fail("Failed to complete task");
507
1031
  console.error(chalk7.red(result.error.message));
508
1032
  process.exit(1);
509
1033
  }
510
1034
  spinner.succeed("Task completed");
1035
+ renderOutput(
1036
+ {
1037
+ id: options.id,
1038
+ completed: true
1039
+ },
1040
+ {
1041
+ format: options.format,
1042
+ pretty: () => {
1043
+ console.log(chalk7.green(`Completed task: ${options.id}`));
1044
+ }
1045
+ }
1046
+ );
511
1047
  } catch (error) {
512
1048
  spinner.fail("Failed to complete task");
513
1049
  throw error;
514
1050
  }
515
1051
  }
516
- async function listWorkflows(client) {
517
- const spinner = ora2("Fetching workflows...").start();
1052
+ async function listWorkflows(client, options = {}) {
1053
+ const spinner = createSpinner("Fetching workflows...", options.format);
518
1054
  try {
519
- const result = await client.workflow.listWorkflows();
1055
+ const workflowClient = client.workflow;
1056
+ const result = await workflowClient.listWorkflows();
520
1057
  if (result.error) {
521
1058
  spinner.fail("Failed to fetch workflows");
522
1059
  console.error(chalk7.red(result.error.message));
@@ -524,24 +1061,30 @@ async function listWorkflows(client) {
524
1061
  }
525
1062
  spinner.succeed(`Found ${result.data?.length || 0} workflows`);
526
1063
  const workflows = result.data || [];
527
- console.log(chalk7.blue("\n\u26A1 Workflows\n"));
528
- for (const workflow of workflows) {
529
- console.log(` ${chalk7.green("\u2022")} ${chalk7.bold(workflow.code || workflow.id)}`);
530
- console.log(` ${chalk7.gray("Name:")} ${workflow.name || "N/A"}`);
531
- console.log(` ${chalk7.gray("Description:")} ${workflow.description || "N/A"}`);
532
- console.log(` ${chalk7.gray("Status:")} ${workflow.status || "N/A"}`);
533
- console.log();
534
- }
1064
+ renderOutput(workflows, {
1065
+ format: options.format,
1066
+ pretty: () => {
1067
+ console.log(chalk7.blue("\n\u26A1 Workflows\n"));
1068
+ for (const workflow of workflows) {
1069
+ console.log(` ${chalk7.green("\u2022")} ${chalk7.bold(workflow.code || workflow.id)}`);
1070
+ console.log(` ${chalk7.gray("Name:")} ${workflow.name || "N/A"}`);
1071
+ console.log(` ${chalk7.gray("Description:")} ${workflow.description || "N/A"}`);
1072
+ console.log(` ${chalk7.gray("Status:")} ${workflow.status || "N/A"}`);
1073
+ console.log();
1074
+ }
1075
+ }
1076
+ });
535
1077
  } catch (error) {
536
1078
  spinner.fail("Failed to fetch workflows");
537
1079
  throw error;
538
1080
  }
539
1081
  }
540
1082
  async function executeWorkflow(client, options) {
541
- const spinner = ora2(`Executing workflow: ${options.id}...`).start();
1083
+ const spinner = createSpinner(`Executing workflow: ${options.id}...`, options.format);
542
1084
  try {
1085
+ const workflowClient = client.workflow;
543
1086
  const input = options.input ? JSON.parse(options.input) : {};
544
- const result = await client.workflow.execute(options.id, {
1087
+ const result = await workflowClient.execute(options.id, {
545
1088
  input,
546
1089
  version: options.version
547
1090
  });
@@ -551,22 +1094,28 @@ async function executeWorkflow(client, options) {
551
1094
  process.exit(1);
552
1095
  }
553
1096
  spinner.succeed("Workflow executed");
554
- console.log(chalk7.green("\nExecution Result:"));
555
- console.log(JSON.stringify(result.data, null, 2));
1097
+ renderOutput(result.data, {
1098
+ format: options.format,
1099
+ pretty: () => {
1100
+ console.log(chalk7.green("\nExecution Result:"));
1101
+ console.log(JSON.stringify(result.data, null, 2));
1102
+ }
1103
+ });
556
1104
  } catch (error) {
557
1105
  spinner.fail("Failed to execute workflow");
558
1106
  throw error;
559
1107
  }
560
1108
  }
561
1109
  async function uploadFile(client, options) {
562
- const spinner = ora2("Uploading file...").start();
1110
+ const spinner = createSpinner("Uploading file...", options.format);
563
1111
  try {
1112
+ const s3Client = client.s3;
564
1113
  const filePath = resolve(options.file);
565
1114
  if (!existsSync(filePath)) {
566
1115
  spinner.fail(`File not found: ${options.file}`);
567
1116
  process.exit(1);
568
1117
  }
569
- const result = await client.s3.uploadFile(filePath, {
1118
+ const result = await s3Client.uploadFile(filePath, {
570
1119
  key: options.key,
571
1120
  bucket: options.bucket,
572
1121
  isPublic: options.public
@@ -577,19 +1126,25 @@ async function uploadFile(client, options) {
577
1126
  process.exit(1);
578
1127
  }
579
1128
  spinner.succeed("Upload complete");
580
- console.log(chalk7.green("\nFile uploaded:"));
581
- console.log(` ${chalk7.bold("Key:")} ${result.data?.key}`);
582
- console.log(` ${chalk7.bold("URL:")} ${result.data?.url || "N/A"}`);
583
- console.log(` ${chalk7.bold("Bucket:")} ${result.data?.bucket || options.bucket || "default"}`);
1129
+ renderOutput(result.data, {
1130
+ format: options.format,
1131
+ pretty: () => {
1132
+ console.log(chalk7.green("\nFile uploaded:"));
1133
+ console.log(` ${chalk7.bold("Key:")} ${result.data?.key}`);
1134
+ console.log(` ${chalk7.bold("URL:")} ${result.data?.url || "N/A"}`);
1135
+ console.log(` ${chalk7.bold("Bucket:")} ${result.data?.bucket || options.bucket || "default"}`);
1136
+ }
1137
+ });
584
1138
  } catch (error) {
585
1139
  spinner.fail("Upload failed");
586
1140
  throw error;
587
1141
  }
588
1142
  }
589
1143
  async function listFiles(client, options) {
590
- const spinner = ora2("Fetching files...").start();
1144
+ const spinner = createSpinner("Fetching files...", options.format);
591
1145
  try {
592
- const result = await client.s3.listFiles({
1146
+ const s3Client = client.s3;
1147
+ const result = await s3Client.listFiles({
593
1148
  bucket: options.bucket,
594
1149
  prefix: options.prefix,
595
1150
  page: options.page || 1,
@@ -602,15 +1157,20 @@ async function listFiles(client, options) {
602
1157
  }
603
1158
  spinner.succeed(`Found ${result.data?.total || 0} files`);
604
1159
  const files = result.data?.list || [];
605
- console.log(chalk7.blue(`
1160
+ renderOutput(result.data, {
1161
+ format: options.format,
1162
+ pretty: () => {
1163
+ console.log(chalk7.blue(`
606
1164
  \u{1F4C1} Files${options.bucket ? ` in ${options.bucket}` : ""}
607
1165
  `));
608
- for (const file of files) {
609
- console.log(` ${chalk7.green("\u2022")} ${chalk7.bold(file.key)}`);
610
- console.log(` ${chalk7.gray("Size:")} ${formatBytes(file.size || 0)}`);
611
- console.log(` ${chalk7.gray("Modified:")} ${file.lastModified || "N/A"}`);
612
- console.log();
613
- }
1166
+ for (const file of files) {
1167
+ console.log(` ${chalk7.green("\u2022")} ${chalk7.bold(file.key)}`);
1168
+ console.log(` ${chalk7.gray("Size:")} ${formatBytes(file.size || 0)}`);
1169
+ console.log(` ${chalk7.gray("Modified:")} ${file.lastModified || "N/A"}`);
1170
+ console.log();
1171
+ }
1172
+ }
1173
+ });
614
1174
  } catch (error) {
615
1175
  spinner.fail("Failed to fetch files");
616
1176
  throw error;
@@ -649,7 +1209,14 @@ function getAppMcpConfigPath(appCode) {
649
1209
  return `/openclaw/apps/${appCode}/mcp-config.yaml`;
650
1210
  }
651
1211
  async function initOpenClaw(options) {
652
- const spinner = ora2(`Initializing app: ${options.appCode}...`).start();
1212
+ const spinner = createSpinner(`Initializing app: ${options.appCode}...`, options.format);
1213
+ const pretty = isPrettyOutput(options.format);
1214
+ const ossEndpoint = options.ossEndpoint || DEFAULT_OSS_ENDPOINT;
1215
+ let installedSkills = 0;
1216
+ let configuredMcpServers = 0;
1217
+ let skillsError = null;
1218
+ let mcpError = null;
1219
+ const openClawDetected = existsSync(OPENCLAW_CONFIG_DIR);
653
1220
  try {
654
1221
  const existingConfig = getAppConfig(options.appCode);
655
1222
  if (existingConfig && !options.force) {
@@ -658,29 +1225,45 @@ async function initOpenClaw(options) {
658
1225
  console.log(chalk7.gray(`Current URL: ${existingConfig.baseURL}`));
659
1226
  process.exit(1);
660
1227
  }
661
- if (!existsSync(OPENCLAW_CONFIG_DIR)) {
662
- spinner.fail("OpenClaw not detected");
663
- console.log(chalk7.yellow("\n\u26A0\uFE0F Please install OpenClaw first:"));
664
- console.log(chalk7.gray(" npm install -g openclaw"));
665
- process.exit(1);
666
- }
667
1228
  addApp(options.appCode, {
668
1229
  baseURL: options.baseURL,
669
- ossEndpoint: options.ossEndpoint || DEFAULT_OSS_ENDPOINT,
1230
+ ossEndpoint,
670
1231
  initializedAt: (/* @__PURE__ */ new Date()).toISOString()
671
1232
  });
1233
+ if (!openClawDetected) {
1234
+ spinner.succeed(`App initialized: ${options.appCode}`);
1235
+ if (pretty) {
1236
+ console.log(chalk7.yellow("\n\u26A0\uFE0F OpenClaw not detected, skipping skill download"));
1237
+ console.log(chalk7.gray(" Install OpenClaw: npm install -g openclaw"));
1238
+ } else {
1239
+ renderOutput(
1240
+ {
1241
+ appCode: options.appCode,
1242
+ baseURL: options.baseURL,
1243
+ ossEndpoint,
1244
+ openClawDetected: false,
1245
+ installedSkills: 0,
1246
+ configuredMcpServers: 0
1247
+ },
1248
+ { format: options.format }
1249
+ );
1250
+ }
1251
+ return;
1252
+ }
672
1253
  spinner.succeed(`App initialized: ${options.appCode}`);
673
- console.log(chalk7.blue("\n\u{1F4CB} Configuration:\n"));
674
- console.log(` App Code: ${chalk7.green(options.appCode)}`);
675
- console.log(` Base URL: ${chalk7.gray(options.baseURL)}`);
676
- console.log();
677
- const ossEndpoint = options.ossEndpoint || DEFAULT_OSS_ENDPOINT;
1254
+ if (pretty) {
1255
+ console.log(chalk7.blue("\n\u{1F4CB} Configuration:\n"));
1256
+ console.log(` App Code: ${chalk7.green(options.appCode)}`);
1257
+ console.log(` Base URL: ${chalk7.gray(options.baseURL)}`);
1258
+ console.log();
1259
+ }
678
1260
  spinner.start("Downloading skills...");
679
1261
  try {
680
1262
  const skills = await downloadSkillManifest(ossEndpoint, options.appCode);
681
1263
  if (skills.length === 0) {
682
1264
  spinner.warn("No skills found");
683
1265
  } else {
1266
+ installedSkills = skills.length;
684
1267
  spinner.text = `Installing ${skills.length} skills...`;
685
1268
  const appSkillsDir = join(OPENCLAW_SKILLS_DIR, options.appCode);
686
1269
  if (options.force && existsSync(appSkillsDir)) {
@@ -696,12 +1279,14 @@ async function initOpenClaw(options) {
696
1279
  spinner.succeed(`Installed ${skills.length} skills`);
697
1280
  }
698
1281
  } catch (error) {
1282
+ skillsError = error instanceof Error ? error.message : String(error);
699
1283
  spinner.warn("Skills download failed (optional)");
700
1284
  }
701
1285
  spinner.start("Configuring MCP servers...");
702
1286
  try {
703
1287
  const mcpServers = await downloadMcpConfig(ossEndpoint, options.appCode);
704
1288
  if (Object.keys(mcpServers).length > 0) {
1289
+ configuredMcpServers = Object.keys(mcpServers).length;
705
1290
  const openClawConfig = getOpenClawConfig();
706
1291
  if (!openClawConfig.mcpServers) {
707
1292
  openClawConfig.mcpServers = {};
@@ -715,23 +1300,48 @@ async function initOpenClaw(options) {
715
1300
  spinner.succeed("No MCP servers to configure");
716
1301
  }
717
1302
  } catch (error) {
1303
+ mcpError = error instanceof Error ? error.message : String(error);
718
1304
  spinner.warn("MCP configuration failed (optional)");
719
1305
  }
720
- console.log();
721
- console.log(chalk7.green("\u2705 Initialization complete!"));
722
- console.log();
723
- console.log(`Next step: Login to your app`);
724
- console.log(chalk7.gray(` amaster login --app ${options.appCode}`));
725
- console.log();
726
1306
  const apps = listApps();
727
- if (apps.length > 1) {
728
- console.log(chalk7.blue("Configured apps:"));
729
- for (const app of apps) {
730
- const config = getAppConfig(app);
731
- console.log(` ${chalk7.gray("\u2022")} ${app} - ${config?.baseURL}`);
1307
+ const configuredApps = apps.map((app) => {
1308
+ const config = getAppConfig(app);
1309
+ return {
1310
+ appCode: app,
1311
+ baseURL: config?.baseURL || null
1312
+ };
1313
+ });
1314
+ const summary = {
1315
+ appCode: options.appCode,
1316
+ baseURL: options.baseURL,
1317
+ ossEndpoint,
1318
+ openClawDetected: true,
1319
+ installedSkills,
1320
+ configuredMcpServers,
1321
+ configuredApps,
1322
+ warnings: {
1323
+ skills: skillsError,
1324
+ mcpServers: mcpError
732
1325
  }
1326
+ };
1327
+ if (pretty) {
1328
+ console.log();
1329
+ console.log(chalk7.green("\u2705 Initialization complete!"));
733
1330
  console.log();
1331
+ console.log(`Next step: Login to your app`);
1332
+ console.log(chalk7.gray(` amaster login --app ${options.appCode}`));
1333
+ console.log();
1334
+ if (apps.length > 1) {
1335
+ console.log(chalk7.blue("Configured apps:"));
1336
+ for (const app of apps) {
1337
+ const config = getAppConfig(app);
1338
+ console.log(` ${chalk7.gray("\u2022")} ${app} - ${config?.baseURL}`);
1339
+ }
1340
+ console.log();
1341
+ }
1342
+ return;
734
1343
  }
1344
+ renderOutput(summary, { format: options.format });
735
1345
  } catch (error) {
736
1346
  spinner.fail("Initialization failed");
737
1347
  throw error;
@@ -854,163 +1464,257 @@ function createAmasterClient(appCode) {
854
1464
  process.exit(1);
855
1465
  }
856
1466
  if (shouldRefreshToken(appCode)) {
857
- console.log(chalk7.yellow("\u26A0\uFE0F Session expiring soon. Please login again."));
1467
+ console.error(chalk7.yellow("\u26A0\uFE0F Session expiring soon. Please login again."));
858
1468
  }
859
- return createClient({
1469
+ const client = createClient({
860
1470
  baseURL: appConfig.baseURL,
861
1471
  headers: {
862
1472
  Authorization: `Bearer ${token}`
863
1473
  },
864
1474
  onUnauthorized: () => {
865
1475
  console.error(chalk7.red("\n\u274C Session expired. Please login again."));
866
- console.log(chalk7.yellow(`Run: amaster login --app ${appCode}`));
1476
+ console.error(chalk7.yellow(`Run: amaster login --app ${appCode}`));
867
1477
  process.exit(1);
868
1478
  }
869
1479
  });
1480
+ client.setAccessToken(token);
1481
+ return client;
870
1482
  }
871
1483
  var program = new Command();
872
1484
  program.name("amaster").description("CLI for Amaster SDK - Multi-app support for OpenClaw").version("1.0.0");
873
- program.command("apps").description("List all configured apps").action(() => {
1485
+ program.command("apps").description("List all configured apps").addOption(createFormatOption()).action((options) => {
874
1486
  const apps = listApps();
875
1487
  const current = getCurrentApp();
876
- console.log(chalk7.blue("\n\u{1F4F1} Configured Apps\n"));
877
- if (apps.length === 0) {
878
- console.log(chalk7.gray(" No apps configured"));
879
- console.log(chalk7.gray(" Run: amaster init --app-code <code> --url <url>"));
880
- } else {
881
- for (const appCode of apps) {
882
- const config = getAppConfig(appCode);
883
- const isAuth = isAuthenticated(appCode);
884
- const isCurrent = appCode === current;
885
- let prefix = isCurrent ? chalk7.green("\u2192 ") : " ";
886
- console.log(`${prefix}${chalk7.bold(appCode)}${isCurrent ? chalk7.green(" (current)") : ""}`);
887
- console.log(` ${chalk7.gray(config?.baseURL || "No URL")}`);
888
- console.log(` ${isAuth ? chalk7.green("\u25CF Authenticated") : chalk7.yellow("\u25CB Not authenticated")}`);
1488
+ const appSummaries = apps.map((appCode) => {
1489
+ const config = getAppConfig(appCode);
1490
+ return {
1491
+ appCode,
1492
+ baseURL: config?.baseURL || null,
1493
+ authenticated: isAuthenticated(appCode),
1494
+ current: appCode === current
1495
+ };
1496
+ });
1497
+ renderOutput(appSummaries, {
1498
+ format: options.format,
1499
+ pretty: () => {
1500
+ console.log(chalk7.blue("\n\u{1F4F1} Configured Apps\n"));
1501
+ if (appSummaries.length === 0) {
1502
+ console.log(chalk7.gray(" No apps configured"));
1503
+ console.log(chalk7.gray(" Run: amaster init --app-code <code> --url <url>"));
1504
+ } else {
1505
+ for (const app of appSummaries) {
1506
+ const prefix = app.current ? chalk7.green("\u2192 ") : " ";
1507
+ console.log(`${prefix}${chalk7.bold(app.appCode)}${app.current ? chalk7.green(" (current)") : ""}`);
1508
+ console.log(` ${chalk7.gray(app.baseURL || "No URL")}`);
1509
+ console.log(
1510
+ ` ${app.authenticated ? chalk7.green("\u25CF Authenticated") : chalk7.yellow("\u25CB Not authenticated")}`
1511
+ );
1512
+ console.log();
1513
+ }
1514
+ }
889
1515
  console.log();
890
1516
  }
891
- }
892
- console.log();
1517
+ });
893
1518
  });
894
- program.command("use <app-code>").description("Set the default app for subsequent commands").action((appCode) => {
1519
+ program.command("use <app-code>").description("Set the default app for subsequent commands").addOption(createFormatOption()).action((appCode, options) => {
895
1520
  if (setCurrentApp(appCode)) {
896
- console.log(chalk7.green(`\u2705 Now using app: ${appCode}`));
1521
+ renderOutput(
1522
+ {
1523
+ appCode,
1524
+ current: true
1525
+ },
1526
+ {
1527
+ format: options.format,
1528
+ pretty: () => {
1529
+ console.log(chalk7.green(`\u2705 Now using app: ${appCode}`));
1530
+ }
1531
+ }
1532
+ );
897
1533
  } else {
898
1534
  console.error(chalk7.red(`\u274C App not found: ${appCode}`));
899
1535
  process.exit(1);
900
1536
  }
901
1537
  });
902
- program.command("init").description("Initialize an app for OpenClaw integration").requiredOption("--app-code <code>", "Application code (e.g., fhv94bto1)").requiredOption("--url <url>", "Base URL (e.g., https://fhv94bto1.helige.cn)").option("--api-key <key>", "API Key for OSS access").option("--oss-endpoint <endpoint>", "OSS endpoint").action(async (options) => {
1538
+ program.command("init").description("Initialize an app for OpenClaw integration").requiredOption("--app-code <code>", "Application code (e.g., fhv94bto1)").requiredOption("--url <url>", "Base URL (e.g., https://fhv94bto1.helige.cn)").option("--api-key <key>", "API Key for OSS access").option("--oss-endpoint <endpoint>", "OSS endpoint").option("--force", "Reinitialize an existing app").addOption(createFormatOption()).action(async (options) => {
903
1539
  await initOpenClaw({
904
1540
  appCode: options.appCode,
905
1541
  baseURL: options.url,
906
1542
  apiKey: options.apiKey,
907
- ossEndpoint: options.ossEndpoint
1543
+ ossEndpoint: options.ossEndpoint,
1544
+ force: options.force,
1545
+ format: options.format
908
1546
  });
909
1547
  });
910
- program.command("login").description("Authenticate with an app").option("--app <app-code>", "App code (uses default if not specified)").option("-e, --email <email>", "Email address").option("-p, --password <password>", "Password").action(async (options) => {
1548
+ program.command("login").description("Authenticate with an app").option("--app <app-code>", "App code (uses default if not specified)").option("-u, --username <username>", "Username").option("-e, --email <email>", "Email address").option("-p, --password <password>", "Password").addOption(createFormatOption()).action(async (options) => {
911
1549
  const appCode = resolveAppCode(options.app);
912
- await login(appCode, { email: options.email, password: options.password });
1550
+ await login(appCode, {
1551
+ username: options.username,
1552
+ email: options.email,
1553
+ password: options.password,
1554
+ format: options.format
1555
+ });
913
1556
  });
914
- program.command("logout").description("Logout from an app").option("--app <app-code>", "App code (uses default if not specified)").action(async (options) => {
1557
+ program.command("logout").description("Logout from an app").option("--app <app-code>", "App code (uses default if not specified)").addOption(createFormatOption()).action(async (options) => {
915
1558
  const appCode = resolveAppCode(options.app);
916
- await logout(appCode);
1559
+ await logout(appCode, { format: options.format });
917
1560
  });
918
- program.command("whoami").description("Show current user information").option("--app <app-code>", "App code (uses default if not specified)").action(async (options) => {
1561
+ program.command("whoami").description("Show current user information").option("--app <app-code>", "App code (uses default if not specified)").addOption(createFormatOption()).action(async (options) => {
919
1562
  const appCode = resolveAppCode(options.app);
920
- await getMe(() => createAmasterClient(appCode));
1563
+ await getMe(() => createAmasterClient(appCode), { format: options.format });
921
1564
  });
922
1565
  var entityCmd = program.command("entity").description("Manage entities");
923
- entityCmd.command("list <namespace> <entity>").description("List entities").option("--app <app-code>", "App code (uses default if not specified)").option("--page <page>", "Page number", "1").option("--page-size <size>", "Page size", "10").action(async (namespace, entityName, options) => {
1566
+ entityCmd.command("list <namespace> <entity>").description("List entities").option("--app <app-code>", "App code (uses default if not specified)").option("--page <page>", "Page number", "1").option("--page-size <size>", "Page size", "10").option("-f, --fields <fields>", "Comma-separated fields to return").option("-r, --relations <relations>", "Comma-separated relations to load").option("-k, --keyword <keyword>", "Keyword to search").option("--keyword-fields <fields>", "Comma-separated fields for keyword search").option("--order-by <field>", "Field to sort by").addOption(new Option("--order-dir <dir>", "Sort direction").choices(["asc", "desc"])).option("--orders <orders>", "Multi-order expression, e.g. created_at:desc,name:asc").option("--filter <json>", "Advanced __filter JSON or @file").option("--limit <limit>", "Limit number of records").option("--offset <offset>", "Offset number of records").option("-q, --query <json>", "Additional EntityQueryParams as JSON or @file").addOption(createFormatOption()).action(async (namespace, entityName, options) => {
924
1567
  const appCode = resolveAppCode(options.app);
925
1568
  await listEntities(createAmasterClient(appCode), {
926
1569
  namespace,
927
1570
  entity: entityName,
928
1571
  page: parseInt(options.page),
929
- pageSize: parseInt(options.pageSize)
1572
+ pageSize: parseInt(options.pageSize),
1573
+ fields: options.fields,
1574
+ relations: options.relations,
1575
+ keyword: options.keyword,
1576
+ keywordFields: options.keywordFields,
1577
+ orderBy: options.orderBy,
1578
+ orderDir: options.orderDir,
1579
+ orders: options.orders,
1580
+ filter: options.filter,
1581
+ limit: options.limit ? parseInt(options.limit) : void 0,
1582
+ offset: options.offset ? parseInt(options.offset) : void 0,
1583
+ query: options.query,
1584
+ format: options.format
930
1585
  });
931
1586
  });
932
- entityCmd.command("get <namespace> <entity> <id>").description("Get entity by ID").option("--app <app-code>", "App code (uses default if not specified)").action(async (namespace, entityName, id, options) => {
1587
+ entityCmd.command("get <namespace> <entity> <id>").description("Get entity by ID").option("--app <app-code>", "App code (uses default if not specified)").addOption(createFormatOption()).action(async (namespace, entityName, id, options) => {
933
1588
  const appCode = resolveAppCode(options.app);
934
- await getEntity(createAmasterClient(appCode), { namespace, entity: entityName, id });
1589
+ await getEntity(createAmasterClient(appCode), {
1590
+ namespace,
1591
+ entity: entityName,
1592
+ id,
1593
+ format: options.format
1594
+ });
935
1595
  });
936
- entityCmd.command("create <namespace> <entity>").description("Create new entity").option("--app <app-code>", "App code (uses default if not specified)").option("-d, --data <json>", "Entity data as JSON").action(async (namespace, entityName, options) => {
1596
+ entityCmd.command("create <namespace> <entity>").description("Create new entity").option("--app <app-code>", "App code (uses default if not specified)").option("-d, --data <json>", "Entity data as JSON or @file").addOption(createFormatOption()).action(async (namespace, entityName, options) => {
937
1597
  const appCode = resolveAppCode(options.app);
938
1598
  await createEntity(createAmasterClient(appCode), {
939
1599
  namespace,
940
1600
  entity: entityName,
941
- data: options.data
1601
+ data: options.data,
1602
+ format: options.format
942
1603
  });
943
1604
  });
944
- entityCmd.command("update <namespace> <entity> <id>").description("Update entity").option("--app <app-code>", "App code (uses default if not specified)").option("-d, --data <json>", "Entity data as JSON").action(async (namespace, entityName, id, options) => {
1605
+ entityCmd.command("update <namespace> <entity> <id>").description("Update entity").option("--app <app-code>", "App code (uses default if not specified)").option("-d, --data <json>", "Entity data as JSON or @file").addOption(createFormatOption()).action(async (namespace, entityName, id, options) => {
945
1606
  const appCode = resolveAppCode(options.app);
946
1607
  await updateEntity(createAmasterClient(appCode), {
947
1608
  namespace,
948
1609
  entity: entityName,
949
1610
  id,
950
- data: options.data
1611
+ data: options.data,
1612
+ format: options.format
951
1613
  });
952
1614
  });
953
- entityCmd.command("delete <namespace> <entity> <id>").description("Delete entity").option("--app <app-code>", "App code (uses default if not specified)").action(async (namespace, entityName, id, options) => {
1615
+ entityCmd.command("delete <namespace> <entity> <id>").description("Delete entity").option("--app <app-code>", "App code (uses default if not specified)").addOption(createFormatOption()).action(async (namespace, entityName, id, options) => {
954
1616
  const appCode = resolveAppCode(options.app);
955
1617
  await deleteEntity(createAmasterClient(appCode), {
956
1618
  namespace,
957
1619
  entity: entityName,
958
- id
1620
+ id,
1621
+ format: options.format
1622
+ });
1623
+ });
1624
+ entityCmd.command("options <namespace> <entity>").description("List entity options").option("--app <app-code>", "App code (uses default if not specified)").option("-f, --fields <fields>", "Comma-separated fields to return").addOption(createFormatOption()).action(async (namespace, entityName, options) => {
1625
+ const appCode = resolveAppCode(options.app);
1626
+ await listEntityOptions(createAmasterClient(appCode), {
1627
+ namespace,
1628
+ entity: entityName,
1629
+ fields: options.fields,
1630
+ format: options.format
1631
+ });
1632
+ });
1633
+ entityCmd.command("bulk-update <namespace> <entity>").description("Bulk update entities").option("--app <app-code>", "App code (uses default if not specified)").option("-i, --items <json>", "Items array as JSON or @file").addOption(createFormatOption()).action(async (namespace, entityName, options) => {
1634
+ const appCode = resolveAppCode(options.app);
1635
+ await bulkUpdateEntities(createAmasterClient(appCode), {
1636
+ namespace,
1637
+ entity: entityName,
1638
+ items: options.items,
1639
+ format: options.format
1640
+ });
1641
+ });
1642
+ entityCmd.command("bulk-delete <namespace> <entity>").description("Bulk delete entities").option("--app <app-code>", "App code (uses default if not specified)").option("--ids <ids>", "Comma-separated IDs, JSON array, or @file").addOption(createFormatOption()).action(async (namespace, entityName, options) => {
1643
+ const appCode = resolveAppCode(options.app);
1644
+ await bulkDeleteEntities(createAmasterClient(appCode), {
1645
+ namespace,
1646
+ entity: entityName,
1647
+ ids: options.ids,
1648
+ format: options.format
959
1649
  });
960
1650
  });
961
1651
  var bpmCmd = program.command("bpm").description("Manage BPM processes and tasks");
962
- bpmCmd.command("processes").description("List process definitions").option("--app <app-code>", "App code (uses default if not specified)").action(async (options) => {
1652
+ bpmCmd.command("processes").description("List process definitions").option("--app <app-code>", "App code (uses default if not specified)").addOption(createFormatOption()).action(async (options) => {
963
1653
  const appCode = resolveAppCode(options.app);
964
- await listProcesses(createAmasterClient(appCode));
1654
+ await listProcesses(createAmasterClient(appCode), { format: options.format });
965
1655
  });
966
- bpmCmd.command("start <key>").description("Start a process instance").option("--app <app-code>", "App code (uses default if not specified)").option("-v, --variables <json>", "Process variables as JSON").action(async (key, options) => {
1656
+ bpmCmd.command("start <key>").description("Start a process instance").option("--app <app-code>", "App code (uses default if not specified)").option("-v, --variables <json>", "Process variables as JSON").addOption(createFormatOption()).action(async (key, options) => {
967
1657
  const appCode = resolveAppCode(options.app);
968
1658
  await startProcess(createAmasterClient(appCode), {
969
1659
  key,
970
- variables: options.variables
1660
+ variables: options.variables,
1661
+ format: options.format
971
1662
  });
972
1663
  });
973
- bpmCmd.command("tasks").description("List tasks").option("--app <app-code>", "App code (uses default if not specified)").option("-a, --assignee <assignee>", "Filter by assignee").action(async (options) => {
1664
+ bpmCmd.command("tasks").description("List tasks").option("--app <app-code>", "App code (uses default if not specified)").option("-a, --assignee <assignee>", "Filter by assignee").addOption(createFormatOption()).action(async (options) => {
974
1665
  const appCode = resolveAppCode(options.app);
975
- await listTasks(createAmasterClient(appCode), { assignee: options.assignee });
1666
+ await listTasks(createAmasterClient(appCode), {
1667
+ assignee: options.assignee,
1668
+ format: options.format
1669
+ });
976
1670
  });
977
- bpmCmd.command("complete <id>").description("Complete a task").option("--app <app-code>", "App code (uses default if not specified)").option("-v, --variables <json>", "Task variables as JSON").action(async (id, options) => {
1671
+ bpmCmd.command("complete <id>").description("Complete a task").option("--app <app-code>", "App code (uses default if not specified)").option("-v, --variables <json>", "Task variables as JSON").addOption(createFormatOption()).action(async (id, options) => {
978
1672
  const appCode = resolveAppCode(options.app);
979
1673
  await completeTask(createAmasterClient(appCode), {
980
1674
  id,
981
- variables: options.variables
1675
+ variables: options.variables,
1676
+ format: options.format
982
1677
  });
983
1678
  });
984
1679
  var workflowCmd = program.command("workflow").description("Manage workflows");
985
- workflowCmd.command("list").description("List workflows").option("--app <app-code>", "App code (uses default if not specified)").action(async (options) => {
1680
+ workflowCmd.command("list").description("List workflows").option("--app <app-code>", "App code (uses default if not specified)").addOption(createFormatOption()).action(async (options) => {
986
1681
  const appCode = resolveAppCode(options.app);
987
- await listWorkflows(createAmasterClient(appCode));
1682
+ await listWorkflows(createAmasterClient(appCode), { format: options.format });
988
1683
  });
989
- workflowCmd.command("execute <id>").description("Execute a workflow").option("--app <app-code>", "App code (uses default if not specified)").option("-i, --input <json>", "Workflow input as JSON").action(async (id, options) => {
1684
+ workflowCmd.command("execute <id>").description("Execute a workflow").option("--app <app-code>", "App code (uses default if not specified)").option("-i, --input <json>", "Workflow input as JSON").addOption(createFormatOption()).action(async (id, options) => {
990
1685
  const appCode = resolveAppCode(options.app);
991
1686
  await executeWorkflow(createAmasterClient(appCode), {
992
1687
  id,
993
- input: options.input
1688
+ input: options.input,
1689
+ format: options.format
994
1690
  });
995
1691
  });
996
1692
  var s3Cmd = program.command("s3").description("Manage S3 files");
997
- s3Cmd.command("list").description("List files").option("--app <app-code>", "App code (uses default if not specified)").option("-b, --bucket <bucket>", "Bucket name").action(async (options) => {
1693
+ s3Cmd.command("list").description("List files").option("--app <app-code>", "App code (uses default if not specified)").option("-b, --bucket <bucket>", "Bucket name").addOption(createFormatOption()).action(async (options) => {
998
1694
  const appCode = resolveAppCode(options.app);
999
1695
  await listFiles(createAmasterClient(appCode), {
1000
- bucket: options.bucket
1696
+ bucket: options.bucket,
1697
+ format: options.format
1001
1698
  });
1002
1699
  });
1003
- s3Cmd.command("upload <file>").description("Upload a file").option("--app <app-code>", "App code (uses default if not specified)").option("-b, --bucket <bucket>", "Bucket name").option("-k, --key <key>", "Object key").action(async (file, options) => {
1700
+ s3Cmd.command("upload <file>").description("Upload a file").option("--app <app-code>", "App code (uses default if not specified)").option("-b, --bucket <bucket>", "Bucket name").option("-k, --key <key>", "Object key").addOption(createFormatOption()).action(async (file, options) => {
1004
1701
  const appCode = resolveAppCode(options.app);
1005
1702
  await uploadFile(createAmasterClient(appCode), {
1006
1703
  file,
1007
1704
  bucket: options.bucket,
1008
- key: options.key
1705
+ key: options.key,
1706
+ format: options.format
1009
1707
  });
1010
1708
  });
1011
1709
  var isMainModule = import.meta.url === new URL(process.argv[1] || "", import.meta.url).href || import.meta.url.endsWith(process.argv[1] || "") || process.argv[1]?.includes("cli.js") || false;
1012
1710
  if (isMainModule) {
1013
- program.parse();
1711
+ program.parseAsync(process.argv).then(
1712
+ () => process.exit(0),
1713
+ (err) => {
1714
+ console.error(err);
1715
+ process.exit(1);
1716
+ }
1717
+ );
1014
1718
  }
1015
1719
 
1016
1720
  export { createAmasterClient, resolveAppCode };