apiblaze 0.19.16 → 0.19.17

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 +101 -50
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -137,14 +137,13 @@ async function createProxyAnonymous(body) {
137
137
  }
138
138
  return res.json();
139
139
  }
140
- async function apiFetch(path8, options = {}) {
141
- const token = getAccessToken();
140
+ async function apiFetch(path8, options = {}, auth) {
142
141
  const url = `${DASHBOARD_BASE}${path8}`;
143
142
  const res = await fetch(url, {
144
143
  ...options,
145
144
  headers: {
146
145
  "Content-Type": "application/json",
147
- Authorization: `Bearer ${token}`,
146
+ ...auth?.apiKey ? { "X-API-Key": auth.apiKey } : { Authorization: `Bearer ${getAccessToken()}` },
148
147
  ...options.headers ?? {}
149
148
  }
150
149
  });
@@ -187,8 +186,8 @@ async function getTeams() {
187
186
  return { teamId: teamId ?? "", name: t.name ?? teamId ?? "" };
188
187
  }).filter((t) => t.teamId);
189
188
  }
190
- async function getLocalhostTargets(teamId) {
191
- return apiFetch(`/api/cli/localhost-targets?team_id=${encodeURIComponent(teamId)}`);
189
+ async function getLocalhostTargets(teamId, auth) {
190
+ return apiFetch(`/api/cli/localhost-targets?team_id=${encodeURIComponent(teamId)}`, {}, auth);
192
191
  }
193
192
  async function getProjects(teamId) {
194
193
  return apiFetch(`/api/cli/projects?team_id=${encodeURIComponent(teamId)}`);
@@ -220,17 +219,17 @@ async function sidecarInitAnonymous() {
220
219
  if (!res.ok) throw new ApiError(res.status, data?.error ?? "init_failed", data);
221
220
  return data;
222
221
  }
223
- async function putDevTunnel(payload) {
222
+ async function putDevTunnel(payload, auth) {
224
223
  return apiFetch("/api/cli/dev-tunnel", {
225
224
  method: "PUT",
226
225
  body: JSON.stringify(payload)
227
- });
226
+ }, auth);
228
227
  }
229
- async function deleteDevTunnel(restore) {
228
+ async function deleteDevTunnel(restore, auth) {
230
229
  return apiFetch("/api/cli/dev-tunnel", {
231
230
  method: "DELETE",
232
231
  body: JSON.stringify({ restore })
233
- });
232
+ }, auth);
234
233
  }
235
234
  var DASHBOARD_BASE, PUBLIC_API_BASE;
