@ait-co/console-cli 0.1.12 → 0.1.14

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.mjs CHANGED
@@ -1275,6 +1275,10 @@ async function uploadOne(uploadImpl, input) {
1275
1275
  }
1276
1276
  });
1277
1277
  }
1278
+ function categoryHintFor(err) {
1279
+ if ((err.field ?? "") === "categoryIds" || /categoryIds/.test(err.message)) return "Tip: run `aitcc app categories --selectable` to list valid category ids.";
1280
+ return null;
1281
+ }
1278
1282
  function emitManifestError(json, err) {
1279
1283
  if (json) if (err.kind === "missing-required-field") emitJson({
1280
1284
  ok: false,
@@ -1287,7 +1291,11 @@ function emitManifestError(json, err) {
1287
1291
  reason: "invalid-config",
1288
1292
  message: err.message
1289
1293
  });
1290
- else process.stderr.write(`${err.message}\n`);
1294
+ else {
1295
+ process.stderr.write(`${err.message}\n`);
1296
+ const hint = categoryHintFor(err);
1297
+ if (hint) process.stderr.write(`${hint}\n`);
1298
+ }
1291
1299
  }
1292
1300
  function emitImageDimensionError(json, err) {
1293
1301
  if (json) if (err.reason === "mismatch") emitJson({
@@ -1489,6 +1497,7 @@ const showCommand$2 = defineCommand({
1489
1497
  try {
1490
1498
  const envelope = await fetchMiniAppWithDraft(workspaceId, appId, session.cookies);
1491
1499
  const miniApp = pickMiniAppView(envelope, view);
1500
+ if (miniApp === null && view === "current" && envelope.draft !== null) process.stderr.write(`App ${appId} has no \`current\` view yet (not reviewed). Re-run with \`--view draft\` to see the pending record.\n`);
1492
1501
  if (args.json) {
1493
1502
  emitJson({
1494
1503
  ok: true,
@@ -1500,7 +1509,7 @@ const showCommand$2 = defineCommand({
1500
1509
  return exitAfterFlush(ExitCode.Ok);
1501
1510
  }
1502
1511
  if (miniApp === null) {
1503
- if (view === "current" && envelope.draft !== null) process.stdout.write(`App ${appId} has no \`current\` view yet (not reviewed). Try --view draft.\n`);
1512
+ if (view === "current" && envelope.draft !== null) process.stdout.write(`App ${appId} has no \`current\` view yet.\n`);
1504
1513
  else process.stdout.write(`App ${appId} has no data for view=${view}.\n`);
1505
1514
  return exitAfterFlush(ExitCode.Ok);
1506
1515
  }
@@ -1627,29 +1636,40 @@ const statusCommand = defineCommand({
1627
1636
  const ctx = await resolveWorkspaceContext(args);
1628
1637
  if (!ctx) return;
1629
1638
  const { session, workspaceId } = ctx;
1630
- const emit = (status) => {
1639
+ const emit = (status, service) => {
1631
1640
  if (args.json) emitJson({
1632
1641
  ok: true,
1633
1642
  workspaceId,
1634
1643
  appId,
1635
- ...status
1644
+ ...status,
1645
+ serviceStatus: service?.serviceStatus ?? null,
1646
+ shutdownCandidateStatus: service?.shutdownCandidateStatus ?? null,
1647
+ scheduledShutdownAt: service?.scheduledShutdownAt ?? null
1636
1648
  });
1637
- else process.stdout.write(`App ${appId} (ws ${workspaceId}): ${status.state}` + (status.rejectedMessage ? `\n reason: ${status.rejectedMessage}` : "") + "\n");
1649
+ else {
1650
+ const svc = service ? ` [${service.serviceStatus}]` : "";
1651
+ process.stdout.write(`App ${appId} (ws ${workspaceId}): ${status.state}${svc}` + (status.rejectedMessage ? `\n reason: ${status.rejectedMessage}` : "") + (service?.scheduledShutdownAt ? `\n scheduled shutdown: ${service.scheduledShutdownAt}` : "") + "\n");
1652
+ }
1638
1653
  };
1639
1654
  try {
1640
1655
  const once = async () => {
1641
- return deriveReviewState(await fetchMiniAppWithDraft(workspaceId, appId, session.cookies));
1656
+ const [env, service] = await Promise.all([fetchMiniAppWithDraft(workspaceId, appId, session.cookies), fetchAppServiceStatus(workspaceId, appId, session.cookies).catch(() => null)]);
1657
+ return [deriveReviewState(env), service];
1642
1658
  };
1643
1659
  if (!args.watch) {
1644
- emit(await once());
1660
+ const [status, service] = await once();
1661
+ emit(status, service);
1645
1662
  return exitAfterFlush(ExitCode.Ok);
1646
1663
  }
1647
1664
  let lastState = null;
1665
+ let lastServiceStatus = null;
1648
1666
  while (true) {
1649
- const status = await once();
1650
- if (args.json) emit(status);
1651
- else if (status.state !== lastState) emit(status);
1667
+ const [status, service] = await once();
1668
+ const svc = service?.serviceStatus ?? null;
1669
+ if (args.json) emit(status, service);
1670
+ else if (status.state !== lastState || svc !== lastServiceStatus) emit(status, service);
1652
1671
  lastState = status.state;
1672
+ lastServiceStatus = svc;
1653
1673
  if (status.state !== "under-review") return exitAfterFlush(ExitCode.Ok);
1654
1674
  await new Promise((resolve) => setTimeout(resolve, intervalSec * 1e3));
1655
1675
  }
@@ -2949,6 +2969,178 @@ const appCommand = defineCommand({
2949
2969
  }
2950
2970
  });
2951
2971
  //#endregion
2972
+ //#region src/commands/completion.ts
2973
+ const TOP_LEVEL = [
2974
+ "whoami",
2975
+ "login",
2976
+ "logout",
2977
+ "upgrade",
2978
+ "workspace",
2979
+ "app",
2980
+ "members",
2981
+ "keys",
2982
+ "notices",
2983
+ "me",
2984
+ "completion"
2985
+ ];
2986
+ const SUB_COMMANDS = {
2987
+ workspace: [
2988
+ "ls",
2989
+ "partner",
2990
+ "segments",
2991
+ "show",
2992
+ "terms",
2993
+ "use"
2994
+ ],
2995
+ app: [
2996
+ "bundles",
2997
+ "categories",
2998
+ "certs",
2999
+ "events",
3000
+ "ls",
3001
+ "messages",
3002
+ "metrics",
3003
+ "ratings",
3004
+ "register",
3005
+ "reports",
3006
+ "service-status",
3007
+ "share-rewards",
3008
+ "show",
3009
+ "status",
3010
+ "templates"
3011
+ ],
3012
+ notices: [
3013
+ "categories",
3014
+ "ls",
3015
+ "show"
3016
+ ],
3017
+ me: ["terms"],
3018
+ completion: [
3019
+ "bash",
3020
+ "zsh",
3021
+ "fish"
3022
+ ]
3023
+ };
3024
+ function emitBash() {
3025
+ const top = TOP_LEVEL.join(" ");
3026
+ const cases = [];
3027
+ for (const [ns, subs] of Object.entries(SUB_COMMANDS)) {
3028
+ cases.push(` ${ns})`);
3029
+ cases.push(` COMPREPLY=( $(compgen -W "${subs.join(" ")}" -- "$cur") )`);
3030
+ cases.push(" return 0 ;;");
3031
+ }
3032
+ return `# bash completion for aitcc. Generated by \`aitcc completion bash\`.
3033
+ # Install:
3034
+ # aitcc completion bash > /etc/bash_completion.d/aitcc
3035
+ # # or add to ~/.bashrc:
3036
+ # source <(aitcc completion bash)
3037
+
3038
+ _aitcc_completion() {
3039
+ local cur prev
3040
+ COMPREPLY=()
3041
+ cur="\${COMP_WORDS[COMP_CWORD]}"
3042
+ prev="\${COMP_WORDS[COMP_CWORD-1]}"
3043
+
3044
+ if [[ $COMP_CWORD -eq 1 ]]; then
3045
+ COMPREPLY=( $(compgen -W "${top}" -- "$cur") )
3046
+ return 0
3047
+ fi
3048
+
3049
+ case "\${COMP_WORDS[1]}" in
3050
+ ${cases.join("\n")}
3051
+ esac
3052
+
3053
+ return 0
3054
+ }
3055
+
3056
+ complete -F _aitcc_completion aitcc
3057
+ `;
3058
+ }
3059
+ function emitZsh() {
3060
+ const top = TOP_LEVEL.join(" ");
3061
+ const nsClauses = [];
3062
+ for (const [ns, subs] of Object.entries(SUB_COMMANDS)) nsClauses.push(` ${ns}) _values 'subcommand' ${subs.map((s) => `'${s}'`).join(" ")} ;;`);
3063
+ return `#compdef aitcc
3064
+ # zsh completion for aitcc. Generated by \`aitcc completion zsh\`.
3065
+ # Install:
3066
+ # aitcc completion zsh > "\${fpath[1]}/_aitcc"
3067
+ # # then in a fresh shell (or run \`autoload -U compinit && compinit\`)
3068
+
3069
+ _aitcc() {
3070
+ local -a commands
3071
+ commands=(${TOP_LEVEL.map((c) => `'${c}'`).join(" ")})
3072
+
3073
+ if (( CURRENT == 2 )); then
3074
+ _values 'command' ${TOP_LEVEL.map((c) => `'${c}'`).join(" ")}
3075
+ return
3076
+ fi
3077
+
3078
+ case "\${words[2]}" in
3079
+ ${nsClauses.join("\n")}
3080
+ esac
3081
+ }
3082
+
3083
+ _aitcc "$@"
3084
+ # ${top}
3085
+ `;
3086
+ }
3087
+ function emitFish() {
3088
+ const lines = [
3089
+ "# fish completion for aitcc. Generated by `aitcc completion fish`.",
3090
+ "# Install:",
3091
+ "# aitcc completion fish > ~/.config/fish/completions/aitcc.fish",
3092
+ ""
3093
+ ];
3094
+ for (const c of TOP_LEVEL) lines.push(`complete -c aitcc -n "__fish_use_subcommand" -a "${c}" -f`);
3095
+ for (const [ns, subs] of Object.entries(SUB_COMMANDS)) for (const s of subs) lines.push(`complete -c aitcc -n "__fish_seen_subcommand_from ${ns}" -a "${s}" -f`);
3096
+ return `${lines.join("\n")}\n`;
3097
+ }
3098
+ const completionCommand = defineCommand({
3099
+ meta: {
3100
+ name: "completion",
3101
+ description: "Emit a shell completion script for bash, zsh, or fish."
3102
+ },
3103
+ args: {
3104
+ shell: {
3105
+ type: "positional",
3106
+ description: "Target shell: bash, zsh, or fish.",
3107
+ required: false
3108
+ },
3109
+ json: {
3110
+ type: "boolean",
3111
+ description: "Emit { ok: false, reason: 'invalid-shell' } on bad input.",
3112
+ default: false
3113
+ }
3114
+ },
3115
+ async run({ args }) {
3116
+ const raw = args.shell === void 0 ? "" : String(args.shell).toLowerCase();
3117
+ if (raw === "bash") {
3118
+ process.stdout.write(emitBash());
3119
+ return exitAfterFlush(ExitCode.Ok);
3120
+ }
3121
+ if (raw === "zsh") {
3122
+ process.stdout.write(emitZsh());
3123
+ return exitAfterFlush(ExitCode.Ok);
3124
+ }
3125
+ if (raw === "fish") {
3126
+ process.stdout.write(emitFish());
3127
+ return exitAfterFlush(ExitCode.Ok);
3128
+ }
3129
+ if (args.json) emitJson({
3130
+ ok: false,
3131
+ reason: "invalid-shell",
3132
+ allowed: [
3133
+ "bash",
3134
+ "zsh",
3135
+ "fish"
3136
+ ],
3137
+ message: `completion shell must be one of: bash, zsh, fish (got ${JSON.stringify(raw)})`
3138
+ });
3139
+ else process.stderr.write("Usage: aitcc completion <bash|zsh|fish>\n\nExamples:\n aitcc completion bash > /etc/bash_completion.d/aitcc\n aitcc completion zsh > \"${fpath[1]}/_aitcc\"\n aitcc completion fish > ~/.config/fish/completions/aitcc.fish\n");
3140
+ return exitAfterFlush(ExitCode.Usage);
3141
+ }
3142
+ });
3143
+ //#endregion
2952
3144
  //#region src/api/api-keys.ts
2953
3145
  const BASE$3 = "https://apps-in-toss.toss.im/console/api-public/v3/appsintossconsole";
2954
3146
  async function fetchApiKeys(workspaceId, cookies, opts = {}) {
@@ -4219,7 +4411,7 @@ function resolveVersion() {
4219
4411
  if (typeof injected === "string" && injected.length > 0) return injected;
4220
4412
  } catch {}
4221
4413
  try {
4222
- return "0.1.12";
4414
+ return "0.1.14";
4223
4415
  } catch {}
4224
4416
  return "0.0.0-dev";
4225
4417
  }
@@ -5126,7 +5318,8 @@ runMain(defineCommand({
5126
5318
  members: membersCommand,
5127
5319
  keys: keysCommand,
5128
5320
  notices: noticesCommand,
5129
- me: meCommand
5321
+ me: meCommand,
5322
+ completion: completionCommand
5130
5323
  }
5131
5324
  }));
5132
5325
  //#endregion