apiblaze 0.1.6 → 0.1.7

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 +130 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -87,6 +87,8 @@ var init_auth = __esm({
87
87
  // src/lib/api.ts
88
88
  var api_exports = {};
89
89
  __export(api_exports, {
90
+ checkProxyName: () => checkProxyName,
91
+ createProxy: () => createProxy,
90
92
  deleteDevTunnel: () => deleteDevTunnel,
91
93
  getLocalhostTargets: () => getLocalhostTargets,
92
94
  getProjects: () => getProjects,
@@ -132,6 +134,15 @@ async function getLocalhostTargets(teamId) {
132
134
  async function getProjects(teamId) {
133
135
  return apiFetch(`/api/cli/projects?team_id=${encodeURIComponent(teamId)}`);
134
136
  }
137
+ async function checkProxyName(name) {
138
+ return apiFetch(`/api/cli/check-name?name=${encodeURIComponent(name)}`);
139
+ }
140
+ async function createProxy(payload) {
141
+ return apiFetch("/api/cli/create-proxy", {
142
+ method: "POST",
143
+ body: JSON.stringify(payload)
144
+ });
145
+ }
135
146
  async function putDevTunnel(payload) {
136
147
  return apiFetch("/api/cli/dev-tunnel", {
137
148
  method: "PUT",
@@ -153,7 +164,7 @@ var init_api = __esm({
153
164
 
154
165
  // src/index.ts
155
166
  var import_commander = require("commander");
156
- var import_chalk5 = __toESM(require("chalk"));
167
+ var import_chalk6 = __toESM(require("chalk"));
157
168
  init_types();
158
169
 
159
170
  // src/commands/login.ts
@@ -231,7 +242,7 @@ async function runLogin() {
231
242
  });
232
243
  spinner.succeed(import_chalk.default.green("Authorized!"));
233
244
  if (githubHandle) {
234
- console.log(`${import_chalk.default.cyan("\u2192")} Logged in as ${import_chalk.default.bold("@" + githubHandle)}${apiblazeUserId ? import_chalk.default.dim(` (${apiblazeUserId})`) : ""}`);
245
+ console.log(`${import_chalk.default.cyan("\u2192")} Logged in as ${import_chalk.default.bold("@" + githubHandle)}`);
235
246
  }
236
247
  let teamId = defaultTeamId ?? void 0;
237
248
  let teamName;
@@ -607,9 +618,7 @@ async function runProjects() {
607
618
  process.exit(1);
608
619
  }
609
620
  if (creds.githubHandle) {
610
- console.log(
611
- `${import_chalk4.default.cyan("\u2192")} Logged in as ${import_chalk4.default.bold("@" + creds.githubHandle)}` + (creds.apiblazeUserId ? import_chalk4.default.dim(` (${creds.apiblazeUserId})`) : "")
612
- );
621
+ console.log(`${import_chalk4.default.cyan("\u2192")} Logged in as ${import_chalk4.default.bold("@" + creds.githubHandle)}`);
613
622
  }
614
623
  let teamId = creds.teamId;
615
624
  let teamName = creds.teamName;
@@ -634,7 +643,7 @@ async function runProjects() {
634
643
  console.error(import_chalk4.default.red("No team found. Run `apiblaze login` to set up your team."));
635
644
  process.exit(1);
636
645
  }
637
- console.log(`${import_chalk4.default.cyan("\u2192")} Team: ${import_chalk4.default.bold(teamName ?? teamId)} ${import_chalk4.default.dim(teamId)}
646
+ console.log(`${import_chalk4.default.cyan("\u2192")} Team: ${import_chalk4.default.bold(teamName ?? teamId)}
638
647
  `);
639
648
  const spinner = (0, import_ora4.default)("Fetching projects...").start();
640
649
  let projects;
@@ -649,12 +658,113 @@ async function runProjects() {
649
658
  console.log(import_chalk4.default.yellow("No projects found for this team."));
650
659
  return;
651
660
  }
661
+ const width = Math.max(...projects.map((p) => p.projectName.length));
652
662
  for (const p of projects) {
653
- console.log(`${import_chalk4.default.bold(p.projectName)} ${import_chalk4.default.dim(p.projectId)}`);
654
- console.log(` ${import_chalk4.default.dim("version:")} ${p.apiVersion} ${import_chalk4.default.dim("team:")} ${p.teamId}`);
663
+ console.log(` ${import_chalk4.default.bold(p.projectName.padEnd(width))} ${import_chalk4.default.dim("v" + p.apiVersion)}`);
655
664
  }
656
665
  console.log(import_chalk4.default.dim(`
657
- ${projects.length} project(s).`));
666
+ ${projects.length} project${projects.length === 1 ? "" : "s"}`));
667
+ }
668
+
669
+ // src/commands/create.ts
670
+ var import_chalk5 = __toESM(require("chalk"));
671
+ var import_ora5 = __toESM(require("ora"));
672
+ init_auth();
673
+ init_api();
674
+ function normalizeName(raw) {
675
+ return (raw || "").toLowerCase().replace(/[^a-z0-9]/g, "");
676
+ }
677
+ function isHttpUrl(s) {
678
+ try {
679
+ const u = new URL(s.trim());
680
+ return u.protocol === "http:" || u.protocol === "https:";
681
+ } catch {
682
+ return false;
683
+ }
684
+ }
685
+ async function runCreate() {
686
+ const creds = loadCredentials();
687
+ if (!creds) {
688
+ console.error(import_chalk5.default.red("Not logged in. Run `apiblaze login` first."));
689
+ process.exit(1);
690
+ }
691
+ console.log(import_chalk5.default.bold("\nCreate an API proxy\n"));
692
+ const { default: inquirer2 } = await import("inquirer");
693
+ let name = "";
694
+ for (; ; ) {
695
+ const { rawName } = await inquirer2.prompt([{
696
+ type: "input",
697
+ name: "rawName",
698
+ message: "Proxy name (your API will live at <name>.apiblaze.com):",
699
+ transformer: (v) => normalizeName(v)
700
+ }]);
701
+ name = normalizeName(rawName);
702
+ if (name.length < 3) {
703
+ console.log(import_chalk5.default.yellow(" Name must be at least 3 characters (letters and digits only).\n"));
704
+ continue;
705
+ }
706
+ const spinner2 = (0, import_ora5.default)("Checking availability...").start();
707
+ try {
708
+ const check = await checkProxyName(name);
709
+ spinner2.stop();
710
+ if (!check.canUseProjectName || !check.canUseApiVersion) {
711
+ const why = check.message ? ` \u2014 ${check.message}` : "";
712
+ console.log(import_chalk5.default.yellow(` "${name}" is not available${why}. Try another.
713
+ `));
714
+ continue;
715
+ }
716
+ } catch {
717
+ spinner2.stop();
718
+ console.log(import_chalk5.default.dim(" (could not verify availability; continuing)"));
719
+ }
720
+ console.log(`${import_chalk5.default.cyan("\u2192")} Your API will live at ${import_chalk5.default.bold(`https://${name}.apiblaze.com`)}
721
+ `);
722
+ break;
723
+ }
724
+ let targetUrl = "";
725
+ for (; ; ) {
726
+ const { url } = await inquirer2.prompt([{
727
+ type: "input",
728
+ name: "url",
729
+ message: "Target URL to forward requests to (e.g. https://httpbin.org):"
730
+ }]);
731
+ if (!isHttpUrl(url)) {
732
+ console.log(import_chalk5.default.yellow(" Enter a valid http(s) URL.\n"));
733
+ continue;
734
+ }
735
+ targetUrl = url.trim();
736
+ break;
737
+ }
738
+ console.log(`${import_chalk5.default.cyan("\u2192")} Auth: ${import_chalk5.default.bold("API key")} \u2014 consumers send an X-API-Key header
739
+ `);
740
+ const spinner = (0, import_ora5.default)("Creating proxy (tenant, keys, dev portal)...").start();
741
+ let result;
742
+ try {
743
+ result = await createProxy({ name, target_url: targetUrl, auth_type: "api_key" });
744
+ spinner.succeed(import_chalk5.default.green("Proxy created!"));
745
+ } catch (err) {
746
+ spinner.fail("Failed to create proxy.");
747
+ throw err;
748
+ }
749
+ const version = result.api_version || "1.0.0";
750
+ const keys = result.api_keys ?? {};
751
+ const adminKey = keys.prod ?? Object.values(keys)[0];
752
+ console.log();
753
+ console.log(` ${import_chalk5.default.dim("Proxy URL: ")} ${import_chalk5.default.bold(`https://${name}.apiblaze.com/${version}/prod`)}`);
754
+ if (result.devPortal) {
755
+ console.log(` ${import_chalk5.default.dim("Dev portal:")} ${import_chalk5.default.bold(result.devPortal)}`);
756
+ }
757
+ if (adminKey) {
758
+ console.log();
759
+ console.log(` ${import_chalk5.default.dim("Consumer admin API key (prod):")}`);
760
+ console.log(` ${import_chalk5.default.bold.green(adminKey)}`);
761
+ 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."));
762
+ const otherEnvs = Object.keys(keys).filter((e) => e !== "prod");
763
+ if (otherEnvs.length) {
764
+ console.log(import_chalk5.default.dim(` (Separate keys were also created for: ${otherEnvs.join(", ")}.)`));
765
+ }
766
+ }
767
+ console.log();
658
768
  }
659
769
 
660
770
  // src/index.ts
@@ -668,6 +778,14 @@ program.command("login").description("Authenticate with APIblaze").action(async
668
778
  process.exit(1);
669
779
  }
670
780
  });
781
+ program.command("create").description("Create a new API proxy").action(async () => {
782
+ try {
783
+ await runCreate();
784
+ } catch (err) {
785
+ printError(err);
786
+ process.exit(1);
787
+ }
788
+ });
671
789
  program.command("projects").description("List the projects in your team").action(async () => {
672
790
  try {
673
791
  await runProjects();
@@ -686,13 +804,13 @@ program.command("dev").description("Start a dev tunnel for your localhost projec
686
804
  });
687
805
  function printError(err) {
688
806
  if (err instanceof ApiError) {
689
- console.error(import_chalk5.default.red(`
807
+ console.error(import_chalk6.default.red(`
690
808
  API error (${err.status}): ${err.message}`));
691
809
  } else if (err instanceof Error) {
692
- console.error(import_chalk5.default.red(`
810
+ console.error(import_chalk6.default.red(`
693
811
  Error: ${err.message}`));
694
812
  } else {
695
- console.error(import_chalk5.default.red("\nUnknown error"));
813
+ console.error(import_chalk6.default.red("\nUnknown error"));
696
814
  }
697
815
  }
698
816
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Dev tunnel CLI for APIblaze — route localhost projects through Cloudflare tunnels",
5
5
  "keywords": [
6
6
  "apiblaze",