apiblaze 0.4.2 → 0.4.4

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 +58 -36
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ var import_commander = require("commander");
28
28
  var import_chalk26 = __toESM(require("chalk"));
29
29
 
30
30
  // package.json
31
- var version = "0.4.2";
31
+ var version = "0.4.4";
32
32
 
33
33
  // src/types.ts
34
34
  var ApiError = class extends Error {
@@ -1104,14 +1104,23 @@ function fail(message) {
1104
1104
  console.error(import_chalk6.default.red(`Error: ${message}`));
1105
1105
  process.exit(1);
1106
1106
  }
1107
- function printCurlExample(url, apiKey) {
1107
+ function buildTryItCurl(url, authType, apiKey) {
1108
+ if (authType === "api_key") {
1109
+ if (!apiKey) return null;
1110
+ return `curl ${url} -H "X-API-Key: ${apiKey}"`;
1111
+ }
1112
+ if (authType === "none") return `curl ${url}`;
1113
+ return null;
1114
+ }
1115
+ function printCurlExample(url, authType, apiKey, devPortal) {
1116
+ const curl = buildTryItCurl(url, authType, apiKey);
1108
1117
  console.log();
1109
- console.log(` ${import_chalk6.default.dim("Try it with curl:")}`);
1110
- if (apiKey) {
1111
- console.log(` ${import_chalk6.default.cyan(`curl ${url} \\`)}`);
1112
- console.log(` ${import_chalk6.default.cyan(` -H "X-API-Key: ${apiKey}"`)}`);
1113
- } else {
1114
- console.log(` ${import_chalk6.default.cyan(`curl ${url}`)}`);
1118
+ if (curl) {
1119
+ console.log(` ${import_chalk6.default.dim("Try it \u2014 copy/paste:")}`);
1120
+ console.log(` ${import_chalk6.default.cyan(curl)}`);
1121
+ } else if (authType === "oauth") {
1122
+ console.log(` ${import_chalk6.default.dim("Try it:")} this proxy uses OAuth \u2014 sign in at ${import_chalk6.default.bold(devPortal ?? "the dev portal")} to get a token,`);
1123
+ console.log(` ${import_chalk6.default.dim(`then call ${url} with`)} ${import_chalk6.default.cyan('-H "Authorization: Bearer <token>"')}`);
1115
1124
  }
1116
1125
  }
1117
1126
  var VALID_AUTH = ["api_key", "none", "oauth"];
@@ -1259,7 +1268,7 @@ async function runCreate(opts = {}) {
1259
1268
  console.log(import_chalk6.default.dim(` (Separate keys were also created for: ${otherEnvs.join(", ")}.)`));
1260
1269
  }
1261
1270
  }
1262
- printCurlExample(proxyUrl, auth === "none" ? void 0 : adminKey);
1271
+ printCurlExample(proxyUrl, auth, adminKey, devPortal);
1263
1272
  console.log();
1264
1273
  }
1265
1274
  async function runAnonymousCreate(opts) {
@@ -1370,7 +1379,7 @@ async function runAnonymousCreate(opts) {
1370
1379
  console.log(` ${import_chalk6.default.bold.green(apiKey)}`);
1371
1380
  console.log(import_chalk6.default.dim("\n Save this now \u2014 send it as the X-API-Key header. It may not be shown again."));
1372
1381
  }
1373
- if (prodEndpoint) printCurlExample(prodEndpoint, apiKey);
1382
+ if (prodEndpoint) printCurlExample(prodEndpoint, opts.auth || "api_key", apiKey, result.portal);
1374
1383
  if (result.claim_url) {
1375
1384
  console.log();
1376
1385
  console.log(` ${import_chalk6.default.yellow("\u26A0 Anonymous proxy \u2014 claim it to your account within 30 days or it expires:")}`);
@@ -1984,6 +1993,7 @@ var import_chalk16 = __toESM(require("chalk"));
1984
1993
 
1985
1994
  // src/lib/trace.ts
1986
1995
  var import_chalk15 = __toESM(require("chalk"));
1996
+ var CONTROL_API_VERSION = "1.0.0";
1987
1997
  var verbose = false;
1988
1998
  var entries = [];
1989
1999
  function setVerbose(v) {
@@ -2002,24 +2012,23 @@ function renderTrace() {
2002
2012
  console.log(import_chalk15.default.dim("\n" + "\u2500".repeat(64)));
2003
2013
  console.log(import_chalk15.default.bold(`--verbose: ${entries.length} API call${entries.length === 1 ? "" : "s"} this command made`));
2004
2014
  console.log(
2005
- import_chalk15.default.dim("Copy/paste the curl below to do it yourself \u2014 it uses your own login token.\n")
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")
2006
2016
  );
2007
2017
  entries.forEach((e, i) => {
2008
2018
  const n = entries.length > 1 ? import_chalk15.default.bold(`${i + 1}. `) : "";
2009
2019
  if (e.summary) console.log(`${n}${import_chalk15.default.cyan(e.summary)}${e.status ? import_chalk15.default.dim(` (HTTP ${e.status})`) : ""}`);
2020
+ const url = `https://api.apiblaze.com/${CONTROL_API_VERSION}/prod${e.path}`;
2010
2021
  const masked = maskBody(e.body);
2011
- const payload = JSON.stringify({ path: e.path, method: e.method, ...masked ? { body: JSON.parse(masked) } : {} });
2012
- console.log(import_chalk15.default.green(" curl -sS -X POST https://dashboard.apiblaze.com/api/cli/admin \\"));
2013
- console.log(import_chalk15.default.green(' -H "Authorization: Bearer $(jq -r .accessToken ~/.apiblaze/credentials.json)" \\'));
2014
- console.log(import_chalk15.default.green(" -H 'Content-Type: application/json' \\"));
2015
- console.log(import_chalk15.default.green(` -d '${payload}'`));
2016
- console.log(
2017
- import_chalk15.default.dim(
2018
- ` # \u2192 admin-api leaf (Lane 3, X-User-Assertion minted server-side): ${e.method} ${e.path}`
2019
- )
2020
- );
2022
+ const hasBody = e.method !== "GET" && masked !== void 0;
2023
+ 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 ? " \\" : "")));
2025
+ if (hasBody) {
2026
+ console.log(import_chalk15.default.green(" -H 'Content-Type: application/json' \\"));
2027
+ console.log(import_chalk15.default.green(` -d '${masked}'`));
2028
+ }
2021
2029
  if (i < entries.length - 1) console.log();
2022
2030
  });
2031
+ entries.length = 0;
2023
2032
  }
2024
2033
 
2025
2034
  // src/lib/admin.ts
@@ -2148,7 +2157,7 @@ async function runDelete(project, version2, opts) {
2148
2157
  try {
2149
2158
  await admin({
2150
2159
  method: "DELETE",
2151
- path: `/${proj2.projectId}/${proj2.apiVersion}`,
2160
+ path: `/projects/${proj2.projectId}/${proj2.apiVersion}`,
2152
2161
  summary: `Delete proxy ${proj2.projectName} v${proj2.apiVersion} (full cascade)`
2153
2162
  });
2154
2163
  s2.succeed(`Deleted ${proj2.projectName} v${proj2.apiVersion}.`);
@@ -2169,7 +2178,7 @@ async function patchConfig(project, opts, body, summary) {
2169
2178
  try {
2170
2179
  const out = await admin({
2171
2180
  method: "PATCH",
2172
- path: `/${proj2.projectId}/${proj2.apiVersion}/config`,
2181
+ path: `/projects/${proj2.projectId}/${proj2.apiVersion}`,
2173
2182
  body,
2174
2183
  summary
2175
2184
  });
@@ -2228,9 +2237,10 @@ async function runDomainAdd(project, opts) {
2228
2237
  try {
2229
2238
  const out = await admin({
2230
2239
  method: "POST",
2231
- path: `/projects/${proj2.projectId}/cf-domains`,
2240
+ path: `/projects/${proj2.projectId}/domains`,
2241
+ // --tenant binds the domain to one of the project's tenants (per-tenant scope).
2232
2242
  body: { hostname: opts.domain, api_version: proj2.apiVersion, ...opts.tenant ? { tenant_name: opts.tenant } : {} },
2233
- summary: `Add custom domain ${opts.domain} to ${proj2.projectName} v${proj2.apiVersion}`
2243
+ summary: `Add custom domain ${opts.domain} to ${proj2.projectName} v${proj2.apiVersion}${opts.tenant ? ` (tenant ${opts.tenant})` : ""}`
2234
2244
  });
2235
2245
  spinner.succeed(`Registered ${opts.domain}. Add these DNS records, then run \`apiblaze domain status\`:`);
2236
2246
  if (opts.json) {
@@ -2250,7 +2260,7 @@ async function runDomainList(project, opts) {
2250
2260
  const proj2 = await resolveProject(teamId, project, opts.apiversion);
2251
2261
  const out = await admin({
2252
2262
  method: "GET",
2253
- path: `/projects/${proj2.projectId}/cf-domains?api_version=${encodeURIComponent(proj2.apiVersion)}`,
2263
+ path: `/projects/${proj2.projectId}/domains?api_version=${encodeURIComponent(proj2.apiVersion)}`,
2254
2264
  summary: `List custom domains for ${proj2.projectName} v${proj2.apiVersion}`
2255
2265
  });
2256
2266
  const domains = out?.domains ?? [];
@@ -2273,7 +2283,7 @@ async function runDomainStatus(project, opts) {
2273
2283
  const proj2 = await resolveProject(teamId, project, opts.apiversion);
2274
2284
  const out = await admin({
2275
2285
  method: "GET",
2276
- path: `/projects/${proj2.projectId}/cf-domains/${encodeURIComponent(opts.id)}/status`,
2286
+ path: `/projects/${proj2.projectId}/domains/${encodeURIComponent(opts.id)}/status`,
2277
2287
  summary: `Check custom-domain status`
2278
2288
  });
2279
2289
  console.log(opts.json ? JSON.stringify(out) : ` ${import_chalk20.default.bold(out?.hostname ?? opts.id)}: ${import_chalk20.default.cyan(out?.status ?? "unknown")}`);
@@ -2289,7 +2299,7 @@ async function runDomainRemove(project, opts) {
2289
2299
  try {
2290
2300
  await admin({
2291
2301
  method: "DELETE",
2292
- path: `/projects/${proj2.projectId}/cf-domains/${encodeURIComponent(opts.id)}`,
2302
+ path: `/projects/${proj2.projectId}/domains/${encodeURIComponent(opts.id)}`,
2293
2303
  summary: `Remove custom domain ${opts.id}`
2294
2304
  });
2295
2305
  spinner.succeed("Removed.");
@@ -2568,7 +2578,16 @@ var TOOLS = [
2568
2578
  name: "create_proxy",
2569
2579
  description: "Create a new API proxy (project) from a backend URL. auth is one of: api_key, none, oauth.",
2570
2580
  params: { name: "proxy name (becomes its subdomain)", target: "backend URL to forward to", auth: "api_key | none | oauth (default api_key)" },
2571
- run: async (a, { teamId }) => createProxy({ name: a.name, target_url: a.target ?? a.target_url ?? a.url, auth_type: a.auth ?? a.auth_type ?? "api_key", team_id: teamId })
2581
+ run: async (a, { teamId }) => {
2582
+ const auth = a.auth ?? a.auth_type ?? "api_key";
2583
+ const res = await createProxy({ name: a.name, target_url: a.target ?? a.target_url ?? a.url, auth_type: auth, team_id: teamId });
2584
+ const version2 = res.api_version || "1.0.0";
2585
+ const keys = res.api_keys ?? {};
2586
+ const key = keys.dev ?? Object.values(keys)[0];
2587
+ const url = `https://${a.name}.apiblaze.com/${version2}/dev`;
2588
+ const tryIt = buildTryItCurl(url, auth, key);
2589
+ return { ...res, proxy_url: url, ...tryIt ? { try_it: tryIt } : {} };
2590
+ }
2572
2591
  },
2573
2592
  {
2574
2593
  name: "list_projects",
@@ -2583,7 +2602,7 @@ var TOOLS = [
2583
2602
  run: async (a, { teamId }) => {
2584
2603
  const p = await proj(teamId, a.project, a.apiversion);
2585
2604
  const body = a.env ? { environments: { [a.env]: { target: a.url } } } : { target_url: a.url };
2586
- return admin({ method: "PATCH", path: `/${p.projectId}/${p.apiVersion}/config`, body, summary: `Set target for ${p.projectName}` });
2605
+ return admin({ method: "PATCH", path: `/projects/${p.projectId}/${p.apiVersion}`, body, summary: `Set target for ${p.projectName}` });
2587
2606
  }
2588
2607
  },
2589
2608
  {
@@ -2596,7 +2615,7 @@ var TOOLS = [
2596
2615
  if (a.rate != null) throttling.userRateLimit = Number(a.rate);
2597
2616
  if (a.quota != null) throttling.proxyQuota = Number(a.quota);
2598
2617
  if (a.period) throttling.quotaPeriod = a.period;
2599
- return admin({ method: "PATCH", path: `/${p.projectId}/${p.apiVersion}/config`, body: { throttling }, summary: `Throttle ${p.projectName}` });
2618
+ return admin({ method: "PATCH", path: `/projects/${p.projectId}/${p.apiVersion}`, body: { throttling }, summary: `Throttle ${p.projectName}` });
2600
2619
  }
2601
2620
  },
2602
2621
  {
@@ -2605,7 +2624,7 @@ var TOOLS = [
2605
2624
  params: { project: "project name or id", display_name: "new display name" },
2606
2625
  run: async (a, { teamId }) => {
2607
2626
  const p = await proj(teamId, a.project, a.apiversion);
2608
- return admin({ method: "PATCH", path: `/${p.projectId}/${p.apiVersion}/config`, body: { display_name: a.display_name }, summary: `Rename ${p.projectName}` });
2627
+ return admin({ method: "PATCH", path: `/projects/${p.projectId}/${p.apiVersion}`, body: { display_name: a.display_name }, summary: `Rename ${p.projectName}` });
2609
2628
  }
2610
2629
  },
2611
2630
  {
@@ -2614,7 +2633,7 @@ var TOOLS = [
2614
2633
  params: { project: "project name or id", version: "optional api version" },
2615
2634
  run: async (a, { teamId }) => {
2616
2635
  const p = await proj(teamId, a.project, a.version);
2617
- return admin({ method: "DELETE", path: `/${p.projectId}/${p.apiVersion}`, summary: `Delete ${p.projectName} (cascade)` });
2636
+ return admin({ method: "DELETE", path: `/projects/${p.projectId}/${p.apiVersion}`, summary: `Delete ${p.projectName} (cascade)` });
2618
2637
  }
2619
2638
  },
2620
2639
  {
@@ -2661,7 +2680,7 @@ var TOOLS = [
2661
2680
  params: { project: "project name or id" },
2662
2681
  run: async (a, { teamId }) => {
2663
2682
  const p = await proj(teamId, a.project, a.apiversion);
2664
- return admin({ method: "GET", path: `/projects/${p.projectId}/cf-domains?api_version=${encodeURIComponent(p.apiVersion)}`, summary: `List domains for ${p.projectName}` });
2683
+ return admin({ method: "GET", path: `/projects/${p.projectId}/domains?api_version=${encodeURIComponent(p.apiVersion)}`, summary: `List domains for ${p.projectName}` });
2665
2684
  }
2666
2685
  },
2667
2686
  {
@@ -2768,6 +2787,7 @@ async function runAgent(opts) {
2768
2787
  const msg = err instanceof Error ? err.message : String(err);
2769
2788
  history.push({ role: "user", content: `TOOL_RESULT ${tool.name}: error \u2014 ${truncate(msg, 400)}` });
2770
2789
  }
2790
+ renderTrace();
2771
2791
  if (step === MAX_TOOL_STEPS - 1) {
2772
2792
  console.log(import_chalk24.default.dim(" (paused after several steps \u2014 tell me how to continue)"));
2773
2793
  }
@@ -2956,7 +2976,9 @@ function action(fn) {
2956
2976
  return async (...args) => {
2957
2977
  try {
2958
2978
  await fn(...args);
2979
+ renderTrace();
2959
2980
  } catch (err) {
2981
+ renderTrace();
2960
2982
  printError(err);
2961
2983
  process.exit(1);
2962
2984
  }
@@ -2970,7 +2992,7 @@ program.command("login").description("Authenticate with APIblaze").action(async
2970
2992
  process.exit(1);
2971
2993
  }
2972
2994
  });
2973
- 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("--tenant <slug>", "Tenant slug (anonymous create; generated if omitted)").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) => {
2995
+ 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) => {
2974
2996
  try {
2975
2997
  await runCreate(opts);
2976
2998
  } catch (err) {
@@ -3037,7 +3059,7 @@ program.command("target").description("Change where a proxy forwards requests").
3037
3059
  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)));
3038
3060
  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)));
3039
3061
  var domain = program.command("domain").description("Use your own domain for a proxy");
3040
- domain.command("add").description("Add your own domain (shows the DNS records to set)").argument("<project>", "Project name or id").requiredOption("--domain <host>", "Custom hostname to add").option("--tenant <slug>", "Tenant to scope the domain to").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").action(action((project, opts) => runDomainAdd(project, opts)));
3062
+ domain.command("add").description("Add your own domain (shows the DNS records to set)").argument("<project>", "Project name or id").requiredOption("--domain <host>", "Custom hostname to add").option("--tenant <slug>", "Bind the domain to one of the project's tenants (per-tenant scope)").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").action(action((project, opts) => runDomainAdd(project, opts)));
3041
3063
  domain.command("list").description("List custom domains for a proxy").argument("<project>", "Project name or id").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").action(action((project, opts) => runDomainList(project, opts)));
3042
3064
  domain.command("status").description("Check a custom domain's validation status").argument("<project>", "Project name or id").requiredOption("--id <domainId>", "Domain id (see `domain list`)").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").option("--json", "Output machine-readable JSON").action(action((project, opts) => runDomainStatus(project, opts)));
3043
3065
  domain.command("rm").description("Remove a custom domain").argument("<project>", "Project name or id").requiredOption("--id <domainId>", "Domain id (see `domain list`)").option("--team <id|name>", "Team the project is in").option("--apiversion <version>", "API version").action(action((project, opts) => runDomainRemove(project, opts)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Dev tunnel CLI for APIblaze — route localhost projects through your APIblaze endpoints",
5
5
  "keywords": [
6
6
  "apiblaze",