apiblaze 0.19.7 → 0.19.9

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 +45 -17
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -933,7 +933,7 @@ var import_commander = require("commander");
933
933
  var import_chalk44 = __toESM(require("chalk"));
934
934
 
935
935
  // package.json
936
- var version = "0.19.7";
936
+ var version = "0.19.9";
937
937
 
938
938
  // src/index.ts
939
939
  init_types();
@@ -1989,8 +1989,19 @@ async function runCreate(opts = {}) {
1989
1989
  } else {
1990
1990
  fail("--name is required in non-interactive mode.");
1991
1991
  }
1992
+ let openapiContent = null;
1993
+ if (opts.openapi !== void 0) {
1994
+ if (opts.target !== void 0) fail("Provide only one of --target or --openapi.");
1995
+ try {
1996
+ openapiContent = import_fs2.default.readFileSync(opts.openapi, "utf8");
1997
+ } catch {
1998
+ fail(`Cannot read --openapi file: ${opts.openapi}`);
1999
+ }
2000
+ if (!openapiContent || !openapiContent.trim()) fail(`--openapi file is empty: ${opts.openapi}`);
2001
+ }
1992
2002
  let targetUrl = "";
1993
- if (opts.target !== void 0) {
2003
+ if (openapiContent) {
2004
+ } else if (opts.target !== void 0) {
1994
2005
  if (!isHttpUrl(opts.target)) fail("--target must be a valid http(s) URL.");
1995
2006
  targetUrl = opts.target.trim();
1996
2007
  } else if (interactive) {
@@ -2009,7 +2020,7 @@ async function runCreate(opts = {}) {
2009
2020
  break;
2010
2021
  }
2011
2022
  } else {
2012
- fail("--target is required in non-interactive mode.");
2023
+ fail("--target or --openapi is required in non-interactive mode.");
2013
2024
  }
2014
2025
  if (interactive && !opts.yes) {
2015
2026
  const { default: inquirer3 } = await import("inquirer");
@@ -2017,7 +2028,7 @@ async function runCreate(opts = {}) {
2017
2028
  const { ok } = await inquirer3.prompt([{
2018
2029
  type: "confirm",
2019
2030
  name: "ok",
2020
- message: `Create proxy "${name}" \u2192 ${targetUrl}?`,
2031
+ message: openapiContent ? `Create proxy "${name}" from ${opts.openapi}?` : `Create proxy "${name}" \u2192 ${targetUrl}?`,
2021
2032
  default: true
2022
2033
  }]);
2023
2034
  if (!ok) {
@@ -2028,7 +2039,14 @@ async function runCreate(opts = {}) {
2028
2039
  const spinner = !opts.json ? (0, import_ora5.default)("Creating proxy (tenant, keys, dev portal)...").start() : null;
2029
2040
  let result;
2030
2041
  try {
2031
- result = await createProxy({ name, target_url: targetUrl, auth_type: auth, team_id: teamId, ...opts.apiversion ? { api_version: opts.apiversion } : {} });
2042
+ result = await createProxy({
2043
+ name,
2044
+ ...openapiContent ? { openapi: openapiContent } : { target_url: targetUrl },
2045
+ auth_type: auth,
2046
+ team_id: teamId,
2047
+ ...opts.tenant ? { tenant: normalizeName(opts.tenant) } : {},
2048
+ ...opts.apiversion ? { api_version: opts.apiversion } : {}
2049
+ });
2032
2050
  spinner?.succeed(import_chalk10.default.green("Proxy created!"));
2033
2051
  } catch (err) {
2034
2052
  spinner?.fail("Failed to create proxy.");
@@ -2044,6 +2062,7 @@ async function runCreate(opts = {}) {
2044
2062
  process.stdout.write(JSON.stringify({
2045
2063
  project_id: result.project_id,
2046
2064
  api_version: version2,
2065
+ tenant: result.tenant ?? null,
2047
2066
  proxy_url: proxyUrl,
2048
2067
  dev_portal: devPortal,
2049
2068
  api_key: adminKey,
@@ -2102,6 +2121,13 @@ async function runAnonymousCreate(opts) {
2102
2121
  if (opts.name !== void 0 && name.length < 3) {
2103
2122
  fail("Proxy name must be at least 3 characters (letters and digits only).");
2104
2123
  }
2124
+ if (opts.openapi !== void 0) {
2125
+ try {
2126
+ body.openapi = import_fs2.default.readFileSync(opts.openapi, "utf8");
2127
+ } catch {
2128
+ fail(`Cannot read --openapi file: ${opts.openapi}`);
2129
+ }
2130
+ }
2105
2131
  if (opts.target && !isHttpUrl(opts.target)) fail("--target must be a valid http(s) URL.");
2106
2132
  let target = opts.target?.trim() || (typeof body.target === "string" ? body.target : "") || (typeof body.target_url === "string" ? body.target_url : "");
2107
2133
  const hasOtherSource = !!(body.openapi || body.github);
@@ -5228,6 +5254,17 @@ async function userByRef(t, ref) {
5228
5254
  return u;
5229
5255
  }
5230
5256
  var label2 = (u) => u.display_name || u.email || u.abz_sub;
5257
+ async function userByRefOrCreate(t, ref) {
5258
+ try {
5259
+ return await userByRef(t, ref);
5260
+ } catch (e) {
5261
+ if (!ref.includes("@")) throw e;
5262
+ const created = await t.call("/v1/admin/users", "POST", { email: ref.trim().toLowerCase() });
5263
+ if (!created?.abz_sub) throw e;
5264
+ console.log(import_chalk34.default.dim(` ${ref} wasn't a user yet \u2014 created.`));
5265
+ return { abz_sub: created.abz_sub, email: created.email ?? ref, display_name: null };
5266
+ }
5267
+ }
5231
5268
  async function runGroupList(opts) {
5232
5269
  const t = await resolveTransport(opts);
5233
5270
  const groups = await listGroups(t);
@@ -5242,7 +5279,7 @@ async function runGroupList(opts) {
5242
5279
  async function runGroupCreate(name, opts) {
5243
5280
  const t = await resolveTransport(opts);
5244
5281
  let adminSub;
5245
- if (opts.admin) adminSub = (await userByRef(t, opts.admin)).abz_sub;
5282
+ if (opts.admin) adminSub = (await userByRefOrCreate(t, opts.admin)).abz_sub;
5246
5283
  else {
5247
5284
  const users = await listUsers(t);
5248
5285
  if (t.selfEmail) adminSub = users.find((u) => (u.email ?? "").toLowerCase() === t.selfEmail.toLowerCase())?.abz_sub;
@@ -5298,16 +5335,7 @@ async function runGroupMembers(name, opts) {
5298
5335
  async function runGroupAddUser(userRef, groupName, opts) {
5299
5336
  const t = await resolveTransport(opts);
5300
5337
  const g = await groupByName(t, groupName);
5301
- let u;
5302
- try {
5303
- u = await userByRef(t, userRef);
5304
- } catch (e) {
5305
- if (!userRef.includes("@")) throw e;
5306
- const created = await t.call("/v1/admin/users", "POST", { email: userRef.trim().toLowerCase() });
5307
- if (!created?.abz_sub) throw e;
5308
- console.log(import_chalk34.default.dim(` ${userRef} wasn't a user yet \u2014 created.`));
5309
- u = { abz_sub: created.abz_sub, email: created.email ?? userRef, display_name: null };
5310
- }
5338
+ const u = await userByRefOrCreate(t, userRef);
5311
5339
  const role = opts.role === "admin" ? "admin" : "member";
5312
5340
  const spinner = (0, import_ora17.default)(`Adding ${label2(u)} to ${g.name}...`).start();
5313
5341
  try {
@@ -7364,7 +7392,7 @@ program.command("login").description("Authenticate with APIblaze").action(async
7364
7392
  process.exit(1);
7365
7393
  }
7366
7394
  });
7367
- 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("--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("--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) => {
7395
+ 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("--openapi <file>", "Create FROM an OpenAPI file instead of --target: routes, API version and environments (one per `servers` entry) all come from the spec").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("--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) => {
7368
7396
  try {
7369
7397
  await runCreate(opts);
7370
7398
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.19.7",
3
+ "version": "0.19.9",
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",