apiblaze 0.19.16 → 0.19.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.
- package/README.md +5 -0
- package/dist/index.js +127 -63
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,6 +33,10 @@ npx apiblaze apichat --openapi https://apiblaze.com/pokeapi_openapi.yaml
|
|
|
33
33
|
# Make an API in one line — no account needed (prints a claim URL)
|
|
34
34
|
npx apiblaze create --target https://api.example.com
|
|
35
35
|
|
|
36
|
+
# Or build it straight from an OpenAPI spec — a URL or a local file.
|
|
37
|
+
# The routes, the API version and one environment per `servers` entry all come from the spec.
|
|
38
|
+
npx apiblaze create --openapi https://petstore3.swagger.io/api/v3/openapi.json
|
|
39
|
+
|
|
36
40
|
# Configure how your backend is accessed through the proxy
|
|
37
41
|
npx apiblaze config
|
|
38
42
|
|
|
@@ -114,6 +118,7 @@ Every chat turn shows its cost.
|
|
|
114
118
|
| Command | What it does |
|
|
115
119
|
|---|---|
|
|
116
120
|
| `apiblaze create --target <url>` | Make an API from a backend (no account needed) |
|
|
121
|
+
| `apiblaze create --openapi <file\|url>` | Make an API from an OpenAPI spec — a local file or a spec URL (`--openapispec` is the same flag) |
|
|
117
122
|
| `apiblaze sidecar` | Route a Next.js app's external `fetch()` calls through APIblaze (one command) |
|
|
118
123
|
| `apiblaze dev [port]` | Put your localhost behind a public URL |
|
|
119
124
|
| `apiblaze login` / `logout` | Sign in / out (logout asks producer or consumer) |
|
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 ${
|
|
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.
|
|
935
|
+
var version = "0.19.18";
|
|
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
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
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 {
|
|
1555
|
+
const { create } = await import_inquirer.default.prompt([{
|
|
1551
1556
|
type: "confirm",
|
|
1552
|
-
name: "
|
|
1553
|
-
message:
|
|
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 (!
|
|
1557
|
-
|
|
1558
|
-
|
|
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
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
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
|
-
|
|
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}
|
|
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
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
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
|
-
|
|
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);
|
|
@@ -1897,6 +1948,27 @@ function isHttpUrl(s) {
|
|
|
1897
1948
|
return false;
|
|
1898
1949
|
}
|
|
1899
1950
|
}
|
|
1951
|
+
async function loadOpenapiSource(ref) {
|
|
1952
|
+
let text;
|
|
1953
|
+
if (isHttpUrl(ref)) {
|
|
1954
|
+
const res = await fetch(ref.trim(), {
|
|
1955
|
+
headers: { accept: "application/json, application/yaml, text/yaml, */*" }
|
|
1956
|
+
}).catch((err) => fail(`Could not fetch the OpenAPI spec at ${ref} \u2014 ${err.message}`));
|
|
1957
|
+
if (!res.ok) fail(`Could not fetch the OpenAPI spec at ${ref} (HTTP ${res.status}).`);
|
|
1958
|
+
text = await res.text();
|
|
1959
|
+
} else {
|
|
1960
|
+
try {
|
|
1961
|
+
text = import_fs2.default.readFileSync(ref, "utf8");
|
|
1962
|
+
} catch {
|
|
1963
|
+
fail(`Cannot read the OpenAPI spec "${ref}" \u2014 it is not a readable file, and not an http(s) URL.`);
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
if (!text.trim()) fail(`The OpenAPI spec is empty: ${ref}`);
|
|
1967
|
+
if (!/["']?(openapi|swagger|paths)["']?\s*:/i.test(text)) {
|
|
1968
|
+
fail(`That does not look like an OpenAPI/Swagger document (no openapi/swagger/paths): ${ref}`);
|
|
1969
|
+
}
|
|
1970
|
+
return text;
|
|
1971
|
+
}
|
|
1900
1972
|
function stripTenantFromPortal(devPortal) {
|
|
1901
1973
|
try {
|
|
1902
1974
|
const u = new URL(devPortal);
|
|
@@ -2005,12 +2077,7 @@ async function runCreate(opts = {}) {
|
|
|
2005
2077
|
let openapiContent = null;
|
|
2006
2078
|
if (opts.openapi !== void 0) {
|
|
2007
2079
|
if (opts.target !== void 0) fail("Provide only one of --target or --openapi.");
|
|
2008
|
-
|
|
2009
|
-
openapiContent = import_fs2.default.readFileSync(opts.openapi, "utf8");
|
|
2010
|
-
} catch {
|
|
2011
|
-
fail(`Cannot read --openapi file: ${opts.openapi}`);
|
|
2012
|
-
}
|
|
2013
|
-
if (!openapiContent || !openapiContent.trim()) fail(`--openapi file is empty: ${opts.openapi}`);
|
|
2080
|
+
openapiContent = await loadOpenapiSource(opts.openapi);
|
|
2014
2081
|
}
|
|
2015
2082
|
let targetUrl = "";
|
|
2016
2083
|
if (openapiContent) {
|
|
@@ -2135,11 +2202,7 @@ async function runAnonymousCreate(opts) {
|
|
|
2135
2202
|
fail("Proxy name must be at least 3 characters (letters and digits only).");
|
|
2136
2203
|
}
|
|
2137
2204
|
if (opts.openapi !== void 0) {
|
|
2138
|
-
|
|
2139
|
-
body.openapi = import_fs2.default.readFileSync(opts.openapi, "utf8");
|
|
2140
|
-
} catch {
|
|
2141
|
-
fail(`Cannot read --openapi file: ${opts.openapi}`);
|
|
2142
|
-
}
|
|
2205
|
+
body.openapi = await loadOpenapiSource(opts.openapi);
|
|
2143
2206
|
}
|
|
2144
2207
|
if (opts.target && !isHttpUrl(opts.target)) fail("--target must be a valid http(s) URL.");
|
|
2145
2208
|
let target = opts.target?.trim() || (typeof body.target === "string" ? body.target : "") || (typeof body.target_url === "string" ? body.target_url : "");
|
|
@@ -7416,9 +7479,9 @@ program.command("login").description("Authenticate with APIblaze").option("--tea
|
|
|
7416
7479
|
process.exit(1);
|
|
7417
7480
|
}
|
|
7418
7481
|
});
|
|
7419
|
-
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
|
|
7482
|
+
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|url>", "Create FROM an OpenAPI spec instead of --target \u2014 a local file or a URL (e.g. https://pokeapi.co/openapi.yaml). Routes, API version and environments (one per `servers` entry) all come from the spec").option("--openapispec <file|url>", "Alias for --openapi").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) => {
|
|
7420
7483
|
try {
|
|
7421
|
-
await runCreate(opts);
|
|
7484
|
+
await runCreate({ ...opts, openapi: opts.openapi ?? opts.openapispec });
|
|
7422
7485
|
} catch (err) {
|
|
7423
7486
|
await printError(err);
|
|
7424
7487
|
process.exit(1);
|
|
@@ -7588,6 +7651,7 @@ Examples:
|
|
|
7588
7651
|
$ npx apiblaze apichat --openapi https://pokeapi.co/openapi.yaml # chat with any API
|
|
7589
7652
|
$ npx apiblaze agent # just chat
|
|
7590
7653
|
$ npx apiblaze create --target https://api.example.com # one-line API
|
|
7654
|
+
$ npx apiblaze create --openapi https://pokeapi.co/openapi.yaml # build it from a spec URL
|
|
7591
7655
|
$ npx apiblaze dev 3000 # localhost \u2192 public URL
|
|
7592
7656
|
$ npx apiblaze throttle myapi --rate 50 --verbose # configure + show the API call
|
|
7593
7657
|
$ npx apiblaze consumer login # act as a consumer of your API
|