apiblaze 0.1.20 → 0.1.21

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 +52 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -36,9 +36,10 @@ var init_types = __esm({
36
36
  "src/types.ts"() {
37
37
  "use strict";
38
38
  ApiError = class extends Error {
39
- constructor(status, message) {
39
+ constructor(status, message, body) {
40
40
  super(message);
41
41
  this.status = status;
42
+ this.body = body;
42
43
  this.name = "ApiError";
43
44
  }
44
45
  };
@@ -132,12 +133,14 @@ async function apiFetch(path2, options = {}) {
132
133
  });
133
134
  if (!res.ok) {
134
135
  let message = res.statusText;
136
+ let parsed;
135
137
  try {
136
- const body = await res.json();
137
- message = body.message ?? body.error ?? message;
138
+ parsed = await res.json();
139
+ const b = parsed;
140
+ message = b.message ?? b.error ?? message;
138
141
  } catch {
139
142
  }
140
- throw new ApiError(res.status, message);
143
+ throw new ApiError(res.status, message, parsed);
141
144
  }
142
145
  if (res.status === 204) {
143
146
  return void 0;
@@ -158,9 +161,10 @@ async function getLocalhostTargets(teamId) {
158
161
  async function getProjects(teamId) {
159
162
  return apiFetch(`/api/cli/projects?team_id=${encodeURIComponent(teamId)}`);
160
163
  }
161
- async function checkProxyName(name, teamId) {
164
+ async function checkProxyName(name, teamId, apiVersion) {
162
165
  const q = teamId ? `&team_id=${encodeURIComponent(teamId)}` : "";
163
- return apiFetch(`/api/cli/check-name?name=${encodeURIComponent(name)}${q}`);
166
+ const v = apiVersion ? `&api_version=${encodeURIComponent(apiVersion)}` : "";
167
+ return apiFetch(`/api/cli/check-name?name=${encodeURIComponent(name)}${q}${v}`);
164
168
  }
165
169
  async function createProxy(payload) {
166
170
  return apiFetch("/api/cli/create-proxy", {
@@ -202,7 +206,7 @@ var import_commander = require("commander");
202
206
  var import_chalk10 = __toESM(require("chalk"));
203
207
 
204
208
  // package.json
205
- var version = "0.1.20";
209
+ var version = "0.1.21";
206
210
 
207
211
  // src/index.ts
208
212
  init_types();
@@ -747,7 +751,7 @@ async function runCreate(opts = {}) {
747
751
  if (opts.name !== void 0) {
748
752
  name = normalizeName(opts.name);
749
753
  if (name.length < 3) fail("Proxy name must be at least 3 characters (letters and digits only).");
750
- const check = await checkProxyName(name, teamId).catch(() => null);
754
+ const check = await checkProxyName(name, teamId, opts.apiversion).catch(() => null);
751
755
  if (check && (!check.canUseProjectName || !check.canUseApiVersion)) {
752
756
  fail(`Proxy name "${name}" is not available${check.message ? ` \u2014 ${check.message}` : ""}.`);
753
757
  }
@@ -767,7 +771,7 @@ async function runCreate(opts = {}) {
767
771
  }
768
772
  const spinner2 = (0, import_ora4.default)("Checking availability...").start();
769
773
  try {
770
- const check = await checkProxyName(name, teamId);
774
+ const check = await checkProxyName(name, teamId, opts.apiversion);
771
775
  spinner2.stop();
772
776
  if (!check.canUseProjectName || !check.canUseApiVersion) {
773
777
  console.log(import_chalk5.default.yellow(` "${name}" is not available${check.message ? ` \u2014 ${check.message}` : ""}. Try another.
@@ -824,11 +828,46 @@ async function runCreate(opts = {}) {
824
828
  const spinner = !opts.json ? (0, import_ora4.default)("Creating proxy (tenant, keys, dev portal)...").start() : null;
825
829
  let result;
826
830
  try {
827
- result = await createProxy({ name, target_url: targetUrl, auth_type: auth, team_id: teamId });
831
+ result = await createProxy({ name, target_url: targetUrl, auth_type: auth, team_id: teamId, ...opts.apiversion ? { api_version: opts.apiversion } : {} });
828
832
  spinner?.succeed(import_chalk5.default.green("Proxy created!"));
829
833
  } catch (err) {
834
+ const e = err;
835
+ const ownedByYou = e?.status === 409 && e?.body?.reason === "slug_owned_by_your_other_team" && !opts.team;
830
836
  spinner?.fail("Failed to create proxy.");
831
- throw err;
837
+ if (ownedByYou) {
838
+ const ownerId = e.body.owning_team_id;
839
+ const ownerName = e.body.owning_team_name || ownerId;
840
+ if (!opts.json) console.log(import_chalk5.default.yellow(`
841
+ You already own "${e.body.product_slug}" under your team "${ownerName}".`));
842
+ let doSwitch = false;
843
+ if (interactive && !opts.yes) {
844
+ const { default: inquirer2 } = await import("inquirer");
845
+ const { ok } = await inquirer2.prompt([{
846
+ type: "confirm",
847
+ name: "ok",
848
+ message: `Switch to team "${ownerName}" and create "${name}" there?`,
849
+ default: true
850
+ }]);
851
+ doSwitch = ok;
852
+ }
853
+ if (!doSwitch) {
854
+ if (!opts.json) console.log(import_chalk5.default.dim(` Run \`apiblaze team ${ownerId}\` to switch, then retry \u2014 or pick another --name.`));
855
+ throw err;
856
+ }
857
+ const creds2 = loadCredentials();
858
+ if (creds2) saveCredentials({ ...creds2, teamId: ownerId, teamName: ownerName });
859
+ teamId = ownerId;
860
+ const spinner2 = !opts.json ? (0, import_ora4.default)(`Creating proxy under "${ownerName}"...`).start() : null;
861
+ try {
862
+ result = await createProxy({ name, target_url: targetUrl, auth_type: auth, team_id: ownerId, ...opts.apiversion ? { api_version: opts.apiversion } : {} });
863
+ spinner2?.succeed(import_chalk5.default.green(`Proxy created \u2014 active team switched to "${ownerName}".`));
864
+ } catch (err2) {
865
+ spinner2?.fail("Failed to create proxy after switching team.");
866
+ throw err2;
867
+ }
868
+ } else {
869
+ throw err;
870
+ }
832
871
  }
833
872
  const version2 = result.api_version || "1.0.0";
834
873
  const keys = result.api_keys ?? {};
@@ -934,6 +973,7 @@ async function runAnonymousCreate(opts) {
934
973
  if (opts.tenant) body.tenant = normalizeName(opts.tenant);
935
974
  if (opts.product) body.product_slug = normalizeName(opts.product);
936
975
  if (opts.displayName) body.display_name = opts.displayName;
976
+ if (opts.apiversion) body.api_version = opts.apiversion;
937
977
  if (opts.auth && opts.auth !== "api_key") body.auth_type = opts.auth;
938
978
  const spinner = !opts.json ? (0, import_ora4.default)("Creating proxy...").start() : null;
939
979
  let result;
@@ -1159,7 +1199,7 @@ program.command("login").description("Authenticate with APIblaze").action(async
1159
1199
  process.exit(1);
1160
1200
  }
1161
1201
  });
1162
- 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("--tenant <slug>", "Tenant slug (anonymous create; generated if omitted)").option("--product <slug>", "Product slug (anonymous create; defaults to the proxy name)").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) => {
1202
+ 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 slug (anonymous create; defaults to the proxy name)").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) => {
1163
1203
  try {
1164
1204
  await runCreate(opts);
1165
1205
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "Dev tunnel CLI for APIblaze — route localhost projects through your APIblaze endpoints",
5
5
  "keywords": [
6
6
  "apiblaze",