apiblaze 0.20.13 → 0.20.14

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 +40 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1024,7 +1024,7 @@ var import_commander = require("commander");
1024
1024
  var import_chalk53 = __toESM(require("chalk"));
1025
1025
 
1026
1026
  // package.json
1027
- var version = "0.20.13";
1027
+ var version = "0.20.14";
1028
1028
 
1029
1029
  // src/index.ts
1030
1030
  init_types();
@@ -2251,7 +2251,7 @@ async function runCreate(opts = {}) {
2251
2251
  const { classifyTargetInput: classifyTargetInput2 } = await Promise.resolve().then(() => (init_spec_or_target(), spec_or_target_exports));
2252
2252
  const c = await classifyTargetInput2(opts.target, fail);
2253
2253
  if (c.kind === "spec") {
2254
- console.log(import_chalk11.default.dim(` --target is an OpenAPI document (${c.source}) \u2014 creating FROM the spec.`));
2254
+ if (!opts.json) console.log(import_chalk11.default.dim(` --target is an OpenAPI document (${c.source}) \u2014 creating FROM the spec.`));
2255
2255
  opts.openapi = opts.target;
2256
2256
  opts.target = void 0;
2257
2257
  }
@@ -2261,7 +2261,7 @@ async function runCreate(opts = {}) {
2261
2261
  await runAnonymousCreate(opts);
2262
2262
  return;
2263
2263
  }
2264
- const interactive = !!process.stdin.isTTY && !opts.json;
2264
+ const interactive = !!process.stdin.isTTY && !opts.json && !opts.auto;
2265
2265
  if (opts.apikey && opts.oauth !== void 0 && opts.oauth !== false) fail("Pass either --apikey or --oauth, not both.");
2266
2266
  const oauthPlan = parseOauthFlag(opts.oauth);
2267
2267
  const auth = (oauthPlan ? oauthPlan.auth : opts.apikey ? "api_key" : opts.auth ?? "api_key").toLowerCase();
@@ -2323,8 +2323,12 @@ async function runCreate(opts = {}) {
2323
2323
  `);
2324
2324
  break;
2325
2325
  }
2326
+ } else if (opts.auto) {
2327
+ name = await pickGeneratedName(opts, teamId);
2328
+ if (!opts.json) console.log(`${import_chalk11.default.cyan("\u2192")} Your API will live at ${import_chalk11.default.bold(`https://${name}.abz.run`)}
2329
+ `);
2326
2330
  } else {
2327
- fail("--name is required in non-interactive mode.");
2331
+ fail("--name is required in non-interactive mode.", "Or pass --auto to have one generated for you.");
2328
2332
  }
2329
2333
  let openapiContent = null;
2330
2334
  if (opts.openapi !== void 0) {
@@ -2354,7 +2358,7 @@ async function runCreate(opts = {}) {
2354
2358
  } else {
2355
2359
  fail("--target is required in non-interactive mode (a server base URL, a local OpenAPI file, or a remote OpenAPI URL).");
2356
2360
  }
2357
- if (interactive && !opts.yes) {
2361
+ if (interactive && !opts.yes && !opts.auto) {
2358
2362
  const { default: inquirer3 } = await import("inquirer");
2359
2363
  console.log(`${import_chalk11.default.cyan("\u2192")} Auth: ${import_chalk11.default.bold(auth)}${auth === "api_key" ? " \u2014 consumers send an X-API-Key header" : oauthPlan ? ` \u2014 ${oauthPlan.summary}` : ""}`);
2360
2364
  const { ok } = await inquirer3.prompt([{
@@ -2370,7 +2374,7 @@ async function runCreate(opts = {}) {
2370
2374
  }
2371
2375
  const chosenTenant = await chooseTenantForCreate(teamId, name, {
2372
2376
  tenant: opts.tenant,
2373
- yes: opts.yes,
2377
+ yes: opts.yes || opts.auto,
2374
2378
  json: opts.json
2375
2379
  });
2376
2380
  const spinner = !opts.json ? (0, import_ora5.default)("Creating proxy (tenant, keys, dev portal)...").start() : null;
@@ -2432,8 +2436,29 @@ async function applyCreateToggles(name, opts) {
2432
2436
  if (opts.identified) await runIdentifiedToggle2(name, "require", toggleOpts);
2433
2437
  if (opts.iam) await runIamToggle2(name, "on", toggleOpts);
2434
2438
  }
2439
+ function deriveNameFrom(source) {
2440
+ if (!source) return null;
2441
+ try {
2442
+ const host = new URL(source).hostname;
2443
+ let base2 = normalizeName(host.split(".")[0]);
2444
+ if (base2.length < 3) base2 = normalizeName(host);
2445
+ if (base2.length < 3) return null;
2446
+ return `${base2}${Math.random().toString(36).slice(2, 6)}`;
2447
+ } catch {
2448
+ return null;
2449
+ }
2450
+ }
2451
+ async function pickGeneratedName(opts, teamId) {
2452
+ const source = opts.target ?? opts.openapi;
2453
+ for (let attempt = 0; attempt < 4; attempt++) {
2454
+ const candidate = (attempt === 0 ? deriveNameFrom(source) : null) ?? randomProxyName();
2455
+ const check = await checkProxyName(candidate, teamId, opts.apiversion).catch(() => null);
2456
+ if (!check || check.canUseProjectName && check.canUseApiVersion) return candidate;
2457
+ }
2458
+ fail("Could not find a free generated proxy name. Pass --name explicitly.");
2459
+ }
2435
2460
  async function runAnonymousCreate(opts) {
2436
- const interactive = !!process.stdin.isTTY && !opts.json;
2461
+ const interactive = !!process.stdin.isTTY && !opts.json && !opts.auto;
2437
2462
  if (!opts.json) {
2438
2463
  console.log(import_chalk11.default.bold("\nCreate an API proxy"));
2439
2464
  console.log(import_chalk11.default.dim("Not logged in \u2014 creating an anonymous proxy. You can claim it to your account within 30 days.\n"));
@@ -2495,6 +2520,10 @@ async function runAnonymousCreate(opts) {
2495
2520
  fail("A source is required: pass --target, or target/openapi/github in --config.");
2496
2521
  }
2497
2522
  }
2523
+ if (name === void 0 && opts.auto) {
2524
+ const nameSource = target || (typeof opts.openapi === "string" ? opts.openapi : void 0);
2525
+ name = deriveNameFrom(nameSource) ?? randomProxyName();
2526
+ }
2498
2527
  if (target) {
2499
2528
  body.target = target;
2500
2529
  body.target_url = target;
@@ -11264,7 +11293,7 @@ program.command("login").description("Authenticate with APIblaze").option("--tea
11264
11293
  process.exit(1);
11265
11294
  }
11266
11295
  });
11267
- 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|file>", "What to proxy \u2014 pass ANY of: a target server base URL (https://httpbin.org), a local OpenAPI file (./openapi.yaml), or a remote OpenAPI URL (https://acme.com/openapi.yaml). Spec inputs are detected automatically; routes, API version and environments then come from the spec").addOption(new import_commander.Option("--openapi <file|url>", "Deprecated alias \u2014 --target now detects spec files/URLs itself").hideHelp()).addOption(new import_commander.Option("--openapispec <file|url>", "Deprecated alias for --openapi").hideHelp()).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("--apikey", "Protect with API keys and print the bootstrap keys (the default, made explicit). Consumers send X-API-Key.").option("--oauth [config]", `Login door. Bare = APIblaze-hosted GitHub sign-in. '{"iss","aud","jwks"}' = trust YOUR hosted login's JWTs. '{"provider","clientId","clientSecret"}' = APIblaze-hosted login page with YOUR OAuth app (github \xB7 google \xB7 microsoft \xB7 facebook \xB7 auth0).`).option("--identified", "Require every call to identify its end user (X-End-User-Id or a login token); unattributed calls are rejected").option("--iam", "Turn IAM on for the proxy's tenant so users & groups apply to identified calls").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 to attach the proxy to (created if new). Omitted \u2192 your team's most-recently-used tenant.").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("--new-session", "Start a fresh anonymous session (do not group with prior anonymous creates)").option("--json", "Output machine-readable JSON (non-interactive)").action(async (opts) => {
11296
+ 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|file>", "What to proxy \u2014 pass ANY of: a target server base URL (https://httpbin.org), a local OpenAPI file (./openapi.yaml), or a remote OpenAPI URL (https://acme.com/openapi.yaml). Spec inputs are detected automatically; routes, API version and environments then come from the spec").addOption(new import_commander.Option("--openapi <file|url>", "Deprecated alias \u2014 --target now detects spec files/URLs itself").hideHelp()).addOption(new import_commander.Option("--openapispec <file|url>", "Deprecated alias for --openapi").hideHelp()).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("--apikey", "Protect with API keys and print the bootstrap keys (the default, made explicit). Consumers send X-API-Key.").option("--oauth [config]", `Login door. Bare = APIblaze-hosted GitHub sign-in. '{"iss","aud","jwks"}' = trust YOUR hosted login's JWTs. '{"provider","clientId","clientSecret"}' = APIblaze-hosted login page with YOUR OAuth app (github \xB7 google \xB7 microsoft \xB7 facebook \xB7 auth0).`).option("--identified", "Require every call to identify its end user (X-End-User-Id or a login token); unattributed calls are rejected").option("--iam", "Turn IAM on for the proxy's tenant so users & groups apply to identified calls").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 to attach the proxy to (created if new). Omitted \u2192 your team's most-recently-used tenant.").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("--auto", "Zero prompts, start to finish: generates the proxy name when --name is omitted (from the target host, salted), takes every confirmation as yes, auto-picks the tenant. Implies --yes.").option("--new-session", "Start a fresh anonymous session (do not group with prior anonymous creates)").option("--json", "Output machine-readable JSON (non-interactive)").action(async (opts) => {
11268
11297
  try {
11269
11298
  await runCreate({ ...opts, openapi: opts.openapi ?? opts.openapispec });
11270
11299
  } catch (err) {
@@ -11442,14 +11471,15 @@ ${groupedCommandHelp()}
11442
11471
  Tips:
11443
11472
  \u2022 \`apiblaze config <project>\` browses EVERY setting & feature (works logged-out to explore).
11444
11473
  \u2022 Add --verbose to any command to see the equivalent API calls.
11474
+ \u2022 Add --auto to \`create\` for a scriptable run: no prompts, no TTY needed, proxy name generated.
11445
11475
  \u2022 Full API reference: https://api.apiblaze.com/openapi.json
11446
11476
  \u2022 Run \`apiblaze <command> --help\` (e.g. \`apiblaze consumer --help\`) for sub-commands.
11447
11477
 
11448
11478
  Examples:
11449
- $ npx apiblaze apichat --openapi https://pokeapi.co/openapi.yaml # chat with any API
11479
+ $ npx apiblaze apichat --target https://pokeapi.co/openapi.yaml # chat with any API
11450
11480
  $ npx apiblaze agent # just chat
11451
11481
  $ npx apiblaze create --target https://api.example.com # one-line API
11452
- $ npx apiblaze create --openapi https://pokeapi.co/openapi.yaml # build it from a spec URL
11482
+ $ npx apiblaze create --target https://pokeapi.co/openapi.yaml --auto # zero prompts, name generated
11453
11483
  $ npx apiblaze search gmail # find a recipe (no login needed)
11454
11484
  $ npx apiblaze install @julien/gmail # someone's whole working setup, your credentials
11455
11485
  $ npx apiblaze publish mygmail # share yours back, as @yourgithubhandle/mygmail
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.20.13",
3
+ "version": "0.20.14",
4
4
  "description": "APIblaze CLI — Chat with your APIs, Manage your API keys, users and groups with the APIblaze serverless proxy",
5
5
  "keywords": [
6
6
  "apiblaze",