apiblaze 0.6.1 → 0.7.2
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/dist/index.js +415 -111
- package/dist/sidecar/index.d.mts +2 -0
- package/dist/sidecar/index.d.ts +2 -0
- package/dist/sidecar/index.js +8 -2
- package/dist/sidecar/index.mjs +8 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,6 +6,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
12
|
+
var __export = (target, all) => {
|
|
13
|
+
for (var name in all)
|
|
14
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
|
+
};
|
|
9
16
|
var __copyProps = (to, from, except, desc) => {
|
|
10
17
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
18
|
for (let key of __getOwnPropNames(from))
|
|
@@ -23,33 +30,23 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
23
30
|
mod
|
|
24
31
|
));
|
|
25
32
|
|
|
26
|
-
// src/index.ts
|
|
27
|
-
var import_commander = require("commander");
|
|
28
|
-
var import_chalk30 = __toESM(require("chalk"));
|
|
29
|
-
|
|
30
|
-
// package.json
|
|
31
|
-
var version = "0.6.1";
|
|
32
|
-
|
|
33
33
|
// src/types.ts
|
|
34
|
-
var ApiError
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
var ApiError;
|
|
35
|
+
var init_types = __esm({
|
|
36
|
+
"src/types.ts"() {
|
|
37
|
+
"use strict";
|
|
38
|
+
ApiError = class extends Error {
|
|
39
|
+
constructor(status, message, body) {
|
|
40
|
+
super(message);
|
|
41
|
+
this.status = status;
|
|
42
|
+
this.body = body;
|
|
43
|
+
this.name = "ApiError";
|
|
44
|
+
}
|
|
45
|
+
};
|
|
40
46
|
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// src/commands/login.ts
|
|
44
|
-
var import_chalk2 = __toESM(require("chalk"));
|
|
45
|
-
var import_ora = __toESM(require("ora"));
|
|
47
|
+
});
|
|
46
48
|
|
|
47
49
|
// src/lib/auth.ts
|
|
48
|
-
var fs = __toESM(require("fs"));
|
|
49
|
-
var os = __toESM(require("os"));
|
|
50
|
-
var path = __toESM(require("path"));
|
|
51
|
-
var APIBLAZE_DIR = path.join(os.homedir(), ".apiblaze");
|
|
52
|
-
var CREDENTIALS_PATH = path.join(APIBLAZE_DIR, "credentials.json");
|
|
53
50
|
function saveCredentials(creds) {
|
|
54
51
|
fs.mkdirSync(APIBLAZE_DIR, { recursive: true });
|
|
55
52
|
fs.writeFileSync(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), "utf-8");
|
|
@@ -81,17 +78,39 @@ function getAccessToken() {
|
|
|
81
78
|
}
|
|
82
79
|
return creds.accessToken;
|
|
83
80
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
var fs, os, path, APIBLAZE_DIR, CREDENTIALS_PATH;
|
|
82
|
+
var init_auth = __esm({
|
|
83
|
+
"src/lib/auth.ts"() {
|
|
84
|
+
"use strict";
|
|
85
|
+
fs = __toESM(require("fs"));
|
|
86
|
+
os = __toESM(require("os"));
|
|
87
|
+
path = __toESM(require("path"));
|
|
88
|
+
APIBLAZE_DIR = path.join(os.homedir(), ".apiblaze");
|
|
89
|
+
CREDENTIALS_PATH = path.join(APIBLAZE_DIR, "credentials.json");
|
|
90
|
+
}
|
|
91
|
+
});
|
|
87
92
|
|
|
88
93
|
// src/lib/api.ts
|
|
89
|
-
var
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
var api_exports = {};
|
|
95
|
+
__export(api_exports, {
|
|
96
|
+
agentCall: () => agentCall,
|
|
97
|
+
checkProxyName: () => checkProxyName,
|
|
98
|
+
claimProxy: () => claimProxy,
|
|
99
|
+
claimTeam: () => claimTeam,
|
|
100
|
+
createProxy: () => createProxy,
|
|
101
|
+
createProxyAnonymous: () => createProxyAnonymous,
|
|
102
|
+
deleteDevTunnel: () => deleteDevTunnel,
|
|
103
|
+
getLocalhostTargets: () => getLocalhostTargets,
|
|
104
|
+
getProjects: () => getProjects,
|
|
105
|
+
getTeams: () => getTeams,
|
|
106
|
+
putDevTunnel: () => putDevTunnel,
|
|
107
|
+
sidecarApproveAnonymous: () => sidecarApproveAnonymous,
|
|
108
|
+
sidecarInitAnonymous: () => sidecarInitAnonymous
|
|
109
|
+
});
|
|
110
|
+
async function createProxyAnonymous(body, anonSession) {
|
|
92
111
|
const res = await fetch(`${PUBLIC_API_BASE}/proxy`, {
|
|
93
112
|
method: "POST",
|
|
94
|
-
headers: { "Content-Type": "application/json" },
|
|
113
|
+
headers: { "Content-Type": "application/json", ...anonSession ? { "X-Abz-Anon-Session": anonSession } : {} },
|
|
95
114
|
body: JSON.stringify(body)
|
|
96
115
|
});
|
|
97
116
|
if (!res.ok) {
|
|
@@ -105,9 +124,9 @@ async function createProxyAnonymous(body) {
|
|
|
105
124
|
}
|
|
106
125
|
return res.json();
|
|
107
126
|
}
|
|
108
|
-
async function apiFetch(
|
|
127
|
+
async function apiFetch(path6, options = {}) {
|
|
109
128
|
const token = getAccessToken();
|
|
110
|
-
const url = `${DASHBOARD_BASE}${
|
|
129
|
+
const url = `${DASHBOARD_BASE}${path6}`;
|
|
111
130
|
const res = await fetch(url, {
|
|
112
131
|
...options,
|
|
113
132
|
headers: {
|
|
@@ -121,8 +140,9 @@ async function apiFetch(path4, options = {}) {
|
|
|
121
140
|
let parsed;
|
|
122
141
|
try {
|
|
123
142
|
parsed = await res.json();
|
|
143
|
+
const pick2 = (v) => typeof v === "string" ? v : v && typeof v === "object" ? pick2(v.message) ?? pick2(v.error) : void 0;
|
|
124
144
|
const b = parsed;
|
|
125
|
-
message = b.message ?? b.error ?? message;
|
|
145
|
+
message = pick2(b.message) ?? pick2(b.error) ?? pick2(b.details) ?? message;
|
|
126
146
|
} catch {
|
|
127
147
|
}
|
|
128
148
|
throw new ApiError(res.status, message, parsed);
|
|
@@ -132,12 +152,12 @@ async function apiFetch(path4, options = {}) {
|
|
|
132
152
|
}
|
|
133
153
|
return res.json();
|
|
134
154
|
}
|
|
135
|
-
async function agentCall(
|
|
155
|
+
async function agentCall(path6, method, body) {
|
|
136
156
|
const token = getAccessToken();
|
|
137
157
|
const res = await fetch(`${DASHBOARD_BASE}/api/cli/agents`, {
|
|
138
158
|
method: "POST",
|
|
139
159
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
|
|
140
|
-
body: JSON.stringify({ path:
|
|
160
|
+
body: JSON.stringify({ path: path6, method, body })
|
|
141
161
|
});
|
|
142
162
|
let data = null;
|
|
143
163
|
try {
|
|
@@ -177,6 +197,32 @@ async function claimProxy(claimCode, teamId) {
|
|
|
177
197
|
body: JSON.stringify({ claimCode, team_id: teamId })
|
|
178
198
|
});
|
|
179
199
|
}
|
|
200
|
+
async function claimTeam(code) {
|
|
201
|
+
return apiFetch("/api/cli/claim-team", {
|
|
202
|
+
method: "POST",
|
|
203
|
+
body: JSON.stringify({ code })
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
async function sidecarInitAnonymous(anonSession) {
|
|
207
|
+
const res = await fetch(`${PUBLIC_API_BASE}/sidecar/init`, {
|
|
208
|
+
method: "POST",
|
|
209
|
+
headers: { "content-type": "application/json", ...anonSession ? { "X-Abz-Anon-Session": anonSession } : {} },
|
|
210
|
+
body: "{}"
|
|
211
|
+
});
|
|
212
|
+
const data = await res.json().catch(() => ({}));
|
|
213
|
+
if (!res.ok) throw new ApiError(res.status, data?.error ?? "init_failed", data);
|
|
214
|
+
return data;
|
|
215
|
+
}
|
|
216
|
+
async function sidecarApproveAnonymous(invokeKey, origin) {
|
|
217
|
+
const res = await fetch(`${PUBLIC_API_BASE}/sidecar/approve`, {
|
|
218
|
+
method: "POST",
|
|
219
|
+
headers: { "content-type": "application/json", "x-abz-sidecar-key": invokeKey },
|
|
220
|
+
body: JSON.stringify({ origin })
|
|
221
|
+
});
|
|
222
|
+
const data = await res.json().catch(() => ({}));
|
|
223
|
+
if (!res.ok) throw new ApiError(res.status, data?.detail ?? data?.error ?? "approve_failed", data);
|
|
224
|
+
return data;
|
|
225
|
+
}
|
|
180
226
|
async function putDevTunnel(payload) {
|
|
181
227
|
return apiFetch("/api/cli/dev-tunnel", {
|
|
182
228
|
method: "PUT",
|
|
@@ -189,8 +235,81 @@ async function deleteDevTunnel(restore) {
|
|
|
189
235
|
body: JSON.stringify({ restore })
|
|
190
236
|
});
|
|
191
237
|
}
|
|
238
|
+
var DASHBOARD_BASE, PUBLIC_API_BASE;
|
|
239
|
+
var init_api = __esm({
|
|
240
|
+
"src/lib/api.ts"() {
|
|
241
|
+
"use strict";
|
|
242
|
+
init_auth();
|
|
243
|
+
init_types();
|
|
244
|
+
DASHBOARD_BASE = "https://dashboard.apiblaze.com";
|
|
245
|
+
PUBLIC_API_BASE = "https://api.apiblaze.com";
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// src/lib/anon-session.ts
|
|
250
|
+
var anon_session_exports = {};
|
|
251
|
+
__export(anon_session_exports, {
|
|
252
|
+
clearAnonSession: () => clearAnonSession,
|
|
253
|
+
loadAnonSession: () => loadAnonSession,
|
|
254
|
+
saveAnonSession: () => saveAnonSession
|
|
255
|
+
});
|
|
256
|
+
function loadAnonSession() {
|
|
257
|
+
try {
|
|
258
|
+
const s = JSON.parse(fs3.readFileSync(SESSION_PATH, "utf8"));
|
|
259
|
+
return s?.anon_session ? s : null;
|
|
260
|
+
} catch {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function saveAnonSession(anon_session, claim_code) {
|
|
265
|
+
try {
|
|
266
|
+
fs3.mkdirSync(DIR, { recursive: true });
|
|
267
|
+
const prev = loadAnonSession();
|
|
268
|
+
const merged = {
|
|
269
|
+
anon_session,
|
|
270
|
+
claim_code: claim_code ?? prev?.claim_code,
|
|
271
|
+
created_at: prev?.created_at ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
272
|
+
};
|
|
273
|
+
fs3.writeFileSync(SESSION_PATH, JSON.stringify(merged, null, 2));
|
|
274
|
+
} catch {
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
function clearAnonSession() {
|
|
278
|
+
try {
|
|
279
|
+
fs3.unlinkSync(SESSION_PATH);
|
|
280
|
+
} catch {
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
var fs3, path2, os2, DIR, SESSION_PATH;
|
|
284
|
+
var init_anon_session = __esm({
|
|
285
|
+
"src/lib/anon-session.ts"() {
|
|
286
|
+
"use strict";
|
|
287
|
+
fs3 = __toESM(require("fs"));
|
|
288
|
+
path2 = __toESM(require("path"));
|
|
289
|
+
os2 = __toESM(require("os"));
|
|
290
|
+
DIR = path2.join(os2.homedir(), ".apiblaze");
|
|
291
|
+
SESSION_PATH = path2.join(DIR, "anon.json");
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
// src/index.ts
|
|
296
|
+
var import_commander = require("commander");
|
|
297
|
+
var import_chalk30 = __toESM(require("chalk"));
|
|
298
|
+
|
|
299
|
+
// package.json
|
|
300
|
+
var version = "0.7.2";
|
|
301
|
+
|
|
302
|
+
// src/index.ts
|
|
303
|
+
init_types();
|
|
304
|
+
|
|
305
|
+
// src/commands/login.ts
|
|
306
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
307
|
+
var import_ora = __toESM(require("ora"));
|
|
308
|
+
init_auth();
|
|
192
309
|
|
|
193
310
|
// src/lib/team.ts
|
|
311
|
+
var import_chalk = __toESM(require("chalk"));
|
|
312
|
+
init_api();
|
|
194
313
|
async function resolveLinkedTeam(opts) {
|
|
195
314
|
let teams;
|
|
196
315
|
try {
|
|
@@ -326,6 +445,8 @@ var import_fs = __toESM(require("fs"));
|
|
|
326
445
|
var import_chalk4 = __toESM(require("chalk"));
|
|
327
446
|
var import_ora2 = __toESM(require("ora"));
|
|
328
447
|
var import_inquirer = __toESM(require("inquirer"));
|
|
448
|
+
init_auth();
|
|
449
|
+
init_api();
|
|
329
450
|
|
|
330
451
|
// src/lib/traffic.ts
|
|
331
452
|
var import_chalk3 = __toESM(require("chalk"));
|
|
@@ -420,11 +541,11 @@ function decodeJwt(token) {
|
|
|
420
541
|
return null;
|
|
421
542
|
}
|
|
422
543
|
}
|
|
423
|
-
function maskPath(
|
|
424
|
-
const q =
|
|
425
|
-
if (q < 0) return
|
|
426
|
-
const base =
|
|
427
|
-
const query =
|
|
544
|
+
function maskPath(path6) {
|
|
545
|
+
const q = path6.indexOf("?");
|
|
546
|
+
if (q < 0) return path6;
|
|
547
|
+
const base = path6.slice(0, q);
|
|
548
|
+
const query = path6.slice(q + 1);
|
|
428
549
|
const masked = query.split("&").map((pair) => {
|
|
429
550
|
const eq = pair.indexOf("=");
|
|
430
551
|
if (eq < 0) return pair;
|
|
@@ -1018,6 +1139,8 @@ Tunneling ${selectedTargets.length} project(s) to localhost:${options.port}
|
|
|
1018
1139
|
// src/commands/projects.ts
|
|
1019
1140
|
var import_chalk5 = __toESM(require("chalk"));
|
|
1020
1141
|
var import_ora3 = __toESM(require("ora"));
|
|
1142
|
+
init_auth();
|
|
1143
|
+
init_api();
|
|
1021
1144
|
async function runProjects() {
|
|
1022
1145
|
const creds = loadCredentials();
|
|
1023
1146
|
if (!creds) {
|
|
@@ -1077,6 +1200,8 @@ ${projects.length} project${projects.length === 1 ? "" : "s"}`));
|
|
|
1077
1200
|
var import_fs2 = __toESM(require("fs"));
|
|
1078
1201
|
var import_chalk6 = __toESM(require("chalk"));
|
|
1079
1202
|
var import_ora4 = __toESM(require("ora"));
|
|
1203
|
+
init_auth();
|
|
1204
|
+
init_api();
|
|
1080
1205
|
function normalizeName(raw) {
|
|
1081
1206
|
return (raw || "").toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
1082
1207
|
}
|
|
@@ -1345,15 +1470,19 @@ async function runAnonymousCreate(opts) {
|
|
|
1345
1470
|
if (opts.displayName) body.display_name = opts.displayName;
|
|
1346
1471
|
if (opts.apiversion) body.api_version = opts.apiversion;
|
|
1347
1472
|
if (opts.auth && opts.auth !== "api_key") body.auth_type = opts.auth;
|
|
1348
|
-
const
|
|
1473
|
+
const { loadAnonSession: loadAnonSession2, saveAnonSession: saveAnonSession2, clearAnonSession: clearAnonSession2 } = await Promise.resolve().then(() => (init_anon_session(), anon_session_exports));
|
|
1474
|
+
if (opts.newSession) clearAnonSession2();
|
|
1475
|
+
const prior = loadAnonSession2();
|
|
1476
|
+
const spinner = !opts.json ? (0, import_ora4.default)(prior ? "Creating proxy (adding to your anonymous session)..." : "Creating proxy...").start() : null;
|
|
1349
1477
|
let result;
|
|
1350
1478
|
try {
|
|
1351
|
-
result = await createProxyAnonymous(body);
|
|
1479
|
+
result = await createProxyAnonymous(body, prior?.anon_session);
|
|
1352
1480
|
spinner?.succeed(import_chalk6.default.green("Proxy created!"));
|
|
1353
1481
|
} catch (err) {
|
|
1354
1482
|
spinner?.fail("Failed to create proxy.");
|
|
1355
1483
|
throw err;
|
|
1356
1484
|
}
|
|
1485
|
+
if (result.anon_session) saveAnonSession2(result.anon_session, result.team_claim_code);
|
|
1357
1486
|
const version2 = result.api_version || "1.0.0";
|
|
1358
1487
|
const keys = result.api_keys ?? {};
|
|
1359
1488
|
const apiKey = result.apiKey ?? keys.prod ?? Object.values(keys)[0];
|
|
@@ -1380,17 +1509,26 @@ async function runAnonymousCreate(opts) {
|
|
|
1380
1509
|
console.log(import_chalk6.default.dim("\n Save this now \u2014 send it as the X-API-Key header. It may not be shown again."));
|
|
1381
1510
|
}
|
|
1382
1511
|
if (prodEndpoint) printCurlExample(prodEndpoint, opts.auth || "api_key", apiKey, result.portal);
|
|
1383
|
-
if (result.
|
|
1512
|
+
if (result.team_claim_code) {
|
|
1513
|
+
console.log();
|
|
1514
|
+
console.log(` ${import_chalk6.default.yellow("\u26A0 Anonymous \u2014 claim within 30 days or it expires.")} All your anonymous proxies`);
|
|
1515
|
+
console.log(` on this machine share ONE team. To keep them all:`);
|
|
1516
|
+
console.log(` ${import_chalk6.default.cyan("apiblaze login")} then ${import_chalk6.default.cyan("apiblaze claim")} ${import_chalk6.default.dim("(no code needed here)")}`);
|
|
1517
|
+
console.log(import_chalk6.default.dim(` From another machine: apiblaze claim ${result.team_claim_code}`));
|
|
1518
|
+
} else if (result.claim_url) {
|
|
1384
1519
|
console.log();
|
|
1385
1520
|
console.log(` ${import_chalk6.default.yellow("\u26A0 Anonymous proxy \u2014 claim it to your account within 30 days or it expires:")}`);
|
|
1386
1521
|
console.log(` ${import_chalk6.default.bold(result.claim_url)}`);
|
|
1387
|
-
console.log(import_chalk6.default.dim(" (or run `apiblaze login`, then re-run `apiblaze create` to create it under your account)"));
|
|
1388
1522
|
}
|
|
1389
1523
|
console.log();
|
|
1390
1524
|
}
|
|
1391
1525
|
|
|
1392
1526
|
// src/commands/claim.ts
|
|
1393
1527
|
var import_chalk7 = __toESM(require("chalk"));
|
|
1528
|
+
init_auth();
|
|
1529
|
+
init_anon_session();
|
|
1530
|
+
init_api();
|
|
1531
|
+
init_types();
|
|
1394
1532
|
function fail2(message) {
|
|
1395
1533
|
console.error(import_chalk7.default.red(`Error: ${message}`));
|
|
1396
1534
|
process.exit(1);
|
|
@@ -1401,6 +1539,14 @@ async function runClaim(claimCodeArg, opts) {
|
|
|
1401
1539
|
fail2("Not logged in. Run `apiblaze login` first, then claim.");
|
|
1402
1540
|
}
|
|
1403
1541
|
let claimCode = (claimCodeArg ?? "").trim();
|
|
1542
|
+
let fromLocalSession = false;
|
|
1543
|
+
if (!claimCode) {
|
|
1544
|
+
const sess = loadAnonSession();
|
|
1545
|
+
if (sess?.claim_code) {
|
|
1546
|
+
claimCode = sess.claim_code;
|
|
1547
|
+
fromLocalSession = true;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1404
1550
|
if (!claimCode && process.stdin.isTTY) {
|
|
1405
1551
|
const { default: inquirer2 } = await import("inquirer");
|
|
1406
1552
|
const { code } = await inquirer2.prompt([{
|
|
@@ -1411,7 +1557,30 @@ async function runClaim(claimCodeArg, opts) {
|
|
|
1411
1557
|
claimCode = (code ?? "").trim();
|
|
1412
1558
|
}
|
|
1413
1559
|
if (!claimCode) {
|
|
1414
|
-
fail2("
|
|
1560
|
+
fail2("Nothing to claim on this machine. Run `apiblaze claim <code>` with a code, or `apiblaze create`/`init` first.");
|
|
1561
|
+
}
|
|
1562
|
+
try {
|
|
1563
|
+
const t = await claimTeam(claimCode);
|
|
1564
|
+
if (fromLocalSession) clearAnonSession();
|
|
1565
|
+
if (opts.json) {
|
|
1566
|
+
console.log(JSON.stringify(t, null, 2));
|
|
1567
|
+
return;
|
|
1568
|
+
}
|
|
1569
|
+
console.log(import_chalk7.default.green(`
|
|
1570
|
+
\u2714 Claimed the whole team into your account.`));
|
|
1571
|
+
console.log(` Team: ${import_chalk7.default.bold(t.team_id)}`);
|
|
1572
|
+
console.log(` Its proxies + keys are now yours. Switch to it with ${import_chalk7.default.cyan(`apiblaze team ${t.team_id}`)}.`);
|
|
1573
|
+
console.log(`
|
|
1574
|
+
Manage it at ${import_chalk7.default.cyan("https://dashboard.apiblaze.com/dashboard")}`);
|
|
1575
|
+
return;
|
|
1576
|
+
} catch (err) {
|
|
1577
|
+
if (err instanceof ApiError && err.status !== 404) {
|
|
1578
|
+
const code = typeof err.body === "object" && err.body ? err.body.error : void 0;
|
|
1579
|
+
if (code === "already_claimed") fail2("That claim code has already been used.");
|
|
1580
|
+
if (code === "expired") fail2("That claim code has expired. Create a fresh setup with `apiblaze init`.");
|
|
1581
|
+
if (code === "not_claimable") fail2("That team can no longer be claimed (it already belongs to an account).");
|
|
1582
|
+
fail2(`Could not claim: ${err.message}`);
|
|
1583
|
+
}
|
|
1415
1584
|
}
|
|
1416
1585
|
const teams = await getTeams().catch(() => []);
|
|
1417
1586
|
if (teams.length === 0) {
|
|
@@ -1443,7 +1612,13 @@ async function runClaim(claimCodeArg, opts) {
|
|
|
1443
1612
|
fail2(`Specify a team: \`apiblaze claim ${claimCode} --team <name|id>\`. Available: ${teams.map((t) => t.name).join(", ")}.`);
|
|
1444
1613
|
}
|
|
1445
1614
|
const teamName = teams.find((t) => t.teamId === teamId)?.name ?? teamId;
|
|
1446
|
-
|
|
1615
|
+
let result;
|
|
1616
|
+
try {
|
|
1617
|
+
result = await claimProxy(claimCode, teamId);
|
|
1618
|
+
} catch (err) {
|
|
1619
|
+
if (err instanceof ApiError) fail2(`That claim code isn't valid \u2014 it may be mistyped, already claimed, or expired.`);
|
|
1620
|
+
throw err;
|
|
1621
|
+
}
|
|
1447
1622
|
if (opts.json) {
|
|
1448
1623
|
console.log(JSON.stringify(result, null, 2));
|
|
1449
1624
|
return;
|
|
@@ -1461,32 +1636,33 @@ async function runClaim(claimCodeArg, opts) {
|
|
|
1461
1636
|
|
|
1462
1637
|
// src/commands/logout.ts
|
|
1463
1638
|
var import_chalk8 = __toESM(require("chalk"));
|
|
1639
|
+
init_auth();
|
|
1464
1640
|
|
|
1465
1641
|
// src/lib/consumer-auth.ts
|
|
1466
|
-
var
|
|
1467
|
-
var
|
|
1468
|
-
var
|
|
1642
|
+
var fs5 = __toESM(require("fs"));
|
|
1643
|
+
var os3 = __toESM(require("os"));
|
|
1644
|
+
var path3 = __toESM(require("path"));
|
|
1469
1645
|
var crypto = __toESM(require("crypto"));
|
|
1470
1646
|
var import_child_process = require("child_process");
|
|
1471
1647
|
var AUTH_BASE = process.env.APIBLAZE_AUTH_BASE || "https://auth.apiblaze.com";
|
|
1472
|
-
var APIBLAZE_DIR2 =
|
|
1473
|
-
var CONSUMER_PATH =
|
|
1648
|
+
var APIBLAZE_DIR2 = path3.join(os3.homedir(), ".apiblaze");
|
|
1649
|
+
var CONSUMER_PATH = path3.join(APIBLAZE_DIR2, "consumer.json");
|
|
1474
1650
|
var DEVICE_GRANT = "urn:ietf:params:oauth:grant-type:device_code";
|
|
1475
1651
|
function loadConsumer() {
|
|
1476
1652
|
try {
|
|
1477
|
-
return JSON.parse(
|
|
1653
|
+
return JSON.parse(fs5.readFileSync(CONSUMER_PATH, "utf-8"));
|
|
1478
1654
|
} catch {
|
|
1479
1655
|
return null;
|
|
1480
1656
|
}
|
|
1481
1657
|
}
|
|
1482
1658
|
function saveConsumer(creds) {
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1659
|
+
fs5.mkdirSync(APIBLAZE_DIR2, { recursive: true });
|
|
1660
|
+
fs5.writeFileSync(CONSUMER_PATH, JSON.stringify(creds, null, 2), "utf-8");
|
|
1661
|
+
fs5.chmodSync(CONSUMER_PATH, 384);
|
|
1486
1662
|
}
|
|
1487
1663
|
function clearConsumer() {
|
|
1488
1664
|
try {
|
|
1489
|
-
|
|
1665
|
+
fs5.unlinkSync(CONSUMER_PATH);
|
|
1490
1666
|
return true;
|
|
1491
1667
|
} catch {
|
|
1492
1668
|
return false;
|
|
@@ -1628,6 +1804,7 @@ async function runLogout(opts = {}) {
|
|
|
1628
1804
|
|
|
1629
1805
|
// src/commands/whoami.ts
|
|
1630
1806
|
var import_chalk9 = __toESM(require("chalk"));
|
|
1807
|
+
init_auth();
|
|
1631
1808
|
async function runWhoami(opts = {}) {
|
|
1632
1809
|
const creds = loadCredentials();
|
|
1633
1810
|
const consumer2 = loadConsumer();
|
|
@@ -1668,6 +1845,8 @@ async function runWhoami(opts = {}) {
|
|
|
1668
1845
|
|
|
1669
1846
|
// src/commands/team.ts
|
|
1670
1847
|
var import_chalk10 = __toESM(require("chalk"));
|
|
1848
|
+
init_auth();
|
|
1849
|
+
init_api();
|
|
1671
1850
|
function fail3(message) {
|
|
1672
1851
|
console.error(import_chalk10.default.red(`Error: ${message}`));
|
|
1673
1852
|
process.exit(1);
|
|
@@ -1712,10 +1891,13 @@ async function runTeam(arg) {
|
|
|
1712
1891
|
|
|
1713
1892
|
// src/commands/authz.ts
|
|
1714
1893
|
var import_chalk12 = __toESM(require("chalk"));
|
|
1894
|
+
init_auth();
|
|
1895
|
+
init_api();
|
|
1715
1896
|
|
|
1716
1897
|
// src/lib/agent-chat.ts
|
|
1717
1898
|
var import_readline = __toESM(require("readline"));
|
|
1718
1899
|
var import_chalk11 = __toESM(require("chalk"));
|
|
1900
|
+
init_api();
|
|
1719
1901
|
async function runAgentChatRepl(opts) {
|
|
1720
1902
|
const { title, subtitle, endpoint, buildBody, seedPrompt, summarizeProposal, commands } = opts;
|
|
1721
1903
|
console.log("\n" + import_chalk11.default.cyan.bold(title));
|
|
@@ -1885,6 +2067,8 @@ async function runAuthz(projectArg, apiVersionArg) {
|
|
|
1885
2067
|
|
|
1886
2068
|
// src/commands/openapi.ts
|
|
1887
2069
|
var import_chalk13 = __toESM(require("chalk"));
|
|
2070
|
+
init_auth();
|
|
2071
|
+
init_api();
|
|
1888
2072
|
async function runOpenapi(projectArg, apiVersionArg) {
|
|
1889
2073
|
const creds = loadCredentials();
|
|
1890
2074
|
if (!creds) throw new Error("Not authenticated. Run `apiblaze login` first.");
|
|
@@ -1949,6 +2133,8 @@ async function runOpenapi(projectArg, apiVersionArg) {
|
|
|
1949
2133
|
|
|
1950
2134
|
// src/commands/mcp.ts
|
|
1951
2135
|
var import_chalk14 = __toESM(require("chalk"));
|
|
2136
|
+
init_auth();
|
|
2137
|
+
init_api();
|
|
1952
2138
|
async function runMcp(projectArg, apiVersionArg, opts) {
|
|
1953
2139
|
const creds = loadCredentials();
|
|
1954
2140
|
if (!creds) throw new Error("Not authenticated. Run `apiblaze login` first.");
|
|
@@ -1994,6 +2180,7 @@ var import_ora5 = __toESM(require("ora"));
|
|
|
1994
2180
|
|
|
1995
2181
|
// src/lib/admin.ts
|
|
1996
2182
|
var import_chalk16 = __toESM(require("chalk"));
|
|
2183
|
+
init_auth();
|
|
1997
2184
|
|
|
1998
2185
|
// src/lib/trace.ts
|
|
1999
2186
|
var import_chalk15 = __toESM(require("chalk"));
|
|
@@ -2036,6 +2223,7 @@ function renderTrace() {
|
|
|
2036
2223
|
}
|
|
2037
2224
|
|
|
2038
2225
|
// src/lib/admin.ts
|
|
2226
|
+
init_types();
|
|
2039
2227
|
var DASHBOARD_BASE3 = process.env.APIBLAZE_DASHBOARD_BASE || "https://dashboard.apiblaze.com";
|
|
2040
2228
|
async function admin(call) {
|
|
2041
2229
|
const token = getAccessToken();
|
|
@@ -2068,6 +2256,8 @@ function maybePrintBilling(data) {
|
|
|
2068
2256
|
|
|
2069
2257
|
// src/lib/resolve.ts
|
|
2070
2258
|
var import_chalk17 = __toESM(require("chalk"));
|
|
2259
|
+
init_auth();
|
|
2260
|
+
init_api();
|
|
2071
2261
|
function requireAuth() {
|
|
2072
2262
|
const creds = loadCredentials();
|
|
2073
2263
|
if (!creds) {
|
|
@@ -2175,6 +2365,7 @@ async function runDelete(project, version2, opts) {
|
|
|
2175
2365
|
// src/commands/export.ts
|
|
2176
2366
|
var import_chalk19 = __toESM(require("chalk"));
|
|
2177
2367
|
var import_fs3 = require("fs");
|
|
2368
|
+
init_auth();
|
|
2178
2369
|
var DASHBOARD_BASE4 = process.env.APIBLAZE_DASHBOARD_BASE || "https://dashboard.apiblaze.com";
|
|
2179
2370
|
async function runExport(projectArg, versionArg, opts) {
|
|
2180
2371
|
const token = getAccessToken();
|
|
@@ -2581,7 +2772,7 @@ async function runKeyRevoke(keyId, opts) {
|
|
|
2581
2772
|
}
|
|
2582
2773
|
|
|
2583
2774
|
// src/commands/spec.ts
|
|
2584
|
-
var
|
|
2775
|
+
var fs6 = __toESM(require("fs"));
|
|
2585
2776
|
var import_chalk24 = __toESM(require("chalk"));
|
|
2586
2777
|
var import_ora10 = __toESM(require("ora"));
|
|
2587
2778
|
async function runSpecGet(project, opts) {
|
|
@@ -2601,7 +2792,7 @@ async function runSpecSet(project, opts) {
|
|
|
2601
2792
|
}
|
|
2602
2793
|
let specContent;
|
|
2603
2794
|
try {
|
|
2604
|
-
specContent =
|
|
2795
|
+
specContent = fs6.readFileSync(opts.file, "utf-8");
|
|
2605
2796
|
} catch {
|
|
2606
2797
|
console.error(import_chalk24.default.red(`Cannot read file: ${opts.file}`));
|
|
2607
2798
|
process.exit(1);
|
|
@@ -2627,9 +2818,11 @@ async function runSpecSet(project, opts) {
|
|
|
2627
2818
|
// src/commands/agent.ts
|
|
2628
2819
|
var import_chalk26 = __toESM(require("chalk"));
|
|
2629
2820
|
var import_ora11 = __toESM(require("ora"));
|
|
2821
|
+
init_auth();
|
|
2630
2822
|
|
|
2631
2823
|
// src/lib/tools.ts
|
|
2632
2824
|
var import_chalk25 = __toESM(require("chalk"));
|
|
2825
|
+
init_api();
|
|
2633
2826
|
async function proj(teamId, name, version2) {
|
|
2634
2827
|
return resolveProject(teamId, name, version2);
|
|
2635
2828
|
}
|
|
@@ -2779,6 +2972,7 @@ function findTool(name) {
|
|
|
2779
2972
|
}
|
|
2780
2973
|
|
|
2781
2974
|
// src/commands/agent.ts
|
|
2975
|
+
init_types();
|
|
2782
2976
|
var DASHBOARD_BASE5 = process.env.APIBLAZE_DASHBOARD_BASE || "https://dashboard.apiblaze.com";
|
|
2783
2977
|
var MAX_TOOL_STEPS = 6;
|
|
2784
2978
|
async function callAgent(messages, teamId) {
|
|
@@ -3040,44 +3234,59 @@ async function runConsumerApikeys(opts) {
|
|
|
3040
3234
|
// src/commands/sidecar.ts
|
|
3041
3235
|
var import_chalk28 = __toESM(require("chalk"));
|
|
3042
3236
|
var import_ora13 = __toESM(require("ora"));
|
|
3043
|
-
var
|
|
3044
|
-
var
|
|
3237
|
+
var fs7 = __toESM(require("fs"));
|
|
3238
|
+
var path4 = __toESM(require("path"));
|
|
3239
|
+
init_auth();
|
|
3045
3240
|
function detectNextProject(root) {
|
|
3046
|
-
const hasConfig = ["next.config.js", "next.config.mjs", "next.config.ts"].some((f) =>
|
|
3241
|
+
const hasConfig = ["next.config.js", "next.config.mjs", "next.config.ts"].some((f) => fs7.existsSync(path4.join(root, f)));
|
|
3047
3242
|
let hasDep = false;
|
|
3048
3243
|
try {
|
|
3049
|
-
const pkg = JSON.parse(
|
|
3244
|
+
const pkg = JSON.parse(fs7.readFileSync(path4.join(root, "package.json"), "utf8"));
|
|
3050
3245
|
hasDep = !!(pkg.dependencies?.next || pkg.devDependencies?.next);
|
|
3051
3246
|
} catch {
|
|
3052
3247
|
}
|
|
3053
|
-
const appDir =
|
|
3054
|
-
const pagesDir =
|
|
3248
|
+
const appDir = fs7.existsSync(path4.join(root, "app")) || fs7.existsSync(path4.join(root, "src", "app"));
|
|
3249
|
+
const pagesDir = fs7.existsSync(path4.join(root, "pages")) || fs7.existsSync(path4.join(root, "src", "pages"));
|
|
3055
3250
|
return { found: hasConfig || hasDep || appDir || pagesDir, router: appDir ? "app" : pagesDir ? "pages" : null };
|
|
3056
3251
|
}
|
|
3057
3252
|
function upsertEnvLocal(root, token) {
|
|
3058
|
-
const p =
|
|
3253
|
+
const p = path4.join(root, ".env.local");
|
|
3059
3254
|
let existing = "";
|
|
3060
3255
|
try {
|
|
3061
|
-
existing =
|
|
3256
|
+
existing = fs7.readFileSync(p, "utf8");
|
|
3062
3257
|
} catch {
|
|
3063
3258
|
}
|
|
3064
|
-
const had = /^APIBLAZE_TOKEN=/m.test(existing);
|
|
3065
|
-
|
|
3259
|
+
const had = /^APIBLAZE_API_KEY=/m.test(existing) || /^APIBLAZE_TOKEN=/m.test(existing);
|
|
3260
|
+
let next = existing.replace(/^APIBLAZE_TOKEN=.*\n?/m, "");
|
|
3261
|
+
next = /^APIBLAZE_API_KEY=/m.test(next) ? next.replace(/^APIBLAZE_API_KEY=.*$/m, `APIBLAZE_API_KEY=${token}`) : (next && !next.endsWith("\n") ? next + "\n" : next) + `APIBLAZE_API_KEY=${token}
|
|
3262
|
+
`;
|
|
3263
|
+
if (!/^APIBLAZE_SIDECAR=/m.test(next)) {
|
|
3264
|
+
next = (next.endsWith("\n") ? next : next + "\n") + `APIBLAZE_SIDECAR=on
|
|
3066
3265
|
`;
|
|
3067
|
-
|
|
3266
|
+
}
|
|
3267
|
+
fs7.writeFileSync(p, next);
|
|
3068
3268
|
return had ? "rotated" : "created";
|
|
3069
3269
|
}
|
|
3270
|
+
function readEnvKey(root) {
|
|
3271
|
+
try {
|
|
3272
|
+
const s = fs7.readFileSync(path4.join(root, ".env.local"), "utf8");
|
|
3273
|
+
const m = s.match(/^APIBLAZE_API_KEY=(.+)$/m) ?? s.match(/^APIBLAZE_TOKEN=(.+)$/m);
|
|
3274
|
+
return m ? m[1].trim() : null;
|
|
3275
|
+
} catch {
|
|
3276
|
+
return null;
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3070
3279
|
function ensureGitignored(root) {
|
|
3071
|
-
const p =
|
|
3280
|
+
const p = path4.join(root, ".gitignore");
|
|
3072
3281
|
let c = "";
|
|
3073
3282
|
try {
|
|
3074
|
-
c =
|
|
3283
|
+
c = fs7.readFileSync(p, "utf8");
|
|
3075
3284
|
} catch {
|
|
3076
3285
|
}
|
|
3077
|
-
if (!/^\.env\.local$/m.test(c) && !/^\.env\*/m.test(c))
|
|
3286
|
+
if (!/^\.env\.local$/m.test(c) && !/^\.env\*/m.test(c)) fs7.writeFileSync(p, (c && !c.endsWith("\n") ? c + "\n" : c) + ".env.local\n");
|
|
3078
3287
|
}
|
|
3079
3288
|
function wireInstrumentation(root) {
|
|
3080
|
-
const existing = ["instrumentation.ts", "instrumentation.js",
|
|
3289
|
+
const existing = ["instrumentation.ts", "instrumentation.js", path4.join("src", "instrumentation.ts")].map((c) => path4.join(root, c)).find((f) => fs7.existsSync(f));
|
|
3081
3290
|
const body = `import { register as apiblaze } from "apiblaze/sidecar";
|
|
3082
3291
|
|
|
3083
3292
|
export function register() {
|
|
@@ -3085,18 +3294,18 @@ export function register() {
|
|
|
3085
3294
|
}
|
|
3086
3295
|
`;
|
|
3087
3296
|
if (!existing) {
|
|
3088
|
-
|
|
3297
|
+
fs7.writeFileSync(path4.join(root, "instrumentation.ts"), body);
|
|
3089
3298
|
return "created";
|
|
3090
3299
|
}
|
|
3091
|
-
const cur =
|
|
3300
|
+
const cur = fs7.readFileSync(existing, "utf8");
|
|
3092
3301
|
if (cur.includes("apiblaze/sidecar")) return "present";
|
|
3093
3302
|
if (/export\s+function\s+register\s*\(/.test(cur)) {
|
|
3094
|
-
|
|
3303
|
+
fs7.writeFileSync(existing, `import { register as apiblaze } from "apiblaze/sidecar";
|
|
3095
3304
|
` + cur.replace(/export\s+function\s+register\s*\(\s*\)\s*\{/, (m) => `${m}
|
|
3096
3305
|
apiblaze();`));
|
|
3097
3306
|
return "patched";
|
|
3098
3307
|
}
|
|
3099
|
-
|
|
3308
|
+
fs7.writeFileSync(existing, `import { register as apiblaze } from "apiblaze/sidecar";
|
|
3100
3309
|
${cur}
|
|
3101
3310
|
// call apiblaze() inside your register() export.
|
|
3102
3311
|
`);
|
|
@@ -3132,51 +3341,100 @@ export default async function Page() {
|
|
|
3132
3341
|
function generateInspector(root, router) {
|
|
3133
3342
|
try {
|
|
3134
3343
|
if (router === "pages") {
|
|
3135
|
-
const dir2 =
|
|
3136
|
-
const f2 =
|
|
3137
|
-
|
|
3138
|
-
return
|
|
3139
|
-
}
|
|
3140
|
-
const base =
|
|
3141
|
-
const dir =
|
|
3142
|
-
|
|
3143
|
-
const f =
|
|
3144
|
-
|
|
3145
|
-
return
|
|
3344
|
+
const dir2 = fs7.existsSync(path4.join(root, "src", "pages")) ? path4.join(root, "src", "pages") : path4.join(root, "pages");
|
|
3345
|
+
const f2 = path4.join(dir2, "abz-inspector.tsx");
|
|
3346
|
+
fs7.writeFileSync(f2, INSPECTOR_PAGE);
|
|
3347
|
+
return path4.relative(root, f2);
|
|
3348
|
+
}
|
|
3349
|
+
const base = fs7.existsSync(path4.join(root, "src", "app")) ? path4.join(root, "src", "app") : path4.join(root, "app");
|
|
3350
|
+
const dir = path4.join(base, "abz-inspector");
|
|
3351
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
3352
|
+
const f = path4.join(dir, "page.tsx");
|
|
3353
|
+
fs7.writeFileSync(f, INSPECTOR_PAGE);
|
|
3354
|
+
return path4.relative(root, f);
|
|
3146
3355
|
} catch {
|
|
3147
3356
|
return null;
|
|
3148
3357
|
}
|
|
3149
3358
|
}
|
|
3150
|
-
async function
|
|
3151
|
-
const
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3359
|
+
async function runAnonymousInit(root, router, opts) {
|
|
3360
|
+
const { sidecarInitAnonymous: sidecarInitAnonymous2 } = await Promise.resolve().then(() => (init_api(), api_exports));
|
|
3361
|
+
const { loadAnonSession: loadAnonSession2, saveAnonSession: saveAnonSession2, clearAnonSession: clearAnonSession2 } = await Promise.resolve().then(() => (init_anon_session(), anon_session_exports));
|
|
3362
|
+
if (opts.newSession) clearAnonSession2();
|
|
3363
|
+
const prior = loadAnonSession2();
|
|
3364
|
+
const spinner = (0, import_ora13.default)(prior ? "Adding to your anonymous session..." : "Setting up a sidecar (no login needed)...").start();
|
|
3365
|
+
let out;
|
|
3366
|
+
try {
|
|
3367
|
+
out = await sidecarInitAnonymous2(prior?.anon_session);
|
|
3368
|
+
spinner.succeed("Sidecar ready (anonymous trial).");
|
|
3369
|
+
} catch (err) {
|
|
3370
|
+
spinner.fail("Setup failed.");
|
|
3371
|
+
throw err;
|
|
3155
3372
|
}
|
|
3373
|
+
if (out.anon_session) saveAnonSession2(out.anon_session, out.claim_code);
|
|
3374
|
+
const envState = upsertEnvLocal(root, out.token);
|
|
3375
|
+
ensureGitignored(root);
|
|
3376
|
+
console.log(` ${import_chalk28.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
|
|
3377
|
+
console.log(` ${import_chalk28.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
|
|
3378
|
+
let inspectorPath = null;
|
|
3379
|
+
if (!opts.noInspector) {
|
|
3380
|
+
inspectorPath = generateInspector(root, router);
|
|
3381
|
+
if (inspectorPath) console.log(` ${import_chalk28.default.green("\u2713")} inspector at ${inspectorPath}`);
|
|
3382
|
+
}
|
|
3383
|
+
console.log("");
|
|
3384
|
+
console.log(import_chalk28.default.bold("Done (no account needed). What happens next:"));
|
|
3385
|
+
console.log(` 1. ${import_chalk28.default.cyan("npm install apiblaze")} then ${import_chalk28.default.cyan("npm run dev")} and use your app.`);
|
|
3386
|
+
console.log(` 2. Each external origin your app calls is logged in the console \u2014 approve one with:`);
|
|
3387
|
+
console.log(` ${import_chalk28.default.cyan("apiblaze origins approve api.stripe.com")} (no login needed)`);
|
|
3388
|
+
console.log("");
|
|
3389
|
+
console.log(import_chalk28.default.bold(" \u{1F511} Keep your setup \u2014 claim it into an account:"));
|
|
3390
|
+
console.log(` ${import_chalk28.default.cyan("apiblaze login")} then ${import_chalk28.default.cyan("apiblaze claim")} ${import_chalk28.default.dim("(no code needed here)")}`);
|
|
3391
|
+
console.log(import_chalk28.default.dim(` From another machine: apiblaze claim ${out.claim_code} \xB7 expires in 30 days`));
|
|
3392
|
+
}
|
|
3393
|
+
async function runSidecar(opts) {
|
|
3394
|
+
const root = path4.resolve(opts.dir ?? process.cwd());
|
|
3156
3395
|
const detected = detectNextProject(root);
|
|
3157
3396
|
if (!detected.found) {
|
|
3158
3397
|
console.log(import_chalk28.default.yellow(`No Next.js project detected in ${root}.`));
|
|
3159
3398
|
console.log("Create one (e.g. `npx create-next-app`) and re-run `apiblaze init` inside it.");
|
|
3160
3399
|
return;
|
|
3161
3400
|
}
|
|
3401
|
+
if (!loadCredentials() && !readEnvKey(root)) {
|
|
3402
|
+
await runAnonymousInit(root, detected.router, opts);
|
|
3403
|
+
return;
|
|
3404
|
+
}
|
|
3405
|
+
if (!loadCredentials()) {
|
|
3406
|
+
upsertEnvLocal(root, readEnvKey(root));
|
|
3407
|
+
ensureGitignored(root);
|
|
3408
|
+
console.log(` ${import_chalk28.default.green("\u2713")} .env.local present (APIBLAZE_API_KEY) \u2014 reusing`);
|
|
3409
|
+
console.log(` ${import_chalk28.default.green("\u2713")} instrumentation.ts ${wireInstrumentation(root)}`);
|
|
3410
|
+
console.log(import_chalk28.default.dim(" Log in and run `apiblaze claim <code>` to keep this setup, or `apiblaze login` to manage it."));
|
|
3411
|
+
return;
|
|
3412
|
+
}
|
|
3162
3413
|
const { teamId, teamName } = await resolveTeam(opts.team);
|
|
3163
|
-
const
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3414
|
+
const existingKey = readEnvKey(root);
|
|
3415
|
+
const switchingTeam = !!opts.team;
|
|
3416
|
+
const mustMint = !existingKey || opts.rotate || switchingTeam;
|
|
3417
|
+
let token = existingKey ?? "";
|
|
3418
|
+
if (mustMint) {
|
|
3419
|
+
const spinner = (0, import_ora13.default)(existingKey ? "Re-establishing the sidecar (minting a fresh invoke key)..." : "Setting up the sidecar (tenant + non-expiring invoke key)...").start();
|
|
3420
|
+
try {
|
|
3421
|
+
const out = await admin({
|
|
3422
|
+
method: "POST",
|
|
3423
|
+
path: `/teams/${encodeURIComponent(teamId)}/sidecar/setup`,
|
|
3424
|
+
summary: `Set up sidecar for team ${teamName ?? teamId}`
|
|
3425
|
+
});
|
|
3426
|
+
token = out.token;
|
|
3427
|
+
spinner.succeed(existingKey ? `Sidecar re-established on team ${teamName ?? teamId}.` : "Sidecar ready.");
|
|
3428
|
+
} catch (err) {
|
|
3429
|
+
spinner.fail("Setup failed.");
|
|
3430
|
+
throw err;
|
|
3431
|
+
}
|
|
3432
|
+
} else {
|
|
3433
|
+
console.log(import_chalk28.default.dim(` Reusing the existing APIBLAZE_API_KEY (run with --rotate to mint a fresh one, or --team <name> to switch teams).`));
|
|
3176
3434
|
}
|
|
3177
3435
|
const envState = upsertEnvLocal(root, token);
|
|
3178
3436
|
ensureGitignored(root);
|
|
3179
|
-
console.log(` ${import_chalk28.default.green("\u2713")} .env.local ${envState} (
|
|
3437
|
+
console.log(` ${import_chalk28.default.green("\u2713")} .env.local ${envState} (APIBLAZE_API_KEY) \u2014 gitignored`);
|
|
3180
3438
|
const wireState = wireInstrumentation(root);
|
|
3181
3439
|
console.log(` ${import_chalk28.default.green("\u2713")} instrumentation.ts ${wireState}`);
|
|
3182
3440
|
let inspectorPath = null;
|
|
@@ -3191,15 +3449,33 @@ async function runSidecar(opts) {
|
|
|
3191
3449
|
console.log(` 3. The origins your app calls appear as ${import_chalk28.default.bold("candidates")} \u2014 list them: ${import_chalk28.default.cyan("apiblaze origins")}`);
|
|
3192
3450
|
console.log(` 4. Approve the ones to route: ${import_chalk28.default.cyan("apiblaze origins approve api.stripe.com")} (or in the dashboard)`);
|
|
3193
3451
|
console.log(` \u2026within ~5 min your app starts routing that origin through APIblaze.`);
|
|
3194
|
-
if (inspectorPath) console.log(` \u2022 Try it now: open ${import_chalk28.default.underline("http://localhost:3000/abz-inspector")} (dev only; rm ${
|
|
3452
|
+
if (inspectorPath) console.log(` \u2022 Try it now: open ${import_chalk28.default.underline("http://localhost:3000/abz-inspector")} (dev only; rm ${path4.dirname(inspectorPath)} before shipping)`);
|
|
3453
|
+
if (switchingTeam) console.log(import_chalk28.default.dim(` \u2022 Approved origins are per-team \u2014 re-approve them on ${teamName ?? teamId} with \`apiblaze origins approve <origin>\`.`));
|
|
3454
|
+
console.log("");
|
|
3455
|
+
console.log(import_chalk28.default.dim(" Manage: apiblaze origins (list/approve/deny/remove)"));
|
|
3456
|
+
console.log(import_chalk28.default.dim(" Rotate: apiblaze init --rotate \xB7 Switch team: apiblaze init --team <name>"));
|
|
3457
|
+
console.log(import_chalk28.default.dim(" Turn off: set APIBLAZE_SIDECAR=off in .env.local (flip back to on anytime; key stays put)."));
|
|
3195
3458
|
console.log("");
|
|
3196
|
-
console.log(import_chalk28.default.yellow(" \u26A0
|
|
3459
|
+
console.log(import_chalk28.default.yellow(" \u26A0 APIBLAZE_API_KEY is long-lived and lets a holder call your team's proxies. Never commit it."));
|
|
3197
3460
|
console.log(import_chalk28.default.dim(" Your control-plane login stays in ~/.apiblaze \u2014 it never entered this project."));
|
|
3198
3461
|
}
|
|
3199
3462
|
|
|
3200
3463
|
// src/commands/origins.ts
|
|
3201
3464
|
var import_chalk29 = __toESM(require("chalk"));
|
|
3202
3465
|
var import_ora14 = __toESM(require("ora"));
|
|
3466
|
+
var fs8 = __toESM(require("fs"));
|
|
3467
|
+
var path5 = __toESM(require("path"));
|
|
3468
|
+
init_auth();
|
|
3469
|
+
init_api();
|
|
3470
|
+
function readEnvKey2() {
|
|
3471
|
+
try {
|
|
3472
|
+
const s = fs8.readFileSync(path5.join(process.cwd(), ".env.local"), "utf8");
|
|
3473
|
+
const m = s.match(/^APIBLAZE_API_KEY=(.+)$/m) ?? s.match(/^APIBLAZE_TOKEN=(.+)$/m);
|
|
3474
|
+
return m ? m[1].trim() : null;
|
|
3475
|
+
} catch {
|
|
3476
|
+
return null;
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3203
3479
|
async function runOriginsList(opts) {
|
|
3204
3480
|
const { teamId, teamName } = await resolveTeam(opts.team);
|
|
3205
3481
|
const out = await admin({
|
|
@@ -3230,6 +3506,22 @@ Candidates \u2014 going direct, not yet approved (${candidates.length})`));
|
|
|
3230
3506
|
}
|
|
3231
3507
|
}
|
|
3232
3508
|
async function runOriginsApprove(origin, opts) {
|
|
3509
|
+
if (!loadCredentials()) {
|
|
3510
|
+
const key = readEnvKey2();
|
|
3511
|
+
if (!key) {
|
|
3512
|
+
console.error(import_chalk29.default.red("Not logged in and no .env.local APIBLAZE_API_KEY found. Run `apiblaze init` first."));
|
|
3513
|
+
process.exit(1);
|
|
3514
|
+
}
|
|
3515
|
+
const spinner2 = (0, import_ora14.default)(`Approving ${origin} (anonymous)...`).start();
|
|
3516
|
+
try {
|
|
3517
|
+
const out = await sidecarApproveAnonymous(key, origin.replace(/^https?:\/\//, ""));
|
|
3518
|
+
spinner2.succeed(`Approved ${origin} \u2192 proxy ${out.project_id}. Routing within ~5 min.`);
|
|
3519
|
+
} catch (err) {
|
|
3520
|
+
spinner2.fail("Approve failed.");
|
|
3521
|
+
throw err;
|
|
3522
|
+
}
|
|
3523
|
+
return;
|
|
3524
|
+
}
|
|
3233
3525
|
const { teamId } = await resolveTeam(opts.team);
|
|
3234
3526
|
const spinner = (0, import_ora14.default)(`Approving ${origin}...`).start();
|
|
3235
3527
|
try {
|
|
@@ -3257,6 +3549,17 @@ async function runOriginsDeny(origin, opts) {
|
|
|
3257
3549
|
throw err;
|
|
3258
3550
|
}
|
|
3259
3551
|
}
|
|
3552
|
+
async function runOriginsRemove(origin, opts) {
|
|
3553
|
+
const { teamId } = await resolveTeam(opts.team);
|
|
3554
|
+
const spinner = (0, import_ora14.default)(`Removing the proxy for ${origin}...`).start();
|
|
3555
|
+
try {
|
|
3556
|
+
await admin({ method: "POST", path: `/teams/${encodeURIComponent(teamId)}/sidecar/remove`, body: { origin }, summary: `Un-route sidecar origin ${origin}` });
|
|
3557
|
+
spinner.succeed(`Removed ${origin}. Your app will stop routing it (goes direct) within ~5 min.`);
|
|
3558
|
+
} catch (err) {
|
|
3559
|
+
spinner.fail("Remove failed.");
|
|
3560
|
+
throw err;
|
|
3561
|
+
}
|
|
3562
|
+
}
|
|
3260
3563
|
|
|
3261
3564
|
// src/index.ts
|
|
3262
3565
|
var program = new import_commander.Command();
|
|
@@ -3285,7 +3588,7 @@ program.command("login").description("Authenticate with APIblaze").action(async
|
|
|
3285
3588
|
process.exit(1);
|
|
3286
3589
|
}
|
|
3287
3590
|
});
|
|
3288
|
-
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("--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("--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("--json", "Output machine-readable JSON (non-interactive)").action(async (opts) => {
|
|
3591
|
+
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("--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("--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) => {
|
|
3289
3592
|
try {
|
|
3290
3593
|
await runCreate(opts);
|
|
3291
3594
|
} catch (err) {
|
|
@@ -3297,10 +3600,11 @@ var agent = program.command("agent").description("Chat with an assistant that bu
|
|
|
3297
3600
|
agent.command("authz").description("Chat to design and turn on access rules for an API").argument("<project>", "Project name or id").argument("[apiVersion]", "API version (defaults to the project's)").action(action((project, apiVersion) => runAuthz(project, apiVersion)));
|
|
3298
3601
|
agent.command("openapi").description("Chat to build your API spec from real traffic").argument("<project>", "Project name or id").argument("[apiVersion]", "API version (defaults to the project's)").action(action((project, apiVersion) => runOpenapi(project, apiVersion)));
|
|
3299
3602
|
agent.command("mcp").description("Chat to build an MCP server for an API").argument("<project>", "Project name or id").argument("[apiVersion]", "API version (defaults to the project's)").option("--environment <env>", "Environment to publish (default: prod)").action(action((project, apiVersion, opts) => runMcp(project, apiVersion, opts)));
|
|
3300
|
-
program.command("init").aliases(["sidecar"]).description("Wire a Next.js app to route its external fetches through APIblaze (one command)").option("--team <id|name>", "Team to set up under (defaults to your active team)").option("--dir <path>", "Project directory (defaults to cwd)").option("--no-inspector", "Skip generating the dev-only /abz-inspector page").option("-y, --yes", "Skip prompts").action(action((opts) => runSidecar({ team: opts.team, dir: opts.dir, yes: opts.yes, noInspector: opts.inspector === false })));
|
|
3603
|
+
program.command("init").aliases(["sidecar"]).description("Wire a Next.js app to route its external fetches through APIblaze (one command)").option("--team <id|name>", "Team to set up under (defaults to your active team)").option("--dir <path>", "Project directory (defaults to cwd)").option("--no-inspector", "Skip generating the dev-only /abz-inspector page").option("--rotate", "Mint a fresh invoke key even if one already exists").option("--new-session", "Start a fresh anonymous session (logged-out only)").option("-y, --yes", "Skip prompts").action(action((opts) => runSidecar({ team: opts.team, dir: opts.dir, yes: opts.yes, noInspector: opts.inspector === false, rotate: opts.rotate, newSession: opts.newSession })));
|
|
3301
3604
|
var origins = program.command("origins").description("See which external origins your app calls; approve the ones to route through APIblaze").option("--team <id|name>", "Team (defaults to active team)").option("--json", "Machine-readable output").action(action((opts) => runOriginsList(opts)));
|
|
3302
3605
|
origins.command("approve").description("Route an origin through APIblaze (creates its proxy)").argument("<origin>", "Origin, e.g. api.stripe.com").option("--team <id|name>", "Team (defaults to active team)").option("--json", "Machine-readable output").action(action((origin, opts) => runOriginsApprove(origin, opts)));
|
|
3303
3606
|
origins.command("deny").description("Dismiss a candidate origin so it stops being suggested").argument("<origin>", "Origin, e.g. sentry.io").option("--team <id|name>", "Team (defaults to active team)").action(action((origin, opts) => runOriginsDeny(origin, opts)));
|
|
3607
|
+
origins.command("remove").description("Un-route an approved origin (deletes its proxy; the app goes direct again)").argument("<origin>", "Origin, e.g. api.stripe.com").option("--team <id|name>", "Team (defaults to active team)").action(action((origin, opts) => runOriginsRemove(origin, opts)));
|
|
3304
3608
|
program.command("dev").description("Put your localhost behind a public URL (dev tunnel)").argument("[port]", "Local port to tunnel (positional; overrides --port)").option("-p, --port <number>", "Local port to tunnel", "3000").option("-o, --capture-file <path>", "Stream full request/response traffic to a file (JSON lines)").action(async (port, opts) => {
|
|
3305
3609
|
try {
|
|
3306
3610
|
const resolved = parseInt(port ?? opts.port, 10);
|
package/dist/sidecar/index.d.mts
CHANGED
|
@@ -17,6 +17,8 @@ interface SidecarOptions {
|
|
|
17
17
|
exclude?: string[];
|
|
18
18
|
include?: string[];
|
|
19
19
|
quiet?: boolean;
|
|
20
|
+
/** Explicit on/off. Overrides the APIBLAZE_SIDECAR env toggle when set. */
|
|
21
|
+
enabled?: boolean;
|
|
20
22
|
}
|
|
21
23
|
declare function register(opts?: SidecarOptions): void;
|
|
22
24
|
declare function withApiblaze<T extends Record<string, unknown>>(nextConfig?: T): T;
|
package/dist/sidecar/index.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ interface SidecarOptions {
|
|
|
17
17
|
exclude?: string[];
|
|
18
18
|
include?: string[];
|
|
19
19
|
quiet?: boolean;
|
|
20
|
+
/** Explicit on/off. Overrides the APIBLAZE_SIDECAR env toggle when set. */
|
|
21
|
+
enabled?: boolean;
|
|
20
22
|
}
|
|
21
23
|
declare function register(opts?: SidecarOptions): void;
|
|
22
24
|
declare function withApiblaze<T extends Record<string, unknown>>(nextConfig?: T): T;
|
package/dist/sidecar/index.js
CHANGED
|
@@ -53,6 +53,7 @@ var NOISE_DENYLIST = [
|
|
|
53
53
|
"registry.npmjs.org",
|
|
54
54
|
"pypi.org"
|
|
55
55
|
];
|
|
56
|
+
var OFF_VALUES = /* @__PURE__ */ new Set(["off", "false", "0", "no", "disabled"]);
|
|
56
57
|
var installed = false;
|
|
57
58
|
function canonicalOrigin(input) {
|
|
58
59
|
try {
|
|
@@ -83,9 +84,14 @@ function isPrivateOrLocal(host) {
|
|
|
83
84
|
}
|
|
84
85
|
function register(opts) {
|
|
85
86
|
if (installed) return;
|
|
86
|
-
const
|
|
87
|
+
const off = opts?.enabled === false || opts?.enabled === void 0 && OFF_VALUES.has((process.env.APIBLAZE_SIDECAR ?? "").trim().toLowerCase());
|
|
88
|
+
if (off) {
|
|
89
|
+
if (!opts?.quiet) console.log("[apiblaze/sidecar] off (APIBLAZE_SIDECAR=off) \u2014 fetches go direct.");
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const token = opts?.token ?? process.env.APIBLAZE_API_KEY ?? process.env.APIBLAZE_TOKEN;
|
|
87
93
|
if (!token) {
|
|
88
|
-
if (!opts?.quiet) console.
|
|
94
|
+
if (!opts?.quiet) console.log("[apiblaze/sidecar] off (no APIBLAZE_API_KEY set) \u2014 fetches go direct.");
|
|
89
95
|
return;
|
|
90
96
|
}
|
|
91
97
|
const original = globalThis.fetch;
|
package/dist/sidecar/index.mjs
CHANGED
|
@@ -27,6 +27,7 @@ var NOISE_DENYLIST = [
|
|
|
27
27
|
"registry.npmjs.org",
|
|
28
28
|
"pypi.org"
|
|
29
29
|
];
|
|
30
|
+
var OFF_VALUES = /* @__PURE__ */ new Set(["off", "false", "0", "no", "disabled"]);
|
|
30
31
|
var installed = false;
|
|
31
32
|
function canonicalOrigin(input) {
|
|
32
33
|
try {
|
|
@@ -57,9 +58,14 @@ function isPrivateOrLocal(host) {
|
|
|
57
58
|
}
|
|
58
59
|
function register(opts) {
|
|
59
60
|
if (installed) return;
|
|
60
|
-
const
|
|
61
|
+
const off = opts?.enabled === false || opts?.enabled === void 0 && OFF_VALUES.has((process.env.APIBLAZE_SIDECAR ?? "").trim().toLowerCase());
|
|
62
|
+
if (off) {
|
|
63
|
+
if (!opts?.quiet) console.log("[apiblaze/sidecar] off (APIBLAZE_SIDECAR=off) \u2014 fetches go direct.");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const token = opts?.token ?? process.env.APIBLAZE_API_KEY ?? process.env.APIBLAZE_TOKEN;
|
|
61
67
|
if (!token) {
|
|
62
|
-
if (!opts?.quiet) console.
|
|
68
|
+
if (!opts?.quiet) console.log("[apiblaze/sidecar] off (no APIBLAZE_API_KEY set) \u2014 fetches go direct.");
|
|
63
69
|
return;
|
|
64
70
|
}
|
|
65
71
|
const original = globalThis.fetch;
|
package/package.json
CHANGED