apiblaze 0.1.16 → 0.1.18

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 +173 -17
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -86,12 +86,30 @@ var api_exports = {};
86
86
  __export(api_exports, {
87
87
  checkProxyName: () => checkProxyName,
88
88
  createProxy: () => createProxy,
89
+ createProxyAnonymous: () => createProxyAnonymous,
89
90
  deleteDevTunnel: () => deleteDevTunnel,
90
91
  getLocalhostTargets: () => getLocalhostTargets,
91
92
  getProjects: () => getProjects,
92
93
  getTeams: () => getTeams,
93
94
  putDevTunnel: () => putDevTunnel
94
95
  });
96
+ async function createProxyAnonymous(body) {
97
+ const res = await fetch(`${PUBLIC_API_BASE}/proxy`, {
98
+ method: "POST",
99
+ headers: { "Content-Type": "application/json" },
100
+ body: JSON.stringify(body)
101
+ });
102
+ if (!res.ok) {
103
+ let message = res.statusText;
104
+ try {
105
+ const b = await res.json();
106
+ message = b.details ?? b.error ?? message;
107
+ } catch {
108
+ }
109
+ throw new ApiError(res.status, message);
110
+ }
111
+ return res.json();
112
+ }
95
113
  async function apiFetch(path2, options = {}) {
96
114
  const token = getAccessToken();
97
115
  const url = `${DASHBOARD_BASE}${path2}`;
@@ -153,13 +171,14 @@ async function deleteDevTunnel(restore) {
153
171
  body: JSON.stringify({ restore })
154
172
  });
155
173
  }
156
- var DASHBOARD_BASE;
174
+ var DASHBOARD_BASE, PUBLIC_API_BASE;
157
175
  var init_api = __esm({
158
176
  "src/lib/api.ts"() {
159
177
  "use strict";
160
178
  init_auth();
161
179
  init_types();
162
180
  DASHBOARD_BASE = "https://dashboard.apiblaze.com";
181
+ PUBLIC_API_BASE = "https://api.apiblaze.com";
163
182
  }
164
183
  });
165
184
 
@@ -168,7 +187,7 @@ var import_commander = require("commander");
168
187
  var import_chalk7 = __toESM(require("chalk"));
169
188
 
170
189
  // package.json
171
- var version = "0.1.16";
190
+ var version = "0.1.18";
172
191
 
173
192
  // src/index.ts
174
193
  init_types();
@@ -521,21 +540,21 @@ async function runDev(options) {
521
540
  }
522
541
  selectedTargets = targets;
523
542
  } else {
543
+ const ALL = "__all__";
524
544
  const { chosen } = await import_inquirer.default.prompt([{
525
- type: "checkbox",
545
+ type: "list",
526
546
  name: "chosen",
527
- message: `Found ${targets.length} projects with an internal target \u2014 pick which to tunnel (space to select, a for all):`,
528
- choices: targets.map((t) => ({
529
- name: `${import_chalk3.default.bold(t.projectName)} (${t.tenantName}) \u2014 ${t.target}`,
530
- value: t,
531
- checked: false
532
- }))
547
+ message: `Found ${targets.length} projects with an internal target \u2014 pick one to tunnel:`,
548
+ choices: [
549
+ ...targets.map((t) => ({
550
+ name: `${import_chalk3.default.bold(t.projectName)} (${t.tenantName}) \u2014 ${t.target}`,
551
+ value: t
552
+ })),
553
+ new import_inquirer.default.Separator(),
554
+ { name: `Tunnel all ${targets.length}`, value: ALL }
555
+ ]
533
556
  }]);
534
- if (chosen.length === 0) {
535
- console.log("No projects selected. Aborted.");
536
- process.exit(0);
537
- }
538
- selectedTargets = chosen;
557
+ selectedTargets = chosen === ALL ? targets : [chosen];
539
558
  }
540
559
  console.log(
541
560
  import_chalk3.default.green(`
@@ -649,6 +668,7 @@ ${projects.length} project${projects.length === 1 ? "" : "s"}`));
649
668
  }
650
669
 
651
670
  // src/commands/create.ts
671
+ var import_fs = __toESM(require("fs"));
652
672
  var import_chalk5 = __toESM(require("chalk"));
653
673
  var import_ora4 = __toESM(require("ora"));
654
674
  init_auth();
