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