236
235
  var init_api = __esm({
@@ -933,7 +932,7 @@ var import_commander = require("commander");
933
932
  var import_chalk44 = __toESM(require("chalk"));
934
933
 
935
934
  // package.json
936
- var version = "0.19.16";
935
+ var version = "0.19.17";
937
936
 
938
937
  // src/index.ts
939
938
  init_types();
@@ -1539,31 +1538,61 @@ function startTunnelClient(opts) {
1539
1538
  }
1540
1539
 
1541
1540
  // src/commands/dev.ts
1542
- async function ensureLoggedIn(interactive) {
1543
- const existing = loadCredentials();
1544
- if (existing && Date.now() < existing.expiresAt) return existing;
1545
- console.log(import_chalk4.default.yellow(existing ? "\nYour APIblaze session has expired." : "\nYou're not logged in to APIblaze."));
1546
- if (!interactive) {
1547
- console.error(import_chalk4.default.red("Run `apiblaze login` first."));
1548
- process.exit(1);
1541
+ init_anon_cred();
1542
+ function resolveDevAuth() {
1543
+ const creds = loadCredentials();
1544
+ if (creds && Date.now() < creds.expiresAt) return { mode: "session", creds };
1545
+ const anon = loadAnonCred();
1546
+ if (anon?.cp_key) return { mode: "key", apiKey: anon.cp_key, teamId: anon.team_id };
1547
+ return { mode: "none" };
1548
+ }
1549
+ async function offerAutoCreateAnon(existingKey, port) {
1550
+ if (!process.stdin.isTTY) {
1551
+ console.log(import_chalk4.default.yellow("No projects found with an internal target."));
1552
+ console.log("Run `apiblaze create --target http://localhost:" + port + "` first, or run `apiblaze dev` in an interactive terminal to create one automatically.");
1553
+ return null;
1549
1554
  }
1550
- const { doLogin } = await import_inquirer.default.prompt([{
1555
+ const { create } = await import_inquirer.default.prompt([{
1551
1556
  type: "confirm",
1552
- name: "doLogin",
1553
- message: "Log in now?",
1557
+ name: "create",
1558
+ message: `No project points at this machine. Create a quick dev proxy \u2192 ${import_chalk4.default.bold(`http://localhost:${port}`)} and tunnel it?`,
1554
1559
  default: true
1555
1560
  }]);
1556
- if (!doLogin) {
1557
- console.log(import_chalk4.default.dim("Run `apiblaze login` when you're ready."));
1558
- process.exit(0);
1561
+ if (!create) return null;
1562
+ const spinner = (0, import_ora2.default)("Creating dev proxy (anonymous workspace)...").start();
1563
+ let result = null;
1564
+ let lastErr = null;
1565
+ for (let i = 0; i < 4 && !result?.project_id; i++) {
1566
+ const body = { name: randomProxyName(), target_url: `http://localhost:${port}`, auth_type: "none" };
1567
+ try {
1568
+ result = existingKey ? await cpFetch(existingKey, "/projects", { method: "POST", body: JSON.stringify(body) }) : await createProxyAnonymous(body);
1569
+ } catch (err) {
1570
+ lastErr = err;
1571
+ }
1559
1572
  }
1560
- await runLogin();
1561
- const creds = loadCredentials();
1562
- if (!creds) {
1563
- console.error(import_chalk4.default.red("Login did not complete. Run `apiblaze login` and try again."));
1564
- process.exit(1);
1573
+ if (!result?.project_id) {
1574
+ spinner.fail("Failed to create the dev proxy.");
1575
+ throw lastErr instanceof Error ? lastErr : new Error("create failed");
1565
1576
  }
1566
- return creds;
1577
+ spinner.succeed(import_chalk4.default.green(`Created dev proxy "${result.project_id}".`));
1578
+ let apiKey = existingKey ?? "";
1579
+ if (!existingKey && result.cp_key && result.team_id) {
1580
+ saveAnonCred(result.cp_key, result.team_id, result.claim_code);
1581
+ apiKey = result.cp_key;
1582
+ console.log(import_chalk4.default.dim(" Anonymous workspace created \u2014 claim it into a free account anytime: npx apiblaze claim"));
1583
+ }
1584
+ if (!apiKey) {
1585
+ console.log(import_chalk4.default.red(" The anonymous create returned no workspace key \u2014 run `apiblaze create` once, then retry."));
1586
+ return null;
1587
+ }
1588
+ const anonTeamId = result.team_id ?? loadAnonCred()?.team_id ?? "";
1589
+ const targets = await getLocalhostTargets(anonTeamId, { apiKey }).catch(() => []);
1590
+ const created = targets.find((t) => t.projectId === result.project_id);
1591
+ if (!created) {
1592
+ console.log(import_chalk4.default.yellow(" Proxy created, but it did not appear as a localhost target \u2014 try `apiblaze dev` again."));
1593
+ return null;
1594
+ }
1595
+ return { target: created, apiKey, teamId: anonTeamId };
1567
1596
  }
1568
1597
  async function offerAutoCreate(teamId, port) {
1569
1598
  if (!process.stdin.isTTY) {
@@ -1627,9 +1656,10 @@ function isInternalTarget(url) {
1627
1656
  return false;
1628
1657
  }
1629
1658
  }
1630
- function printTunnelEndpoints(restore, targets) {
1659
+ function printTunnelEndpoints(restore, targets, anon) {
1631
1660
  if (restore.length === 0) return;
1632
1661
  console.log(import_chalk4.default.bold("\nYour proxy is live at:"));
1662
+ const domain2 = anon ? "tryabz.run" : "abz.run";
1633
1663
  for (const r of restore) {
1634
1664
  const label3 = targets.find((t) => t.projectId === r.projectId)?.projectName ?? r.projectId;
1635
1665
  console.log(`
@@ -1637,7 +1667,7 @@ function printTunnelEndpoints(restore, targets) {
1637
1667
  const internalEnvs = Object.keys(r.environments ?? {}).filter((e) => isInternalTarget(r.environments[e]?.target));
1638
1668
  const envs = internalEnvs.includes("dev") ? ["dev"] : internalEnvs.length ? internalEnvs : ["dev"];
1639
1669
  for (const env of envs) {
1640
- console.log(` ${import_chalk4.default.dim("API: ")} ${import_chalk4.default.cyan(`https://${r.projectId}.abz.run/${r.apiVersion}/${env}/`)}`);
1670
+ console.log(` ${import_chalk4.default.dim("API: ")} ${import_chalk4.default.cyan(`https://${r.projectId}.${domain2}/${r.apiVersion}/${env}/`)}`);
1641
1671
  }
1642
1672
  if (r.tenant) {
1643
1673
  console.log(` ${import_chalk4.default.dim("Portal:")} ${import_chalk4.default.cyan(`https://${r.tenant}.portal.apiblaze.com/${r.apiVersion}`)}`);
@@ -1659,24 +1689,34 @@ async function probeLocalServer(port) {
1659
1689
  }
1660
1690
  }
1661
1691
  async function runDev(options) {
1662
- const creds = await ensureLoggedIn(!!process.stdin.isTTY);
1663
- const linked = await resolveLinkedTeam({ preferredId: creds.teamId, interactive: !!process.stdin.isTTY });
1664
- if (!linked) {
1665
- console.error(import_chalk4.default.red("No team available. Run `apiblaze login` to set up your team."));
1666
- process.exit(1);
1667
- }
1668
- const teamId = linked.teamId;
1669
- if (linked.teamId !== creds.teamId || linked.teamName !== creds.teamName) {
1670
- saveCredentials({ ...creds, teamId: linked.teamId, teamName: linked.teamName });
1671
- }
1672
- if (linked.teamName) {
1673
- console.log(`${import_chalk4.default.cyan("\u2192")} Team: ${import_chalk4.default.bold(linked.teamName)}`);
1692
+ let auth = resolveDevAuth();
1693
+ let keyAuth = auth.mode === "key" ? { apiKey: auth.apiKey } : void 0;
1694
+ let teamId = "";
1695
+ if (auth.mode === "session") {
1696
+ const { creds } = auth;
1697
+ const linked = await resolveLinkedTeam({ preferredId: creds.teamId, interactive: !!process.stdin.isTTY });
1698
+ if (!linked) {
1699
+ console.error(import_chalk4.default.red("No team available. Run `apiblaze login` to set up your team."));
1700
+ process.exit(1);
1701
+ }
1702
+ teamId = linked.teamId;
1703
+ if (linked.teamId !== creds.teamId || linked.teamName !== creds.teamName) {
1704
+ saveCredentials({ ...creds, teamId: linked.teamId, teamName: linked.teamName });
1705
+ }
1706
+ if (linked.teamName) {
1707
+ console.log(`${import_chalk4.default.cyan("\u2192")} Team: ${import_chalk4.default.bold(linked.teamName)}`);
1708
+ }
1709
+ } else if (auth.mode === "key") {
1710
+ teamId = auth.teamId;
1711
+ console.log(`${import_chalk4.default.cyan("\u2192")} Anonymous workspace ${import_chalk4.default.dim(`(${teamId})`)} \u2014 claim it anytime: ${import_chalk4.default.bold("npx apiblaze claim")}`);
1712
+ } else {
1713
+ console.log(import_chalk4.default.dim("\u2192 No account needed \u2014 this run uses an anonymous workspace (log in anytime with `apiblaze login`)."));
1674
1714
  }
1675
- let targets;
1676
- {
1715
+ let targets = [];
1716
+ if (auth.mode !== "none") {
1677
1717
  const spinner = (0, import_ora2.default)("Fetching your localhost projects...").start();
1678
1718
  try {
1679
- targets = await getLocalhostTargets(teamId);
1719
+ targets = await getLocalhostTargets(teamId, keyAuth);
1680
1720
  spinner.stop();
1681
1721
  } catch (err) {
1682
1722
  spinner.fail("Failed to fetch projects.");
@@ -1700,7 +1740,18 @@ async function runDev(options) {
1700
1740
  }
1701
1741
  selectedTargets = [match];
1702
1742
  } else if (targets.length === 0) {
1703
- const created = await offerAutoCreate(teamId, options.port);
1743
+ let created = null;
1744
+ if (auth.mode === "session") {
1745
+ created = await offerAutoCreate(teamId, options.port);
1746
+ } else {
1747
+ const made = await offerAutoCreateAnon(auth.mode === "key" ? auth.apiKey : null, options.port);
1748
+ if (made) {
1749
+ created = made.target;
1750
+ keyAuth = { apiKey: made.apiKey };
1751
+ teamId = made.teamId;
1752
+ auth = { mode: "key", apiKey: made.apiKey, teamId: made.teamId };
1753
+ }
1754
+ }
1704
1755
  if (!created) {
1705
1756
  console.log("Set a project's upstream target to localhost or a private IP, then try again.");
1706
1757
  process.exit(0);
@@ -1763,7 +1814,7 @@ Tunneling ${selectedTargets.length} project(s) to localhost:${options.port}
1763
1814
  try {
1764
1815
  const result = await putDevTunnel({
1765
1816
  targets: selectedTargets.map((t) => ({ projectId: t.projectId, tenantId: t.tenantId }))
1766
- });
1817
+ }, keyAuth);
1767
1818
  restore = result.restore ?? [];
1768
1819
  connect = result.connect;
1769
1820
  spinner.succeed("Tunnel registered.");
@@ -1772,7 +1823,7 @@ Tunneling ${selectedTargets.length} project(s) to localhost:${options.port}
1772
1823
  throw err;
1773
1824
  }
1774
1825
  }
1775
- printTunnelEndpoints(restore, selectedTargets);
1826
+ printTunnelEndpoints(restore, selectedTargets, auth.mode === "key");
1776
1827
  const clients = connect.projects.map(
1777
1828
  (projectId) => startTunnelClient({
1778
1829
  connectUrl: connect.url,
@@ -1809,7 +1860,7 @@ Tunneling ${selectedTargets.length} project(s) to localhost:${options.port}
1809
1860
  console.log(import_chalk4.default.gray("\n\nShutting down..."));
1810
1861
  for (const client of clients) client.close();
1811
1862
  captureStream?.end();
1812
- await deleteDevTunnel(restore).catch(() => {
1863
+ await deleteDevTunnel(restore, keyAuth).catch(() => {
1813
1864
  });
1814
1865
  console.log(import_chalk4.default.green("Tunnel stopped."));
1815
1866
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apiblaze",
3
- "version": "0.19.16",
3
+ "version": "0.19.17",
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",