@devkong/cli 0.0.67-alpha.1 → 0.0.67-alpha.3

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/index.js CHANGED
@@ -60750,10 +60750,8 @@ async function spawnCommand(commandText, logger = null, shell = false) {
60750
60750
  }
60751
60751
  async function spawnCommandWithArgs(command, commandArgs, logger = null, shell = false) {
60752
60752
  return new Promise((resolve2, reject) => {
60753
- const child = (0, import_child_process.spawn)(command, commandArgs, {
60754
- shell: shell || process.platform !== "win32",
60755
- stdio: ["pipe", "pipe", "pipe"]
60756
- });
60753
+ const useShell = shell || process.platform !== "win32";
60754
+ const child = useShell ? (0, import_child_process.spawn)([command, ...commandArgs].join(" "), { shell: true, stdio: ["pipe", "pipe", "pipe"] }) : (0, import_child_process.spawn)(command, commandArgs, { shell: false, stdio: ["pipe", "pipe", "pipe"] });
60757
60755
  let stdout = "";
60758
60756
  let stderr = "";
60759
60757
  child.stdout.on("data", (data) => {
@@ -60797,13 +60795,6 @@ function printError(message2, error) {
60797
60795
  function escapePathSpaces(sourcePath) {
60798
60796
  return sourcePath.indexOf(" ") <= 0 ? sourcePath : `"${sourcePath}"`;
60799
60797
  }
60800
- function renderProgressBar(elapsedSeconds, timeoutSeconds, status) {
60801
- const width = 24;
60802
- const ratio = timeoutSeconds > 0 ? Math.min(1, elapsedSeconds / timeoutSeconds) : 0;
60803
- const filled = Math.round(width * ratio);
60804
- const bar = "\u2588".repeat(filled) + "\u2591".repeat(width - filled);
60805
- return `[${bar}] ${elapsedSeconds}s / ${timeoutSeconds}s \xB7 ${status}`;
60806
- }
60807
60798
 
60808
60799
  // packages/kong-cli/src/common/profile.ts
60809
60800
  var KONG_CONFIG_DIR = import_path3.default.join((0, import_os.homedir)(), ".kong");
@@ -63467,19 +63458,33 @@ async function getDeploymentLog(management, query) {
63467
63458
  ]);
63468
63459
  return [...aliasEvents, ...baseEvents].sort((a, b) => b.created.localeCompare(a.created));
63469
63460
  }
63461
+ function deploymentErrorMessage(events) {
63462
+ const failure = events.find(isFailureEvent);
63463
+ if (!failure) {
63464
+ return "Deployment failed.";
63465
+ }
63466
+ const data = failure.eventData;
63467
+ const detail = typeof data?.message === "string" ? data.message : typeof data?.error === "string" ? data.error : void 0;
63468
+ return detail ? `${failure.action}: ${detail}` : failure.action;
63469
+ }
63470
63470
  var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
63471
63471
  async function pollDeployment(management, input) {
63472
63472
  const interval = input.intervalMs ?? 2e3;
63473
63473
  const startedAt = Date.now();
63474
63474
  const deadline = startedAt + input.timeoutSeconds * 1e3;
63475
63475
  const elapsed = () => Math.min(input.timeoutSeconds, Math.round((Date.now() - startedAt) / 1e3));
63476
- const report = (status) => input.onProgress?.({ status, elapsedSeconds: elapsed(), timeoutSeconds: input.timeoutSeconds });
63476
+ const report = (current) => input.onProgress?.({
63477
+ status: current.status,
63478
+ events: current.events,
63479
+ elapsedSeconds: elapsed(),
63480
+ timeoutSeconds: input.timeoutSeconds
63481
+ });
63477
63482
  let result = analyzeDeployment(await getDeploymentLog(management, input));
63478
- report(result.status);
63483
+ report(result);
63479
63484
  while (!result.terminal && Date.now() < deadline) {
63480
63485
  await sleep(interval);
63481
63486
  result = analyzeDeployment(await getDeploymentLog(management, input));
63482
- report(result.status);
63487
+ report(result);
63483
63488
  }
63484
63489
  return {
63485
63490
  ...result,
@@ -63566,44 +63571,39 @@ var SetAliasCommand = class {
63566
63571
  updatedBy: ""
63567
63572
  };
63568
63573
  await this.publicClient.assignExtensionAlias(ctx.kongJson.id, alias);
63569
- task.output = [
63570
- "Please wait a moment for it to appear in the UI",
63571
- joinUrlAndPath(this.profile.kongBaseUrl, "/extensions/aliases")
63572
- ].join("\n");
63574
+ task.output = joinUrlAndPath(this.profile.kongBaseUrl, "/extensions/aliases");
63573
63575
  },
63574
63576
  rendererOptions: { persistentOutput: true }
63575
63577
  },
63576
63578
  {
63577
63579
  title: "Wait for deployment",
63578
63580
  task: async (ctx, task) => {
63579
- let status = "pending";
63580
- const startedAt = Date.now();
63581
- const render = () => {
63582
- const elapsed = Math.min(timeoutSeconds, Math.round((Date.now() - startedAt) / 1e3));
63583
- task.output = renderProgressBar(elapsed, timeoutSeconds, status);
63584
- };
63585
- render();
63586
- const ticker = setInterval(render, 1e3);
63587
- try {
63588
- const result = await pollDeployment(this.managementClient, {
63589
- objectType: "extension_alias" /* EXTENSION_ALIAS */,
63590
- basedOnId: ctx.kongJson.id,
63591
- aliasName,
63592
- timeoutSeconds,
63593
- onProgress: (progress) => {
63594
- status = progress.status;
63595
- render();
63581
+ const seen = /* @__PURE__ */ new Set();
63582
+ const printNewEvents = (events) => {
63583
+ for (const event of [...events].reverse()) {
63584
+ const key = `${event.created}|${event.action}`;
63585
+ if (seen.has(key)) {
63586
+ continue;
63596
63587
  }
63597
- });
63598
- if (result.status === "failed") {
63599
- throw new AppError("Deployment failed. Check the alias logs in the UI.");
63588
+ seen.add(key);
63589
+ task.output = `${event.eventType === "error" ? "\u2717" : "\u2713"} ${event.action}`;
63600
63590
  }
63601
- task.output = result.timedOut ? `Still deploying after ${result.waitedSeconds}s \u2014 check the UI for completion.` : `Deployment ${result.status} in ${result.waitedSeconds}s.`;
63602
- } finally {
63603
- clearInterval(ticker);
63591
+ };
63592
+ const result = await pollDeployment(this.managementClient, {
63593
+ objectType: "EXTENSION_ALIAS",
63594
+ basedOnId: ctx.kongJson.id,
63595
+ aliasName,
63596
+ timeoutSeconds,
63597
+ onProgress: (progress) => printNewEvents(progress.events)
63598
+ });
63599
+ if (result.status === "failed") {
63600
+ throw new AppError(deploymentErrorMessage(result.events));
63601
+ }
63602
+ if (result.timedOut) {
63603
+ task.output = `Still deploying after ${result.waitedSeconds}s \u2014 check the UI for completion.`;
63604
63604
  }
63605
63605
  },
63606
- rendererOptions: { persistentOutput: true }
63606
+ rendererOptions: { bottomBar: Infinity, persistentOutput: true }
63607
63607
  }
63608
63608
  ],
63609
63609
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devkong/cli",
3
- "version": "0.0.67-alpha.1",
3
+ "version": "0.0.67-alpha.3",
4
4
  "type": "commonjs",
5
5
  "main": "./index.js",
6
6
  "typings": "./index.d.ts",
@@ -1,8 +1,13 @@
1
- import { AppAuditLog, AuditObjectType } from "@kong/contract";
1
+ import { AppAuditLog } from "@kong/contract";
2
2
  import { Loading } from "@kong/ts";
3
3
  import { ManagementClient } from "../services/managementClient";
4
- /** Audit object types that carry a deployment trail. */
5
- export type DeployObjectType = AuditObjectType.EXTENSION_ALIAS | AuditObjectType.PROCESS_ALIAS;
4
+ /**
5
+ * Audit object types that carry a deployment trail. These are the management
6
+ * `AuditObjectType` JVM enum *constant names* (not the `extension_alias` JSON
7
+ * wire value): the `/v1/audit` `objectType` query param is resolved server-side
8
+ * via `Enum.valueOf`, which matches the constant name.
9
+ */
10
+ export type DeployObjectType = "EXTENSION_ALIAS" | "PROCESS_ALIAS";
6
11
  export interface DeploymentQuery {
7
12
  objectType: DeployObjectType;
8
13
  basedOnId: string;
@@ -31,9 +36,17 @@ export declare function analyzeDeployment(events: AppAuditLog[]): DeploymentResu
31
36
  * `basedOnId`, so both object ids are fetched and merged newest-first.
32
37
  */
33
38
  export declare function getDeploymentLog(management: ManagementClient, query: DeploymentQuery): Promise<AppAuditLog[]>;
39
+ /**
40
+ * Best-effort human-readable reason for a failed deployment, pulled from the
41
+ * first failure event's `eventData` (falling back to its action label) so the
42
+ * actual backend error can be surfaced to the console.
43
+ */
44
+ export declare function deploymentErrorMessage(events: AppAuditLog[]): string;
34
45
  export interface PollProgress {
35
46
  /** Latest analyzed deployment status. */
36
47
  status: Loading;
48
+ /** Full deployment audit log analyzed so far, newest first. */
49
+ events: AppAuditLog[];
37
50
  /** Seconds elapsed since polling started (capped at `timeoutSeconds`). */
38
51
  elapsedSeconds: number;
39
52
  /** The configured deploy-wait budget. */
@@ -1,4 +1,4 @@
1
- import { Loading, Optional, ShortUUID } from "@kong/ts";
1
+ import { Optional, ShortUUID } from "@kong/ts";
2
2
  export interface ILogger {
3
3
  info(message: string): void;
4
4
  debug(message: string): void;
@@ -14,5 +14,3 @@ export declare function spawnCommand(commandText: string, logger?: ILogger | nul
14
14
  export declare function spawnCommandWithArgs(command: string, commandArgs: string[], logger?: ILogger | null, shell?: boolean): Promise<string>;
15
15
  export declare function printError(message: string, error: unknown): void;
16
16
  export declare function escapePathSpaces(sourcePath: string): string;
17
- /** Render a fixed-width textual progress bar for live task output. */
18
- export declare function renderProgressBar(elapsedSeconds: number, timeoutSeconds: number, status: Loading): string;
@@ -1,5 +1,6 @@
1
- import { AppAuditLog, AppExtension, AppExtensionAlias, AppSnapshot, AppSnapshotDetails, AuditObjectType } from "@kong/contract";
1
+ import { AppAuditLog, AppExtension, AppExtensionAlias, AppSnapshot, AppSnapshotDetails } from "@kong/contract";
2
2
  import { Optional, UrlText } from "@kong/ts";
3
+ import { DeployObjectType } from "../common/deployment";
3
4
  import { RequestConfigProvider } from "./api";
4
5
  export declare class ManagementClient {
5
6
  private requestConfigProvider;
@@ -10,5 +11,5 @@ export declare class ManagementClient {
10
11
  getExtensionSnapshot(extensionId: AppExtension["id"], extensionSnapshotVersion: AppSnapshot["version"]): Promise<Optional<AppSnapshotDetails>>;
11
12
  getExtensionSnapshotVersions(extensionId: AppExtension["id"]): Promise<AppSnapshot[]>;
12
13
  getExtensionSnapshotAliases(extensionId: AppExtension["id"]): Promise<AppExtensionAlias[]>;
13
- getAuditLog(objectType: AuditObjectType, objectId: string): Promise<AppAuditLog[]>;
14
+ getAuditLog(objectType: DeployObjectType, objectId: string): Promise<AppAuditLog[]>;
14
15
  }