apiblaze 0.4.8 → 0.4.10

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.
Files changed (2) hide show
  1. package/dist/index.js +143 -86
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -25,10 +25,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/index.ts
27
27
  var import_commander = require("commander");
28
- var import_chalk27 = __toESM(require("chalk"));
28
+ var import_chalk28 = __toESM(require("chalk"));
29
29
 
30
30
  // package.json
31
- var version = "0.4.8";
31
+ var version = "0.4.10";
32
32
 
33
33
  // src/types.ts
34
34
  var ApiError = class extends Error {
@@ -1165,7 +1165,7 @@ async function runCreate(opts = {}) {
1165
1165
  const { rawName } = await inquirer2.prompt([{
1166
1166
  type: "input",
1167
1167
  name: "rawName",
1168
- message: "Proxy name (your API will live at <name>.apiblaze.com):",
1168
+ message: "Proxy name (your API will live at <name>.abz.run):",
1169
1169
  transformer: (v) => normalizeName(v)
1170
1170
  }]);
1171
1171
  name = normalizeName(rawName);
@@ -1186,7 +1186,7 @@ async function runCreate(opts = {}) {
1186
1186
  spinner2.stop();
1187
1187
  console.log(import_chalk6.default.dim(" (could not verify availability; continuing)"));
1188
1188
  }
1189
- console.log(`${import_chalk6.default.cyan("\u2192")} Your API will live at ${import_chalk6.default.bold(`https://${name}.apiblaze.com`)}
1189
+ console.log(`${import_chalk6.default.cyan("\u2192")} Your API will live at ${import_chalk6.default.bold(`https://${name}.abz.run`)}
1190
1190
  `);
1191
1191
  break;
1192
1192
  }
@@ -1241,7 +1241,7 @@ async function runCreate(opts = {}) {
1241
1241
  const version2 = result.api_version || "1.0.0";
1242
1242
  const keys = result.api_keys ?? {};
1243
1243
  const adminKey = keys.dev ?? Object.values(keys)[0];
1244
- const proxyUrl = `https://${name}.apiblaze.com/${version2}/dev`;
1244
+ const proxyUrl = `https://${name}.abz.run/${version2}/dev`;
1245
1245
  const devPortal = result.devPortal ? stripTenantFromPortal(result.devPortal) : void 0;
1246
1246
  if (opts.json) {
1247
1247
  process.stdout.write(JSON.stringify({
@@ -2172,8 +2172,64 @@ async function runDelete(project, version2, opts) {
2172
2172
  if (opts.json) console.log(JSON.stringify({ project_id: proj2.projectId, api_version: proj2.apiVersion, deleted: true }));
2173
2173
  }
2174
2174
 
2175
- // src/commands/config.ts
2175
+ // src/commands/export.ts
2176
2176
  var import_chalk19 = __toESM(require("chalk"));
2177
+ var import_fs3 = require("fs");
2178
+ var DASHBOARD_BASE4 = process.env.APIBLAZE_DASHBOARD_BASE || "https://dashboard.apiblaze.com";
2179
+ async function runExport(projectArg, versionArg, opts) {
2180
+ const token = getAccessToken();
2181
+ if (!token) throw new Error("Not authenticated. Run `apiblaze login` first.");
2182
+ const projects = await getProjects(opts.team ?? "");
2183
+ const match = projects.find((p) => p.projectId === projectArg || p.projectName === projectArg);
2184
+ if (!match) throw new Error(`Project "${projectArg}" not found. Run \`apiblaze projects\`.`);
2185
+ const projectId = match.projectId;
2186
+ const version2 = versionArg || match.apiVersion;
2187
+ const target = opts.kong ? "kong" : "data";
2188
+ const q = new URLSearchParams();
2189
+ if (opts.secrets) q.set("include_secrets", "1");
2190
+ if (opts.noConsumers) q.set("include_consumers", "0");
2191
+ if (opts.keys) q.set("keys", opts.keys);
2192
+ const qs = q.toString() ? `?${q.toString()}` : "";
2193
+ console.log(import_chalk19.default.dim(`Queuing ${target} export of ${projectId}@${version2}\u2026`));
2194
+ const job = await admin({
2195
+ path: `/projects/${projectId}/${version2}/export/${target}${qs}`,
2196
+ method: "GET",
2197
+ summary: `export ${projectId} (${target})`
2198
+ });
2199
+ if (!job?.job_id) throw new Error("Failed to queue export.");
2200
+ const statusPath = `/projects/${projectId}/${version2}/export/jobs/${job.job_id}`;
2201
+ let status = "queued";
2202
+ const started = Date.now();
2203
+ process.stdout.write(import_chalk19.default.dim("Building bundle"));
2204
+ while (status !== "ready" && status !== "failed") {
2205
+ if (Date.now() - started > 10 * 6e4) throw new Error("Export timed out after 10 minutes.");
2206
+ await new Promise((r) => setTimeout(r, 3e3));
2207
+ process.stdout.write(import_chalk19.default.dim("."));
2208
+ const st = await admin({ path: statusPath, method: "GET", summary: "poll export" });
2209
+ status = st?.status ?? "queued";
2210
+ if (status === "failed") {
2211
+ process.stdout.write("\n");
2212
+ throw new Error(`Export failed: ${st?.error ?? "unknown error"}`);
2213
+ }
2214
+ }
2215
+ process.stdout.write("\n");
2216
+ const outFile = opts.out || `apiblaze-export-${projectId}-${version2}-${target}.zip`;
2217
+ const res = await fetch(`${DASHBOARD_BASE4}/api/cli/admin/download`, {
2218
+ method: "POST",
2219
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
2220
+ body: JSON.stringify({ path: `${statusPath}?download=1` })
2221
+ });
2222
+ if (!res.ok) throw new Error(`Download failed (${res.status}): ${await res.text().catch(() => "")}`);
2223
+ const buf = Buffer.from(await res.arrayBuffer());
2224
+ (0, import_fs3.writeFileSync)(outFile, buf);
2225
+ console.log(import_chalk19.default.green(`\u2713 Saved ${outFile} (${(buf.length / 1024).toFixed(0)} KB)`));
2226
+ if (job.decryption_key) console.log(import_chalk19.default.yellow(`Decryption key (shown once): ${job.decryption_key}`));
2227
+ console.log(import_chalk19.default.dim("Read MIGRATION-REPORT.json inside the zip for the full fidelity ledger."));
2228
+ if (target === "kong") console.log(import_chalk19.default.dim("Kong: unzip, then `cd kong && docker compose up` (see kong/README.md)."));
2229
+ }
2230
+
2231
+ // src/commands/config.ts
2232
+ var import_chalk20 = __toESM(require("chalk"));
2177
2233
  var import_ora6 = __toESM(require("ora"));
2178
2234
  async function patchConfig(project, opts, body, summary) {
2179
2235
  const { teamId } = await resolveTeam(opts.team);
@@ -2195,7 +2251,7 @@ async function patchConfig(project, opts, body, summary) {
2195
2251
  }
2196
2252
  async function runTargetSet(project, opts) {
2197
2253
  if (!opts.url) {
2198
- console.error(import_chalk19.default.red("--url is required."));
2254
+ console.error(import_chalk20.default.red("--url is required."));
2199
2255
  process.exit(1);
2200
2256
  }
2201
2257
  const body = opts.env ? { environments: { [opts.env]: { target: opts.url } } } : { target_url: opts.url };
@@ -2208,31 +2264,31 @@ async function runThrottleSet(project, opts) {
2208
2264
  if (opts.quota !== void 0) throttling.proxyQuota = Number(opts.quota);
2209
2265
  if (opts.period !== void 0) {
2210
2266
  if (!["daily", "weekly", "monthly"].includes(opts.period)) {
2211
- console.error(import_chalk19.default.red("--period must be daily, weekly, or monthly."));
2267
+ console.error(import_chalk20.default.red("--period must be daily, weekly, or monthly."));
2212
2268
  process.exit(1);
2213
2269
  }
2214
2270
  throttling.quotaPeriod = opts.period;
2215
2271
  }
2216
2272
  if (Object.keys(throttling).length === 0) {
2217
- console.error(import_chalk19.default.red("Nothing to set. Pass at least one of --rate, --end-user-rate, --quota, --period."));
2273
+ console.error(import_chalk20.default.red("Nothing to set. Pass at least one of --rate, --end-user-rate, --quota, --period."));
2218
2274
  process.exit(1);
2219
2275
  }
2220
2276
  await patchConfig(project, opts, { throttling }, `Update throttling ${JSON.stringify(throttling)}`);
2221
2277
  }
2222
2278
  async function runRename(project, opts) {
2223
2279
  if (!opts.displayName) {
2224
- console.error(import_chalk19.default.red("--display-name is required."));
2280
+ console.error(import_chalk20.default.red("--display-name is required."));
2225
2281
  process.exit(1);
2226
2282
  }
2227
2283
  await patchConfig(project, opts, { display_name: opts.displayName }, `Rename \u2192 "${opts.displayName}"`);
2228
2284
  }
2229
2285
 
2230
2286
  // src/commands/domain.ts
2231
- var import_chalk20 = __toESM(require("chalk"));
2287
+ var import_chalk21 = __toESM(require("chalk"));
2232
2288
  var import_ora7 = __toESM(require("ora"));
2233
2289
  async function runDomainAdd(project, opts) {
2234
2290
  if (!opts.domain) {
2235
- console.error(import_chalk20.default.red("--domain is required."));
2291
+ console.error(import_chalk21.default.red("--domain is required."));
2236
2292
  process.exit(1);
2237
2293
  }
2238
2294
  const { teamId } = await resolveTeam(opts.team);
@@ -2251,9 +2307,9 @@ async function runDomainAdd(project, opts) {
2251
2307
  console.log(JSON.stringify(out));
2252
2308
  return;
2253
2309
  }
2254
- if (out?.cnameRecord) console.log(` ${import_chalk20.default.cyan("CNAME")} ${out.cnameRecord.name ?? opts.domain} \u2192 ${out.cnameRecord.value ?? out.cnameRecord.target}`);
2255
- if (out?.dcv) console.log(` ${import_chalk20.default.cyan("TXT")} ${out.dcv.name} = ${out.dcv.value}`);
2256
- if (out?.id) console.log(import_chalk20.default.dim(` domain id: ${out.id}`));
2310
+ if (out?.cnameRecord) console.log(` ${import_chalk21.default.cyan("CNAME")} ${out.cnameRecord.name ?? opts.domain} \u2192 ${out.cnameRecord.value ?? out.cnameRecord.target}`);
2311
+ if (out?.dcv) console.log(` ${import_chalk21.default.cyan("TXT")} ${out.dcv.name} = ${out.dcv.value}`);
2312
+ if (out?.id) console.log(import_chalk21.default.dim(` domain id: ${out.id}`));
2257
2313
  } catch (err) {
2258
2314
  spinner.fail("Domain registration failed.");
2259
2315
  throw err;
@@ -2273,14 +2329,14 @@ async function runDomainList(project, opts) {
2273
2329
  return;
2274
2330
  }
2275
2331
  if (!domains.length) {
2276
- console.log(import_chalk20.default.yellow("No custom domains."));
2332
+ console.log(import_chalk21.default.yellow("No custom domains."));
2277
2333
  return;
2278
2334
  }
2279
- for (const d of domains) console.log(` ${import_chalk20.default.bold(d.hostname)} ${import_chalk20.default.dim(d.status ?? "")} ${import_chalk20.default.dim(d.id ?? "")}`);
2335
+ for (const d of domains) console.log(` ${import_chalk21.default.bold(d.hostname)} ${import_chalk21.default.dim(d.status ?? "")} ${import_chalk21.default.dim(d.id ?? "")}`);
2280
2336
  }
2281
2337
  async function runDomainStatus(project, opts) {
2282
2338
  if (!opts.id) {
2283
- console.error(import_chalk20.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
2339
+ console.error(import_chalk21.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
2284
2340
  process.exit(1);
2285
2341
  }
2286
2342
  const { teamId } = await resolveTeam(opts.team);
@@ -2290,11 +2346,11 @@ async function runDomainStatus(project, opts) {
2290
2346
  path: `/projects/${proj2.projectId}/domains/${encodeURIComponent(opts.id)}/status`,
2291
2347
  summary: `Check custom-domain status`
2292
2348
  });
2293
- console.log(opts.json ? JSON.stringify(out) : ` ${import_chalk20.default.bold(out?.hostname ?? opts.id)}: ${import_chalk20.default.cyan(out?.status ?? "unknown")}`);
2349
+ console.log(opts.json ? JSON.stringify(out) : ` ${import_chalk21.default.bold(out?.hostname ?? opts.id)}: ${import_chalk21.default.cyan(out?.status ?? "unknown")}`);
2294
2350
  }
2295
2351
  async function runDomainRemove(project, opts) {
2296
2352
  if (!opts.id) {
2297
- console.error(import_chalk20.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
2353
+ console.error(import_chalk21.default.red("--id <domainId> is required (see `apiblaze domain list`)."));
2298
2354
  process.exit(1);
2299
2355
  }
2300
2356
  const { teamId } = await resolveTeam(opts.team);
@@ -2332,7 +2388,7 @@ async function runDomainSetBase(project, opts) {
2332
2388
  }
2333
2389
 
2334
2390
  // src/commands/tenant.ts
2335
- var import_chalk21 = __toESM(require("chalk"));
2391
+ var import_chalk22 = __toESM(require("chalk"));
2336
2392
  var import_ora8 = __toESM(require("ora"));
2337
2393
  async function runTenantList(opts) {
2338
2394
  const { teamId, teamName } = await resolveTeam(opts.team);
@@ -2347,18 +2403,18 @@ async function runTenantList(opts) {
2347
2403
  return;
2348
2404
  }
2349
2405
  if (!tenants.length) {
2350
- console.log(import_chalk21.default.yellow("No tenants."));
2406
+ console.log(import_chalk22.default.yellow("No tenants."));
2351
2407
  return;
2352
2408
  }
2353
2409
  for (const t of tenants) {
2354
2410
  const name = typeof t === "string" ? t : t.tenant_name;
2355
- const display = typeof t === "string" ? "" : import_chalk21.default.dim(` ${t.display_name ?? ""}`);
2356
- console.log(` ${import_chalk21.default.bold(name)}${display}`);
2411
+ const display = typeof t === "string" ? "" : import_chalk22.default.dim(` ${t.display_name ?? ""}`);
2412
+ console.log(` ${import_chalk22.default.bold(name)}${display}`);
2357
2413
  }
2358
2414
  }
2359
2415
  async function runTenantCreate(opts) {
2360
2416
  if (!opts.name) {
2361
- console.error(import_chalk21.default.red("--name (display name) is required."));
2417
+ console.error(import_chalk22.default.red("--name (display name) is required."));
2362
2418
  process.exit(1);
2363
2419
  }
2364
2420
  const { teamId } = await resolveTeam(opts.team);
@@ -2370,7 +2426,7 @@ async function runTenantCreate(opts) {
2370
2426
  body: { display_name: opts.name, ...opts.slug ? { tenant_name: opts.slug } : {} },
2371
2427
  summary: `Create tenant "${opts.name}"`
2372
2428
  });
2373
- spinner.succeed(`Created tenant ${import_chalk21.default.bold(out?.tenant_name ?? opts.name)}.`);
2429
+ spinner.succeed(`Created tenant ${import_chalk22.default.bold(out?.tenant_name ?? opts.name)}.`);
2374
2430
  if (opts.json) console.log(JSON.stringify(out));
2375
2431
  } catch (err) {
2376
2432
  spinner.fail("Tenant create failed.");
@@ -2379,7 +2435,7 @@ async function runTenantCreate(opts) {
2379
2435
  }
2380
2436
  async function runTenantAttach(project, opts) {
2381
2437
  if (!opts.tenant) {
2382
- console.error(import_chalk21.default.red("--tenant <slug> is required."));
2438
+ console.error(import_chalk22.default.red("--tenant <slug> is required."));
2383
2439
  process.exit(1);
2384
2440
  }
2385
2441
  const { teamId } = await resolveTeam(opts.team);
@@ -2407,7 +2463,7 @@ async function runTenantDelete(slug, opts) {
2407
2463
  { type: "confirm", name: "confirm", message: `Permanently delete tenant "${slug}" and everything under it? This cannot be undone.`, default: false }
2408
2464
  ]);
2409
2465
  if (!confirm) {
2410
- console.log(import_chalk21.default.dim("Aborted."));
2466
+ console.log(import_chalk22.default.dim("Aborted."));
2411
2467
  return;
2412
2468
  }
2413
2469
  }
@@ -2426,7 +2482,7 @@ async function runTenantDelete(slug, opts) {
2426
2482
  }
2427
2483
  async function runTenantCors(opts) {
2428
2484
  if (!opts.tenant) {
2429
- console.error(import_chalk21.default.red("--tenant <slug> is required."));
2485
+ console.error(import_chalk22.default.red("--tenant <slug> is required."));
2430
2486
  process.exit(1);
2431
2487
  }
2432
2488
  const { teamId } = await resolveTeam(opts.team);
@@ -2448,7 +2504,7 @@ async function runTenantCors(opts) {
2448
2504
  }
2449
2505
 
2450
2506
  // src/commands/key.ts
2451
- var import_chalk22 = __toESM(require("chalk"));
2507
+ var import_chalk23 = __toESM(require("chalk"));
2452
2508
  var import_ora9 = __toESM(require("ora"));
2453
2509
  async function runApikeysMenu(opts) {
2454
2510
  await runKeyList(opts);
@@ -2476,11 +2532,11 @@ async function runKeyList(opts) {
2476
2532
  return;
2477
2533
  }
2478
2534
  if (!keys.length) {
2479
- console.log(import_chalk22.default.yellow("No developer keys."));
2535
+ console.log(import_chalk23.default.yellow("No developer keys."));
2480
2536
  return;
2481
2537
  }
2482
2538
  for (const k of keys) {
2483
- console.log(` ${import_chalk22.default.bold(k.key_id ?? k.id)} ${import_chalk22.default.dim(k.description ?? "")} ${import_chalk22.default.dim(k.expires_at ?? "no expiry")}`);
2539
+ console.log(` ${import_chalk23.default.bold(k.key_id ?? k.id)} ${import_chalk23.default.dim(k.description ?? "")} ${import_chalk23.default.dim(k.expires_at ?? "no expiry")}`);
2484
2540
  }
2485
2541
  }
2486
2542
  async function runKeyMint(opts) {
@@ -2501,9 +2557,9 @@ async function runKeyMint(opts) {
2501
2557
  console.log(JSON.stringify(out));
2502
2558
  return;
2503
2559
  }
2504
- console.log(` ${import_chalk22.default.bold("key_id")}: ${out?.key_id}`);
2505
- console.log(` ${import_chalk22.default.bold("key")}: ${import_chalk22.default.green(out?.key)} ${import_chalk22.default.dim("(shown once \u2014 store it now)")}`);
2506
- if (out?.expires_at) console.log(` ${import_chalk22.default.dim("expires:")} ${out.expires_at}`);
2560
+ console.log(` ${import_chalk23.default.bold("key_id")}: ${out?.key_id}`);
2561
+ console.log(` ${import_chalk23.default.bold("key")}: ${import_chalk23.default.green(out?.key)} ${import_chalk23.default.dim("(shown once \u2014 store it now)")}`);
2562
+ if (out?.expires_at) console.log(` ${import_chalk23.default.dim("expires:")} ${out.expires_at}`);
2507
2563
  } catch (err) {
2508
2564
  spinner.fail("Mint failed.");
2509
2565
  throw err;
@@ -2527,7 +2583,7 @@ async function runKeyRevoke(keyId, opts) {
2527
2583
 
2528
2584
  // src/commands/spec.ts
2529
2585
  var fs5 = __toESM(require("fs"));
2530
- var import_chalk23 = __toESM(require("chalk"));
2586
+ var import_chalk24 = __toESM(require("chalk"));
2531
2587
  var import_ora10 = __toESM(require("ora"));
2532
2588
  async function runSpecGet(project, opts) {
2533
2589
  const { teamId } = await resolveTeam(opts.team);
@@ -2541,14 +2597,14 @@ async function runSpecGet(project, opts) {
2541
2597
  }
2542
2598
  async function runSpecSet(project, opts) {
2543
2599
  if (!opts.file) {
2544
- console.error(import_chalk23.default.red("--file <path> is required (OpenAPI JSON or YAML)."));
2600
+ console.error(import_chalk24.default.red("--file <path> is required (OpenAPI JSON or YAML)."));
2545
2601
  process.exit(1);
2546
2602
  }
2547
2603
  let specContent;
2548
2604
  try {
2549
2605
  specContent = fs5.readFileSync(opts.file, "utf-8");
2550
2606
  } catch {
2551
- console.error(import_chalk23.default.red(`Cannot read file: ${opts.file}`));
2607
+ console.error(import_chalk24.default.red(`Cannot read file: ${opts.file}`));
2552
2608
  process.exit(1);
2553
2609
  }
2554
2610
  const { teamId } = await resolveTeam(opts.team);
@@ -2570,11 +2626,11 @@ async function runSpecSet(project, opts) {
2570
2626
  }
2571
2627
 
2572
2628
  // src/commands/agent.ts
2573
- var import_chalk25 = __toESM(require("chalk"));
2629
+ var import_chalk26 = __toESM(require("chalk"));
2574
2630
  var import_ora11 = __toESM(require("ora"));
2575
2631
 
2576
2632
  // src/lib/tools.ts
2577
- var import_chalk24 = __toESM(require("chalk"));
2633
+ var import_chalk25 = __toESM(require("chalk"));
2578
2634
  async function proj(teamId, name, version2) {
2579
2635
  return resolveProject(teamId, name, version2);
2580
2636
  }
@@ -2589,17 +2645,17 @@ var TOOLS = [
2589
2645
  const version2 = res.api_version || "1.0.0";
2590
2646
  const keys = res.api_keys ?? {};
2591
2647
  const key = keys.dev ?? Object.values(keys)[0];
2592
- const url = `https://${a.name}.apiblaze.com/${version2}/dev`;
2648
+ const url = `https://${a.name}.abz.run/${version2}/dev`;
2593
2649
  const tryIt = buildTryItCurl(url, auth, key);
2594
- const lines = [` ${import_chalk24.default.dim("Proxy URL:")} ${import_chalk24.default.bold(url)}`];
2595
- if (res.devPortal) lines.push(` ${import_chalk24.default.dim("Dev portal:")} ${res.devPortal}`);
2650
+ const lines = [` ${import_chalk25.default.dim("Proxy URL:")} ${import_chalk25.default.bold(url)}`];
2651
+ if (res.devPortal) lines.push(` ${import_chalk25.default.dim("Dev portal:")} ${res.devPortal}`);
2596
2652
  const envs = Object.keys(keys);
2597
2653
  if (envs.length) {
2598
- lines.push("", ` ${import_chalk24.default.bold("API keys")} ${import_chalk24.default.dim("(bootstrapped \u2014 send as the X-API-Key header; shown once):")}`);
2654
+ lines.push("", ` ${import_chalk25.default.bold("API keys")} ${import_chalk25.default.dim("(bootstrapped \u2014 send as the X-API-Key header; shown once):")}`);
2599
2655
  const w = Math.max(...envs.map((e) => e.length));
2600
- for (const env of envs) lines.push(` ${import_chalk24.default.cyan(env.padEnd(w))} ${import_chalk24.default.green(keys[env])}`);
2656
+ for (const env of envs) lines.push(` ${import_chalk25.default.cyan(env.padEnd(w))} ${import_chalk25.default.green(keys[env])}`);
2601
2657
  }
2602
- if (tryIt) lines.push("", ` ${import_chalk24.default.dim("Try it:")}`, ` ${import_chalk24.default.cyan(tryIt)}`);
2658
+ if (tryIt) lines.push("", ` ${import_chalk25.default.dim("Try it:")}`, ` ${import_chalk25.default.cyan(tryIt)}`);
2603
2659
  return { ...res, proxy_url: url, keys, ...tryIt ? { try_it: tryIt } : {}, display: lines.join("\n") };
2604
2660
  }
2605
2661
  },
@@ -2724,11 +2780,11 @@ function findTool(name) {
2724
2780
  }
2725
2781
 
2726
2782
  // src/commands/agent.ts
2727
- var DASHBOARD_BASE4 = process.env.APIBLAZE_DASHBOARD_BASE || "https://dashboard.apiblaze.com";
2783
+ var DASHBOARD_BASE5 = process.env.APIBLAZE_DASHBOARD_BASE || "https://dashboard.apiblaze.com";
2728
2784
  var MAX_TOOL_STEPS = 6;
2729
2785
  async function callAgent(messages, teamId) {
2730
2786
  const token = getAccessToken();
2731
- const res = await fetch(`${DASHBOARD_BASE4}/api/cli/agent`, {
2787
+ const res = await fetch(`${DASHBOARD_BASE5}/api/cli/agent`, {
2732
2788
  method: "POST",
2733
2789
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
2734
2790
  body: JSON.stringify({ messages: messages.slice(-20), tools: toolCatalogue(), team_id: teamId })
@@ -2753,17 +2809,17 @@ function truncate(value, max = 1500) {
2753
2809
  }
2754
2810
  function printCost(llm) {
2755
2811
  const usd = llm.cost > 0 ? `$${llm.cost.toFixed(4)}` : "<$0.0001";
2756
- console.log(import_chalk25.default.magenta(` \u{1F4B3} ${usd}`) + import_chalk25.default.dim(` (${llm.model}, ${llm.total_tokens} tok)`));
2812
+ console.log(import_chalk26.default.magenta(` \u{1F4B3} ${usd}`) + import_chalk26.default.dim(` (${llm.model}, ${llm.total_tokens} tok)`));
2757
2813
  }
2758
2814
  async function runAgent(opts) {
2759
2815
  requireAuth();
2760
2816
  const { teamId, teamName } = await resolveTeam(opts.team);
2761
2817
  const { default: inquirer2 } = await import("inquirer");
2762
- console.log(import_chalk25.default.bold("APIblaze agent") + import_chalk25.default.dim(` \xB7 team ${teamName ?? teamId}`));
2763
- console.log(import_chalk25.default.dim('Ask me to create/delete/configure proxies, tenants, keys, domains, specs. Type "exit" to quit.\n'));
2818
+ console.log(import_chalk26.default.bold("APIblaze agent") + import_chalk26.default.dim(` \xB7 team ${teamName ?? teamId}`));
2819
+ console.log(import_chalk26.default.dim('Ask me to create/delete/configure proxies, tenants, keys, domains, specs. Type "exit" to quit.\n'));
2764
2820
  const history = [];
2765
2821
  while (true) {
2766
- const { input } = await inquirer2.prompt([{ type: "input", name: "input", message: import_chalk25.default.cyan("you") + " \u203A" }]);
2822
+ const { input } = await inquirer2.prompt([{ type: "input", name: "input", message: import_chalk26.default.cyan("you") + " \u203A" }]);
2767
2823
  const text = (input ?? "").trim();
2768
2824
  if (!text) continue;
2769
2825
  if (["exit", "quit", ":q"].includes(text.toLowerCase())) break;
@@ -2777,14 +2833,14 @@ async function runAgent(opts) {
2777
2833
  } catch (err) {
2778
2834
  spinner.stop();
2779
2835
  if (err instanceof ApiError && err.status === 402) {
2780
- console.log(import_chalk25.default.yellow(" Insufficient credits \u2014 top up to keep using the agent."));
2836
+ console.log(import_chalk26.default.yellow(" Insufficient credits \u2014 top up to keep using the agent."));
2781
2837
  break;
2782
2838
  }
2783
2839
  throw err;
2784
2840
  }
2785
2841
  history.push({ role: "assistant", content: resp.raw });
2786
2842
  printCost(resp.llm);
2787
- if (resp.reply) console.log(import_chalk25.default.green("agent") + " \u203A " + resp.reply);
2843
+ if (resp.reply) console.log(import_chalk26.default.green("agent") + " \u203A " + resp.reply);
2788
2844
  if (!resp.action) break;
2789
2845
  const tool = findTool(resp.action.tool);
2790
2846
  if (!tool) {
@@ -2809,15 +2865,15 @@ async function runAgent(opts) {
2809
2865
  }
2810
2866
  renderTrace();
2811
2867
  if (step === MAX_TOOL_STEPS - 1) {
2812
- console.log(import_chalk25.default.dim(" (paused after several steps \u2014 tell me how to continue)"));
2868
+ console.log(import_chalk26.default.dim(" (paused after several steps \u2014 tell me how to continue)"));
2813
2869
  }
2814
2870
  }
2815
2871
  }
2816
- console.log(import_chalk25.default.dim("\nBye."));
2872
+ console.log(import_chalk26.default.dim("\nBye."));
2817
2873
  }
2818
2874
 
2819
2875
  // src/commands/consumer.ts
2820
- var import_chalk26 = __toESM(require("chalk"));
2876
+ var import_chalk27 = __toESM(require("chalk"));
2821
2877
  var import_ora12 = __toESM(require("ora"));
2822
2878
  var DEFAULT_SCOPE = "openid email profile offline_access";
2823
2879
  var APIKEYS_BASE = process.env.APIBLAZE_APIKEYS_BASE || "https://apikeys.apiblaze.com";
@@ -2837,7 +2893,7 @@ async function consumerFetch(creds, suffix, init) {
2837
2893
  function requireConsumer() {
2838
2894
  const c = loadConsumer();
2839
2895
  if (!c) {
2840
- console.error(import_chalk26.default.red("Not logged in as a consumer. Run `apiblaze consumer login` first."));
2896
+ console.error(import_chalk27.default.red("Not logged in as a consumer. Run `apiblaze consumer login` first."));
2841
2897
  process.exit(1);
2842
2898
  }
2843
2899
  return c;
@@ -2848,7 +2904,7 @@ async function runConsumerLogin(opts) {
2848
2904
  let clientId = opts.client;
2849
2905
  if (clientId) {
2850
2906
  if (!tenant2) {
2851
- console.error(import_chalk26.default.red("When using --client, also pass --tenant <slug> (it sets which portal/keys host to use)."));
2907
+ console.error(import_chalk27.default.red("When using --client, also pass --tenant <slug> (it sets which portal/keys host to use)."));
2852
2908
  process.exit(1);
2853
2909
  }
2854
2910
  } else {
@@ -2861,7 +2917,7 @@ async function runConsumerLogin(opts) {
2861
2917
  (t) => typeof t === "string" ? { tenant_name: t } : t
2862
2918
  );
2863
2919
  if (!tenants.length) {
2864
- console.error(import_chalk26.default.red("This team has no tenants. Create one with `apiblaze tenant create`."));
2920
+ console.error(import_chalk27.default.red("This team has no tenants. Create one with `apiblaze tenant create`."));
2865
2921
  process.exit(1);
2866
2922
  }
2867
2923
  if (!tenant2) {
@@ -2877,19 +2933,19 @@ async function runConsumerLogin(opts) {
2877
2933
  const usable = (Array.isArray(clients) ? clients : []).filter((c) => c && (c.client_id || c.clientId));
2878
2934
  const pick2 = usable.find((c) => c.is_default || c.default) ?? usable.find((c) => c.verified !== false) ?? usable[0];
2879
2935
  if (!pick2) {
2880
- console.error(import_chalk26.default.red(`Tenant "${tenant2}" has no login app configured. Set one up in the dashboard (or \`apiblaze create\` with auth).`));
2936
+ console.error(import_chalk27.default.red(`Tenant "${tenant2}" has no login app configured. Set one up in the dashboard (or \`apiblaze create\` with auth).`));
2881
2937
  process.exit(1);
2882
2938
  }
2883
2939
  clientId = pick2.client_id ?? pick2.clientId;
2884
2940
  }
2885
2941
  const portalResource = `https://${tenant2}.portal.apiblaze.com/1.0.0`;
2886
- console.log(`${import_chalk26.default.cyan("\u2192")} Logging in to ${import_chalk26.default.bold(tenant2)} as a consumer...`);
2942
+ console.log(`${import_chalk27.default.cyan("\u2192")} Logging in to ${import_chalk27.default.bold(tenant2)} as a consumer...`);
2887
2943
  const result = await deviceLogin(clientId, DEFAULT_SCOPE, ({ verificationUri, userCode }) => {
2888
2944
  console.log(`
2889
- Open: ${import_chalk26.default.underline(verificationUri)}`);
2890
- console.log(` Code: ${import_chalk26.default.bold(userCode)}
2945
+ Open: ${import_chalk27.default.underline(verificationUri)}`);
2946
+ console.log(` Code: ${import_chalk27.default.bold(userCode)}
2891
2947
  `);
2892
- console.log(import_chalk26.default.dim(" (opening your browser\u2026 waiting for you to finish)"));
2948
+ console.log(import_chalk27.default.dim(" (opening your browser\u2026 waiting for you to finish)"));
2893
2949
  }, portalResource);
2894
2950
  const claims = result.idToken && decodeJwt2(result.idToken) || (decodeJwt2(result.accessToken) ?? {});
2895
2951
  const creds = {
@@ -2904,7 +2960,7 @@ async function runConsumerLogin(opts) {
2904
2960
  obtainedAt: Date.now()
2905
2961
  };
2906
2962
  saveConsumer(creds);
2907
- console.log(import_chalk26.default.green(`\u2714 Logged in as consumer${creds.email ? ` ${creds.email}` : ""} on ${tenant2}.`));
2963
+ console.log(import_chalk27.default.green(`\u2714 Logged in as consumer${creds.email ? ` ${creds.email}` : ""} on ${tenant2}.`));
2908
2964
  }
2909
2965
  async function runConsumerTokens(opts) {
2910
2966
  const creds = requireConsumer();
@@ -2917,18 +2973,18 @@ async function runConsumerTokens(opts) {
2917
2973
  console.log(JSON.stringify({ tenant: fresh.tenant, access_token: fresh.accessToken, refresh_token: fresh.refreshToken, id_token: fresh.idToken, expires_at: new Date(fresh.expiresAt).toISOString() }, null, 2));
2918
2974
  return;
2919
2975
  }
2920
- console.log(`${import_chalk26.default.cyan("Consumer")} ${import_chalk26.default.bold(fresh.email ?? fresh.tenant)} on ${import_chalk26.default.bold(fresh.tenant)}
2976
+ console.log(`${import_chalk27.default.cyan("Consumer")} ${import_chalk27.default.bold(fresh.email ?? fresh.tenant)} on ${import_chalk27.default.bold(fresh.tenant)}
2921
2977
  `);
2922
- console.log(`${import_chalk26.default.bold("access_token")} ${import_chalk26.default.dim("exp " + (exp(fresh.accessToken) ?? "?"))}
2978
+ console.log(`${import_chalk27.default.bold("access_token")} ${import_chalk27.default.dim("exp " + (exp(fresh.accessToken) ?? "?"))}
2923
2979
  ${fresh.accessToken}
2924
2980
  `);
2925
- if (fresh.idToken) console.log(`${import_chalk26.default.bold("id_token")} ${import_chalk26.default.dim("exp " + (exp(fresh.idToken) ?? "?"))}
2981
+ if (fresh.idToken) console.log(`${import_chalk27.default.bold("id_token")} ${import_chalk27.default.dim("exp " + (exp(fresh.idToken) ?? "?"))}
2926
2982
  ${fresh.idToken}
2927
2983
  `);
2928
- if (fresh.refreshToken) console.log(`${import_chalk26.default.bold("refresh_token")}
2984
+ if (fresh.refreshToken) console.log(`${import_chalk27.default.bold("refresh_token")}
2929
2985
  ${fresh.refreshToken}
2930
2986
  `);
2931
- console.log(import_chalk26.default.dim("These are your own tokens \u2014 keep them secret."));
2987
+ console.log(import_chalk27.default.dim("These are your own tokens \u2014 keep them secret."));
2932
2988
  }
2933
2989
  async function runConsumerApikeys(opts) {
2934
2990
  const creds = requireConsumer();
@@ -2938,8 +2994,8 @@ async function runConsumerApikeys(opts) {
2938
2994
  const revealed = await consumerFetch(list.creds, "/apikeys/reveal").catch(() => ({ status: 0, data: null, creds: list.creds }));
2939
2995
  spinner.stop();
2940
2996
  if (list.status >= 400) {
2941
- console.error(import_chalk26.default.red(`Failed to list keys (${list.status}): ${list.data?.error ?? ""}`));
2942
- if (list.status === 401) console.error(import_chalk26.default.dim("Your consumer session may have expired \u2014 run `apiblaze consumer login` again."));
2997
+ console.error(import_chalk27.default.red(`Failed to list keys (${list.status}): ${list.data?.error ?? ""}`));
2998
+ if (list.status === 401) console.error(import_chalk27.default.dim("Your consumer session may have expired \u2014 run `apiblaze consumer login` again."));
2943
2999
  process.exit(1);
2944
3000
  }
2945
3001
  const keys = list.data?.keys ?? [];
@@ -2947,16 +3003,16 @@ async function runConsumerApikeys(opts) {
2947
3003
  if (opts.json) {
2948
3004
  console.log(JSON.stringify({ keys, revealed: revealMap }, null, 2));
2949
3005
  } else if (!keys.length) {
2950
- console.log(import_chalk26.default.yellow("No API keys yet."));
3006
+ console.log(import_chalk27.default.yellow("No API keys yet."));
2951
3007
  } else {
2952
3008
  for (const k of keys) {
2953
3009
  const clear = revealMap[k.environment]?.key;
2954
- const shown = clear ? import_chalk26.default.green(clear) : import_chalk26.default.dim(`${k.key_prefix ?? ""}\u2026${k.key_suffix ?? ""}`);
2955
- const exp = k.expires_at ? import_chalk26.default.dim(`exp ${k.expires_at}`) : import_chalk26.default.dim("no expiry");
2956
- console.log(` ${import_chalk26.default.bold(k.environment ?? "")} ${shown} ${exp} ${import_chalk26.default.dim(k.description ?? "")}`);
3010
+ const shown = clear ? import_chalk27.default.green(clear) : import_chalk27.default.dim(`${k.key_prefix ?? ""}\u2026${k.key_suffix ?? ""}`);
3011
+ const exp = k.expires_at ? import_chalk27.default.dim(`exp ${k.expires_at}`) : import_chalk27.default.dim("no expiry");
3012
+ console.log(` ${import_chalk27.default.bold(k.environment ?? "")} ${shown} ${exp} ${import_chalk27.default.dim(k.description ?? "")}`);
2957
3013
  }
2958
3014
  if (Object.keys(revealMap).length === 0 && keys.some((k) => !k.expires_at)) {
2959
- console.log(import_chalk26.default.dim("\n(Only expiring keys can be shown in clear; non-expiring keys show a prefix only.)"));
3015
+ console.log(import_chalk27.default.dim("\n(Only expiring keys can be shown in clear; non-expiring keys show a prefix only.)"));
2960
3016
  }
2961
3017
  }
2962
3018
  if (opts.json) return;
@@ -2978,8 +3034,8 @@ async function runConsumerApikeys(opts) {
2978
3034
  }
2979
3035
  s2.succeed("Key created.");
2980
3036
  const key = created.data?.key ?? created.data?.fullKey;
2981
- if (key) console.log(` ${import_chalk26.default.green(key)} ${import_chalk26.default.dim("(shown once \u2014 store it now)")}`);
2982
- else console.log(import_chalk26.default.dim(" Key created; run `apiblaze consumer apikeys` to reveal it if it expires."));
3037
+ if (key) console.log(` ${import_chalk27.default.green(key)} ${import_chalk27.default.dim("(shown once \u2014 store it now)")}`);
3038
+ else console.log(import_chalk27.default.dim(" Key created; run `apiblaze consumer apikeys` to reveal it if it expires."));
2983
3039
  }
2984
3040
 
2985
3041
  // src/index.ts
@@ -3009,7 +3065,7 @@ program.command("login").description("Authenticate with APIblaze").action(async
3009
3065
  process.exit(1);
3010
3066
  }
3011
3067
  });
3012
- program.command("create").description("Create a new API proxy (no login needed \u2014 without auth it creates an anonymous proxy and prints a claim URL)").option("--name <name>", "Proxy name (becomes <name>.apiblaze.com)").option("--target <url>", "Target URL to forward requests to").option("--team <id|name>", "Team to create under (defaults to your active team)").option("--auth <type>", "Auth type: api_key | none | oauth", "api_key").option("--apiversion <version>", "API version to create (e.g. 2.0.0). Creating a new version of a proxy you own adds a version to the existing project.").option("--product <slug>", "Product tag to group this project under in the portal (team-scoped; anonymous create). Defaults to your team's existing/placeholder tag.").option("--display-name <name>", "Human-friendly display name").option("--subdomain <slug>", "Explicit subdomain (defaults to --name)").option("--config <file>", "JSON file with the full request body (anonymous create): requests_auth, login providers + client/server token types, scopes, callback URLs, etc. See apiblaze_anonymous.yaml. Flags override its fields.").option("-y, --yes", "Skip the confirmation prompt").option("--json", "Output machine-readable JSON (non-interactive)").action(async (opts) => {
3068
+ program.command("create").description("Create a new API proxy (no login needed \u2014 without auth it creates an anonymous proxy and prints a claim URL)").option("--name <name>", "Proxy name (becomes <name>.abz.run)").option("--target <url>", "Target URL to forward requests to").option("--team <id|name>", "Team to create under (defaults to your active team)").option("--auth <type>", "Auth type: api_key | none | oauth", "api_key").option("--apiversion <version>", "API version to create (e.g. 2.0.0). Creating a new version of a proxy you own adds a version to the existing project.").option("--product <slug>", "Product tag to group this project under in the portal (team-scoped; anonymous create). Defaults to your team's existing/placeholder tag.").option("--display-name <name>", "Human-friendly display name").option("--subdomain <slug>", "Explicit subdomain (defaults to --name)").option("--config <file>", "JSON file with the full request body (anonymous create): requests_auth, login providers + client/server token types, scopes, callback URLs, etc. See apiblaze_anonymous.yaml. Flags override its fields.").option("-y, --yes", "Skip the confirmation prompt").option("--json", "Output machine-readable JSON (non-interactive)").action(async (opts) => {
3013
3069
  try {
3014
3070
  await runCreate(opts);
3015
3071
  } catch (err) {
@@ -3025,7 +3081,7 @@ program.command("dev").description("Put your localhost behind a public URL (dev
3025
3081
  try {
3026
3082
  const resolved = parseInt(port ?? opts.port, 10);
3027
3083
  if (Number.isNaN(resolved)) {
3028
- console.error(import_chalk27.default.red(`Invalid port: ${port ?? opts.port}`));
3084
+ console.error(import_chalk28.default.red(`Invalid port: ${port ?? opts.port}`));
3029
3085
  process.exit(1);
3030
3086
  }
3031
3087
  await runDev({ port: resolved, captureFile: opts.captureFile });
@@ -3072,6 +3128,7 @@ program.command("projects").description("List the projects in your team").action
3072
3128
  }
3073
3129
  });
3074
3130
  program.command("delete").description("Delete a proxy and everything under it (asks first)").argument("<project>", "Project name or id (see `apiblaze projects`)").argument("[version]", "API version (defaults to the first match)").option("--team <id|name>", "Team the project is in (defaults to active team)").option("-y, --yes", "Skip the confirmation prompt").option("--json", "Output machine-readable JSON").action(action((project, version2, opts) => runDelete(project, version2, opts)));
3131
+ program.command("export").description("Export everything to migrate off apiblaze (no lock-in): config, users, keys + fidelity report").argument("<project>", "Project name or id (see `apiblaze projects`)").argument("[version]", "API version (defaults to the first match)").option("--kong", "Produce a runnable Kong OSS bundle (decK config + plugins + docker-compose)").option("--data", "Target-neutral data export (default)").option("--secrets", "Include decrypted producer-supplied secrets (member role; audit-logged)").option("--keys <mode>", "API-key export: hashes (default, consumers keep keys) | mint | none").option("--no-consumers", "Skip the end-user lane (users, groups, keys)").option("-o, --out <file>", "Output zip path").option("--team <id|name>", "Team the project is in (defaults to active team)").action(action((project, version2, opts) => runExport(project, version2, { ...opts, noConsumers: opts.consumers === false })));
3075
3132
  program.command("target").description("Change where a proxy forwards requests").argument("<project>", "Project name or id").requiredOption("--url <url>", "Target URL to forward to").option("--env <env>", "Environment to scope the target to (e.g. prod, dev)").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version (defaults to the first match)").option("--json", "Output machine-readable JSON").action(action((project, opts) => runTargetSet(project, opts)));
3076
3133
  program.command("throttle").description("Set rate limits and quotas for a proxy").argument("<project>", "Project name or id").option("--rate <n>", "User rate limit (requests/sec)").option("--end-user-rate <n>", "Per-end-user rate limit (requests/sec)").option("--quota <n>", "Proxy quota (requests/period)").option("--period <p>", "Quota period: daily | weekly | monthly").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").action(action((project, opts) => runThrottleSet(project, opts)));
3077
3134
  program.command("rename").description("Change a proxy's display name").argument("<project>", "Project name or id").requiredOption("--display-name <name>", "New human-friendly display name").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").action(action((project, opts) => runRename(project, opts)));
@@ -3110,7 +3167,7 @@ function groupedCommandHelp() {
3110
3167
  const c = byName.get(n);
3111
3168
  return c ? ` ${n.padEnd(width)}${c.description()}` : "";
3112
3169
  }).filter(Boolean).join("\n");
3113
- return `${import_chalk27.default.bold(g.title)}
3170
+ return `${import_chalk28.default.bold(g.title)}
3114
3171
  ${rows}`;
3115
3172
  }).join("\n\n");
3116
3173
  }
@@ -3136,13 +3193,13 @@ Examples:
3136
3193
  `);
3137
3194
  function printError(err) {
3138
3195
  if (err instanceof ApiError) {
3139
- console.error(import_chalk27.default.red(`
3196
+ console.error(import_chalk28.default.red(`
3140
3197
  API error (${err.status}): ${err.message}`));
3141
3198
  } else if (err instanceof Error) {
3142
- console.error(import_chalk27.default.red(`
3199
+ console.error(import_chalk28.default.red(`
3143
3200
  Error: ${err.message}`));
3144
3201
  } else {
3145
- console.error(import_chalk27.default.red("\nUnknown error"));
3202
+ console.error(import_chalk28.default.red("\nUnknown error"));
3146
3203
  }
3147
3204
  }
3148
3205
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.4.8",
3
+ "version": "0.4.10",
4
4
  "description": "Dev tunnel CLI for APIblaze — route localhost projects through your APIblaze endpoints",
5
5
  "keywords": [
6
6
  "apiblaze",