apiblaze 0.4.4 → 0.4.7

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 +71 -54
  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_chalk26 = __toESM(require("chalk"));
28
+ var import_chalk27 = __toESM(require("chalk"));
29
29
 
30
30
  // package.json
31
- var version = "0.4.4";
31
+ var version = "0.4.7";
32
32
 
33
33
  // src/types.ts
34
34
  var ApiError = class extends Error {
@@ -1516,12 +1516,12 @@ function openBrowser2(url) {
1516
1516
  } catch {
1517
1517
  }
1518
1518
  }
1519
- async function deviceLogin(clientId, scope, onPrompt) {
1519
+ async function deviceLogin(clientId, scope, onPrompt, resource) {
1520
1520
  const { verifier, challenge } = pkce();
1521
1521
  const startRes = await fetch(`${AUTH_BASE}/device_authorization`, {
1522
1522
  method: "POST",
1523
1523
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
1524
- body: new URLSearchParams({ client_id: clientId, scope, code_challenge: challenge, code_challenge_method: "S256" })
1524
+ body: new URLSearchParams({ client_id: clientId, scope, code_challenge: challenge, code_challenge_method: "S256", ...resource ? { resource } : {} })
1525
1525
  });
1526
1526
  const start = await startRes.json().catch(() => ({}));
1527
1527
  if (!startRes.ok) {
@@ -1541,7 +1541,11 @@ async function deviceLogin(clientId, scope, onPrompt) {
1541
1541
  const tokRes = await fetch(`${AUTH_BASE}/token`, {
1542
1542
  method: "POST",
1543
1543
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
1544
- body: new URLSearchParams({ grant_type: DEVICE_GRANT, device_code: deviceCode, code_verifier: verifier })
1544
+ // RFC 8707 resource indicator: sets the access token's `aud` to the portal
1545
+ // resource so the apikeys plane (which derives accepted auds as
1546
+ // https://{tenant}.portal.apiblaze.com/{ver}) accepts this token. Without it the
1547
+ // device grant falls back to aud=https://auth.apiblaze.com/device/callback → 401.
1548
+ body: new URLSearchParams({ grant_type: DEVICE_GRANT, device_code: deviceCode, code_verifier: verifier, ...resource ? { resource } : {} })
1545
1549
  });
1546
1550
  const tok = await tokRes.json().catch(() => ({}));
1547
1551
  if (tokRes.ok && tok.access_token) {
@@ -2012,7 +2016,7 @@ function renderTrace() {
2012
2016
  console.log(import_chalk15.default.dim("\n" + "\u2500".repeat(64)));
2013
2017
  console.log(import_chalk15.default.bold(`--verbose: ${entries.length} API call${entries.length === 1 ? "" : "s"} this command made`));
2014
2018
  console.log(
2015
- import_chalk15.default.dim("The same thing on the official API \u2014 copy/paste with your control-plane key\n(get one with `apiblaze apikeys`, then `export APIBLAZE_KEY=sk_...`):\n")
2019
+ import_chalk15.default.dim("The same thing on the official API \u2014 copy/paste with your control-plane key\n(get one from the Developers section of dashboard.apiblaze.com, then\n`export APIBLAZE_CONTROLPLANE_APIKEY=sk_...`):\n")
2016
2020
  );
2017
2021
  entries.forEach((e, i) => {
2018
2022
  const n = entries.length > 1 ? import_chalk15.default.bold(`${i + 1}. `) : "";
@@ -2021,7 +2025,7 @@ function renderTrace() {
2021
2025
  const masked = maskBody(e.body);
2022
2026
  const hasBody = e.method !== "GET" && masked !== void 0;
2023
2027
  console.log(import_chalk15.default.green(` curl -sS -X ${e.method} ${url}` + (hasBody ? " \\" : "")));
2024
- console.log(import_chalk15.default.green(' -H "X-API-Key: $APIBLAZE_KEY"' + (hasBody ? " \\" : "")));
2028
+ console.log(import_chalk15.default.green(' -H "X-API-Key: $APIBLAZE_CONTROLPLANE_APIKEY"' + (hasBody ? " \\" : "")));
2025
2029
  if (hasBody) {
2026
2030
  console.log(import_chalk15.default.green(" -H 'Content-Type: application/json' \\"));
2027
2031
  console.log(import_chalk15.default.green(` -d '${masked}'`));
@@ -2566,10 +2570,11 @@ async function runSpecSet(project, opts) {
2566
2570
  }
2567
2571
 
2568
2572
  // src/commands/agent.ts
2569
- var import_chalk24 = __toESM(require("chalk"));
2573
+ var import_chalk25 = __toESM(require("chalk"));
2570
2574
  var import_ora11 = __toESM(require("ora"));
2571
2575
 
2572
2576
  // src/lib/tools.ts
2577
+ var import_chalk24 = __toESM(require("chalk"));
2573
2578
  async function proj(teamId, name, version2) {
2574
2579
  return resolveProject(teamId, name, version2);
2575
2580
  }
@@ -2586,7 +2591,16 @@ var TOOLS = [
2586
2591
  const key = keys.dev ?? Object.values(keys)[0];
2587
2592
  const url = `https://${a.name}.apiblaze.com/${version2}/dev`;
2588
2593
  const tryIt = buildTryItCurl(url, auth, key);
2589
- return { ...res, proxy_url: url, ...tryIt ? { try_it: tryIt } : {} };
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}`);
2596
+ const envs = Object.keys(keys);
2597
+ 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):")}`);
2599
+ 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])}`);
2601
+ }
2602
+ if (tryIt) lines.push("", ` ${import_chalk24.default.dim("Try it:")}`, ` ${import_chalk24.default.cyan(tryIt)}`);
2603
+ return { ...res, proxy_url: url, keys, ...tryIt ? { try_it: tryIt } : {}, display: lines.join("\n") };
2590
2604
  }
2591
2605
  },
2592
2606
  {
@@ -2739,17 +2753,17 @@ function truncate(value, max = 1500) {
2739
2753
  }
2740
2754
  function printCost(llm) {
2741
2755
  const usd = llm.cost > 0 ? `$${llm.cost.toFixed(4)}` : "<$0.0001";
2742
- console.log(import_chalk24.default.magenta(` \u{1F4B3} ${usd}`) + import_chalk24.default.dim(` (${llm.model}, ${llm.total_tokens} tok)`));
2756
+ console.log(import_chalk25.default.magenta(` \u{1F4B3} ${usd}`) + import_chalk25.default.dim(` (${llm.model}, ${llm.total_tokens} tok)`));
2743
2757
  }
2744
2758
  async function runAgent(opts) {
2745
2759
  requireAuth();
2746
2760
  const { teamId, teamName } = await resolveTeam(opts.team);
2747
2761
  const { default: inquirer2 } = await import("inquirer");
2748
- console.log(import_chalk24.default.bold("APIblaze agent") + import_chalk24.default.dim(` \xB7 team ${teamName ?? teamId}`));
2749
- console.log(import_chalk24.default.dim('Ask me to create/delete/configure proxies, tenants, keys, domains, specs. Type "exit" to quit.\n'));
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'));
2750
2764
  const history = [];
2751
2765
  while (true) {
2752
- const { input } = await inquirer2.prompt([{ type: "input", name: "input", message: import_chalk24.default.cyan("you") + " \u203A" }]);
2766
+ const { input } = await inquirer2.prompt([{ type: "input", name: "input", message: import_chalk25.default.cyan("you") + " \u203A" }]);
2753
2767
  const text = (input ?? "").trim();
2754
2768
  if (!text) continue;
2755
2769
  if (["exit", "quit", ":q"].includes(text.toLowerCase())) break;
@@ -2763,14 +2777,14 @@ async function runAgent(opts) {
2763
2777
  } catch (err) {
2764
2778
  spinner.stop();
2765
2779
  if (err instanceof ApiError && err.status === 402) {
2766
- console.log(import_chalk24.default.yellow(" Insufficient credits \u2014 top up to keep using the agent."));
2780
+ console.log(import_chalk25.default.yellow(" Insufficient credits \u2014 top up to keep using the agent."));
2767
2781
  break;
2768
2782
  }
2769
2783
  throw err;
2770
2784
  }
2771
2785
  history.push({ role: "assistant", content: resp.raw });
2772
2786
  printCost(resp.llm);
2773
- if (resp.reply) console.log(import_chalk24.default.green("agent") + " \u203A " + resp.reply);
2787
+ if (resp.reply) console.log(import_chalk25.default.green("agent") + " \u203A " + resp.reply);
2774
2788
  if (!resp.action) break;
2775
2789
  const tool = findTool(resp.action.tool);
2776
2790
  if (!tool) {
@@ -2781,7 +2795,13 @@ async function runAgent(opts) {
2781
2795
  try {
2782
2796
  const result = await tool.run(resp.action.args, { teamId });
2783
2797
  runSpinner.succeed(`${tool.name} \u2713`);
2784
- history.push({ role: "user", content: `TOOL_RESULT ${tool.name}: ${truncate(result)}` });
2798
+ let forHistory = result;
2799
+ if (result && typeof result === "object" && typeof result.display === "string") {
2800
+ console.log("\n" + result.display + "\n");
2801
+ const { display, ...rest } = result;
2802
+ forHistory = { ...rest, _note: "Details + keys already shown to the user verbatim; do not repeat the keys." };
2803
+ }
2804
+ history.push({ role: "user", content: `TOOL_RESULT ${tool.name}: ${truncate(forHistory)}` });
2785
2805
  } catch (err) {
2786
2806
  runSpinner.fail(`${tool.name} failed`);
2787
2807
  const msg = err instanceof Error ? err.message : String(err);
@@ -2789,25 +2809,21 @@ async function runAgent(opts) {
2789
2809
  }
2790
2810
  renderTrace();
2791
2811
  if (step === MAX_TOOL_STEPS - 1) {
2792
- console.log(import_chalk24.default.dim(" (paused after several steps \u2014 tell me how to continue)"));
2812
+ console.log(import_chalk25.default.dim(" (paused after several steps \u2014 tell me how to continue)"));
2793
2813
  }
2794
2814
  }
2795
2815
  }
2796
- console.log(import_chalk24.default.dim("\nBye."));
2816
+ console.log(import_chalk25.default.dim("\nBye."));
2797
2817
  }
2798
2818
 
2799
2819
  // src/commands/consumer.ts
2800
- var import_chalk25 = __toESM(require("chalk"));
2820
+ var import_chalk26 = __toESM(require("chalk"));
2801
2821
  var import_ora12 = __toESM(require("ora"));
2802
- var APIKEYS_VER = "1.0.0";
2803
2822
  var DEFAULT_SCOPE = "openid email profile offline_access";
2804
- function apikeysBase(tenant2) {
2805
- const tmpl = process.env.APIBLAZE_APIKEYS_BASE_TMPL;
2806
- return tmpl ? tmpl.replace("{tenant}", tenant2) : `https://${tenant2}.apikeys.apiblaze.com`;
2807
- }
2823
+ var APIKEYS_BASE = process.env.APIBLAZE_APIKEYS_BASE || "https://apikeys.apiblaze.com";
2808
2824
  async function consumerFetch(creds, suffix, init) {
2809
2825
  const fresh = await validConsumerToken(creds) ?? creds;
2810
- const res = await fetch(`${apikeysBase(fresh.tenant)}/${APIKEYS_VER}${suffix}`, {
2826
+ const res = await fetch(`${APIKEYS_BASE}${suffix}`, {
2811
2827
  ...init,
2812
2828
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${fresh.accessToken}`, ...init?.headers ?? {} }
2813
2829
  });
@@ -2821,7 +2837,7 @@ async function consumerFetch(creds, suffix, init) {
2821
2837
  function requireConsumer() {
2822
2838
  const c = loadConsumer();
2823
2839
  if (!c) {
2824
- console.error(import_chalk25.default.red("Not logged in as a consumer. Run `apiblaze consumer login` first."));
2840
+ console.error(import_chalk26.default.red("Not logged in as a consumer. Run `apiblaze consumer login` first."));
2825
2841
  process.exit(1);
2826
2842
  }
2827
2843
  return c;
@@ -2832,7 +2848,7 @@ async function runConsumerLogin(opts) {
2832
2848
  let clientId = opts.client;
2833
2849
  if (clientId) {
2834
2850
  if (!tenant2) {
2835
- console.error(import_chalk25.default.red("When using --client, also pass --tenant <slug> (it sets which portal/keys host to use)."));
2851
+ console.error(import_chalk26.default.red("When using --client, also pass --tenant <slug> (it sets which portal/keys host to use)."));
2836
2852
  process.exit(1);
2837
2853
  }
2838
2854
  } else {
@@ -2845,7 +2861,7 @@ async function runConsumerLogin(opts) {
2845
2861
  (t) => typeof t === "string" ? { tenant_name: t } : t
2846
2862
  );
2847
2863
  if (!tenants.length) {
2848
- console.error(import_chalk25.default.red("This team has no tenants. Create one with `apiblaze tenant create`."));
2864
+ console.error(import_chalk26.default.red("This team has no tenants. Create one with `apiblaze tenant create`."));
2849
2865
  process.exit(1);
2850
2866
  }
2851
2867
  if (!tenant2) {
@@ -2861,19 +2877,20 @@ async function runConsumerLogin(opts) {
2861
2877
  const usable = (Array.isArray(clients) ? clients : []).filter((c) => c && (c.client_id || c.clientId));
2862
2878
  const pick2 = usable.find((c) => c.is_default || c.default) ?? usable.find((c) => c.verified !== false) ?? usable[0];
2863
2879
  if (!pick2) {
2864
- console.error(import_chalk25.default.red(`Tenant "${tenant2}" has no login app configured. Set one up in the dashboard (or \`apiblaze create\` with auth).`));
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).`));
2865
2881
  process.exit(1);
2866
2882
  }
2867
2883
  clientId = pick2.client_id ?? pick2.clientId;
2868
2884
  }
2869
- console.log(`${import_chalk25.default.cyan("\u2192")} Logging in to ${import_chalk25.default.bold(tenant2)} as a consumer...`);
2885
+ 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...`);
2870
2887
  const result = await deviceLogin(clientId, DEFAULT_SCOPE, ({ verificationUri, userCode }) => {
2871
2888
  console.log(`
2872
- Open: ${import_chalk25.default.underline(verificationUri)}`);
2873
- console.log(` Code: ${import_chalk25.default.bold(userCode)}
2889
+ Open: ${import_chalk26.default.underline(verificationUri)}`);
2890
+ console.log(` Code: ${import_chalk26.default.bold(userCode)}
2874
2891
  `);
2875
- console.log(import_chalk25.default.dim(" (opening your browser\u2026 waiting for you to finish)"));
2876
- });
2892
+ console.log(import_chalk26.default.dim(" (opening your browser\u2026 waiting for you to finish)"));
2893
+ }, portalResource);
2877
2894
  const claims = result.idToken && decodeJwt2(result.idToken) || (decodeJwt2(result.accessToken) ?? {});
2878
2895
  const creds = {
2879
2896
  tenant: tenant2,
@@ -2887,7 +2904,7 @@ async function runConsumerLogin(opts) {
2887
2904
  obtainedAt: Date.now()
2888
2905
  };
2889
2906
  saveConsumer(creds);
2890
- console.log(import_chalk25.default.green(`\u2714 Logged in as consumer${creds.email ? ` ${creds.email}` : ""} on ${tenant2}.`));
2907
+ console.log(import_chalk26.default.green(`\u2714 Logged in as consumer${creds.email ? ` ${creds.email}` : ""} on ${tenant2}.`));
2891
2908
  }
2892
2909
  async function runConsumerTokens(opts) {
2893
2910
  const creds = requireConsumer();
@@ -2900,18 +2917,18 @@ async function runConsumerTokens(opts) {
2900
2917
  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));
2901
2918
  return;
2902
2919
  }
2903
- console.log(`${import_chalk25.default.cyan("Consumer")} ${import_chalk25.default.bold(fresh.email ?? fresh.tenant)} on ${import_chalk25.default.bold(fresh.tenant)}
2920
+ console.log(`${import_chalk26.default.cyan("Consumer")} ${import_chalk26.default.bold(fresh.email ?? fresh.tenant)} on ${import_chalk26.default.bold(fresh.tenant)}
2904
2921
  `);
2905
- console.log(`${import_chalk25.default.bold("access_token")} ${import_chalk25.default.dim("exp " + (exp(fresh.accessToken) ?? "?"))}
2922
+ console.log(`${import_chalk26.default.bold("access_token")} ${import_chalk26.default.dim("exp " + (exp(fresh.accessToken) ?? "?"))}
2906
2923
  ${fresh.accessToken}
2907
2924
  `);
2908
- if (fresh.idToken) console.log(`${import_chalk25.default.bold("id_token")} ${import_chalk25.default.dim("exp " + (exp(fresh.idToken) ?? "?"))}
2925
+ if (fresh.idToken) console.log(`${import_chalk26.default.bold("id_token")} ${import_chalk26.default.dim("exp " + (exp(fresh.idToken) ?? "?"))}
2909
2926
  ${fresh.idToken}
2910
2927
  `);
2911
- if (fresh.refreshToken) console.log(`${import_chalk25.default.bold("refresh_token")}
2928
+ if (fresh.refreshToken) console.log(`${import_chalk26.default.bold("refresh_token")}
2912
2929
  ${fresh.refreshToken}
2913
2930
  `);
2914
- console.log(import_chalk25.default.dim("These are your own tokens \u2014 keep them secret."));
2931
+ console.log(import_chalk26.default.dim("These are your own tokens \u2014 keep them secret."));
2915
2932
  }
2916
2933
  async function runConsumerApikeys(opts) {
2917
2934
  const creds = requireConsumer();
@@ -2921,8 +2938,8 @@ async function runConsumerApikeys(opts) {
2921
2938
  const revealed = await consumerFetch(list.creds, "/apikeys/reveal").catch(() => ({ status: 0, data: null, creds: list.creds }));
2922
2939
  spinner.stop();
2923
2940
  if (list.status >= 400) {
2924
- console.error(import_chalk25.default.red(`Failed to list keys (${list.status}): ${list.data?.error ?? ""}`));
2925
- if (list.status === 401) console.error(import_chalk25.default.dim("Your consumer session may have expired \u2014 run `apiblaze consumer login` again."));
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."));
2926
2943
  process.exit(1);
2927
2944
  }
2928
2945
  const keys = list.data?.keys ?? [];
@@ -2930,16 +2947,16 @@ async function runConsumerApikeys(opts) {
2930
2947
  if (opts.json) {
2931
2948
  console.log(JSON.stringify({ keys, revealed: revealMap }, null, 2));
2932
2949
  } else if (!keys.length) {
2933
- console.log(import_chalk25.default.yellow("No API keys yet."));
2950
+ console.log(import_chalk26.default.yellow("No API keys yet."));
2934
2951
  } else {
2935
2952
  for (const k of keys) {
2936
2953
  const clear = revealMap[k.environment]?.key;
2937
- const shown = clear ? import_chalk25.default.green(clear) : import_chalk25.default.dim(`${k.key_prefix ?? ""}\u2026${k.key_suffix ?? ""}`);
2938
- const exp = k.expires_at ? import_chalk25.default.dim(`exp ${k.expires_at}`) : import_chalk25.default.dim("no expiry");
2939
- console.log(` ${import_chalk25.default.bold(k.environment ?? "")} ${shown} ${exp} ${import_chalk25.default.dim(k.description ?? "")}`);
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 ?? "")}`);
2940
2957
  }
2941
2958
  if (Object.keys(revealMap).length === 0 && keys.some((k) => !k.expires_at)) {
2942
- console.log(import_chalk25.default.dim("\n(Only expiring keys can be shown in clear; non-expiring keys show a prefix only.)"));
2959
+ console.log(import_chalk26.default.dim("\n(Only expiring keys can be shown in clear; non-expiring keys show a prefix only.)"));
2943
2960
  }
2944
2961
  }
2945
2962
  if (opts.json) return;
@@ -2961,8 +2978,8 @@ async function runConsumerApikeys(opts) {
2961
2978
  }
2962
2979
  s2.succeed("Key created.");
2963
2980
  const key = created.data?.key ?? created.data?.fullKey;
2964
- if (key) console.log(` ${import_chalk25.default.green(key)} ${import_chalk25.default.dim("(shown once \u2014 store it now)")}`);
2965
- else console.log(import_chalk25.default.dim(" Key created; run `apiblaze consumer apikeys` to reveal it if it expires."));
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."));
2966
2983
  }
2967
2984
 
2968
2985
  // src/index.ts
@@ -3008,7 +3025,7 @@ program.command("dev").description("Put your localhost behind a public URL (dev
3008
3025
  try {
3009
3026
  const resolved = parseInt(port ?? opts.port, 10);
3010
3027
  if (Number.isNaN(resolved)) {
3011
- console.error(import_chalk26.default.red(`Invalid port: ${port ?? opts.port}`));
3028
+ console.error(import_chalk27.default.red(`Invalid port: ${port ?? opts.port}`));
3012
3029
  process.exit(1);
3013
3030
  }
3014
3031
  await runDev({ port: resolved, captureFile: opts.captureFile });
@@ -3093,7 +3110,7 @@ function groupedCommandHelp() {
3093
3110
  const c = byName.get(n);
3094
3111
  return c ? ` ${n.padEnd(width)}${c.description()}` : "";
3095
3112
  }).filter(Boolean).join("\n");
3096
- return `${import_chalk26.default.bold(g.title)}
3113
+ return `${import_chalk27.default.bold(g.title)}
3097
3114
  ${rows}`;
3098
3115
  }).join("\n\n");
3099
3116
  }
@@ -3119,13 +3136,13 @@ Examples:
3119
3136
  `);
3120
3137
  function printError(err) {
3121
3138
  if (err instanceof ApiError) {
3122
- console.error(import_chalk26.default.red(`
3139
+ console.error(import_chalk27.default.red(`
3123
3140
  API error (${err.status}): ${err.message}`));
3124
3141
  } else if (err instanceof Error) {
3125
- console.error(import_chalk26.default.red(`
3142
+ console.error(import_chalk27.default.red(`
3126
3143
  Error: ${err.message}`));
3127
3144
  } else {
3128
- console.error(import_chalk26.default.red("\nUnknown error"));
3145
+ console.error(import_chalk27.default.red("\nUnknown error"));
3129
3146
  }
3130
3147
  }
3131
3148
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.4.4",
3
+ "version": "0.4.7",
4
4
  "description": "Dev tunnel CLI for APIblaze — route localhost projects through your APIblaze endpoints",
5
5
  "keywords": [
6
6
  "apiblaze",