@@ -684,7 +704,8 @@ var VALID_AUTH = ["api_key", "none", "oauth"];
684
704
  async function runCreate(opts = {}) {
685
705
  const creds = loadCredentials();
686
706
  if (!creds) {
687
- fail("Not logged in. Run `apiblaze login` first.");
707
+ await runAnonymousCreate(opts);
708
+ return;
688
709
  }
689
710
  const interactive = !!process.stdin.isTTY && !opts.json;
690
711
  const auth = (opts.auth ?? "api_key").toLowerCase();
@@ -826,6 +847,121 @@ async function runCreate(opts = {}) {
826
847
  }
827
848
  console.log();
828
849
  }
850
+ async function runAnonymousCreate(opts) {
851
+ const interactive = !!process.stdin.isTTY && !opts.json;
852
+ if (!opts.json) {
853
+ console.log(import_chalk5.default.bold("\nCreate an API proxy"));
854
+ console.log(import_chalk5.default.dim("Not logged in \u2014 creating an anonymous proxy. You can claim it to your account within 30 days.\n"));
855
+ }
856
+ let body = {};
857
+ if (opts.config) {
858
+ let raw = "";
859
+ try {
860
+ raw = import_fs.default.readFileSync(opts.config, "utf8");
861
+ } catch {
862
+ fail(`Cannot read --config file: ${opts.config}`);
863
+ }
864
+ let parsed;
865
+ try {
866
+ parsed = JSON.parse(raw);
867
+ } catch {
868
+ fail(`--config is not valid JSON: ${opts.config}`);
869
+ }
870
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) fail("--config must be a JSON object.");
871
+ body = parsed;
872
+ }
873
+ let name = opts.name !== void 0 ? normalizeName(opts.name) : typeof body.name === "string" ? body.name : void 0;
874
+ if (opts.name !== void 0 && name.length < 3) {
875
+ fail("Proxy name must be at least 3 characters (letters and digits only).");
876
+ }
877
+ if (opts.target && !isHttpUrl(opts.target)) fail("--target must be a valid http(s) URL.");
878
+ let target = opts.target?.trim() || (typeof body.target === "string" ? body.target : "") || (typeof body.target_url === "string" ? body.target_url : "");
879
+ const hasOtherSource = !!(body.openapi || body.github);
880
+ if (!target && !hasOtherSource) {
881
+ if (interactive) {
882
+ const { default: inquirer2 } = await import("inquirer");
883
+ if (name === void 0) {
884
+ const { rawName } = await inquirer2.prompt([{
885
+ type: "input",
886
+ name: "rawName",
887
+ message: "Proxy name (leave blank to auto-generate):",
888
+ transformer: (v) => normalizeName(v)
889
+ }]);
890
+ const n = normalizeName(rawName);
891
+ name = n.length >= 3 ? n : void 0;
892
+ }
893
+ for (; ; ) {
894
+ const { url } = await inquirer2.prompt([{
895
+ type: "input",
896
+ name: "url",
897
+ message: "Target URL to forward requests to (e.g. https://httpbin.org):"
898
+ }]);
899
+ if (!isHttpUrl(url)) {
900
+ console.log(import_chalk5.default.yellow(" Enter a valid http(s) URL.\n"));
901
+ continue;
902
+ }
903
+ target = url.trim();
904
+ break;
905
+ }
906
+ } else {
907
+ fail("A source is required: pass --target, or target/openapi/github in --config.");
908
+ }
909
+ }
910
+ if (target) {
911
+ body.target = target;
912
+ body.target_url = target;
913
+ }
914
+ if (name) {
915
+ body.name = name;
916
+ body.subdomain = name;
917
+ }
918
+ if (opts.subdomain) body.subdomain = normalizeName(opts.subdomain);
919
+ if (opts.tenant) body.tenant = normalizeName(opts.tenant);
920
+ if (opts.product) body.product_slug = normalizeName(opts.product);
921
+ if (opts.displayName) body.display_name = opts.displayName;
922
+ if (opts.auth && opts.auth !== "api_key") body.auth_type = opts.auth;
923
+ const spinner = !opts.json ? (0, import_ora4.default)("Creating proxy...").start() : null;
924
+ let result;
925
+ try {
926
+ result = await createProxyAnonymous(body);
927
+ spinner?.succeed(import_chalk5.default.green("Proxy created!"));
928
+ } catch (err) {
929
+ spinner?.fail("Failed to create proxy.");
930
+ throw err;
931
+ }
932
+ const version2 = result.api_version || "1.0.0";
933
+ const keys = result.api_keys ?? {};
934
+ const apiKey = result.apiKey ?? keys.prod ?? Object.values(keys)[0];
935
+ const prodEndpoint = (result.endpoints || []).find((e) => e.endsWith("/prod")) || (result.endpoints || [])[0];
936
+ if (opts.json) {
937
+ process.stdout.write(JSON.stringify({
938
+ project_id: result.project_id,
939
+ api_version: version2,
940
+ endpoints: result.endpoints,
941
+ api_key: apiKey,
942
+ api_keys: keys,
943
+ claim_url: result.claim_url,
944
+ anonymous: true
945
+ }) + "\n");
946
+ return;
947
+ }
948
+ console.log();
949
+ if (prodEndpoint) console.log(` ${import_chalk5.default.dim("Proxy URL: ")} ${import_chalk5.default.bold(prodEndpoint)}`);
950
+ if (result.portal) console.log(` ${import_chalk5.default.dim("Dev portal:")} ${import_chalk5.default.bold(result.portal)}`);
951
+ if (apiKey) {
952
+ console.log();
953
+ console.log(` ${import_chalk5.default.dim("API key:")}`);
954
+ console.log(` ${import_chalk5.default.bold.green(apiKey)}`);
955
+ console.log(import_chalk5.default.dim("\n Save this now \u2014 send it as the X-API-Key header. It may not be shown again."));
956
+ }
957
+ if (result.claim_url) {
958
+ console.log();
959
+ console.log(` ${import_chalk5.default.yellow("\u26A0 Anonymous proxy \u2014 claim it to your account within 30 days or it expires:")}`);
960
+ console.log(` ${import_chalk5.default.bold(result.claim_url)}`);
961
+ console.log(import_chalk5.default.dim(" (or run `apiblaze login`, then re-run `apiblaze create` to create it under your account)"));
962
+ }
963
+ console.log();
964
+ }
829
965
 
