@dashai/cli 0.11.1 → 0.12.1

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/bin.js CHANGED
@@ -5535,7 +5535,11 @@ async function modulePublishCommand(options) {
5535
5535
  method: "POST",
5536
5536
  headers: {
5537
5537
  Accept: "application/json",
5538
- Authorization: `Bearer ${cfg.token}`
5538
+ Authorization: `Bearer ${cfg.token}`,
5539
+ // Opt into the async (202 + poll) contract. On the CodeBuild backend a
5540
+ // markerless client is rejected with 426; the E2B backend ignores it
5541
+ // and still responds synchronously (201).
5542
+ "X-Dashwise-CLI-Async": "1"
5539
5543
  },
5540
5544
  body: form
5541
5545
  });
@@ -5546,6 +5550,12 @@ async function modulePublishCommand(options) {
5546
5550
  const body = await res.json().catch(() => null);
5547
5551
  if (!res.ok) {
5548
5552
  const env = body && typeof body === "object" ? body : null;
5553
+ if (res.status === 426) {
5554
+ fail(
5555
+ `Your @dashai/cli is out of date for this backend. Upgrade with ${code("npm i -g @dashai/cli@latest")}, then re-run ${code("dashwise module publish")}.`
5556
+ );
5557
+ return 1;
5558
+ }
5549
5559
  fail(
5550
5560
  `Publish failed (${res.status}${env?.code ? ` ${env.code}` : ""}): ${env?.message ?? "(no message)"}`
5551
5561
  );
@@ -5554,16 +5564,40 @@ async function modulePublishCommand(options) {
5554
5564
  }
5555
5565
  return 1;
5556
5566
  }
5567
+ if (options.dryRun) {
5568
+ const dr = body;
5569
+ const target = dr.target_version ?? dr.version;
5570
+ if (options.json) out(JSON.stringify(body));
5571
+ else success(`Dry run OK \u2014 would publish ${code(`v${target ?? "?"}`)}`);
5572
+ return 0;
5573
+ }
5574
+ if (res.status === 202) {
5575
+ const enq = body;
5576
+ if (!enq?.build_id) {
5577
+ fail("Publish enqueued but the response was missing a build id.");
5578
+ return 1;
5579
+ }
5580
+ if (options.noWait) {
5581
+ success(`Build ${code(`#${enq.build_id}`)} queued for ${code(mod.slug)}.`);
5582
+ info(`Not waiting (${code("--no-wait")}). Re-run publish or poll the build to check.`);
5583
+ if (options.json) out(JSON.stringify(enq));
5584
+ return 0;
5585
+ }
5586
+ if (!options.json) {
5587
+ info(`Build ${code(`#${enq.build_id}`)} queued \u2014 building on the platform\u2026`);
5588
+ }
5589
+ return pollBuild(enq.build_id, enq.module_id, mod.slug, options);
5590
+ }
5557
5591
  const result = body;
5558
5592
  if (!result) {
5559
5593
  fail("Publish succeeded but the response body was empty or malformed.");
5560
5594
  return 1;
5561
5595
  }
5562
- if (options.dryRun) {
5563
- success(`Dry run OK \u2014 would publish ${code(`v${result.version}`)}`);
5564
- } else {
5565
- success(`Published ${code(mod.slug)} ${code(`v${result.version}`)}`);
5596
+ if (options.json) {
5597
+ out(JSON.stringify(result));
5598
+ return 0;
5566
5599
  }
5600
+ success(`Published ${code(mod.slug)} ${code(`v${result.version}`)}`);
5567
5601
  info(`Bundle: ${code(result.bundle_url)}`);
5568
5602
  info(`Hash: ${dim(result.bundle_hash)}`);
5569
5603
  info(`Size: ${formatBytes2(result.bytes_uploaded)}`);
@@ -5573,9 +5607,61 @@ async function modulePublishCommand(options) {
5573
5607
  out(` ${dim("\u2022")} ${w}`);
5574
5608
  }
5575
5609
  }
5576
- if (process.stdout.isTTY && !options.dryRun) outro("Done.");
5610
+ if (process.stdout.isTTY) outro("Done.");
5577
5611
  return 0;
5578
5612
  }
5613
+ async function pollBuild(buildId, moduleId, slug, options) {
5614
+ const timeoutMs = (options.timeoutSec ?? 360) * 1e3;
5615
+ const intervalMs = options.pollIntervalMs ?? 4e3;
5616
+ const deadline = Date.now() + timeoutMs;
5617
+ let lastStatus = "";
5618
+ while (Date.now() < deadline) {
5619
+ let build;
5620
+ try {
5621
+ build = await apiRequest(
5622
+ "GET",
5623
+ `/api/modules/${moduleId}/builds/${buildId}`
5624
+ );
5625
+ } catch {
5626
+ await sleep2(intervalMs);
5627
+ continue;
5628
+ }
5629
+ if (!options.json && build.status !== lastStatus) {
5630
+ info(`Build ${code(`#${buildId}`)}: ${build.status}`);
5631
+ lastStatus = build.status;
5632
+ }
5633
+ if (build.status === "succeeded") {
5634
+ if (options.json) {
5635
+ out(JSON.stringify(build));
5636
+ } else {
5637
+ success(`Published ${code(slug)} ${code(`v${build.version ?? "?"}`)}`);
5638
+ info(`Build: ${dim(`#${buildId}`)}`);
5639
+ if (process.stdout.isTTY) outro("Done.");
5640
+ }
5641
+ return 0;
5642
+ }
5643
+ if (build.status === "failed") {
5644
+ if (options.json) {
5645
+ out(JSON.stringify(build));
5646
+ } else {
5647
+ fail(
5648
+ `Build ${code(`#${buildId}`)} failed (${build.error_code ?? "BUILD_FAILED"}): ${build.error_message ?? "(no detail)"}`
5649
+ );
5650
+ if (build.log_url) info(`Logs: ${code(build.log_url)}`);
5651
+ info(`Re-run ${code("dashwise module publish")} to try again.`);
5652
+ }
5653
+ return 1;
5654
+ }
5655
+ await sleep2(intervalMs);
5656
+ }
5657
+ warn(
5658
+ `Still building after ${options.timeoutSec ?? 360}s \u2014 the build is likely still running. Re-run ${code("dashwise module publish")} to check, or inspect build ${code(`#${buildId}`)}.`
5659
+ );
5660
+ return 0;
5661
+ }
5662
+ function sleep2(ms) {
5663
+ return new Promise((r) => setTimeout(r, ms));
5664
+ }
5579
5665
  function formatBytes2(n) {
5580
5666
  if (n < 1024) return `${n}B`;
5581
5667
  if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)}KB`;
@@ -8360,7 +8446,7 @@ async function runTail(moduleId, options) {
8360
8446
  } catch (err) {
8361
8447
  info(dim(`(tail poll error: ${err.message})`));
8362
8448
  }
8363
- await sleep2(POLL_INTERVAL_MS);
8449
+ await sleep3(POLL_INTERVAL_MS);
8364
8450
  }
8365
8451
  }
8366
8452
  function buildTailParams(options) {
@@ -8473,7 +8559,7 @@ function formatRow(row) {
8473
8559
  function formatTimestamp(iso) {
8474
8560
  return iso.slice(0, 19).replace("T", " ");
8475
8561
  }
8476
- function sleep2(ms) {
8562
+ function sleep3(ms) {
8477
8563
  return new Promise((resolve13) => setTimeout(resolve13, ms));
8478
8564
  }
8479
8565
 
@@ -9096,14 +9182,25 @@ envCmd.command("export").description(
9096
9182
  moduleCmd.command("publish").description("Pack the current directory + upload it as a new module version.").option("--dir <path>", "Project root (default: current directory).").option("--bump <direction>", "Semver bump: patch | minor | major.").option("--dry-run", "Validate + upload but do not persist the version row.").option("-y, --yes", "Skip the confirmation prompt (for CI / scripted use).").option(
9097
9183
  "--exclude <pattern...>",
9098
9184
  "Extra exclude patterns (segment-matched) appended to the defaults."
9099
- ).action(
9185
+ ).option(
9186
+ "--no-wait",
9187
+ "Enqueue the build and exit immediately (print the build id) instead of polling to completion."
9188
+ ).option(
9189
+ "--timeout <seconds>",
9190
+ "Max seconds to wait for an async build before giving up polling (default 360)."
9191
+ ).option("--json", "Emit the final build result as machine-readable JSON.").action(
9100
9192
  async (cmdOpts) => {
9193
+ const timeoutSec = cmdOpts.timeout !== void 0 ? Number(cmdOpts.timeout) : void 0;
9101
9194
  process.exitCode = await modulePublishCommand({
9102
9195
  ...cmdOpts.dir !== void 0 ? { dir: cmdOpts.dir } : {},
9103
9196
  ...cmdOpts.bump !== void 0 ? { bump: cmdOpts.bump } : {},
9104
9197
  ...cmdOpts.dryRun !== void 0 ? { dryRun: cmdOpts.dryRun } : {},
9105
9198
  ...cmdOpts.yes !== void 0 ? { yes: cmdOpts.yes } : {},
9106
- ...cmdOpts.exclude !== void 0 ? { exclude: cmdOpts.exclude } : {}
9199
+ ...cmdOpts.exclude !== void 0 ? { exclude: cmdOpts.exclude } : {},
9200
+ // commander maps `--no-wait` to `wait === false`.
9201
+ ...cmdOpts.wait === false ? { noWait: true } : {},
9202
+ ...timeoutSec !== void 0 && Number.isFinite(timeoutSec) ? { timeoutSec } : {},
9203
+ ...cmdOpts.json !== void 0 ? { json: cmdOpts.json } : {}
9107
9204
  });
9108
9205
  }
9109
9206
  );
@@ -9284,7 +9381,7 @@ fieldCmd.command("set-type <table-slug> <field-slug> <new-type>").description(
9284
9381
  }
9285
9382
  })();
9286
9383
  function getVersion() {
9287
- return "0.11.1";
9384
+ return "0.12.1";
9288
9385
  }
9289
9386
  function parseIntOption(value) {
9290
9387
  const n = Number.parseInt(value, 10);