830
966
  // src/commands/team.ts
831
967
  var import_chalk6 = __toESM(require("chalk"));
@@ -875,7 +1011,7 @@ async function runTeam(arg) {
875
1011
 
876
1012
  // src/index.ts
877
1013
  var program = new import_commander.Command();
878
- program.name("apiblaze").description("APIblaze dev tunnel CLI").version(version);
1014
+ program.name("apiblaze").description("APIblaze CLI \u2014 create & manage API proxies and run dev tunnels").version(version);
879
1015
  program.command("login").description("Authenticate with APIblaze").action(async () => {
880
1016
  try {
881
1017
  await runLogin();
@@ -884,7 +1020,7 @@ program.command("login").description("Authenticate with APIblaze").action(async
884
1020
  process.exit(1);
885
1021
  }
886
1022
  });
887
- program.command("create").description("Create a new API proxy").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("-y, --yes", "Skip the confirmation prompt").option("--json", "Output machine-readable JSON (non-interactive)").action(async (opts) => {
1023
+ 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) => {
888
1024
  try {
889
1025
  await runCreate(opts);
890
1026
  } catch (err) {
@@ -921,6 +1057,26 @@ program.command("dev").description("Start a dev tunnel for your localhost projec
921
1057
  process.exit(1);
922
1058
  }
923
1059
  });
1060
+ program.addHelpText(
1061
+ "after",
1062
+ `
1063
+ Examples:
1064
+ # No account needed \u2014 create an anonymous proxy, get a claim URL:
1065
+ $ npx apiblaze create --target https://api.example.com
1066
+
1067
+ # Non-interactive (CI / scripts):
1068
+ $ npx apiblaze create --target https://api.example.com --name myapi --json
1069
+
1070
+ # Sign in, then create under your team:
1071
+ $ npx apiblaze login
1072
+ $ npx apiblaze create --name myapi --target https://api.example.com --auth api_key
1073
+
1074
+ # Manage:
1075
+ $ npx apiblaze projects
1076
+ $ npx apiblaze team
1077
+ $ npx apiblaze dev 3000
1078
+ `
1079
+ );
924
1080
  function printError(err) {
925
1081
  if (err instanceof ApiError) {
926
1082
  console.error(import_chalk7.default.red(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.1.16",
3
+ "version": "0.1.18",
4
4
  "description": "Dev tunnel CLI for APIblaze — route localhost projects through your APIblaze endpoints",
5
5
  "keywords": [
6
6
  "apiblaze",